'----------------------------------------------------------- ' Atmega168 and ENC28J60 - ARP, PING and Telnet '----------------------------------------------------------- ' Version 1.0 - june 2007 by Ben Zijlstra ' august 2007 addins by Viktor Varga 'fusebits: 'Atmega168 - External clock (from 6.25 Mhz to 12.5 Mhz) No div by 8 $regfile = "m644def.dat" $crystal = 20000000 '12500000 $baud = 19200 'put terminal on 19200 baud $hwstack = 90 $swstack = 90 $framesize = 90 $include "enc28j60.inc" $lib "tcpip.lbx" 'Enc28j60_cs Alias Portb.2 Enc28j60_cs Alias Portb.4 'Led Alias Portb.1 'Constants 'Maximum frame length - The Atmega168 has only 1024 byte internal RAM! Const Max_framelen = 550 '550 byte will be enough for common tasks Const Urg = 5 Const _ack = 4 Const Psh = 3 Const Rst = 2 Const Syn = 1 Const Fin = 0 Const Tcp_data = 55 Config Enc28j60_cs = Output 'Config Led = Output 'Set Led 'Turn off the tuxgraphics board LED 'Global DIM's Dim X As Word Dim A(5) As Byte Dim Enc28j60_bank As Byte Dim Enc28j60_data As Byte Dim Enc28j60_wdata As Word Dim Enc28j60_nextpacketptr As Word Dim Enc28j60_value As Byte ' Dim Buffer(max_framelen) As Byte ' Dim I_chksum32 As Long Dim I_checksum16 As Word Dim I_value16 As Word Dim I_value16h As Byte At I_value16 + 1 Overlay Dim I_value16l As Byte At I_value16 Overlay ' Dim Myip(4) As Byte Dim My_ip As Long At Myip Overlay ' Dim Mymac(6) As Byte ' Dim Tempword As Word Dim Tempwordh As Byte At Tempword + 1 Overlay Dim Tempwordl As Byte At Tempword Overlay Dim Tcp_fin As Bit Dim Tcp_syn As Bit Dim Tcp_rst As Bit Dim Tcp_psh As Bit Dim Tcp_ack As Bit Dim Tcp_urg As Bit Dim Synflag As Bit Dim Packetlength As Word 'Overlays of ethernetpacket ' 'Ethernet packet destination Dim T_enetpacketdest0 As Byte At Buffer Overlay Dim T_enetpacketdest1 As Byte At Buffer + &H01 Overlay Dim T_enetpacketdest2 As Byte At Buffer + &H02 Overlay Dim T_enetpacketdest3 As Byte At Buffer + &H03 Overlay Dim T_enetpacketdest4 As Byte At Buffer + &H04 Overlay Dim T_enetpacketdest5 As Byte At Buffer + &H05 Overlay 'Ethernet packet source Dim T_enetpacketsrc0 As Byte At Buffer + &H06 Overlay Dim T_enetpacketsrc1 As Byte At Buffer + &H07 Overlay Dim T_enetpacketsrc2 As Byte At Buffer + &H08 Overlay Dim T_enetpacketsrc3 As Byte At Buffer + &H09 Overlay Dim T_enetpacketsrc4 As Byte At Buffer + &H0A Overlay Dim T_enetpacketsrc5 As Byte At Buffer + &H0B Overlay 'Ethernet packet type Dim T_enetpackettype0 As Byte At Buffer + &H0C Overlay Dim T_enetpackettype1 As Byte At Buffer + &H0D Overlay 'Arp Dim T_arp_op1 As Byte At Buffer + &H15 Overlay 'arp source ip address Dim T_arp_sipaddr0 As Byte At Buffer + &H1C Overlay Dim T_arp_sipaddr1 As Byte At Buffer + &H1D Overlay Dim T_arp_sipaddr2 As Byte At Buffer + &H1E Overlay Dim T_arp_sipaddr3 As Byte At Buffer + &H1F Overlay 'arp target IP address Dim T_arp_tipaddr0 As Byte At Buffer + &H26 Overlay Dim T_arp_tipaddr1 As Byte At Buffer + &H27 Overlay Dim T_arp_tipaddr2 As Byte At Buffer + &H28 Overlay Dim T_arp_tipaddr3 As Byte At Buffer + &H29 Overlay 'IP header layout IP version and header length Dim T_ip_vers_len As Byte At Buffer + &H0E Overlay 'Arp Dim T_arp_op0 As Byte At Buffer + &H14 Overlay 'arp source mac address Dim T_arp_src_enetpacket0 As Byte At Buffer + &H16 Overlay Dim T_arp_src_enetpacket1 As Byte At Buffer + &H17 Overlay Dim T_arp_src_enetpacket2 As Byte At Buffer + &H18 Overlay Dim T_arp_src_enetpacket3 As Byte At Buffer + &H19 Overlay Dim T_arp_src_enetpacket4 As Byte At Buffer + &H1A Overlay Dim T_arp_src_enetpacket5 As Byte At Buffer + &H1B Overlay 'arp source mac address Dim T_arp_dest_enetpacket0 As Byte At Buffer + &H20 Overlay Dim T_arp_dest_enetpacket1 As Byte At Buffer + &H21 Overlay Dim T_arp_dest_enetpacket2 As Byte At Buffer + &H22 Overlay Dim T_arp_dest_enetpacket3 As Byte At Buffer + &H23 Overlay Dim T_arp_dest_enetpacket4 As Byte At Buffer + &H24 Overlay Dim T_arp_dest_enetpacket5 As Byte At Buffer + &H25 Overlay 'Buffer length Dim T_ip_pktlen0 As Byte At Buffer + &H10 Overlay Dim T_ip_pktlen1 As Byte At Buffer + &H11 Overlay Dim T_id0 As Byte At Buffer + &H12 Overlay Dim T_id1 As Byte At Buffer + &H13 Overlay 'Dim T_flags As Byte At Buffer + &H14 Overlay 'protocol (ICMP=1, TCP=6, UDP=11) Dim T_ip_proto As Byte At Buffer + &H17 Overlay 'header checksum Dim T_ip_hdr_cksum0 As Byte At Buffer + &H18 Overlay Dim T_ip_hdr_cksum1 As Byte At Buffer + &H19 Overlay Dim T_ip_hdr_cksum As Word At Buffer + &H18 Overlay 'IP address of source Dim T_ip_srcaddr0 As Byte At Buffer + &H1A Overlay Dim T_ip_srcaddr1 As Byte At Buffer + &H1B Overlay Dim T_ip_srcaddr2 As Byte At Buffer + &H1C Overlay Dim T_ip_srcaddr3 As Byte At Buffer + &H1D Overlay Dim T_ip_srcaddr As Long At Buffer + &H1A Overlay 'IP address of destination Dim T_ip_destaddr0 As Byte At Buffer + &H1E Overlay Dim T_ip_destaddr1 As Byte At Buffer + &H1F Overlay Dim T_ip_destaddr2 As Byte At Buffer + &H20 Overlay Dim T_ip_destaddr3 As Byte At Buffer + &H21 Overlay Dim T_ip_destaddr As Long At Buffer + &H1E Overlay Dim T_icmp_type As Byte At Buffer + &H22 Overlay Dim T_icmp_code As Byte At Buffer + &H23 Overlay Dim T_icmp_cksum0 As Byte At Buffer + &H24 Overlay Dim T_icmp_cksum1 As Byte At Buffer + &H25 Overlay Dim T_icmp_cksum As Word At Buffer + &H24 Overlay Dim Tcp_srcporth As Byte At Buffer + &H22 Overlay Dim Tcp_srcportl As Byte At Buffer + &H23 Overlay Dim Tcp_destporth As Byte At Buffer + &H24 Overlay Dim Tcp_destportl As Byte At Buffer + &H25 Overlay Dim Tcp_seqnum3 As Byte At Buffer + &H26 Overlay Dim Tcp_seqnum2 As Byte At Buffer + &H27 Overlay Dim Tcp_seqnum1 As Byte At Buffer + &H28 Overlay Dim Tcp_seqnum0 As Byte At Buffer + &H29 Overlay Dim Tcp_acknum3 As Byte At Buffer + &H2A Overlay Dim Tcp_acknum2 As Byte At Buffer + &H2B Overlay Dim Tcp_acknum1 As Byte At Buffer + &H2C Overlay Dim Tcp_acknum0 As Byte At Buffer + &H2D Overlay Dim Tcp_hdr As Byte At Buffer + &H2E Overlay Dim Tcp_flags As Byte At Buffer + &H2F Overlay Dim Tcp_cksumh As Byte At Buffer + &H32 Overlay Dim Tcp_cksuml As Byte At Buffer + &H33 Overlay Dim Tcp_cksum As Word At Buffer + &H32 Overlay Dim Seqnum As Long Dim Seqnum3 As Byte At Seqnum Overlay Dim Seqnum2 As Byte At Seqnum + 1 Overlay Dim Seqnum1 As Byte At Seqnum + 2 Overlay Dim Seqnum0 As Byte At Seqnum + 3 Overlay Dim Acknum As Long Dim Acknum3 As Byte At Acknum Overlay Dim Acknum2 As Byte At Acknum + 1 Overlay Dim Acknum1 As Byte At Acknum + 2 Overlay Dim Acknum0 As Byte At Acknum + 3 Overlay 'Declares Declare Sub Enc28j60_reset Declare Sub Enc28j60_setextclock Declare Sub Enc28j60_init Declare Sub Enc28j60_version Declare Sub Enc28j60_readcontrolregbyte(byval Register As Byte) Declare Sub Enc28j60_writecontrolregbyte(byval Register As Byte , Byval Enc28j60_value As Byte) Declare Sub Enc28j60_selectbank(byval Enc28j60_bank As Byte) Declare Sub Enc28j60_bitfield_set(byval Register As Byte , Byval Enc28j60_value As Byte) Declare Sub Enc28j60_bitfield_clear(byval Register As Byte , Byval Enc28j60_value As Byte) Declare Sub Enc28j60_readphyword(byval Phyregister As Byte) Declare Sub Enc28j60_writephyword(byval Phyregister As Byte , Byval Enc28j60_wdata As Word) Declare Sub Enc28j60_packetsend(byval Pcktlen As Word) Declare Sub Enc28j60_packetreceive Declare Sub Enc28j60_poll Declare Sub Arpreply Declare Sub Pingreply Declare Sub Setip_id Declare Sub Setipaddrs Declare Sub Tcp Declare Sub Ip_header_checksum Declare Sub Icmp_checksum Declare Sub Tcp_checksum Declare Sub Srcdestchksum Declare Sub Telnet Declare Sub Ack2tcp_ack Declare Sub Seq2tcp_seq Declare Sub Swapsrc2dest Declare Sub Swapdestport2srcport Declare Sub Optiona Declare Sub Optionb Declare Sub Optionc Declare Sub Optionquit 'Settings 'MAC address Mymac(1) = &H43 Mymac(2) = &HC6 Mymac(3) = &HB3 Mymac(4) = &HF3 Mymac(5) = &HAB Mymac(6) = &H9E 'IP address Myip(1) = 192 Myip(2) = 168 Myip(3) = 0 Myip(4) = 61 'Start mainprogram '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 'Reset the Enc28J60 Call Enc28j60_reset Call Enc28j60_setextclock Print Print "Starting Tux" Call Enc28j60_version Call Enc28j60_init Do Call Enc28j60_poll Loop End '***************** start of the ENC28J60-routines ******************************* Sub Enc28j60_reset Enc28j60_cs = 0 'reset ENC28J60 X = Enc28j60_soft_reset Spiout X , 1 Enc28j60_cs = 1 Do Call Enc28j60_readcontrolregbyte(estat) X = Enc28j60_data.estat_clkrdy Loop Until X = 1 End Sub Sub Enc28j60_setextclock 'clock from default divide/4 (6.25 Mhz) to divide/2 (12.5 Mhz) Call Enc28j60_writecontrolregbyte(ecocon , &B00000010) Waitms 250 End Sub Sub Enc28j60_version Call Enc28j60_selectbank(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 End Sub Sub Enc28j60_init 'do bank 0 stuff 'initialize receive buffer '16-bit transfers, must write low byte first 'set receive buffer start address Enc28j60_nextpacketptr = Rxstart_init Enc28j60_value = Low(rxstart_init) Call Enc28j60_writecontrolregbyte(erxstl , Enc28j60_value) Enc28j60_value = High(rxstart_init) Call Enc28j60_writecontrolregbyte(erxsth , Enc28j60_value) 'set receive pointer address Enc28j60_value = Low(rxstart_init) Call Enc28j60_writecontrolregbyte(erxrdptl , Enc28j60_value) Enc28j60_value = High(rxstart_init) Call Enc28j60_writecontrolregbyte(erxrdpth , Enc28j60_value) 'set receive buffer end Enc28j60_value = Low(rxstop_init) Call Enc28j60_writecontrolregbyte(erxndl , Enc28j60_value) Enc28j60_value = High(rxstop_init) Call Enc28j60_writecontrolregbyte(erxndh , Enc28j60_value) 'set transmit buffer start Enc28j60_value = Low(txstart_init) Call Enc28j60_writecontrolregbyte(etxstl , Enc28j60_value) Enc28j60_value = High(txstart_init) Call Enc28j60_writecontrolregbyte(etxsth , Enc28j60_value) 'do bank 2 stuff 'enable MAC receive Enc28j60_value = 0 Enc28j60_value.macon1_marxen = 1 Enc28j60_value.macon1_txpaus = 1 Enc28j60_value.macon1_rxpaus = 1 Call Enc28j60_writecontrolregbyte(macon1 , Enc28j60_value) 'bring MAC out of reset 'enable automatic padding and CRC operations Enc28j60_value = 0 Enc28j60_value.macon3_padcfg0 = 1 Enc28j60_value.macon3_txcrcen = 1 Enc28j60_value.macon3_frmlnen = 1 Call Enc28j60_writecontrolregbyte(macon3 , Enc28j60_value) 'set inter-frame gap (non-back-to-back) Call Enc28j60_writecontrolregbyte(maipgl , &H12) Call Enc28j60_writecontrolregbyte(maipgh , &H0C) 'set inter-frame gap (back-to-back) Call Enc28j60_writecontrolregbyte(mabbipg , &H12) 'set the maximum packet size which the controller will accept Enc28j60_value = Low(max_framelen) Call Enc28j60_writecontrolregbyte(mamxfll , Enc28j60_value) Enc28j60_value = High(max_framelen) Call Enc28j60_writecontrolregbyte(mamxflh , Enc28j60_value) 'bank 3 stuff Call Enc28j60_writecontrolregbyte(maadr5 , Mymac(1)) Call Enc28j60_writecontrolregbyte(maadr4 , Mymac(2)) Call Enc28j60_writecontrolregbyte(maadr3 , Mymac(3)) Call Enc28j60_writecontrolregbyte(maadr2 , Mymac(4)) Call Enc28j60_writecontrolregbyte(maadr1 , Mymac(5)) Call Enc28j60_writecontrolregbyte(maadr0 , Mymac(6)) 'no loopback of transmitted frames Call Enc28j60_writephyword(phcon2 , Phcon2_hdldis) 'switch to bank 0 Call Enc28j60_selectbank(0) 'enable interrupts Enc28j60_value = 0 Enc28j60_value.eie_intie = 1 Enc28j60_value.eie_pktie = 1 Call Enc28j60_bitfield_set(eie , Enc28j60_value) 'filters according to Guido Call Enc28j60_writecontrolregbyte(epmm0 , &H3F) Call Enc28j60_writecontrolregbyte(epmm1 , &H30) Call Enc28j60_writecontrolregbyte(epmcsl , &HF9) Call Enc28j60_writecontrolregbyte(epmcsh , &HF7) Enc28j60_value = 0 Enc28j60_value.erxfcon_pmen = 1 'Pattern Match enable (ARP only) Enc28j60_value.erxfcon_ucen = 1 'Unicast enable Call Enc28j60_bitfield_set(erxfcon , Enc28j60_value) Enc28j60_value = 0 Enc28j60_value.erxfcon_bcen = 1 'Broadcast disable Call Enc28j60_bitfield_clear(erxfcon , Enc28j60_value) 'CRC check is enabled by default 'Something is wrong with the Broadcast filter (or the whole theory), it seems 'like every packet is coming in 'enable packet reception Enc28j60_value = 0 Enc28j60_value.econ1_rxen = 1 Call Enc28j60_bitfield_set(econ1 , Enc28j60_value) 'Reset transmit logic Enc28j60_value = 0 Enc28j60_value.econ1_txrst = 1 Call Enc28j60_bitfield_set(econ1 , Enc28j60_value) Call Enc28j60_bitfield_clear(econ1 , Enc28j60_value) End Sub Sub Enc28j60_selectbank(enc28j60_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 Enc28j60_bank A(1) = &B010_11111 Enc28j60_cs = 0 Spiout A(1) , 2 Enc28j60_cs = 1 End Sub Sub Enc28j60_writecontrolregbyte(register As Byte , Enc28j60_value As Byte) Enc28j60_bank = 0 If Register.7 = 1 Then Enc28j60_bank = 2 If Register.6 = 1 Then Enc28j60_bank = Enc28j60_bank + 1 Register = Register And &B00011111 Call Enc28j60_selectbank(enc28j60_bank) Register.6 = 1 'to get a 010_register A(1) = Register A(2) = Enc28j60_value Enc28j60_cs = 0 Spiout A(1) , 2 Enc28j60_cs = 1 End Sub Sub Enc28j60_readcontrolregbyte(register As Byte) Local Mcphy As Byte Enc28j60_bank = 0 Mcphy = 0 If Register.7 = 1 Then Enc28j60_bank = 2 If Register.6 = 1 Then Enc28j60_bank = Enc28j60_bank + 1 If Register.5 = 1 Then Mcphy = 1 Register = Register And &B00011111 Call Enc28j60_selectbank(enc28j60_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 Enc28j60_bitfield_set(register As Byte , Enc28j60_value As Byte) Enc28j60_bank = 0 If Register.7 = 1 Then Enc28j60_bank = 2 If Register.6 = 1 Then Enc28j60_bank = Enc28j60_bank + 1 Register = Register And &B00011111 Call Enc28j60_selectbank(enc28j60_bank) Register = Register Or &B100_00000 A(1) = Register A(2) = Enc28j60_value Enc28j60_cs = 0 Spiout A(1) , 2 Enc28j60_cs = 1 End Sub Sub Enc28j60_bitfield_clear(register As Byte , Enc28j60_value As Byte) Enc28j60_bank = 0 If Register.7 = 1 Then Enc28j60_bank = 2 If Register.6 = 1 Then Enc28j60_bank = Enc28j60_bank + 1 Register = Register And &B00011111 Call Enc28j60_selectbank(enc28j60_bank) Register = Register Or &B101_00000 A(1) = Register A(2) = Enc28j60_value Enc28j60_cs = 0 Spiout A(1) , 2 Enc28j60_cs = 1 End Sub Sub Enc28j60_readphyword(phyregister As Byte) 'set the right address and start the register read operation Call Enc28j60_writecontrolregbyte(miregadr , Phyregister) Call Enc28j60_writecontrolregbyte(micmd , Micmd_miird) 'wait until the PHY read complets Do Call Enc28j60_readcontrolregbyte(mistat) Loop Until Enc28j60_data.mistat_busy = 0 'quit reading Call Enc28j60_writecontrolregbyte(micmd , 0) 'get data value Call Enc28j60_readcontrolregbyte(mirdl) Enc28j60_wdata = Enc28j60_data Shift Enc28j60_wdata , Left , 8 Call Enc28j60_readcontrolregbyte(mirdh) Enc28j60_wdata = Enc28j60_wdata + Enc28j60_data End Sub Sub Enc28j60_writephyword(phyregister As Byte , Enc28j60_wdata As Word) Call Enc28j60_readphyword(phyregister) Local Temp As Byte 'set the PHY register address Call Enc28j60_writecontrolregbyte(miregadr , Phyregister) Call Enc28j60_readcontrolregbyte(miregadr) Temp = Miregadr Enc28j60_value = Low(enc28j60_wdata) Call Enc28j60_writecontrolregbyte(miwrl , Enc28j60_value) Enc28j60_value = High(enc28j60_wdata) Call Enc28j60_writecontrolregbyte(miwrh , Enc28j60_value) Do Call Enc28j60_readcontrolregbyte(mistat) Loop Until Enc28j60_data.mistat_busy = 0 End Sub Sub Enc28j60_poll Call Enc28j60_readcontrolregbyte(epktcnt) If Enc28j60_data > 0 Then Call Enc28j60_packetreceive End If End Sub Sub Enc28j60_packetreceive 'Reset Led Local Length As Word Local Wtemp As Word Local Rxstat As Word 'set the read pointer to the start of the received packet Enc28j60_value = Low(enc28j60_nextpacketptr) Call Enc28j60_writecontrolregbyte(erdptl , Enc28j60_value) Enc28j60_value = High(enc28j60_nextpacketptr) Call Enc28j60_writecontrolregbyte(erdpth , Enc28j60_value) Enc28j60_cs = 0 'Send Read Buffer Memory command Spdr = &H3A Do Loop Until Spsr.spif0 = 1 'Get the first 6 byte (3 word: Nextpacketptr, Packetlength, Rxstat) For X = 1 To 6 Spdr = &HFF 'SPI read Do Loop Until Spsr.spif0 = 1 'SPI ready Buffer(x) = Spdr Next X Enc28j60_nextpacketptr = Buffer(2) * 256 Enc28j60_nextpacketptr = Enc28j60_nextpacketptr + Buffer(1) Length = Buffer(4) * 256 Length = Length + Buffer(3) Rxstat = Buffer(6) * 256 Rxstat = Rxstat + Buffer(5) 'Get the payload Length = Length - 4 'Discard CRC For X = 1 To Length Spdr = &HFF 'SPI read Do Loop Until Spsr.spif0 = 1 'SPI ready Buffer(x) = Spdr Next X Enc28j60_cs = 1 'move the rx read pointer to the start of the next received packet 'this frees the memory we just read out Enc28j60_value = Low(enc28j60_nextpacketptr) Call Enc28j60_writecontrolregbyte(erxrdptl , Enc28j60_value) Enc28j60_value = High(enc28j60_nextpacketptr) Call Enc28j60_writecontrolregbyte(erxrdpth , Enc28j60_value) 'decrement the packet counter indicate we are done with this packet Enc28j60_value = 0 Enc28j60_value.econ2_pktdec = 1 Call Enc28j60_bitfield_set(econ2 , Enc28j60_value) 'Set Led 'Handle the packet If T_enetpackettype0 = &H08 Then If T_enetpackettype1 = &H06 Then 'Type:ARP If T_arp_op0 = &H00 Then 'ARP request If T_arp_op1 = &H01 Then 'ARP request If T_arp_tipaddr0 = Myip(1) Then 'ARP for us If T_arp_tipaddr1 = Myip(2) Then If T_arp_tipaddr2 = Myip(3) Then If T_arp_tipaddr3 = Myip(4) Then Call Arpreply End If End If End If End If End If End If End If If Buffer(14) = &H00 Then 'Type:IP If Buffer(15) = &H45 Then 'We handle only simple IP packets 'If Buffer(21) = 0 Then 'We handle only non fragmented packets If Buffer(31) = Myip(1) Then 'Ip packet for us If Buffer(32) = Myip(2) Then If Buffer(33) = Myip(3) Then If Buffer(34) = Myip(4) Then If T_ip_proto = 1 Then 'Protocol:ICMP If Buffer(35) = &H08 Then 'ICMP echo request Call Pingreply End If End If 'If T_ip_proto = 17 Then 'Protocol:UDP 'Call Udp_receive 'End If If T_ip_proto = 6 Then 'Protocol:TCP Call Tcp End If End If End If End If 'End If End If End If End If End If End Sub Sub Enc28j60_packetsend(pcktlen As Word) 'Load packet into the ENC Enc28j60_cs = 0 Spdr = Enc28j60_write_buf_mem Do Loop Until Spsr.spif0 = 1 Spdr = &B000_1110 'per packet byte Do Loop Until Spsr.spif0 = 1 For X = 1 To Pcktlen Spdr = Buffer(x) Do Loop Until Spsr.spif0 = 1 Next X Enc28j60_cs = 1 'Minimum packet length is 60 If Pcktlen < 60 Then Pcktlen = 60 'Reset transmit logic Enc28j60_value = 0 Enc28j60_value.econ1_txrst = 1 Call Enc28j60_bitfield_set(econ1 , Enc28j60_value) Call Enc28j60_bitfield_clear(econ1 , Enc28j60_value) 'set the write pointer to start of transmit buffer area Enc28j60_value = Low(txstart_init) Call Enc28j60_writecontrolregbyte(ewrptl , Enc28j60_value) Enc28j60_value = High(txstart_init) Call Enc28j60_writecontrolregbyte(ewrpth , Enc28j60_value) 'set the TXND pointer to correspond to the packet size given Enc28j60_value = Low(txstart_init) Enc28j60_value = Enc28j60_value + Low(pcktlen) Call Enc28j60_writecontrolregbyte(etxndl , Enc28j60_value) Enc28j60_value = High(txstart_init) Enc28j60_value = Enc28j60_value + High(pcktlen) Call Enc28j60_writecontrolregbyte(etxndh , Enc28j60_value) 'write per-packet control byte has been put in the writeroutine 'send the contents of the transmit buffer onto the network Enc28j60_value = 0 Enc28j60_value.econ1_txrts = 1 Call Enc28j60_bitfield_set(econ1 , Enc28j60_value) End Sub '***************** end of the ENC28J60-routines ******************************* Sub Arpreply 'The original request packet is in the buffer, we just change some things 'Swap MAC addresses ' Call Src2dest 'move hardware source address to destination address T_enetpacketdest0 = T_enetpacketsrc0 T_enetpacketdest1 = T_enetpacketsrc1 T_enetpacketdest2 = T_enetpacketsrc2 T_enetpacketdest3 = T_enetpacketsrc3 T_enetpacketdest4 = T_enetpacketsrc4 T_enetpacketdest5 = T_enetpacketsrc5 'Set source MAC in ethernet frame, pos 7 'Call Src2mymac 'Make ethernet module mac address the source address T_enetpacketsrc0 = Mymac(1) T_enetpacketsrc1 = Mymac(2) T_enetpacketsrc2 = Mymac(3) T_enetpacketsrc3 = Mymac(4) T_enetpacketsrc4 = Mymac(5) T_enetpacketsrc5 = Mymac(6) 'Copy target MAC in ARP packet T_arp_dest_enetpacket0 = T_enetpacketdest0 T_arp_dest_enetpacket1 = T_enetpacketdest1 T_arp_dest_enetpacket2 = T_enetpacketdest2 T_arp_dest_enetpacket3 = T_enetpacketdest3 T_arp_dest_enetpacket4 = T_enetpacketdest4 T_arp_dest_enetpacket5 = T_enetpacketdest5 'Set target IP in ARP packet T_arp_tipaddr0 = T_arp_sipaddr0 T_arp_tipaddr1 = T_arp_sipaddr1 T_arp_tipaddr2 = T_arp_sipaddr2 T_arp_tipaddr3 = T_arp_sipaddr3 'Copy source MAC to ARP T_arp_src_enetpacket0 = T_enetpacketsrc0 T_arp_src_enetpacket1 = T_enetpacketsrc1 T_arp_src_enetpacket2 = T_enetpacketsrc2 T_arp_src_enetpacket3 = T_enetpacketsrc3 T_arp_src_enetpacket4 = T_enetpacketsrc4 T_arp_src_enetpacket5 = T_enetpacketsrc5 'Set source IP to ARP packet pos 29 T_arp_sipaddr0 = Myip(1) T_arp_sipaddr1 = Myip(2) T_arp_sipaddr2 = Myip(3) T_arp_sipaddr3 = Myip(4) 'Set ARP type from Request to Reply T_arp_op1 = 2 'Send the reply packet Call Enc28j60_packetsend(42) End Sub Sub Pingreply 'Local Packetlength As Word Packetlength = T_ip_pktlen0 * 256 Packetlength = Packetlength + T_ip_pktlen1 Packetlength = Packetlength + 13 'We are going to calculate the checksum till the end of packet (IP length + 14 byte of the ethernet stuff), -1 to get word start 'set echo reply T_icmp_type = &H00 T_icmp_code = &H00 'setup the IP-header Call Setipaddrs Call Icmp_checksum Packetlength = Packetlength + 1 'Send the reply packet Call Enc28j60_packetsend(packetlength) End Sub Sub Setip_id Local Ip_id As Word T_id0 = High(ip_id) T_id1 = Low(ip_id) Ip_id = Ip_id + 1 End Sub ' Routine to calculate a IP-header checksum ' Sub Ip_header_checksum Local Ip_checksum16 As Word Local Ip_header_length As Byte T_ip_hdr_cksum = &H00 'Calculate IP header length Ip_header_length = T_ip_vers_len And &H0F Ip_header_length = 4 * Ip_header_length Ip_checksum16 = Tcpchecksum(buffer(15) , Ip_header_length ) 'Store the checksum value in the packet buffer T_ip_hdr_cksum1 = High(ip_checksum16) T_ip_hdr_cksum0 = Low(ip_checksum16) End Sub ' Routine to calculate a ICMP-checksum ' Sub Icmp_checksum Local I_header_length As Word 'Clear the ICMP checksum before starting calculation T_icmp_cksum = &H00 'Calculate the ICMP checksum I_header_length = T_ip_pktlen1 - 20 I_checksum16 = Tcpchecksum(buffer(35) , I_header_length ) 'built-in way T_icmp_cksum1 = High(i_checksum16) T_icmp_cksum0 = Low(i_checksum16) End Sub ' Routine to handle the source/destination address ' Sub Setipaddrs T_ip_destaddr = T_ip_srcaddr 'make ethernet module IP address source address T_ip_srcaddr = My_ip 'move hardware source address to destination address T_enetpacketdest0 = T_enetpacketsrc0 T_enetpacketdest1 = T_enetpacketsrc1 T_enetpacketdest2 = T_enetpacketsrc2 T_enetpacketdest3 = T_enetpacketsrc3 T_enetpacketdest4 = T_enetpacketsrc4 T_enetpacketdest5 = T_enetpacketsrc5 'Set source MAC in ethernet frame, pos 7 'Make ethernet module mac address the source address T_enetpacketsrc0 = Mymac(1) T_enetpacketsrc1 = Mymac(2) T_enetpacketsrc2 = Mymac(3) T_enetpacketsrc3 = Mymac(4) T_enetpacketsrc4 = Mymac(5) T_enetpacketsrc5 = Mymac(6) ' Call Src2mymac Call Ip_header_checksum End Sub 'Tcp-checksum ' Sub Tcp_checksum Local Whulp1 As Word Local Tempword2 As Word Local Val1 As Word Local Val2 As Word Tcp_cksum = 0 Call Srcdestchksum 'resultaat in I_chksum32 Tempwordh = T_ip_pktlen0 Tempwordl = T_ip_pktlen1 I_chksum32 = I_chksum32 + Tempword Tempword2 = T_ip_vers_len And &H0F Tempword2 = Tempword2 * 4 I_chksum32 = I_chksum32 - Tempword2 Whulp1 = Tempword - 20 Val2 = Highw(i_chksum32) Val1 = I_chksum32 I_checksum16 = Tcpchecksum(buffer(&H23) , Whulp1 , Val2 , Val1) Tcp_cksuml = High(i_checksum16) Tcp_cksumh = Low(i_checksum16) End Sub Sub Srcdestchksum 'checksum TCP header I_chksum32 = 0 I_value16h = T_ip_srcaddr0 I_value16l = T_ip_srcaddr1 I_chksum32 = I_chksum32 + I_value16 I_value16h = T_ip_srcaddr2 I_value16l = T_ip_srcaddr3 I_chksum32 = I_chksum32 + I_value16 I_value16h = T_ip_destaddr0 I_value16l = T_ip_destaddr1 I_chksum32 = I_chksum32 + I_value16 I_value16h = T_ip_destaddr2 I_value16l = T_ip_destaddr3 I_chksum32 = I_chksum32 + I_value16 'proto I_chksum32 = I_chksum32 + T_ip_proto End Sub ' Telnet ' Sub Telnet Local Work As Byte Local D As Byte Local Msg As String * 70 Local Char As String * 1 Local Work2 As Word Local Tcp_header_len As Byte Local Expected_seq As Long Work = Tcp_flags Tcp_fin = Work.0 Tcp_syn = Work.1 Tcp_rst = Work.2 Tcp_psh = Work.3 Tcp_ack = Work.4 Tcp_urg = Work.5 Packetlength = T_ip_pktlen0 * 256 Packetlength = Packetlength + T_ip_pktlen1 Packetlength = Packetlength - 40 Acknum3 = Tcp_acknum0 Acknum2 = Tcp_acknum1 Acknum1 = Tcp_acknum2 Acknum0 = Tcp_acknum3 Seqnum3 = Tcp_seqnum0 Seqnum2 = Tcp_seqnum1 Seqnum1 = Tcp_seqnum2 Seqnum0 = Tcp_seqnum3 Tcp_header_len = Tcp_hdr And &HF0 Shift Tcp_header_len , Right , 4 Tcp_header_len = Tcp_header_len * 4 Call Ack2tcp_ack Call Seq2tcp_seq 'if an ACK is received and the destination port address is valid 'and no data is in the packet If Tcp_ack = 1 Then If Tcp_psh = 0 Then If Synflag = 1 Then Synflag = 0 Expected_seq = Acknum Acknum = Seqnum + Packetlength Seqnum = Expected_seq Call Ack2tcp_ack Call Seq2tcp_seq Call Swapdestport2srcport Call Swapsrc2dest 'Move IP source address to destination address Swap T_ip_destaddr , T_ip_srcaddr Tcp_flags = 0 Set Tcp_flags._ack Msg = "TuxGraphics{010}{010}{010}{013}" Msg = Msg + "1. Info{010}{010}{013}" Msg = Msg + "2. Option B{010}{010}{013}" Msg = Msg + "3. Option C{010}{010}{013}" Msg = Msg + "4. Quit{010}{013}{010}{010}" For Work = 1 To Len(msg) D = 54 + Work Char = Mid(msg , Work , 1) Buffer(d) = Asc(char) Next Work D = Len(msg) Packetlength = 40 + D T_ip_pktlen0 = High(packetlength) T_ip_pktlen1 = Low(packetlength) Call Ip_header_checksum Call Tcp_checksum Packetlength = Packetlength + 20 Call Enc28j60_packetsend(packetlength) End If End If End If 'if an ACK is received and the port address is valid and there is 'data in the incoming packet If Tcp_ack = 1 Then If Tcp_psh = 1 Then If Packetlength > 0 Then Expected_seq = Acknum Acknum = Seqnum + Packetlength Seqnum = Expected_seq Call Ack2tcp_ack Call Seq2tcp_seq Call Swapdestport2srcport Call Swapsrc2dest 'Move IP source address to destination address Swap T_ip_destaddr , T_ip_srcaddr Tcp_flags = 0 Set Tcp_flags._ack 'Here the choices Select Case Buffer(55) Case 49 : Call Optiona Case 50 : Call Optionb Case 51 : Call Optionc Case 52 : Call Optionquit End Select Packetlength = Packetlength + 40 T_ip_pktlen0 = High(packetlength) T_ip_pktlen1 = Low(packetlength) Call Ip_header_checksum Call Tcp_checksum Packetlength = Packetlength + 20 Call Enc28j60_packetsend(packetlength) End If End If End If 'this code segment processes the incoming SYN from the Telnet client 'and sends back the initial sequence number (ISN) and acknowledges 'the incoming SYN packet If Tcp_syn = 1 Then Acknum = Seqnum + 1 Seqnum = &H1011FFFF 'Initial Sequence Number Set Synflag Call Ack2tcp_ack Call Seq2tcp_seq Call Swapdestport2srcport Call Swapsrc2dest 'Move IP source address to destination address Swap T_ip_destaddr , T_ip_srcaddr Tcp_flags = 0 Set Tcp_flags.syn Set Tcp_flags._ack T_ip_pktlen0 = &H00 T_ip_pktlen1 = 48 Call Ip_header_checksum Call Tcp_checksum Call Enc28j60_packetsend(62) End If 'if ACK and FIN If Tcp_ack = 1 Then If Tcp_fin = 1 Then 'end the session 'Print "TCP_ACK en TCP_FIN" End If End If End Sub ' TCP ' Sub Tcp If Tcp_destporth = 0 Then Select Case Tcp_destportl 'Case 80 : Call Http Case 23 : Call Telnet End Select End If End Sub Sub Ack2tcp_ack Tcp_acknum3 = Acknum0 Tcp_acknum2 = Acknum1 Tcp_acknum1 = Acknum2 Tcp_acknum0 = Acknum3 End Sub Sub Seq2tcp_seq Tcp_seqnum3 = Seqnum0 Tcp_seqnum2 = Seqnum1 Tcp_seqnum1 = Seqnum2 Tcp_seqnum0 = Seqnum3 End Sub Sub Swapsrc2dest Swap T_enetpacketdest0 , T_enetpacketsrc0 Swap T_enetpacketdest1 , T_enetpacketsrc1 Swap T_enetpacketdest2 , T_enetpacketsrc2 Swap T_enetpacketdest3 , T_enetpacketsrc3 Swap T_enetpacketdest4 , T_enetpacketsrc4 Swap T_enetpacketdest5 , T_enetpacketsrc5 End Sub Sub Swapdestport2srcport Swap Tcp_srcporth , Tcp_destporth Swap Tcp_srcportl , Tcp_destportl End Sub Sub Optiona Local Msg As String * 70 Local Work As Byte Local D As Byte Local Char As String * 1 Local Pointer As Word Msg = "{013}{010}Info pressed{013}{010}" Pointer = 54 For Work = 1 To Len(msg) D = Pointer + Work Char = Mid(msg , Work , 1) Buffer(d) = Asc(char) Next Work Pointer = Pointer + Len(msg) Packetlength = Len(msg) Msg = "IP-nr. " + Str(myip(1)) Msg = Msg + "." + Str(myip(2)) Msg = Msg + "." + Str(myip(3)) Msg = Msg + "." + Str(myip(4)) Msg = Msg + "{013}{010}" For Work = 1 To Len(msg) D = Pointer + Work Char = Mid(msg , Work , 1) Buffer(d) = Asc(char) Next Work Pointer = Pointer + Len(msg) Packetlength = Packetlength + Len(msg) Msg = "MAC-address " + Hex(mymac(1)) + "-" + Hex(mymac(2)) + "-" + Hex(mymac(3)) + "-" Msg = Msg + Hex(mymac(4)) + "-" + Hex(mymac(5)) + "-" + Hex(mymac(6)) + "{013}{010}" For Work = 1 To Len(msg) D = Pointer + Work Char = Mid(msg , Work , 1) Buffer(d) = Asc(char) Next Work Pointer = Pointer + Len(msg) Packetlength = Packetlength + Len(msg) End Sub Sub Optionb Local Msg As String * 25 Local Work As Byte Local D As Byte Local Char As String * 1 Msg = "{013}{010}Option B pressed{013}{010}" For Work = 1 To Len(msg) D = 54 + Work Char = Mid(msg , Work , 1) Buffer(d) = Asc(char) Next Work Packetlength = Len(msg) End Sub Sub Optionc Local Msg As String * 25 Local Work As Byte Local D As Byte Local Char As String * 1 Msg = "{013}{010}Option C pressed{013}{010}" For Work = 1 To Len(msg) D = 54 + Work Char = Mid(msg , Work , 1) Buffer(d) = Asc(char) Next Work Packetlength = Len(msg) End Sub Sub Optionquit Local Msg As String * 70 Local Work As Byte Local D As Byte Local Char As String * 1 Msg = "{013}{010}{010}Connection closed - Bye{013}{010}" For Work = 1 To Len(msg) D = 54 + Work Char = Mid(msg , Work , 1) Buffer(d) = Asc(char) Next Work Set Tcp_flags.fin Set Tcp_flags.psh Packetlength = Len(msg) End Sub