'----------------------------------------------------------- ' Atmega168 and ENC28J60 '----------------------------------------------------------- ' 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 = "m168def.dat" $crystal = 12500000 $baud = 19200 'put terminal on 19200 baud $hwstack = 128 $swstack = 128 $framesize = 128 Const Debug = 0 $include "enc28j60.inc" $lib "tcpip.lbx" $lib "datetime.lbx" Enc28j60_cs Alias Portb.2 Led Alias Portb.1 '/* Maximum frame length - The Atmega168 has only 1024 byte internal RAM! */ Const Max_framelen = 500 '500 byte will be enough for common tasks Config Enc28j60_cs = Output Config Led = Output Config Date = Dmy , Separator = - Set Led 'Turn off the tuxgraphics board LED 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(max_framelen) As Byte Dim Length As Word Dim Rxstat As Word Dim Ip_id As Word Dim I_header_length As Word Dim Msg_temp As String * 55 '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_enetpackettype As Word At Buffer + &H0C Overlay Dim T_arp_hwtype1 As Byte At Buffer + &H0F Overlay 'Arp Dim T_arp_prttype1 As Byte At Buffer + &H11 Overlay Dim T_arp_hwlen As Byte At Buffer + &H12 Overlay Dim T_arp_prlen As Byte At Buffer + &H13 Overlay 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_tipaddr As Long At Buffer + &H26 Overlay 'IP header layout IP version and header length Dim T_ip_vers_len As Byte At Buffer + &H0E Overlay Dim T_arp_hwtype0 As Byte At Buffer + &H0E Overlay 'Arp Dim T_arp_prttype0 As Byte At Buffer + &H10 Overlay 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 Dim T_tos As Byte At Buffer + &H0F 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 Dim T_offset As Byte At Buffer + &H15 Overlay Dim T_ttl As Byte At Buffer + &H16 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 'UDP header Dim T_udp_srcport0 As Byte At Buffer + &H22 Overlay Dim T_udp_srcport1 As Byte At Buffer + &H23 Overlay Dim T_udp_srcport As Word At Buffer + &H22 Overlay Dim T_udp_destport0 As Byte At Buffer + &H24 Overlay Dim T_udp_destport1 As Byte At Buffer + &H25 Overlay Dim T_udp_destport As Word At Buffer + &H24 Overlay Dim T_udp_len0 As Byte At Buffer + &H26 Overlay Dim T_udp_len1 As Byte At Buffer + &H27 Overlay Dim T_udp_chksum0 As Byte At Buffer + &H28 Overlay Dim T_udp_chksum1 As Byte At Buffer + &H29 Overlay Dim T_udp_chksum As Word At Buffer + &H28 Overlay Dim T_udp_data As Byte At Buffer + &H2A Overlay Dim T_udp_data1 As Byte At Buffer + &H2B Overlay Dim T_udp_data2 As Byte At Buffer + &H2C Overlay Dim T_udp_data3 As Byte At Buffer + &H2D Overlay Dim T_udp_data4 As Byte At Buffer + &H2E Overlay Dim T_udp_data5 As Byte At Buffer + &H2F Overlay Dim T_udp_data6 As Byte At Buffer + &H30 Overlay Dim T_udp_data7 As Byte At Buffer + &H31 Overlay Dim T_udp_data8 As Byte At Buffer + &H32 Overlay Dim T_udp_data9 As Byte At Buffer + &H33 Overlay Dim T_udp_data10 As Byte At Buffer + &H34 Overlay Dim T_udp_data11 As Byte At Buffer + &H35 Overlay Dim T_udp_data12 As Byte At Buffer + &H36 Overlay Dim T_udp_data13 As Byte At Buffer + &H37 Overlay Dim T_udp_data14 As Byte At Buffer + &H38 Overlay Dim T_udp_data15 As Byte At Buffer + &H39 Overlay Dim T_udp_data16 As Byte At Buffer + &H3A Overlay Dim T_udp_data17 As Byte At Buffer + &H3B Overlay Dim T_udp_data18 As Byte At Buffer + &H3C Overlay Dim T_udp_data19 As Byte At Buffer + &H3D Overlay Dim T_udp_data20 As Byte At Buffer + &H3E Overlay Dim T_udp_data21 As Byte At Buffer + &H3F Overlay Dim T_udp_data22 As Byte At Buffer + &H40 Overlay Dim T_udp_data23 As Byte At Buffer + &H41 Overlay Dim T_udp_data24 As Byte At Buffer + &H42 Overlay Dim T_udp_data25 As Byte At Buffer + &H43 Overlay Dim T_udp_data26 As Byte At Buffer + &H44 Overlay Dim T_udp_data27 As Byte At Buffer + &H45 Overlay Dim T_udp_data28 As Byte At Buffer + &H46 Overlay Dim T_udp_data29 As Byte At Buffer + &H47 Overlay Dim T_udp_data30 As Byte At Buffer + &H48 Overlay Dim T_udp_data31 As Byte At Buffer + &H49 Overlay Dim T_udp_data32 As Byte At Buffer + &H4A Overlay Dim I_chksum32 As Long Dim I_odd As Byte Dim I_checksum16 As Word Dim Result16 As Word Dim Result16h As Byte At Result16 + 1 Overlay Dim Result16l As Byte At Result16 Overlay 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 Hulp2 As Word Dim Work As Byte 'variables with overlays Dim Myip(4) As Byte Dim My_ip As Long At Myip Overlay Dim Mymac(6) As Byte Dim Incoming_ack As Long Dim Incoming_ack0 As Byte At Incoming_ack Overlay Dim Incoming_ack1 As Byte At Incoming_ack + 1 Overlay Dim Incoming_ack2 As Byte At Incoming_ack + 2 Overlay Dim Incoming_ack3 As Byte At Incoming_ack + 3 Overlay Dim My_seqnum As Long Dim My_seqnum0 As Byte At My_seqnum Overlay Dim My_seqnum1 As Byte At My_seqnum + 1 Overlay Dim My_seqnum2 As Byte At My_seqnum + 2 Overlay Dim My_seqnum3 As Byte At My_seqnum + 3 Overlay 'for NTP-routine Dim S(4) As Byte Dim L1 As Long At S Overlay ' Overlay a long variable to receive-string ' with overlay you need no transfer from the byte-array to a long-variable Dim L2 As Long 'toegevoegd voor TCP 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 Tcpdatalen_in As Word Dim Tcpdatalen_out As Word Dim Expected_ack As Long Dim Flags As Byte Dim Client_seqnum As Long Dim Client_seqnum0 As Byte At Client_seqnum Overlay Dim Client_seqnum1 As Byte At Client_seqnum + 1 Overlay Dim Client_seqnum2 As Byte At Client_seqnum + 2 Overlay Dim Client_seqnum3 As Byte At Client_seqnum + 3 Overlay Dim Tempword As Word Dim Tempwordh As Byte At Tempword + 1 Overlay Dim Tempwordl As Byte At Tempword Overlay Dim Val1 As Word Dim Val2 As Word Dim Y As Word Const Synflag = 0 Const Finflag = 1 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 Declare Sub Enc28j60poll Declare Sub Arpreply Declare Sub Pingreply Declare Sub Setip_id Declare Sub Setst_mac Declare Sub Udp_receive Declare Sub Udp_checksum Declare Sub Setipaddrs Declare Sub Tcp Declare Sub Echopacket Declare Sub Ip_header_checksum Declare Sub Icmp_checksum Declare Sub Ntp_get Declare Sub Ntp Declare Sub Http Declare Sub Tcp_checksum Declare Sub Packetshape '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 '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 Call Ntp_get 'get the Network Time once Do Call Enc28j60poll 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 , Mymac(1)) Call Enc28j60writecontrolregbyte(maadr4 , Mymac(2)) Call Enc28j60writecontrolregbyte(maadr3 , Mymac(3)) Call Enc28j60writecontrolregbyte(maadr2 , Mymac(4)) Call Enc28j60writecontrolregbyte(maadr1 , Mymac(5)) Call Enc28j60writecontrolregbyte(maadr0 , Mymac(6)) '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) 'filters according to Guido Call Enc28j60writecontrolregbyte(epmm0 , &H3F) Call Enc28j60writecontrolregbyte(epmm1 , &H30) Call Enc28j60writecontrolregbyte(epmcsl , &HF9) Call Enc28j60writecontrolregbyte(epmcsh , &HF7) Value = 0 Value.erxfcon_pmen = 1 'Pattern Match enable (ARP only) Value.erxfcon_ucen = 1 'Unicast enable Call Enc28j60bitfield_set(erxfcon , Value) Value = 0 Value.erxfcon_bcen = 1 'Broadcast disable Call Enc28j60bitfield_clear(erxfcon , 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 Value = 0 Value.econ1_rxen = 1 Call Enc28j60bitfield_set(econ1 , Value) 'Reset transmit logic Value = 0 Value.econ1_txrst = 1 Call Enc28j60bitfield_set(econ1 , Value) Call Enc28j60bitfield_clear(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 Print "Pakketten aanwezig " ; Enc28j60_data Call Enc28j60packetreceive End If End Sub Sub Enc28j60packetreceive Reset Led 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) Enc28j60_cs = 0 'Send Read Buffer Memory command Spdr = &H3A Do Loop Until Spsr.spif = 1 'Get the first 6 byte (3 word: Nextpacketptr, Packetlength, Rxstat) For X = 1 To 6 Spdr = &HFF 'SPI read Do Loop Until Spsr.spif = 1 'SPI ready Buffer(x) = Spdr Next X Nextpacketptr = Buffer(2) * 256 Nextpacketptr = 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.spif = 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 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) Set Led 'Handle the packet If Buffer(13) = &H08 Then If Buffer(14) = &H06 Then 'Type:ARP If Buffer(21) = &H00 Then 'ARP request If Buffer(22) = &H01 Then 'ARP request If Buffer(39) = Myip(1) Then 'ARP for us If Buffer(40) = Myip(2) Then If Buffer(41) = Myip(3) Then If Buffer(42) = 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 Buffer(24) = 1 Then 'Protocol:ICMP If Buffer(35) = &H08 Then 'ICMP echo request Call Pingreply End If End If If Buffer(24) = 17 Then 'Protocol:UDP Call Udp_receive End If If Buffer(24) = 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 Enc28j60packetsend(pcktlen As Word) 'Load packet into the ENC 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 'Minimum packet length is 60 If Pcktlen < 60 Then Pcktlen = 60 'Reset transmit logic Value = 0 Value.econ1_txrst = 1 Call Enc28j60bitfield_set(econ1 , Value) 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 Arpreply 'The original request packet is in the buffer, we just change some things Local I As Byte 'Swap MAC addresses Call Setst_mac 'Copy target MAC in ARP packet - starting at pos 33, copy from pos 1 For I = 1 To 6 Buffer(32 + I) = Buffer(i) Next I 'Set target IP in ARP packet - starting at pos 39, original starting at pos 29 For I = 1 To 4 Buffer(38 + I) = Buffer(28 + I) Next I 'Copy source MAC to ARP packet pos 23 from pos 7 For I = 1 To 6 Buffer(22 + I) = Buffer(6 + I) Next I 'Set source IP to ARP packet pos 29 Buffer(29) = Myip(1) Buffer(30) = Myip(2) Buffer(31) = Myip(3) Buffer(32) = Myip(4) 'Set ARP type from Request to Reply Buffer(22) = 2 'Send the reply packet Call Enc28j60packetsend(42) End Sub Sub Pingreply Local Packetlength As Word Packetlength = Buffer(17) * 256 Packetlength = Packetlength + Buffer(18) 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 Enc28j60packetsend(packetlength) End Sub Sub Setip_id Buffer(19) = High(ip_id) Buffer(20) = Low(ip_id) Ip_id = Ip_id + 1 End Sub Sub Setst_mac Local I As Byte 'Set target MAC in ethernet frame - starting at pos 1, original starting at pos 7 For I = 1 To 6 Buffer(i) = Buffer(6 + I) Next I 'Set source MAC in ethernet frame, pos 7 Buffer(7) = Mymac(1) Buffer(8) = Mymac(2) Buffer(9) = Mymac(3) Buffer(10) = Mymac(4) Buffer(11) = Mymac(5) Buffer(12) = Mymac(6) End Sub ' Routine to handle UDP-traffic ' Sub Udp_receive 'Print "UDP_Receive" Local Udp_port As Word Local Udp_porth As Byte Local Udp_portl As Byte Udp_porth = &H88 Udp_portl = &H13 Udp_port = Udp_porth Shift Udp_port , Left , 8 Udp_port = Udp_port + Udp_portl 'From within a VB-program 'non-echo on PORT 5000 If T_udp_destport = Udp_port Then If T_udp_srcport = &H2500 Then ' &h0025 NTP protocol Call Ntp Exit Sub End If Select Case T_udp_data Case &H00 : Print "Action A" Case &H01 : Print "Action B" Case &H02 : Print "Action C" Case &H03 : Print "Action D" Case &H04 : Print "Action E" Case Else : Print "Action F" End Select Exit Sub End If 'echo on PORT 7 If T_udp_destport = &H0700 Then 'Build The Ip Header Call Setipaddrs 'swap the UDP source and destinations port Swap T_udp_srcport0 , T_udp_destport0 Swap T_udp_srcport1 , T_udp_destport1 Call Udp_checksum Call Echopacket End If End Sub ' Routine to calculate the IP-checkum ' Sub Udp_checksum T_udp_chksum = &H00 '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 'packet length I_value16h = T_udp_len0 I_value16l = T_udp_len1 I_chksum32 = I_chksum32 + I_value16 I_odd = T_udp_len1 Mod 2 Result16h = T_udp_len0 Result16l = T_udp_len1 Val2 = Highw(i_chksum32) Val1 = I_chksum32 I_checksum16 = Tcpchecksum(buffer(&H23) , Result16 , Val1 , Val2) T_udp_chksum1 = High(i_checksum16) T_udp_chksum0 = Low(i_checksum16) 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 'Calc starts with chksum=0 'Calculate IP header length Ip_header_length = T_ip_vers_len And &H0F 'Number of 32 bit words Ip_header_length = 4 * Ip_header_length 'Calc number of bytes 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 '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 echo packet ' Sub Echopacket 'packetlengte Hulp2 = T_udp_len0 * 256 Hulp2 = Hulp2 + T_udp_len1 Hulp2 = Hulp2 + 34 Call Enc28j60packetsend(hulp2) 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 Call Setst_mac Call Ip_header_checksum End Sub ' Routine to get the NetWork Time from a time-server ' Sub Ntp_get 'MAC-header 'Destination hardware address ' You have to put your router-mac-address here T_enetpacketdest0 = &H00 ' 00-0c-41-ae-7a-dc MAC-address of my router T_enetpacketdest1 = &H0C T_enetpacketdest2 = &H41 T_enetpacketdest3 = &HAE T_enetpacketdest4 = &H7A T_enetpacketdest5 = &HDC ' source (own source) T_enetpacketsrc0 = Mymac(1) T_enetpacketsrc1 = Mymac(2) T_enetpacketsrc2 = Mymac(3) T_enetpacketsrc3 = Mymac(4) T_enetpacketsrc4 = Mymac(5) T_enetpacketsrc5 = Mymac(6) T_enetpackettype = &H0008 ' = &h0800 ' fill IP-header T_ip_vers_len = &H45 T_tos = &H00 T_ip_pktlen0 = &H00 T_ip_pktlen1 = &H30 T_id0 = &H4A T_id1 = &HA5 T_flags = &H00 T_offset = &H00 T_ttl = &H80 'protocol (ICMP=1, TCP=6, UDP=11) T_ip_proto = &H11 'header checksum 'T_ip_hdr_cksum0 'T_ip_hdr_cksum1 'IP address of source T_ip_srcaddr0 = Myip(1) T_ip_srcaddr1 = Myip(2) T_ip_srcaddr2 = Myip(3) T_ip_srcaddr3 = Myip(4) 'IP address of destination 'you have to put the IP-number of T_ip_destaddr0 = 193 ' the NTP-server here T_ip_destaddr1 = 67 T_ip_destaddr2 = 79 T_ip_destaddr3 = 202 'UDP-header T_udp_srcport0 = &H13 T_udp_srcport1 = &H88 T_udp_destport0 = &H00 ' port 0025 = 37 NTP T_udp_destport1 = &H25 T_udp_len0 = &H00 T_udp_len1 = &H1C 'T_udp_chksum0 'T_udp_chksum1 T_udp_data = Asc( "X") T_udp_data1 = &H0A ' lf T_udp_data2 = &H0D ' cr Call Ip_header_checksum Call Udp_checksum Call Echopacket End Sub ' Routine to convert the LONG from the NTP-server in to date and time ' Sub Ntp S(1) = T_udp_data S(2) = T_udp_data1 S(3) = T_udp_data2 S(4) = T_udp_data3 Swap S(1) , S(4) : Swap S(2) , S(3) L2 = L1 + 1139293696 L2 = L2 + 3600 ' offset UTC + 1 hour Print "Date : " ; Date(l2) Print "Time : " ; Time(l2) End Sub 'Tcp-checksum ' Sub Tcp_checksum Local Whulp1 As Word Local Tempword2 As Word Tcp_cksum = 0 I_chksum32 = 0 Tempwordh = T_ip_srcaddr0 Tempwordl = T_ip_srcaddr1 I_chksum32 = Tempword Tempwordh = T_ip_srcaddr2 Tempwordl = T_ip_srcaddr3 I_chksum32 = I_chksum32 + Tempword Tempwordh = T_ip_destaddr0 Tempwordl = T_ip_destaddr1 I_chksum32 = I_chksum32 + Tempword Tempwordh = T_ip_destaddr2 Tempwordl = T_ip_destaddr3 I_chksum32 = I_chksum32 + Tempword I_chksum32 = I_chksum32 + T_ip_proto 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 'http ' Sub Http Print "Subroutine HTTP" Local Msg_temp2 As String * 10 Local Tempword3 As Word Local Tempstring1 As String * 1 Local Ackpsh As Byte 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 Print "Flags:" Print "FIN " ; Tcp_fin Print "SYN " ; Tcp_syn Print "RST " ; Tcp_rst Print "PSH " ; Tcp_psh Print "ACK " ; Tcp_ack Print "URG " ; Tcp_urg ' This code segment processes the incoming SYN from the client ' and sends back the initial sequence number (ISN) and acknowledges ' the incoming SYN packet If Tcp_syn = 1 Then 'If Tcp_ack = 0 Then Print "Tcp_syn = 1" 'Move IP source address to destination address T_ip_destaddr = T_ip_srcaddr 'Make ethernet module IP address source address T_ip_srcaddr = My_ip Swap Tcp_srcportl , Tcp_destportl Swap Tcp_srcporth , Tcp_destporth Tcpdatalen_in = 1 Client_seqnum0 = Tcp_seqnum0 Client_seqnum1 = Tcp_seqnum1 Client_seqnum2 = Tcp_seqnum2 Client_seqnum3 = Tcp_seqnum3 Client_seqnum = Client_seqnum + Tcpdatalen_in Tcp_acknum0 = Client_seqnum0 Tcp_acknum1 = Client_seqnum1 Tcp_acknum2 = Client_seqnum2 Tcp_acknum3 = Client_seqnum3 Tcp_seqnum0 = &HFF 'Initial sequencenumber Tcp_seqnum1 = &HFF ' Tcp_seqnum2 = &H10 ' Tcp_seqnum3 = &H11 ' Call Packetshape Set Flags.synflag Tcp_flags = 0 Set Tcp_flags.1 Set Tcp_flags.4 T_ip_pktlen0 = &H00 T_ip_pktlen1 = 48 Call Ip_header_checksum Call Tcp_checksum Call Enc28j60packetsend(62) 'End If End If ' If an ACK and PSH is received and the destination port address is valid If Tcp_ack = 1 Then If Tcp_psh = 1 Then Print "Tcp_ack = 1 AND Tcp_psh = 1 " 'ACK and PSH 'set flags Tcp_flags = 0 Set Tcp_flags.4 'ack 'Move IP source address to destination address T_ip_destaddr = T_ip_srcaddr 'Make ethernet module IP address source address T_ip_srcaddr = My_ip Swap Tcp_srcportl , Tcp_destportl Swap Tcp_srcporth , Tcp_destporth 'swap mac Call Packetshape Incoming_ack0 = Tcp_seqnum0 Incoming_ack1 = Tcp_seqnum1 Incoming_ack2 = Tcp_seqnum2 Incoming_ack3 = Tcp_seqnum3 Incoming_ack = Incoming_ack + 475 '489 - 14 Tcp_seqnum0 = Tcp_acknum0 Tcp_seqnum1 = Tcp_acknum1 Tcp_seqnum2 = Tcp_acknum2 Tcp_seqnum3 = Tcp_acknum3 Tcp_acknum0 = Incoming_ack0 Tcp_acknum1 = Incoming_ack1 Tcp_acknum2 = Incoming_ack2 Tcp_acknum3 = Incoming_ack3 Buffer(17) = 0 Buffer(18) = 40 '5 x 4 = 20 bytes Buffer(47) = &H50 'flag ACK Buffer(48) = &H10 'padding Buffer(55) = 0 Buffer(56) = 0 Buffer(57) = 0 Buffer(58) = 0 Buffer(59) = 0 Buffer(60) = 0 Call Ip_header_checksum Call Tcp_checksum Call Enc28j60packetsend(60) Ackpsh = 1 End If End If If Tcp_ack = 1 Then If Buffer(17) = 0 Then If Buffer(18) = 40 Then If Ackpsh = 1 Then 'ACK after a ACK-PSH 'set flags Tcp_flags = 0 Set Tcp_flags.4 'ack Set Tcp_flags.3 'psh Set Tcp_flags.0 'fin 'Move IP source address to destination address T_ip_destaddr = T_ip_srcaddr 'Make ethernet module IP address source address T_ip_srcaddr = My_ip Swap Tcp_srcportl , Tcp_destportl Swap Tcp_srcporth , Tcp_destporth 'swap mac Call Packetshape Incoming_ack0 = Tcp_seqnum0 Incoming_ack1 = Tcp_seqnum1 Incoming_ack2 = Tcp_seqnum2 Incoming_ack3 = Tcp_seqnum3 Tcp_seqnum0 = Tcp_acknum0 Tcp_seqnum1 = Tcp_acknum1 Tcp_seqnum2 = Tcp_acknum2 Tcp_seqnum3 = Tcp_acknum3 Tcp_acknum0 = Incoming_ack0 Tcp_acknum1 = Incoming_ack1 Tcp_acknum2 = Incoming_ack2 Tcp_acknum3 = Incoming_ack3 Buffer(17) = 0 Buffer(18) = 40 Tempword3 = &H37 Restore Htmlcode Do Read Msg_temp Print Msg_temp Msg_temp2 = Right(msg_temp , 8) If Msg_temp2 = "endblock" Then Exit Do End If For Y = 1 To Len(msg_temp) Tempstring1 = Mid(msg_temp , Y , 1) Buffer(tempword3) = Asc(tempstring1) Incr Tempword3 Next Y Loop Buffer(181) = &H0D Buffer(182) = &H0A T_ip_pktlen0 = 0 T_ip_pktlen1 = 48 Buffer(17) = 0 'HTML-code + 40 Buffer(18) = &HA8 Call Ip_header_checksum Call Tcp_checksum Call Enc28j60packetsend(182) End If End If End If End If End Sub ' TCP ' Sub Tcp If Tcp_destporth = 0 Then If Tcp_destportl = 80 Then Call Http End If End If End Sub Sub Packetshape '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 ' '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) End Sub ' htmlcode ' Htmlcode: Data "HTTP/1.0 200" , &H0D , &H0A , &H0D , &H0A Data "