TACHYON
[~
{ *** WIZnet W5100/5200 driver ***
Implements the SPI interface to the WIZnet W5100 including the primitives to talk to the chip
The aim is to make this talk to the W5200 as well but the W5100 on the Spinneret is being used for development
130218
Looking at dedicating a cog just to high-speed SPI access which will not only speed up processing but also make it easier to multi-task. I/O will be via simple hub variables.
NOTE: Refresh webpage for latest version
Please use latest kernel 2.1 130216
}
\ Module name - reports in list of modules using MODULES word.
pub WIZNET.fth ." WIZNET 5100/5200 driver 130216.1500 " ;
\ Spinneret port definitions
#P0 |< == WDO \ SPI data from WIZNET
#P1 |< == WDI \ SPI data to WIZNET
#P2 |< == WCE \ SPI slave select
#P3 |< == WCK \ SPI clock
#P14 |< == WRST \ Reset WIZNET - active low
#P15 |< == WSEL \ SPI mode select - drive high then reset
pub WIZPINS ( sck.mosi.miso.cs -- )
' WCE 1+ !
' WDO 1+ !
' WDI 1+ !
' WCK 1+ !
;
\ WIZnet SPI OPCODE CONSTANTS
$F0.0000.00 == =WWR
$0F.0000.00 == =WRD
\ Write to the WIZnet register via SPI
pub WIZ! ( data address -- )
8 SHL SWAP >B OR \ position address field and merge with data byte
=WWR OR \ Set write opcode
WCE OUTCLR RUNMOD WCE OUTSET \ chip select, write 32-bits SPI, chip deselect
DROP
;
\ Read from the WIZnet register via SPI
pub WIZ@ ( address -- data )
8 SHL =WRD OR WCE OUTCLR RUNMOD WCE OUTSET >B
;
\ Init the SPI for the WIZnet chip
pub !WIZIO
BL WDO WDI WCK COGREGS \ ( cnt miso mosi clk -- ) use 32-bit transfers
0 4 COGREG! \ disable chip select mask so that we can leave with clock low (may patch later)
WCE OUTSET \ Chip select is an output - active low
WCK OUTCLR \ Clock is an output - leave low
WDI OUTCLR \ MOSI is an output
WSEL OUTSET \ Select SPI mode for W5100
WRST OUTCLR WRST OUTSET \ Reset the chip (ensure pulse is >2us)
[ESPIO] \ Select Enhanced SPIO module
;
\ write a long to 4 consecutive registers in big endian format
pri WIZ4! ( long reg -- )
OVER #24 SHR OVER WIZ! 1+
OVER #16 SHR OVER WIZ! 1+
pri WIZ2! ( word reg -- )
OVER 8 SHR OVER WIZ! 1+
WIZ!
;
pri WIZ2@ ( reg -- word )
DUP WIZ@ 8 SHL SWAP 1+ WIZ@ OR
;
\ common registers
\ Access common registers
pub wMODE ( mask -- ) 0 WIZ! ;
pub GATEWAY ( addr -- ) 1 WIZ4! ;
pub SUBNET ( mask -- ) 5 WIZ4! ;
pub SHAR ( high low -- ) $0B WIZ4! 8 WIZ2! ;
pub SRCIP ( long -- ) $0F WIZ4! ;
pub INTS@ ( -- ints ) $15 WIZ@ ;
pub INTMASK ( mask -- ) $16 WIZ! ;
pub RETRYTIME ( val -- ) $17 WIZ2! ;
pub RETRYS ( cnt -- ) $19 WIZ! ;
pub RXSIZ ( mask -- ) $1A WIZ! ; \ default sets 2K for each socket (%01010101)
pub TXSIZ ( mask -- ) $1B WIZ! ;
pub UIP ( ip -- ) $2A WIZ4! ;
pub UPORT ( port -- ) $2E WIZ2! ;
\ current socket register address offset
$400 == @SOCKET
\ Set the socket number ( calculates address and sets as a SOCKET constant )
pub SOCKET ( socket -- ) 4 + 8 SHL ' @SOCKET 1+ ! ;
\ Socket registers ( -- addr )
pub sMODE @SOCKET ; \ mode
pub sCMD 1 @SOCKET + ; \ command
pub sINTS 2 @SOCKET + ; \ interrupts
pub sSTAT 3 @SOCKET + ; \ status
pub sPORT 4 @SOCKET + ; \ 2 byte src port
pub sDHAR 6 @SOCKET + ; \ 6 byte dest hardware address
pub sDIP $0C @SOCKET + ; \ 4 byte dest IP address
pub sDPORT $10 @SOCKET + ; \ 2 byte dest port
pub sSSIZE $12 @SOCKET + ; \ 2 byte dest max seg size
pub sPRO $14 @SOCKET + ; \ protocol in IP raw mode
pub TXFREE@ $20 @SOCKET + WIZ2@ ;
pub TXREAD $22 @SOCKET + ;
pub TXWRITE $24 @SOCKET + ;
pub RXSIZE@ $26 @SOCKET + WIZ2@ ;
pub RXREAD $28 @SOCKET + ;
( SOCKET COMMANDS )
pub OPEN 1 sCMD WIZ! ;
pub LISTEN 2 sCMD WIZ! ;
pub CONNECT 4 sCMD WIZ! ;
pub DISCON 8 sCMD WIZ! ;
pub CLOSE $10 sCMD WIZ! ;
pub SEND $20 sCMD WIZ! ;
pub SENDMAC $21 sCMD WIZ! ;
pub SENDKEEP $22 sCMD WIZ! ;
pub RECV $40 sCMD WIZ! ;
( SOCKET INTERRUPTS )
4 == =SENDOK
3 == =TIMEOUT
2 == =RECV
1 == =DISCON
0 == =CON
( SOCKET STATUS CODES )
$00 == SOCK_CLOSED
$13 == SOCK_INIT
$14 == SOCK_LISTEN
$17 == SOCK_ESTABLISHED
$1C == SOCK_CLOSE_WAIT
$22 == SOCK_UDP
$32 == SOCK_IPRAW
$42 == SOCK_MACRAW
$5F == SOCK_PPOE
( SOCKET TRANSIENT STATUS CODES )
$15 == SOCK_SYNSENT
$16 == SOCK_SYNRECV
$18 == SOCK_FIN_WAIT
$1A == SOCK_CLOSING
$1B == SOCK_TIME_WAIT
$1D == SOCK_LAST_ACK
$11 == SOCK_ARP
$21 == SOCK_ARP1
$31 == SOCK_ARP2
pub PORT ( srcport -- ) sPORT WIZ2! ;
\ Protocol modes
pub CLOSED 0 sMODE WIZ! ;
pub TCP 1 sMODE WIZ! ;
pub UDP 2 sMODE WIZ! ;
pub IPRAW 3 sMODE WIZ! ;
pub MACRAW 4 sMODE WIZ! ;
pub PPPoE 5 sMODE WIZ! ;
\ Testing some basic transmit functions
pub wTX ( char -- )
TXWRITE WIZ2@ $7FF AND $4000 + WIZ!
TXWRITE WIZ2@ 1+ TXWRITE WIZ2!
;
pub wTXSTR ( str -- )
DUP STRLEN SWAP \ ( strlen str )
TXWRITE WIZ2@ $7FF AND $4000 + \ Get transmit write pointer ( strlen str wrptr )
OVER STRLEN ADO C@++ I WIZ! LOOP \ copy string to WIZnet transmit buffer
DROP \ ( strlen )
TXWRITE WIZ2@ + TXWRITE WIZ2! \ Update TXWRITE index by string length
\ (moved this to wEMIT ) SEND \ Send the contents of the buffer
;
{ In this trial method simply buffer the transmit data into hub RAM and transmit it automatically
when a LF is encountered. The buffer is then erased which also provides null terminators for the next string.
}
pub wEMIT ( ch -- )
DUP BUFFERS C@ BUFFERS 1+ + C! 1 BUFFERS C+!
^J = IF
BEGIN TXFREE@ BUFFERS 1+ STRLEN => UNTIL \ Is there room for this?
BUFFERS 1+ wTXSTR SEND \ Send the buffer off as a string
BUFFERS $80 ERASE \ clear the buffer (also null terminates all data written)
THEN
;
pub (wKEY)
BEGIN RXSIZE@ UNTIL
RXREAD WIZ2@ $7FF AND DUP $6000 + WIZ@
SWAP 1+ RXREAD WIZ2! RECV
;
pub wKEY
BEGIN
(wKEY) DUP $FF = \ When the client connects I need to detect the "garbage" and flush
WHILE RXSIZE@ 0 DO (wKEY) DROP LOOP \ flush buffer
REPEAT
;
{
pub wGET
RXSIZE@
RXREAD WIZ2@ $7FF AND SWAP OVER + SWAP $6000 + \ Physical start address ( size+offset readptr )
SWAP $800 >
IF ( overflow of socket RX memory )
ELSE
THEN
;
}
pub TERM
' wEMIT uemit W! \ direct output to WIZnet transmit
' wKEY ukey W!
;
\ This part works well for directing Console I/O to the TELNET port
\ still needs proper checks etc
pub TELNET
0 SOCKET CLOSE TCP #23 PORT OPEN LISTEN \ primitive - needs checks yet
TERM \ turn over the console I/O to the TELNET server
;
pub FTP
1 SOCKET TCP #21 PORT OPEN LISTEN
\ FTPSERVER
;
pub WEB
2 SOCKET TCP #80 PORT OPEN LISTEN
\ WEBSERVER
;
\
\ Diagnostics - only needed for debugging
pub WDUMP ( addr cnt -- )
ADO BUFFERS I $100 ADO I WIZ@ OVER C! 1+ LOOP DROP I $100 BUFFERS BDUMP $100 +LOOP
;
\ Dump the WIZnet common registers
pub LW 0 $100 WDUMP ;
\ list quick status
pub S
CR ." sSTAT = " sSTAT WIZ@ .
CR ." sINTS = " sINTS WIZ@ .
;
]~
END
\ NOTE: This is the end of the software source code, what follows is normally meant to be entered interactively
\ Preset some initializations
( NOTE: uses new & notation for IP addresses - use Kernel 2.1 130214 onwards)
{
!WIZIO
&192.168.0.1 GATEWAY
&255.255.255.0 SUBNET
&192.168.0.80 SRCIP
$00.08 $DC.01.02.03 SHAR
Try typing TELNET and then connect to the Forth console via a TELNET session
TERM
peter@peter-XPS-L702X-Mint14 ~ $ telnet 192.168.0.80
Trying 192.168.0.80...
Connected to 192.168.0.80.
Escape character is '^]'.
.VER
.VER
Propeller .:.:--TACHYON--:.:. Forth V21130216.1200
ok
MY QWORDS
MY QWORDS
S LW WDUMP TELNET TERM wKEY (wKEY) wEMIT wTXSTR wTX PPPoE MACRAW IPRAW UDP TCP
CLOSED PORT SOCK_ARP2 SOCK_ARP1 SOCK_ARP SOCK_LAST_ACK SOCK_TIME_WAIT SOCK_CLOSING SOCK_FIN_WAIT
SOCK_SYNRECV SOCK_SYNSENT SOCK_PPOE SOCK_MACRAW SOCK_IPRAW SOCK_UDP SOCK_CLOSE_WAIT SOCK_ESTABLISHED
SOCK_LISTEN SOCK_INIT SOCK_CLOSED =CON =DISCON =RECV =TIMEOUT =SENDOK RECV SENDKEEP SENDMAC SEND
CLOSE DISCON CONNECT LISTEN OPEN RXREAD RXSIZE@ TXWRITE TXREAD TXFREE@ sPRO sSSIZE sDPORT
sDIP sDHAR sPORT sSTAT sINTS sCMD sMODE SOCKET @SOCKET UPORT UIP TXSIZ RXSIZ RETRYS
RETRYTIME INTMASK INTS@ SRCIP SHAR SUBNET GATEWAY wMODE WIZ2@ WIZ2! WIZ4! !WIZIO WIZ@ WIZ!
=WRD =WWR WSEL WRST WCK WCE WDI WDO
ok
}
\ Let's try an autostart procedure for a TELNET session
pub WIZ
!WIZIO
&192.168.0.1 GATEWAY
&255.255.255.0 SUBNET
&192.168.0.80 SRCIP
$00.08 $DC.01.02.03 SHAR
TELNET
;
\ Run TELNET as a task but with simple echo while the console debugs
pri WIZECHO
!WIZIO
&192.168.0.1 GATEWAY
&255.255.255.0 SUBNET
&192.168.0.80 SRCIP
$00.08 $DC.01.02.03 SHAR
0 SOCKET CLOSE TCP #23 PORT OPEN LISTEN
BEGIN wKEY wEMIT AGAIN
;
pub WIZTASK
' WIZECHO TASK? RUN
;
AUTORUN WIZ
\ BACKUP