'---------------------------------------------------------------------------------- ' Embedded UDP&WebServer - Atmega32 and RTL8019AS - Embedded UDP&WebServer '---------------------------------------------------------------------------------- ' ' Version 1 - April 1 2005 - Ben Zijlstra - Netherlands - https://benshobbycorner.nl/bzijlstra $crystal = 7372800 $regfile = "M32def.dat" $baud = 57600 Declare Sub Write_rtl8019as(byval Regaddr As Byte , Byval Regdata As Byte) Declare Sub Read_rtl8019as(byval Regaddr As Byte) Declare Sub Init_rtl8019as 'Declare Sub Showregs Declare Sub Getpacket Declare Sub Overrun Declare Sub Arp Declare Sub Icmp Declare Sub Icmp_checksum Declare Sub Tcp Declare Sub Write_dest_mac Declare Sub Packetshape Declare Sub Echopacket Declare Sub Setipaddrs Declare Sub Ip_header_checksum Declare Sub Udp Declare Sub Udp_checksum ' Declare Sub General_part_checksum(byval Val1 As Byte , Byval Val2 As Word) ' ' Declare Sub Lcd_init Declare Sub Lcd_char(byval Lcd_c As Byte) Declare Sub Lcd_txt Declare Sub Lcdhome ' CLS/Home Declare Sub Firstline ' goto 0/0 of LCD Declare Sub Secondline Declare Sub Http Declare Sub Tcp_checksum Declare Sub Send_tcp_packet Declare Sub Setup_packet Declare Sub Assemble_ack Declare Sub Tcpseqtomyseq Declare Sub Relayon(byval X As Byte) Declare Sub Relayoff(byval X As Byte) Declare Sub Status Dim Myip(4) As Byte At &H64 Dim My_ip As Long At &H64 Overlay Dim Client_seqnum As Long At &H8E Dim Client_seqnum0 As Byte At &H8E Overlay Dim Client_seqnum1 As Byte At &H8F Overlay Dim Client_seqnum2 As Byte At &H90 Overlay Dim Client_seqnum3 As Byte At &H91 Overlay Dim Incoming_ack As Long At &H92 Dim Incoming_ack0 As Byte At &H92 Overlay Dim Incoming_ack1 As Byte At &H93 Overlay Dim Incoming_ack2 As Byte At &H94 Overlay Dim Incoming_ack3 As Byte At &H95 Overlay Dim My_seqnum As Long At &HB7 Dim My_seqnum0 As Byte At &HB7 Overlay Dim My_seqnum1 As Byte At &HB8 Overlay Dim My_seqnum2 As Byte At &HB9 Overlay Dim My_seqnum3 As Byte At &HBA Overlay ' Dim Tempword As Word At &H60 Dim Tempwordh As Byte At &H61 Overlay Dim Tempwordl As Byte At &H60 Overlay Dim Val1 As Byte Dim Val2 As Word ' up to 65535 characters Dim Val3 As Byte Dim Val4 As Byte Dim Regaddr As Byte Dim Regdata As Byte 'Ethernet header layout Dim Byte_read As Byte Dim Hulp1 As Byte Dim Mymac(6) As Byte Dim I As Integer Dim Rxlen As Word Dim Hulp2 As Word Dim Hulp3 As Word Dim Hulp4 As Byte Dim Data_l As Byte Dim Data_h As Byte 'RTL8019AS Dim Txstart As Byte Dim Txlen As Word Dim I_header_length As Word Dim I_odd As Byte Dim I_chksum32 As Long Dim Hulp6 As Word At &HAF Dim Hulp6h As Byte At &HB0 Overlay Dim Hulp6l As Byte At &HAF Overlay Dim I_x As Word Dim I_checksum16 As Word Dim I_value16 As Word At &HB1 Dim I_value16h As Byte At &HB2 Overlay Dim I_value16l As Byte At &HB1 Overlay Dim Result16 As Word At &HB5 Dim Result16h As Byte At &HB6 Overlay Dim Result16l As Byte At &HB5 Overlay 'variables with overlays Dim Pageheader(4) As Byte At &HAB Dim T_enetpacketlenl As Byte At &HAD Overlay Dim T_enetpacketlenh As Byte At &HAE Overlay Dim Resend As Byte Dim T As Byte Dim Packet(1500) As Byte At &HC0 'Ethernet packet destination Dim T_enetpacketdest0 As Byte At &HC0 Overlay Dim T_enetpacketdest1 As Byte At &HC1 Overlay Dim T_enetpacketdest2 As Byte At &HC2 Overlay Dim T_enetpacketdest3 As Byte At &HC3 Overlay Dim T_enetpacketdest4 As Byte At &HC4 Overlay Dim T_enetpacketdest5 As Byte At &HC5 Overlay 'Ethernet packet source Dim T_enetpacketsrc0 As Byte At &HC6 Overlay Dim T_enetpacketsrc1 As Byte At &HC7 Overlay Dim T_enetpacketsrc2 As Byte At &HC8 Overlay Dim T_enetpacketsrc3 As Byte At &HC9 Overlay Dim T_enetpacketsrc4 As Byte At &HCA Overlay Dim T_enetpacketsrc5 As Byte At &HCB Overlay 'Ethernet packet type Dim T_enetpackettype As Word At &HCC Overlay Dim T_arp_hwtype1 As Byte At &HCF Overlay 'Arp Dim T_arp_prttype1 As Byte At &HD1 Overlay Dim T_arp_hwlen As Byte At &HD2 Overlay Dim T_arp_prlen As Byte At &HD3 Overlay Dim T_arp_op1 As Byte At &HD5 Overlay 'arp source ip address Dim T_arp_sipaddr0 As Byte At &HDC Overlay Dim T_arp_sipaddr1 As Byte At &HDD Overlay Dim T_arp_sipaddr2 As Byte At &HDE Overlay Dim T_arp_sipaddr3 As Byte At &HDF Overlay 'arp target IP address Dim T_arp_tipaddr As Long At &HE6 Overlay 'IP header layout IP version and header length Dim T_ip_vers_len As Byte At &HCE Overlay 'packet length Dim T_ip_pktlen0 As Byte At &HD0 Overlay Dim T_ip_pktlen1 As Byte At &HD1 Overlay 'protocol (ICMP=1, TCP=6, UDP=11) Dim T_ip_proto As Byte At &HD7 Overlay 'header checksum Dim T_ip_hdr_cksum0 As Byte At &HD8 Overlay Dim T_ip_hdr_cksum1 As Byte At &HD9 Overlay Dim T_ip_hdr_cksum As Word At &HD8 Overlay 'IP address of source Dim T_ip_srcaddr0 As Byte At &HDA Overlay Dim T_ip_srcaddr1 As Byte At &HDB Overlay Dim T_ip_srcaddr2 As Byte At &HDC Overlay Dim T_ip_srcaddr3 As Byte At &HDD Overlay Dim T_ip_srcaddr As Long At &HDA Overlay 'IP address of destination Dim T_ip_destaddr0 As Byte At &HDE Overlay Dim T_ip_destaddr1 As Byte At &HDF Overlay Dim T_ip_destaddr2 As Byte At &HE0 Overlay Dim T_ip_destaddr3 As Byte At &HE1 Overlay Dim T_ip_destaddr As Long At &HDE Overlay Dim T_icmp_type As Byte At &HE2 Overlay Dim T_icmp_code As Byte At &HE3 Overlay Dim T_icmp_cksum0 As Byte At &HE4 Overlay Dim T_icmp_cksum1 As Byte At &HE5 Overlay Dim T_icmp_cksum As Word At &HE4 Overlay Dim Tcp_srcporth As Byte At &HE2 Overlay Dim Tcp_srcportl As Byte At &HE3 Overlay Dim Tcp_destporth As Byte At &HE4 Overlay Dim Tcp_destportl As Byte At &HE5 Overlay Dim Tcp_seqnum3 As Byte At &HE6 Overlay Dim Tcp_seqnum2 As Byte At &HE7 Overlay Dim Tcp_seqnum1 As Byte At &HE8 Overlay Dim Tcp_seqnum0 As Byte At &HE9 Overlay Dim Tcp_acknum3 As Byte At &HEA Overlay Dim Tcp_acknum2 As Byte At &HEB Overlay Dim Tcp_acknum1 As Byte At &HEC Overlay Dim Tcp_acknum0 As Byte At &HED Overlay Dim Tcp_hdr As Byte At &HEE Overlay Dim Tcp_flags As Byte At &HEF Overlay Dim Tcp_cksumh As Byte At &HF2 Overlay Dim Tcp_cksuml As Byte At &HF3 Overlay Dim Tcp_cksum As Word At &HF2 Overlay 'UDP header Dim T_udp_srcport0 As Byte At &HE2 Overlay Dim T_udp_srcport1 As Byte At &HE3 Overlay Dim T_udp_destport0 As Byte At &HE4 Overlay Dim T_udp_destport1 As Byte At &HE5 Overlay Dim T_udp_destport As Word At &HE4 Overlay Dim T_udp_len0 As Byte At &HE6 Overlay Dim T_udp_len1 As Byte At &HE7 Overlay Dim T_udp_chksum0 As Byte At &HE8 Overlay Dim T_udp_chksum1 As Byte At &HE9 Overlay Dim T_udp_data As Byte At &HEA Overlay 'LCD variables Dim Lcd_t As String * 40 Dim Lcd_tempstr As String * 1 Dim Lcd_temp As Byte Dim Lcd_x As Byte Dim Lcd_hulp As Byte Dim Lcd_h As Byte Dim Lcdpresent As Byte 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 Ip_packet_len As Word Dim Flags As Byte Dim Msg_temp As String * 55 Dim Y As Word Dim Tempstring1 As String * 1 Dim Expected_ack As Long Dim Triggerstr As String * 20 Dim Tempstring As String * 10 Dim Portpntr As Byte At &HEA Overlay Dim Portval As String * 4 At &HEB Overlay Dim Relaypntr As Byte At &HEF Overlay Dim Relval As String * 4 At &HF0 Overlay 'Dim Temppntr As Byte At &HF4 Overlay 'Dim Tempval As String * 5 At &HF5 Overlay Dim Relaystatus As Byte 'idle time Dim Idletime As Long Const Debug = 0 ' put 1 for debug, 0 for no debug Const Rstport = &H18 Const Isr = &H07 Const Msg_initfail = "Init failed" Const Cr = &H00 Const Dcrval = &H58 Const Dcr = &H0E Const Rbcr0 = &H0A Const Rbcr1 = &H0B Const Rcr = &H0C Const Tpsr = &H04 Const Txtstart = &H40 Const Tcr = &H0D Const Pstart = &H01 Const Rxstart = &H46 Const Bnry = &H03 Const Pstop = &H02 Const Rxstop = &H60 Const Curr = &H07 Const Imr = &H0F Const Imrval = &H11 Const Tcrval = &H00 Const Rdmaport = &H10 Const Rsar0 = &H08 Const Rsar1 = &H09 Const Tbcr0 = &H05 Const Tbcr1 = &H06 'IP protocol types 'icmp Const Prot_icmp = &H01 'tcp Const Prot_tcp = &H06 'udp Const Prot_udp = &H11 Const Synflag = 0 Const Finflag = 1 'LCD Const Rs = 4 Const E = 7 Const Pcf8574 = &H40 Const Triggerstring = "SEND INFORMATION NOW" 'RTL8019AS ISR Register definitions Const Rdc = &H40 Config Int0 = Rising 'I2c Config Scl = Portc.0 Config Sda = Portc.1 Lcdpresent = 1 Mymac(1) = &H00 Mymac(2) = &H10 Mymac(3) = &H20 Mymac(4) = &H30 Mymac(5) = &H40 Mymac(6) = &H50 Myip(1) = 192 Myip(2) = 168 Myip(3) = 0 Myip(4) = 100 #if Debug = 1 Print "Hello world" #endif Databus Alias Porta _databus Alias Pina Rtldata Alias Porta Databus_ddr Alias Ddra Addrbus Alias Portb Addrbus_ddr Alias Ddrb Resetport Alias Portd Eeprom Alias Portd Ior_pin Alias Portd.6 Iow_pin Alias Portd.7 Resetport_ddr Alias Ddrd Inputport1 Alias Pinc Inputport2 Alias Portc Latch Alias Portd.3 Resetport_ddr = &HF8 ' leave RXD and TXD Main: Reset Latch Databus_ddr = &HFF Databus = 0 ' put zero's on relays-port Set Latch Reset Latch Relaystatus = 0 ' put zero's in the relaystatus byte Call Lcd_init Lcd_t = "VA3TO/EIO-board" Call Lcd_txt Call Secondline Lcd_t = "Tutorial" Call Lcd_txt Call Init_rtl8019as 'Call Showregs Enable Interrupts Enable Int0 On Int0 Rtl8019as_interrupt 'start the NIC Call Write_rtl8019as(cr , &H22) Do Loop End ' Routine to handle an interrupt on the RTL8019AS ' Rtl8019as_interrupt: #if Debug = 1 Print "Interrupt from RTL8019as" #endif Disable Int0 'read the interrupt status register Call Read_rtl8019as(isr) 'if the receive buffer has been overrun If Byte_read.4 = 1 Then Call Overrun End If 'if the receive buffer holds a good packet If Byte_read.0 = 1 Then Call Getpacket End If 'make sure the receive buffer ring is empty. If BNRY = CURR, the buffer is empty Call Read_rtl8019as(bnry) Data_l = Byte_read Call Write_rtl8019as(cr , &H62) Call Read_rtl8019as(curr) Data_h = Byte_read Call Write_rtl8019as(cr , &H22) 'buffer is not empty, get next packet If Data_l <> Data_h Then Call Getpacket End If 'reset the interrupts bits Call Write_rtl8019as(isr , &HFF) Call Write_rtl8019as(cr , &H22) Enable Int0 Return ' Routine to Write to NIC Control register ' Sub Write_rtl8019as(regaddr , Regdata) Addrbus = Regaddr Databus = Regdata Databus_ddr = &HFF nop Reset Iow_pin nop Set Iow_pin nop Databus_ddr = &H00 Databus = &HFF End Sub ' Routine to read from NIC Control register ' Sub Read_rtl8019as(regaddr) Databus_ddr = &H00 Databus = &HFF Addrbus = Regaddr Reset Ior_pin nop Byte_read = Pina nop Set Ior_pin nop End Sub ' Routine to initialise the RTL8019AS ethernetchip ' Sub Init_rtl8019as Databus_ddr = &H00 Databus = &HFF Addrbus_ddr = &HFF Addrbus = &H00 Resetport_ddr = &HF8 Reset Eeprom.5 Set Iow_pin Set Ior_pin Set Resetport.4 Waitms 2 Reset Resetport.4 Call Read_rtl8019as(rstport) Call Write_rtl8019as(rstport , Byte_read) Waitms 10 'check for good soft reset Call Read_rtl8019as(isr) If Byte_read.7 = 0 Then Print Msg_initfail End If Call Write_rtl8019as(cr , &H21) Waitms 2 Call Write_rtl8019as(dcr , Dcrval) Call Write_rtl8019as(rbcr0 , &H00) Call Write_rtl8019as(rbcr1 , &H00) Call Write_rtl8019as(rcr , &H04) Call Write_rtl8019as(tpsr , Txtstart) Call Write_rtl8019as(tcr , &H02) Call Write_rtl8019as(pstart , Rxstart) Call Write_rtl8019as(bnry , Rxstart) Call Write_rtl8019as(pstop , Rxstop) Call Write_rtl8019as(cr , &H61) Waitms 2 Call Write_rtl8019as(curr , Rxstart) For Hulp1 = 1 To 6 Call Write_rtl8019as(hulp1 , Mymac(hulp1)) Next Hulp1 Call Write_rtl8019as(cr , &H21) Call Write_rtl8019as(dcr , Dcrval) Call Write_rtl8019as(cr , &H22) Call Write_rtl8019as(isr , &HFF) Call Write_rtl8019as(imr , Imrval) Call Write_rtl8019as(tcr , Tcrval) End Sub '( ' Routine show the contents of the RTL8019as registers ' Sub Showregs Local Cntr1 As Byte Local Cntr2 As Byte Call Write_rtl8019as(cr , &H21) Print Print "Realtek 8019AS Register dump" Print Print "REG Page0 Page1 Page2 Page3" Print For Cntr1 = 0 To 15 Cntr2 = Cntr1 Print Hex(cntr2); Print " "; Call Write_rtl8019as(cr , &H21) Cntr2 = Cntr1 Call Read_rtl8019as(cntr2) Print Hex(byte_read); Print " "; Call Write_rtl8019as(cr , &H61) Cntr2 = Cntr1 Call Read_rtl8019as(cntr2) Print Hex(byte_read); Print " "; Call Write_rtl8019as(cr , &HA1) Cntr2 = Cntr1 Call Read_rtl8019as(cntr2) Print Hex(byte_read); Print " "; Call Write_rtl8019as(cr , &HE1) Cntr2 = Cntr1 Call Read_rtl8019as(cntr2) Print Hex(byte_read) Next Cntr1 End Sub ') Sub Overrun Call Read_rtl8019as(cr) Data_l = Byte_read Call Write_rtl8019as(cr , &H21) Waitms 2 Call Write_rtl8019as(rbcr0 , &H00) Call Write_rtl8019as(rbcr1 , &H00) Hulp1 = Data_l And &H04 If Hulp1 <> 0 Then Resend = 0 Else If Hulp1 = 0 Then Call Read_rtl8019as(isr) Data_l = Byte_read Hulp1 = Data_l And &H02 Hulp4 = Data_l And &H08 Hulp3 = Hulp1 Or Hulp4 If Hulp3 > 0 Then Resend = 0 Else Resend = 1 End If End If End If Call Write_rtl8019as(tcr , &H02) Call Write_rtl8019as(cr , &H22) Call Write_rtl8019as(bnry , Rxstart) Call Write_rtl8019as(cr , &H62) Call Write_rtl8019as(curr , Rxstart) Call Write_rtl8019as(cr , &H22) Call Write_rtl8019as(isr , &H10) Call Write_rtl8019as(tcr , Tcrval) End Sub ' Routine to execute send packet command to retrieve the packet ' Sub Getpacket Call Write_rtl8019as(cr , &H1A) For I = 0 To 4 Call Read_rtl8019as(rdmaport) Pageheader(i + 1) = Byte_read Next I 'watch it. overlay variables Result16h = T_enetpacketlenh Result16l = T_enetpacketlenl Rxlen = Result16 Hulp2 = Rxlen + 1 For I = 1 To Hulp2 Call Read_rtl8019as(rdmaport) 'dump any bytes that will overrun the receive buffer If I < 1500 Then Packet(i + 1) = Byte_read End If Next I Hulp1 = Byte_read And Rdc If Hulp1 <> 64 Then Call Read_rtl8019as(isr) End If Call Write_rtl8019as(isr , &HFF) ' Routine to process an ARP packet ' If T_enetpackettype = &H0608 Then If T_arp_hwtype1 = &H01 Then If T_arp_prttype1 = &H00 Then If T_arp_hwlen = &H06 Then If T_arp_prlen = &H04 Then If T_arp_op1 = &H01 Then If My_ip = T_arp_tipaddr Then Call Arp End If End If End If End If End If End If End If ' Routine to go ahead with icmp or udp ' If T_enetpackettype = &H0008 Then If T_ip_destaddr = My_ip Then Select Case T_ip_proto Case Prot_icmp : Call Icmp Case Prot_tcp : Call Tcp Case Prot_udp : Call Udp End Select End If End If End Sub ' Routine to handle ARP-traffic ' Sub Arp 'Start the NIC Call Write_rtl8019as(cr , &H22) 'load beginning page for transmit buffer Call Write_rtl8019as(tpsr , Txtstart) 'set start address for remote DMA operation Call Write_rtl8019as(rsar0 , &H00) Call Write_rtl8019as(rsar1 , &H40) 'clear the interrupts Call Write_rtl8019as(isr , &HFF) 'load data byte count for remote DMA Call Write_rtl8019as(rbcr0 , &H3C) Call Write_rtl8019as(rbcr1 , &H00) 'do remote write operation Call Write_rtl8019as(cr , &H12) 'write destination MAC address Call Write_dest_mac 'write source address For I = 1 To 6 Call Write_rtl8019as(rdmaport , Mymac(i)) Next I 'arp target IP address 'arp_op1 = packet(&h16) Packet(&H16) = &H02 For I = 0 To 9 Hulp1 = &HCC + I T = Peek(hulp1) Call Write_rtl8019as(rdmaport , T) Next I 'write ethernet module mac address For I = 1 To 6 Call Write_rtl8019as(rdmaport , Mymac(i)) Next I 'write myip For I = 1 To 4 Call Write_rtl8019as(rdmaport , Myip(i)) Next I 'write remote mac address Call Write_dest_mac 'write remote IP address Call Write_rtl8019as(rdmaport , T_arp_sipaddr0) Call Write_rtl8019as(rdmaport , T_arp_sipaddr1) Call Write_rtl8019as(rdmaport , T_arp_sipaddr2) Call Write_rtl8019as(rdmaport , T_arp_sipaddr3) 'write som pad characters to fill out the packet to the minimum length For I = 0 To &H11 Call Write_rtl8019as(rdmaport , &H00) Next I 'make sure the DMA operation has succesfully completed Byte_read = 0 Do Hulp1 = Byte_read And Rdc Call Read_rtl8019as(isr) Loop Until Hulp1 = 0 'load numbers of bytes to be transmitted Call Write_rtl8019as(tbcr0 , &H3C) Call Write_rtl8019as(tbcr1 , &H00) 'send the contents of the transmit buffer onto the network Call Write_rtl8019as(cr , &H24) End Sub Sub Write_dest_mac Call Write_rtl8019as(rdmaport , T_enetpacketsrc0) Call Write_rtl8019as(rdmaport , T_enetpacketsrc1) Call Write_rtl8019as(rdmaport , T_enetpacketsrc2) Call Write_rtl8019as(rdmaport , T_enetpacketsrc3) Call Write_rtl8019as(rdmaport , T_enetpacketsrc4) Call Write_rtl8019as(rdmaport , T_enetpacketsrc5) End Sub Sub Icmp 'set echo reply T_icmp_type = &H00 T_icmp_code = &H00 'setup the IP-header Call Setipaddrs Call Icmp_checksum Call Echopacket 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 Packetshape Call Ip_header_checksum End Sub ' Routine to echo a complete packet ' Sub Echopacket Call Write_rtl8019as(cr , &H22) Call Write_rtl8019as(tpsr , Txtstart) Call Write_rtl8019as(rsar0 , &H00) Call Write_rtl8019as(rsar1 , &H40) Call Write_rtl8019as(isr , &HFF) Hulp1 = T_enetpacketlenl - 4 Call Write_rtl8019as(rbcr0 , Hulp1) Call Write_rtl8019as(rbcr1 , T_enetpacketlenh) Call Write_rtl8019as(cr , &H12) Result16h = T_enetpacketlenh Result16l = T_enetpacketlenl Result16 = Result16 - 4 Txlen = Result16 'write the complete packet to the RTL8019AS from packet(1) to packet(txlen+1) Hulp2 = Txlen + 1 For I = 1 To Hulp2 Call Write_rtl8019as(rdmaport , Packet(i)) Next I Byte_read = 0 While Hulp1 <> 0 Hulp1 = Byte_read And Rdc Call Read_rtl8019as(isr) Wend Hulp1 = T_enetpacketlenl - 4 Call Write_rtl8019as(tbcr0 , Hulp1) Call Write_rtl8019as(tbcr1 , T_enetpacketlenh) Call Write_rtl8019as(cr , &H24) 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 ' Routine to calculate a ICMP-checksum ' Sub Icmp_checksum 'clear the ICMP checksum T_icmp_cksum = &H00 'calculate the ICMP checksum I_header_length = T_ip_pktlen1 - 20 'I_header_length = I_header_length - 20 I_odd = I_header_length Mod 2 '14 for MAC-part '20 for IP-header 'start on 35 'ip_pktlen = 00 3c (60) 'icmp-packetlengte = ip_pktlen - ip_header I_chksum32 = 0 'Total packetlength - ip_header - 1 Hulp6h = T_ip_pktlen0 Hulp6l = T_ip_pktlen1 Val1 = 35 Val2 = Hulp6 + 13 Call General_part_checksum(val1 , Val2) T_icmp_cksum0 = Val3 T_icmp_cksum1 = Val4 End Sub ' Routine to calculate a IP-header checksum ' Sub Ip_header_checksum Local Ip_x As Byte Local Ip_hulp1 As Byte Local Ip_chksum32 As Long Local Ip_checksum16 As Word Local Ip_temp16 As Word Local Ip_header_length As Byte 'calculate the IP header checksum T_ip_hdr_cksum = &H00 ' Hdr_chksum = 0 I_chksum32 = 0 Ip_header_length = T_ip_vers_len And &H0F Ip_header_length = 4 * Ip_header_length I_chksum32 = 0 I_odd = 0 Val1 = 15 Val2 = &H0E + Ip_header_length Call General_part_checksum(val1 , Val2) T_ip_hdr_cksum0 = Val3 T_ip_hdr_cksum1 = Val4 End Sub ' Routine to handle UDP-traffic ' Sub Udp Triggerstr = "" Hulp1 = &HEA For Hulp2 = 1 To 20 Hulp3 = Peek(hulp1) Triggerstr = Triggerstr + Chr(hulp3) Incr Hulp1 Next Hulp2 'From within a VB-program If T_udp_destport = &H8813 Then Select Case T_udp_data Case &H01 : Call Relayon(1) Case &H02 : Call Relayon(2) Case &H03 : Call Relayon(3) Case &H04 : Call Relayon(4) Case &HA1 : Call Relayoff(5) Case &HA2 : Call Relayoff(6) Case &HA3 : Call Relayoff(7) Case &HA4 : Call Relayoff(8) End Select If Triggerstr = Triggerstring Then If Lcdpresent = 1 Then Lcd_t = "*UDP request#Sending: " Call Lcd_txt End If Portpntr = Asc( "P") Tempstring = Bin(inputport1) Portval = Left(tempstring , 4) If Lcdpresent = 1 Then Lcd_t = "P" + Portval End If Relaypntr = Asc( "R") Tempstring = Bin(relaystatus) Relval = Right(tempstring , 4) If Lcdpresent = 1 Then Lcd_t = Lcd_t + "R" Lcd_t = Lcd_t + Relval Call Lcd_txt Idletime = 0 End If '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 Write_rtl8019as(cr , &H22) Call Echopacket End If End If End Sub ' Routine to calculate the Udp-checksum ' Sub Udp_checksum T_udp_chksum0 = &H00 T_udp_chksum1 = &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 'udp_srcport0 = packet(&h23) Val1 = &H23 Val2 = &H23 + Result16 Val2 = Val2 - 2 Call General_part_checksum(val1 , Val2) T_udp_chksum0 = Val3 T_udp_chksum1 = Val4 End Sub Sub General_part_checksum(byval Val1 As Byte , Byval Val2 As Word) For I_x = Val1 To Val2 Step 2 I_value16h = Packet(i_x) Hulp3 = I_x + 1 I_value16l = Packet(hulp3) I_chksum32 = I_chksum32 + I_value16 Next I_x If I_odd = 1 Then Incr Val2 I_value16h = Packet(val2) I_value16l = 0 I_chksum32 = I_chksum32 + I_value16 End If I_checksum16 = Highw(i_chksum32) I_checksum16 = I_checksum16 + I_chksum32 ' only 16 lower bits of i_chksum32 is taken... I_checksum16 = Not I_checksum16 Val3 = High(i_checksum16) Val4 = Low(i_checksum16) End Sub ' Subroutine to initialize the LCD-display Sub Lcd_init Waitms 15 'set 8-bit mode (attention) 'toggle the E -line I2csend Pcf8574 , &B10000011 I2csend Pcf8574 , &B00000011 Waitms 4 'set 8-bit mode (attention) I2csend Pcf8574 , &B10000011 I2csend Pcf8574 , &B00000011 Waitms 1 'set 8-bit mode (attention) I2csend Pcf8574 , &B10000011 I2csend Pcf8574 , &B00000011 Waitms 4 'set 4-bit operation I2csend Pcf8574 , &B10000010 I2csend Pcf8574 , &B00000010 Waitms 1 'set 8-bit mode (attention) I2csend Pcf8574 , &B10000010 I2csend Pcf8574 , &B00000010 I2csend Pcf8574 , &B10001000 I2csend Pcf8574 , &B00001000 Waitms 1 I2csend Pcf8574 , &B10000000 I2csend Pcf8574 , &B00000000 'Display off, cursor off, blink off I2csend Pcf8574 , &B10001000 I2csend Pcf8574 , &B00001000 Waitms 1 I2csend Pcf8574 , &B10000000 I2csend Pcf8574 , &B00000000 'display on, cursor off, blinking off I2csend Pcf8574 , &B10001100 I2csend Pcf8574 , &B00001100 Waitms 1 I2csend Pcf8574 , &B10000000 I2csend Pcf8574 , &B00000000 'clear display and send cursor to address 0 I2csend Pcf8574 , &B10000001 I2csend Pcf8574 , &B00000001 Waitms 1 End Sub ' Routine to send a character to the LCD-display ' Sub Lcd_char(lcd_c As Byte) If Lcd_c = 42 Then '* CLS/HOME Call Lcdhome Elseif Lcd_c = 35 Then '# second line Call Secondline Else Lcd_temp = Lcd_c And &HF0 Rotate Lcd_temp , Right , 4 I2csend Pcf8574 , Lcd_temp Set Lcd_temp.e Set Lcd_temp.rs I2csend Pcf8574 , Lcd_temp Reset Lcd_temp.e Reset Lcd_temp.rs I2csend Pcf8574 , Lcd_temp Lcd_temp = Lcd_c And &H0F I2csend Pcf8574 , Lcd_temp Set Lcd_temp.e Set Lcd_temp.rs I2csend Pcf8574 , Lcd_temp Reset Lcd_temp.e Reset Lcd_temp.rs I2csend Pcf8574 , Lcd_temp End If End Sub ' Routine to send a string to the LCD-display ' ' Fill lcd_t with the text and call lcd_txt ' Sub Lcd_txt Lcd_hulp = Len(lcd_t) For Lcd_x = 1 To Lcd_hulp Lcd_tempstr = Mid(lcd_t , Lcd_x , 1) Lcd_temp = Asc(lcd_tempstr) Call Lcd_char(lcd_temp) Next Lcd_x End Sub Sub Lcdhome I2csend Pcf8574 , &B10000000 I2csend Pcf8574 , &B00000000 Waitms 2 I2csend Pcf8574 , &B10000001 I2csend Pcf8574 , &B00000001 Waitms 2 End Sub Sub Secondline Call Firstline For Lcd_h = 1 To 40 I2csend Pcf8574 , &B10000001 I2csend Pcf8574 , &B00000001 Waitms 2 I2csend Pcf8574 , &B10000100 I2csend Pcf8574 , &B00000100 Waitms 2 Next Lcd_h End Sub Sub Firstline I2csend Pcf8574 , &B10000000 I2csend Pcf8574 , &B00000000 Waitms 2 I2csend Pcf8574 , &B10000010 I2csend Pcf8574 , &B00000010 Waitms 2 End Sub ' TCP ' Sub Tcp Local Work 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 If Tcp_destporth = 0 Then Select Case Tcp_destportl Case 80 : Call Http End Select End If End Sub Sub Http #if Debug = 1 Print "HTTP" Print Print "Destination port low " ; Tcp_destportl Print "Destination port high " ; Tcp_destporth Print Print "TCPdatalen_in " ; Tcpdatalen_in Print 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 Print Print "Incoming:" Print "Tcp_seqnum3 " ; Hex(tcp_seqnum3) Print "Tcp_seqnum2 " ; Hex(tcp_seqnum2) Print "Tcp_seqnum1 " ; Hex(tcp_seqnum1) Print "Tcp_seqnum0 " ; Hex(tcp_seqnum0) Print Print "Tcp_acknum3 " ; Hex(tcp_acknum3) Print "Tcp_acknum2 " ; Hex(tcp_acknum2) Print "Tcp_acknum1 " ; Hex(tcp_acknum1) Print "Tcp_acknum0 " ; Hex(tcp_acknum0) #endif Local Msg_temp2 As String * 10 Local Tempword3 As Word Local Z As Word Local Ztemp As Word Local Tempstring2 As String * 5 Result16h = T_ip_pktlen0 Result16l = T_ip_pktlen1 ' ' calculate IP header length ' MSN is version (IPv4) ' LSN is length Hulp1 = T_ip_vers_len And &H0F Hulp1 = Hulp1 * 4 ' calculate TCP header length ' MSN is length / 4 Hulp2 = Tcp_hdr And &HF0 Shift Hulp2 , Right , 4 Hulp2 = Hulp2 * 4 Tcpdatalen_in = Result16 - Hulp1 Tcpdatalen_in = Tcpdatalen_in - Hulp2 ' 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 Tcpdatalen_in = 0 Then #if Debug = 1 Print "Tcp_ack = 1 , Tcpdatalen_in = 0 " #endif Incoming_ack0 = Tcp_acknum0 Incoming_ack1 = Tcp_acknum1 Incoming_ack2 = Tcp_acknum2 Incoming_ack3 = Tcp_acknum3 If Flags.synflag = 1 Then Reset Flags.synflag My_seqnum = Incoming_ack Tempword3 = &H37 Restore Htmlcode Do Read 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) Packet(tempword3) = Asc(tempstring1) Incr Tempword3 Next Y 'End If Loop Tcpdatalen_out = Tempword3 - 55 'minus headerlength ' expect to get an acknowledgment of the message Expected_ack = My_seqnum + Tcpdatalen_out ' send the TCP/IP packet Call Send_tcp_packet End If End If End If ' This code segment processes the incoming SYN from the Tenet client ' and sends back the initial sequence number (ISN) and acknowledges ' the incoming SYN packet If Tcp_syn = 1 Then #if Debug = 1 Print "Tcp_syn = 1" #endif Tcpdatalen_in = 1 Set Flags.synflag Call Setup_packet Swap Tcp_srcportl , Tcp_destportl Swap Tcp_srcporth , Tcp_destporth Call Assemble_ack Call Tcpseqtomyseq Tcp_flags = 0 Set Tcp_flags.1 Set Tcp_flags.4 Call Tcp_checksum Call Echopacket End If If Tcp_fin = 1 Then #if Debug = 1 Print "Tcp_fin = 1" #endif End If If Tcp_psh = 1 Then #if Debug = 1 Print "Tcp_psh = 1" #endif ' walk through the packet until GET / is found For Z = 40 To 255 Ztemp = Z Tempstring2 = Chr(packet(ztemp)) Incr Ztemp Tempstring2 = Tempstring2 + Chr(packet(ztemp)) Incr Ztemp Tempstring2 = Tempstring2 + Chr(packet(ztemp)) Incr Ztemp Tempstring2 = Tempstring2 + Chr(packet(ztemp)) Incr Ztemp Tempstring2 = Tempstring2 + Chr(packet(ztemp)) If Tempstring2 = "GET /" Then Ztemp = Ztemp + 301 Exit For End If #if Debug = 1 Print "/GET gevonden" #endif Next Z 'ztemp > 300 when GET / is found 'ztemp <= 300 when GET / not found 'when found ztemp has the pointer to it (plus 300) If Ztemp > 300 Then Ztemp = Ztemp - 300 If Chr(packet(ztemp)) = "R" Then Incr Ztemp Hulp1 = Val(packet(ztemp)) Select Case Hulp1 Case 1 To 4 : 'Call Relayon(hulp1) Case 5 To 8 : 'Call Relayoff(hulp1) End Select End If End If End If End Sub Sub Tcp_checksum Local Whulp1 As Word Local Whulp2 As Word Local Whulp3 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 Tempword2 = T_ip_vers_len And &H0F Tempword2 = Tempword2 * 4 I_chksum32 = I_chksum32 + Tempword I_chksum32 = I_chksum32 - Tempword2 Whulp2 = Tempword - 20 Whulp2 = Whulp2 + &H23 Whulp2 = Whulp2 - 2 Val1 = &H23 Val2 = Whulp2 I_odd = Val2 - Val1 I_odd = I_odd Mod 2 Call General_part_checksum(val1 , Val2) Tcp_cksumh = Val3 Tcp_cksuml = Val4 End Sub ' Send the TCP-packet, a bit different then echopacket ' Sub Send_tcp_packet Ip_packet_len = 40 + Tcpdatalen_out T_ip_pktlen1 = Low(ip_packet_len) T_ip_pktlen0 = High(ip_packet_len) Call Setup_packet Swap Tcp_srcporth , Tcp_destporth Swap Tcp_srcportl , Tcp_destportl Call Assemble_ack Call Tcpseqtomyseq Tcp_flags = 0 'fin_out Set Tcp_flags.0 ' piggyback FIN onto the page date 'ack_out Set Tcp_flags.4 If Flags.finflag = 1 Then 'fin_out Set Tcp_flags.0 'clr_finflag Reset Flags.finflag End If Call Tcp_checksum Txlen = Ip_packet_len + 14 If Txlen < 60 Then Txlen = 60 End If Call Write_rtl8019as(cr , &H22) Call Write_rtl8019as(tpsr , Txstart) Call Write_rtl8019as(rsar0 , &H00) Call Write_rtl8019as(rsar1 , &H40) Call Write_rtl8019as(isr , &HFF) Hulp1 = Low(txlen) Call Write_rtl8019as(rbcr0 , Hulp1) Hulp1 = High(txlen) Call Write_rtl8019as(rbcr1 , Hulp1) Call Write_rtl8019as(cr , &H12) For I = 1 To Txlen Call Write_rtl8019as(rdmaport , Packet(i)) Next 'make sure the DMA operation has succesfully completed Byte_read = 0 Do Hulp1 = Byte_read And Rdc Call Read_rtl8019as(isr) Loop Until Hulp1 = 0 Hulp1 = Low(txlen) Call Write_rtl8019as(tbcr0 , Hulp1) Hulp1 = High(txlen) Call Write_rtl8019as(tbcr1 , Hulp1) Call Write_rtl8019as(cr , &H24) End Sub Sub Setup_packet '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 'Move hardware source address to destinatin address Call Packetshape Call Ip_header_checksum End Sub Sub Assemble_ack 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 End Sub Sub Tcpseqtomyseq Tcp_seqnum0 = My_seqnum0 Tcp_seqnum1 = My_seqnum1 Tcp_seqnum2 = My_seqnum2 Tcp_seqnum3 = My_seqnum3 End Sub ' Routine to switch on relay X and update status ' Sub Relayon(x) Decr X Relaystatus.x = 1 Call Status End Sub ' Routine to switch off relay X and update status ' Sub Relayoff(x) X = X - 5 Relaystatus.x = 0 Call Status End Sub ' Routine to switch on/off relais and get the status ' Sub Status Databus_ddr = &HFF Databus = Relaystatus Set Latch Reset Latch End Sub ' htmlcode ' Htmlcode: Data "HTTP/1.0 200" , &H0D , &H0A , &H0D , &H0A Data "Ethernet I/O board" Data "" Data "TCP TEST
" Data "

" Data "" Data "

Small tutorial. RTL8019as and Atmega" Data "endblock"