'----------------------------------------------------------- ' Atmega168 and ENC28J60 '----------------------------------------------------------- ' Version 1.0 - june 2007 'fusebits: 'Atmega168 - External clock (gaat van 6.25 Mhz naar 12.5 Mhz) No div by 8 $regfile = "m168def.dat" $crystal = 6250000 $baud = 9600 'put terminal on 19200 baud $hwstack = 64 $swstack = 64 $framesize = 64 $include "enc28j60.inc" Config Portb.1 = Output Config Portb.2 = Output Enc28j60_cs Alias Portb.2 Dim X As Byte Dim A(5) As Byte Dim Bank As Byte Dim Enc28j60_data As Byte Dim Nextpacketptr As Word Dim Value As Byte Dim Wdata As Word Dim Buffer(60) As Byte Dim Rstatus As Byte Dim Length As Word Dim Rxstat As Word Dim Tempx As Byte Declare Sub Enc28j60init Declare Sub Enc28j60readcontrolregbyte(byval Register As Byte) Declare Sub Enc28j60writecontrolregbyte(byval Register As Byte , Byval Value As Byte) Declare Sub Enc28j60selectbank(byval Bank As Byte) Declare Sub Enc28j60bitfield_set(byval Register As Byte , Byval Value As Byte) Declare Sub Enc28j60bitfield_clear(byval Register As Byte , Byval Value As Byte) Declare Sub Enc28j60readphyword(byval Phyregister As Byte) Declare Sub Enc28j60writephyword(byval Phyregister As Byte , Byval Wdata As Word) Declare Sub Enc28j60packetsend(byval Pcktlen As Word) Declare Sub Enc28j60packetreceive(byval Maxlen As Word) Declare Sub Enc28j60readbuffer(byval Pcktlen As Word) Declare Sub Enc28j60writebuffer(byval Pcktlen As Word) 'Declare Sub Enc28j60regdump Declare Sub Enc28j60poll '/* The Ethernet address. */ Const Ethaddr0 = &H43 Const Ethaddr1 = &HC6 Const Ethaddr2 = &HB3 Const Ethaddr3 = &HF3 Const Ethaddr4 = &HAB Const Ethaddr5 = &H9E max_framelen = 200 'Configuration of the SPI-bus Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = Low , Phase = 0 , Clockrate = 4 , Noss = 0 'init the spi pins Spiinit Enc28j60_cs = 0 'reset ENC28J60 X = Enc28j60_soft_reset Spiout X , 1 Enc28j60_cs = 1 Do Call Enc28j60readcontrolregbyte(estat) X = Enc28j60_data.estat_clkrdy Loop Until X = 1 'clock from default divide/4 (6.25 Mhz) to divide/2 (12.5 Mhz) Call Enc28j60writecontrolregbyte(ecocon , &B00000010) Waitms 250 Print Print "Starting Tux" Call Enc28j60selectbank(3) 'EREVID A(1) = &B000_10010 Enc28j60_cs = 0 Spiout A(1) , 1 Spiin A(1) , 2 Print "Enc28j60-version = " ; A(2) Enc28j60_cs = 1 Call Enc28j60init Value = 0 Value.econ1_txrst = 1 Call Enc28j60bitfield_set(econ1 , Value) Call Enc28j60bitfield_clear(econ1 , Value) 'ARP-test. Fill buffer and send it on its way. 'ARP Buffer(1) = &HFF : Buffer(2) = &HFF Buffer(3) = &HFF : Buffer(4) = &HFF Buffer(5) = &HFF : Buffer(6) = &HFF Buffer(7) = Ethaddr0 : Buffer(8) = Ethaddr1 'MAC-address of TUX-board Buffer(9) = Ethaddr2 : Buffer(10) = Ethaddr3 Buffer(11) = Ethaddr4 : Buffer(12) = Ethaddr5 Buffer(13) = &H08 : Buffer(14) = &H06 Buffer(15) = &H00 : Buffer(16) = &H01 Buffer(17) = &H08 : Buffer(18) = &H00 Buffer(19) = &H06 : Buffer(20) = &H04 Buffer(21) = &H00 : Buffer(22) = &H01 Buffer(23) = Ethaddr0 : Buffer(24) = Ethaddr1 Buffer(25) = Ethaddr2 : Buffer(26) = Ethaddr3 Buffer(27) = Ethaddr4 : Buffer(28) = Ethaddr5 Buffer(29) = 192 Buffer(30) = 168 Buffer(31) = 0 Buffer(32) = 61 Buffer(33) = &H00 'MAC-address router Buffer(34) = &H0C Buffer(35) = &H41 Buffer(36) = &HAE Buffer(37) = &H7A Buffer(38) = &HDC Buffer(39) = 192 'IP-nummer router Buffer(40) = 168 Buffer(41) = 0 Buffer(42) = 254 '( Buffer(43) = &H00 'padding Buffer(44) = &H00 Buffer(45) = &H00 Buffer(46) = &H00 Buffer(47) = &H00 Buffer(48) = &H00 Buffer(49) = &H00 Buffer(50) = &H00 Buffer(51) = &H00 Buffer(52) = &H00 Buffer(53) = &H00 Buffer(54) = &H00 Buffer(55) = &H00 Buffer(56) = &H00 Buffer(57) = &H00 Buffer(58) = &H00 Buffer(59) = &H00 Buffer(60) = &H00 ') Call Enc28j60writebuffer(42) Call Enc28j60packetsend(60) Do Call Enc28j60poll 'watch the terminal screen.... All traffic visible Loop End Sub Enc28j60init 'do bank 0 stuff 'initialize receive buffer '16-bit transfers, must write low byte first 'set receive buffer start address Nextpacketptr = Rxstart_init Value = Low(rxstart_init) Call Enc28j60writecontrolregbyte(erxstl , Value) Value = High(rxstart_init) Call Enc28j60writecontrolregbyte(erxsth , Value) 'set receive pointer address Value = Low(rxstart_init) Call Enc28j60writecontrolregbyte(erxrdptl , Value) Value = High(rxstart_init) Call Enc28j60writecontrolregbyte(erxrdpth , Value) 'set receive buffer end Value = Low(rxstop_init) Call Enc28j60writecontrolregbyte(erxndl , Value) Value = High(rxstop_init) Call Enc28j60writecontrolregbyte(erxndh , Value) 'set transmit buffer start Value = Low(txstart_init) Call Enc28j60writecontrolregbyte(etxstl , Value) Value = High(txstart_init) Call Enc28j60writecontrolregbyte(etxsth , Value) 'do bank 2 stuff 'enable MAC receive Value = 0 Value.macon1_marxen = 1 Value.macon1_txpaus = 1 Value.macon1_rxpaus = 1 Call Enc28j60writecontrolregbyte(macon1 , Value) 'bring MAC out of reset 'enable automatic padding and CRC operations Value = 0 Value.macon3_padcfg0 = 1 Value.macon3_txcrcen = 1 Value.macon3_frmlnen = 1 Call Enc28j60writecontrolregbyte(macon3 , Value) 'set inter-frame gap (non-back-to-back) Call Enc28j60writecontrolregbyte(maipgl , &H12) Call Enc28j60writecontrolregbyte(maipgh , &H0C) 'set inter-frame gap (back-to-back) Call Enc28j60writecontrolregbyte(mabbipg , &H12) 'set the maximum packet size which the controller will accept Value = Low(max_framelen) Call Enc28j60writecontrolregbyte(mamxfll , Value) Value = High(max_framelen) Call Enc28j60writecontrolregbyte(mamxflh , Value) 'bank 3 stuff Call Enc28j60writecontrolregbyte(maadr5 , Ethaddr0) Call Enc28j60writecontrolregbyte(maadr4 , Ethaddr1) Call Enc28j60writecontrolregbyte(maadr3 , Ethaddr2) Call Enc28j60writecontrolregbyte(maadr2 , Ethaddr3) Call Enc28j60writecontrolregbyte(maadr1 , Ethaddr4) Call Enc28j60writecontrolregbyte(maadr0 , Ethaddr5) 'no loopback of transmitted frames Call Enc28j60writephyword(phcon2 , Phcon2_hdldis) 'switch to bank 0 Call Enc28j60selectbank(0) 'enable interrupts Value = 0 Value.eie_intie = 1 Value.eie_pktie = 1 Call Enc28j60bitfield_set(eie , Value) 'enable packet reception Value = 0 Value.econ1_rxen = 1 Call Enc28j60bitfield_set(econ1 , Value) End Sub Sub Enc28j60selectbank(bank As Byte) 'get ECON1 (BSEL1 en BSEL0) A(1) = &B000_11111 Enc28j60_cs = 0 Spiout A(1) , 1 Spiin A(1) , 2 Enc28j60_cs = 1 A(2) = A(2) And &B1111_1100 'strip bank part A(2) = A(2) Or Bank A(1) = &B010_11111 Enc28j60_cs = 0 Spiout A(1) , 2 Enc28j60_cs = 1 End Sub Sub Enc28j60writecontrolregbyte(register As Byte , Value As Byte) Bank = 0 If Register.7 = 1 Then Bank = 2 If Register.6 = 1 Then Bank = Bank + 1 Register = Register And &B00011111 Call Enc28j60selectbank(bank) Register.6 = 1 'to get a 010_register A(1) = Register A(2) = Value Enc28j60_cs = 0 Spiout A(1) , 2 Enc28j60_cs = 1 End Sub Sub Enc28j60readcontrolregbyte(register As Byte) Local Mcphy As Byte Bank = 0 Mcphy = 0 If Register.7 = 1 Then Bank = 2 If Register.6 = 1 Then Bank = Bank + 1 If Register.5 = 1 Then Mcphy = 1 Register = Register And &B00011111 Call Enc28j60selectbank(bank) A(1) = Register Enc28j60_cs = 0 Spiout A(1) , 1 Spiin A(1) , 3 Enc28j60_cs = 1 'Depending of register (E, MAC, MII) yes or no dummybyte If Mcphy = 1 Then Enc28j60_data = A(2) Else Enc28j60_data = A(3) End If End Sub Sub Enc28j60bitfield_set(register As Byte , Value As Byte) Bank = 0 If Register.7 = 1 Then Bank = 2 If Register.6 = 1 Then Bank = Bank + 1 Register = Register And &B00011111 Call Enc28j60selectbank(bank) Register = Register Or &B100_00000 A(1) = Register A(2) = Value Enc28j60_cs = 0 Spiout A(1) , 2 Enc28j60_cs = 1 End Sub Sub Enc28j60bitfield_clear(register As Byte , Value As Byte) Bank = 0 If Register.7 = 1 Then Bank = 2 If Register.6 = 1 Then Bank = Bank + 1 Register = Register And &B00011111 Call Enc28j60selectbank(bank) Register = Register Or &B101_00000 A(1) = Register A(2) = Value Enc28j60_cs = 0 Spiout A(1) , 2 Enc28j60_cs = 1 End Sub Sub Enc28j60readphyword(phyregister As Byte) 'set the right address and start the register read operation Call Enc28j60writecontrolregbyte(miregadr , Phyregister) Call Enc28j60writecontrolregbyte(micmd , Micmd_miird) 'wait until the PHY read complets Do Call Enc28j60readcontrolregbyte(mistat) Loop Until Enc28j60_data.mistat_busy = 0 'quit reading Call Enc28j60writecontrolregbyte(micmd , 0) 'get data value Call Enc28j60readcontrolregbyte(mirdl) Wdata = Enc28j60_data Shift Wdata , Left , 8 Call Enc28j60readcontrolregbyte(mirdh) Wdata = Wdata + Enc28j60_data End Sub Sub Enc28j60writephyword(phyregister As Byte , Wdata As Word) Call Enc28j60readphyword(phyregister) Local Temp As Byte 'set the PHY register address Call Enc28j60writecontrolregbyte(miregadr , Phyregister) Call Enc28j60readcontrolregbyte(miregadr) Temp = Miregadr Value = Low(wdata) Call Enc28j60writecontrolregbyte(miwrl , Value) Value = High(wdata) Call Enc28j60writecontrolregbyte(miwrh , Value) Do Call Enc28j60readcontrolregbyte(mistat) Loop Until Enc28j60_data.mistat_busy = 0 End Sub Sub Enc28j60poll Call Enc28j60readcontrolregbyte(epktcnt) If Enc28j60_data > 0 Then Call Enc28j60packetreceive(64) End If End Sub Sub Enc28j60packetreceive(maxlen As Word) Print "EPKTCNT = " ; Bin(enc28j60_data) 'Print "Sub Enc28j60packetreceive" Local Wtemp As Word 'set the read pointer to the start of the received packet Value = Low(nextpacketptr) Call Enc28j60writecontrolregbyte(erdptl , Value) Value = High(nextpacketptr) Call Enc28j60writecontrolregbyte(erdpth , Value) Print "Present nextpacketpntr " ; Hex(nextpacketptr) 'read the next packet pointer Call Enc28j60readbuffer(1) 'Print "Nextpktpntr " ; Hex(buffer(1)) Nextpacketptr = Buffer(1) Call Enc28j60readbuffer(1) Wtemp = Buffer(1) * 256 Nextpacketptr = Nextpacketptr + Wtemp Print "New Nextpacketpntr " ; Hex(nextpacketptr) 'read the packet length Call Enc28j60readbuffer(1) Length = Buffer(1) Call Enc28j60readbuffer(1) Wtemp = Buffer(1) * 256 Length = Length + Wtemp Print "Packetlength = " ; Length 'read the receive status Call Enc28j60readbuffer(1) Rxstat = Buffer(1) Call Enc28j60readbuffer(1) Wtemp = Buffer(1) * 256 Rxstat = Rxstat + Wtemp Print "Rxstat = " ; Bin(rxstat) 'limit retrieve length 'we reduce the MAC-reported length by 4 to remove the CRC '( If Length > Maxlen Then Length = Maxlen End If ') 'copy the packet from the receive buffer 'Call Enc28j60readbuffer(length) 'not needed in this test 'move the rx read pointer to the start of the next received packet 'this frees the memory we just read out Value = Low(nextpacketptr) Call Enc28j60writecontrolregbyte(erxrdptl , Value) Value = High(nextpacketptr) Call Enc28j60writecontrolregbyte(erxrdpth , Value) 'decrement the packet counter indicate we are done with this packet Value = 0 Value.econ2_pktdec = 1 Call Enc28j60bitfield_set(econ2 , Value) End Sub Sub Enc28j60packetsend(pcktlen As Word) Value = 0 Value.econ1_txrst = 1 Call Enc28j60bitfield_set(econ1 , Value) Value.econ1_txrst = 1 Call Enc28j60bitfield_clear(econ1 , Value) 'set the write pointer to start of transmit buffer area Value = Low(txstart_init) Call Enc28j60writecontrolregbyte(ewrptl , Value) Value = High(txstart_init) Call Enc28j60writecontrolregbyte(ewrpth , Value) 'set the TXND pointer to correspond to the packet size given Value = Low(txstart_init) Value = Value + Low(pcktlen) Call Enc28j60writecontrolregbyte(etxndl , Value) Value = High(txstart_init) Value = Value + High(pcktlen) Call Enc28j60writecontrolregbyte(etxndh , Value) 'write per-packet control byte has been put in the writeroutine 'send the contents of the transmit buffer onto the network Value = 0 Value.econ1_txrts = 1 Call Enc28j60bitfield_set(econ1 , Value) End Sub Sub Enc28j60writebuffer(pcktlen As Word) Enc28j60_cs = 0 Spdr = Enc28j60_write_buf_mem Do Loop Until Spsr.spif = 1 Spdr = &B000_1110 'per packet byte Do Loop Until Spsr.spif = 1 For X = 1 To Pcktlen Spdr = Buffer(x) Do Loop Until Spsr.spif = 1 Next X Enc28j60_cs = 1 End Sub Sub Enc28j60readbuffer(pcktlen As Word) Enc28j60_cs = 0 Spdr = &H3A Do Loop Until Spsr.spif = 1 Spdr = &HFF 'dummy byte Do Loop Until Spsr.spif = 1 Buffer(1) = Spdr Buffer(1) = Spdr If Pcktlen > 1 Then For X = 1 To Pcktlen Spdr = &HFF 'dummy byte Buffer(x) = Spdr 'Print Hex(buffer(x)) ; " " ; X Next X End If Enc28j60_cs = 1 End Sub '( Sub Enc28j60regdump Print Print "Registerdump ENC28J60" Print Call Enc28j60readcontrolregbyte(erevid) Print "Version: " ; Enc28j60_data Print 'ok Print "Cntrl: ECON1 ECON2 ESTAT EIR EIE" Call Enc28j60readcontrolregbyte(econ1) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(econ2) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(estat) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(eir) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(eie) Print " " ; Hex(enc28j60_data) Print 'ok Print "MAC : MACON1 MACON2 MACON3 MACON4 MAC-Address" Call Enc28j60readcontrolregbyte(macon1) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(macon2) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(macon3) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(macon4) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(maadr5) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(maadr4) Print "." ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(maadr3) Print "." ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(maadr2) Print "." ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(maadr1) Print "." ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(maadr0) Print "." ; Hex(enc28j60_data) Print Print "Rx : ERXST ERXND ERXWRPT ERXRDPT ERXFCON EPKTCNT MAMXFL" Call Enc28j60readcontrolregbyte(erxsth) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(erxstl) Print Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(erxndh) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(erxndl) Print Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(erxwrpth) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(erxwrptl) Print Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(erxrdpth) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(erxrdptl) Print Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(erxfcon) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(epktcnt) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(mamxflh) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(mamxfll) Print Hex(enc28j60_data) Print Print "Tx : ETXST ETXND MACLCON1 MACLCON2 MAPHSUP" Call Enc28j60readcontrolregbyte(etxsth) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(etxstl) Print Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(etxndh) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(etxndl) Print Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(maclcon1) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(maclcon2) Print " " ; Hex(enc28j60_data); Call Enc28j60readcontrolregbyte(maphsup) Print " " ; Hex(enc28j60_data) Print End Sub ')