; info : http://www.networksorcery.com/enp/default0602.htm ; : http://www.networkuptime.com/tutorials/arp/ : uitleg ARP ; STATUS : ARP PING HTTP werkt. (Maar niet helemaal conform de regels ;-) ; TODO : - kijken of "call MOVFF_POSTINC1_POSTINC0_2X" op sommige plaatsen niet beter weg kan en ; vervangen worden door 2 gewone movff... ; - Boel grondig opkuisen, nu is alles een echte rommel geworden. ; - ... ; Met dank aan Gerard voor zijn bijdrage aan de broncode van dit programma! ; test lengte bv.: ping -s 1472 192.168.1.99 LIST p = p18f452 #INCLUDE ; - remove ";" below for LCD-routines ; - Verwijder ";" hieronder voor de LCD-routines #define LCD 1 ; - define the IP-address here ; - stel hier het IP adres in #define IP0 D'192' #define IP1 D'168' #define IP2 D'001' #define IP3 D'099' ; - define the MAC-address here ; - stel hier het MAC-adres in #define MAC0 H'3C' #define MAC1 H'50' #define MAC2 H'9B' #define MAC3 H'18' #define MAC4 H'F4' #define MAC5 H'52' ;-) --- Definieer de poorten. #DEFINE RS PORTE, 0 ; RE0 = RS LCD #DEFINE E PORTE, 1 ; RE1 = E LCD #define a0 PORTD,0 ; adres-lijnen 3COM #define a1 PORTD,1 #define a2 PORTD,2 #define a3 PORTD,3 #define a9 PORTD,4 ; ; a19 a18 a17 a16 a15 a14 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 ; 0 0 0 0 0 0 0 0 0 0 x 1 0 0 0 0 y y y y ; ; x = 1 --> 110000yyyy --> 0x300 - 0x30F ; x = 0 --> 010000yyyy --> 0x100 - 0x10F #define ior PORTD,5 #define iow PORTD,7 #define reset PORTD,6 ;-) --- PIC configuratie __CONFIG _CONFIG1H, _OSCS_OFF_1H & _XT_OSC_1H __CONFIG _CONFIG2L, _BOR_OFF_2L & _BORV_20_2L & _PWRT_ON_2L __CONFIG _CONFIG2H, _WDT_OFF_2H __CONFIG _CONFIG4L, _STVR_OFF_4L & _LVP_OFF_4L & _DEBUG_OFF_4L ; __CONFIG _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L & _CP2_OFF_5L & _CP3_OFF_5L ; __CONFIG _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H ; __CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L & _WRT2_OFF_6L & _WRT3_OFF_6L ; __CONFIG _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H ; __CONFIG _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L & _EBTR2_OFF_7L & _EBTR3_OFF_7L ; __CONFIG _CONFIG7H, _EBTRB_OFF_7H ;-) --- Variabelen cblock 0x00 ; Start RAM ; delay ; gebruikt in vertragings-routine en .... delay2 ; .... als hulpvariable Hchecksum ; gebruikt in checksum-routine en .... Lchecksum ; .... als hulpvariable ; seq1 ; sequence-number TCP-packets seq2 seq3 seq4 ; getfileH getfileL ; GET /bestandnaam ; ; ^--------------getfileH:getfileL ; Llow ; Lengte van het pakket + hulp-variabele Lhigh endc IFDEF LCD cblock ; Temp ; Enkel gebruikt in LCD-routine hundreds ; BCD hundreds result tens_and_ones ; BCD tens and ones result bin ; binary number to be converted to BCD ; endc ENDIF cblock ; RAM ; Start van het nog VRIJE RAM geheugen ; Hier niets plaatsen! endc ;-) --- Macro's EStrobe MACRO ; Strobe the "E" Bit bsf E bcf E ENDM INCa0123 MACRO incf PORTD,f ENDM DECa0123 MACRO decf PORTD,f ENDM a0123 MACRO a IF a==H'0' call CLEARa0123 ENDIF IF a==H'1' ERROR "a0123 ERROR" ENDIF IF a==H'2' ERROR "a0123 ERROR" ENDIF IF a==H'3' ERROR "a0123 ERROR" ENDIF IF a==H'4' call CLEARa0123 bsf a2 ENDIF IF a==H'5' ERROR "a0123 ERROR" ENDIF IF a==H'6' ERROR "a0123 ERROR" ENDIF IF a==H'7' ERROR "a0123 ERROR" ENDIF IF a==H'8' call CLEARa0123 bsf a3 ENDIF IF a==H'9' ERROR "a0123 ERROR" ENDIF IF a==H'A' bcf a0 bcf a2 bsf a3 bsf a1 ENDIF IF a==H'B' bsf a0 bcf a2 bsf a3 bsf a1 ENDIF IF a==H'C' ERROR "a0123 ERROR" ENDIF IF a==H'D' ERROR "a0123 ERROR" ENDIF IF a==H'E' call MOVL_E_a0123 ENDIF IF a==H'f' ERROR "a0123 ERROR" ENDIF ENDM ;-) --- Ok, laten we eindelijk eens serieus beginnen. org 0x0000 ; Reset vector goto start org 0x0008 ; Lhigh priority interrupt vector goto $ ; Trap org 0x0018 ; Llow priority interrupt vector goto $ ; Trap ;-) --- Init het LCD-scherm IFDEF LCD initlcd: call wacht40ms bcf RS ; send an 8 bit instruction movlw 0x03 ; Reset Command call NybbleOut ; Send the Nybble call wacht5ms EStrobe call wacht160us EStrobe call wacht160us bcf RS ; send an 8 bit instruction movlw 0x02 ; Set 4 Bit Mode call NybbleOut call wacht160us movlw 0x028 ; 4 bit, 2 Line, 5x7 font call SendINS movlw 0x010 ; display shift off call SendINS movlw 0x006 ; increment cursor call SendINS movlw 0x00C ; display on cursor off call SendINS cls: movlw 0x001 ; Clear the Display RAM call SendINS call wacht5ms return ;-) --- LCD goto lijn goto1: movlw H'80' ; we gaan naar lijn 2 call SendINS Return goto2: movlw H'C0' ; we gaan naar lijn 2 call SendINS Return goto3: movlw H'94' ; we gaan naar lijn 3 call SendINS Return goto4: movlw H'D4' ; we gaan naar lijn 4 call SendINS Return NybbleOut: ; Send a Nybble to the LCD movwf PORTA EStrobe ; Strobe out the LCD Data call wacht160us return SendINS: ; Send the Instruction to the LCD movwf Temp ; Save the Temporary Value swapf Temp, w ; Send the Lhigh Nybble bcf RS ; RS = 0 call NybbleOut movf Temp, w ; Send the Llow Nybble bcf RS call NybbleOut return SendASCII addlw '0' ; Send nbr as ASCII character SendCHAR ; Send the Character to the LCD movwf Temp ; Save the Temporary Value swapf Temp, w ; Send the Lhigh Nybble bsf RS ; RS = 1 call NybbleOut movf Temp, w ; Send the Llow Nybble bsf RS call NybbleOut return DispDec: movwf bin call binary_to_bcd movf hundreds, W call SendASCII swapf tens_and_ones, W andlw H'F' call SendASCII movf tens_and_ones, W andlw H'F' call SendASCII return binary_to_bcd: ; by Scott Dattalo clrf hundreds swapf bin, W addwf bin, W andlw B'00001111' skpndc addlw 0x16 skpndc addlw 0x06 addlw 0x06 skpdc addlw -0x06 btfsc bin,4 addlw 0x16 - 1 + 0x6 skpdc addlw -0x06 btfsc bin,5 addlw 0x30 btfsc bin, 6 addlw 0x60 btfsc bin,7 addlw 0x20 addlw 0x60 rlcf hundreds, f btfss hundreds, 0 addlw -0x60 movwf tens_and_ones btfsc bin,7 incf hundreds, f return ENDIF ;-) --- Delay routines - klokfrekwentie = 4Mhz ; - de 160us routine is berekend via ; - de 250us is hetzelfde als 160us, maar gebruikt 250 klokpulsen ; - de xxx ms routines roepen 4 * de 250us routine aan om aan de ms timing te komen. ; Bij een andere klok dient dus de 160us en 250us aangepast te worden. wacht250us: ;250 cycles movlw 0x53 goto wachtxxxus wacht160us: ; Delay = 160 instruction cycles ; Clock frequency = 4 MHz ; Actual delay = 0.00016 seconds = 160 cycles ; Error = 0 % ;160 cycles movlw 0x35 ; Merk op dat 0x20 ook nog werkt en snellere pings teruggeeft wachtxxxus: movwf delay Delay_0 decfsz delay, f goto Delay_0 return wacht250ms: movlw D'250' goto wachtxxxms wacht5ms: movlw D'5' goto wachtxxxms wacht40ms: movlw D'40' wachtxxxms: movwf delay2 w2: call wacht1ms decfsz delay2, F goto w2 return wacht1ms: call wacht250us call wacht250us call wacht250us call wacht250us return wacht1s: call wacht250ms call wacht250ms call wacht250ms call wacht250ms return ;-) --- Start --------------------------------------------------------------- start: ; --- INIT pic ------------------------------------------------------ ; ; setf ADCON1 ; ; ; clrf INTCON ; ; ; clrf TRISA ; Zet alles op OUTPUT ; clrf TRISB ; clrf TRISC ; clrf TRISD ; clrf TRISE ; ; ; ; ------------------------------------------------------------------- IFDEF LCD call initlcd ENDIF bcf reset bsf reset ; RESET 3COM call wacht1s bcf reset call wacht250ms bsf ior ; Initialisatie bsf iow bcf a9 ; Zet 0x100 op adres-bus : A0, A1, A2, A3, A9 = 0 a0123 0 ; ------------------------------------------------------------------- ; ; ; We gaan nu de PDF volgen op blz 66/67/68 ; ; Schrijf eerst 2 * 0 naar de ISA-kaart om de aandacht te trekken. ; ; ; call ISAout0 ; call ISAout0 ; ; ; ; Schrijf dan een bepaalde 'code' naar de kaart om hem wakker te ; ; maken. ; ; ; setf RAM ; setf RAM+1 ; Seq1: ; movf RAM+1,w ; call ISAout ; bcf STATUS,C ; rlcf RAM+1,f ; bnc Seq2 ; movlw 0xcf ; xorwf RAM+1,f ; Seq2: ; decfsz RAM,f ; goto Seq1 ; ; ; ; ------------------------------------------------------------------- IFDEF LCD call goto1 movlw D'000' call DispDec call wacht1s ENDIF ; ------------------------------------------------------------------- ; ; ; Nu de kaart wakker is, lees voldoende gegevens om hem wakker te ; ; houden. En nu we toch bezig zijn, kunnen we hier dus ineens ; ; nuttige informatie opvragen. ; ; ; ; We lezen van 0x87 en 0x98 en gaan na of we 0x6D50 binnenkrijgen. ; ; Indien niet dan is er iets mis. Kaart niet aanwezig, draadbreuk, ; ; geen 3COM ISA-kaart, ... ; ; ; movlw H'87' ; Start met 0x87 ; ee1: ; movwf RAM+3 ; Om straks te weten of we H'87' ... ; rcall ISAout ; ... of H'98' hebben gedaan. ; clrf Llow ; clrf Lhigh ; movlw D'16' ; Lees gegevens uit de EEprom. ; ; ; De gevens worden bit per bit doorgestuurd ; ; ; 16 keer lezen en tot een 'woord' ... ; ; ; ... samenvoegen. ; movwf RAM+1 ; ee2: ; rcall ISAin ; movwf RAM+4 ; zet ingelezen waarde op RAM+4 ; rrcf RAM+4,w ; C = bit0 van RAM+4 ; rlcf Llow,f ; schuif 1 plaatsje naar links op met C ; rlcf Lhigh,f ; decfsz RAM+1,f ; alle 16bits gedaan? ; bra ee2 ; nee, doe dan voort ; ; ; movlw H'6D' ; vergelijk met 6D50 ; cpfseq Lhigh ; bra start ; movlw H'50' ; cpfseq Llow ; bra start ; geen 6D50, ga terug naar start... ; ; ; movlw H'98' ; Herhaal nogmaals met 0x98 ; cpfseq RAM+3 ; bra ee1 ; ; ; ; ------------------------------------------------------------------- IFDEF LCD call goto1 movlw D'001' call DispDec call wacht1s ENDIF ; ------------------------------------------------------------------- ; ; ; Nu de kaart wakker is, moeten we hem nog aktief maken. ; ; ; movlw 0xf0 ; activate adapter IO = 0x300 ; call ISAout ; ; ; ; ------------------------------------------------------------------- ; ------------------------------------------------------------------- ; ; ; Nu de kaart aktief is kunnen we adreslijn A9 hoog maken zodat we ; ; via IO 0x300 kunnen kommuniceren. ; ; ; bsf a9 ; ; ; ; ------------------------------------------------------------------- ;-) --- ; OK, zover zijn we al. Voor het verdere verloop raadplegen we de ; PDF A-3 : Driver Routine Flowchart ; ------------------------------------------------------------------- ; ; ; We moeten de kaart nu eerst nog enablen voordat we hem echt ; ; kunnen gaan gebruiken. ; ; ; a0123 4 ; Configuration Control Register ... ; ; ; ... (Read/Write - Offset 4) ; movlw B'00000001' ; call ISAout ; Schrijf een 1 naar dit register ENA --> 1 ; ; ; adapter is nu ge-enabled ; INCa0123 ; adres + 1 (WORD) ; call ISAout0 ; ; ; ; ------------------------------------------------------------------- TXreset: ; ------------------------------------------------------------------- ; ; ; Reset transmitter door naar het Command register (offset 0e) ; ; het tx-reset commando te sturen (zie pdf blz 38) ; ; ; a0123 H'E' ; call ISAout0 ; INCa0123 ; movlw B'01011000' ; call ISAout ; ; ; ; ------------------------------------------------------------------- ; ------------------------------------------------------------------- ; ; ; Reset receiver door naar het Command register (offset 0e) het ; ; rx-reset commando te sturen (zie pdf blz 37) ; ; ; DECa0123 ; call ISAout0 ; INCa0123 ; movlw B'00101000' ; call ISAout ; ; ; ; ------------------------------------------------------------------- ; ------------------------------------------------------------------- ; ; ; rx-filter instellen : zie pdf blz 41 ; ; ; DECa0123 ; movlw B'00000101' ; 0001 Individual address ; ; ; 0010 Group (multicast) addresses ; ; ; 0100 Broadcast address ; ; ; 1000 All addresses (promiscuous mode) ; call ISAout ; INCa0123 ; movlw B'10000000' ; call ISAout ; ; ; ; ------------------------------------------------------------------- ; ------------------------------------------------------------------- ; ; ; Nu moeten we het MAC-adres nog instellen. ; ; naar WINDOW 2 , zie blz 28 pdf ; ; ; ; Kies eerst WINDOW 2 (zie pdf blz 36) ; ; ; DECa0123 ; movlw 0x02 ; call ISAout ; INCa0123 ; movlw 0x08 ; call ISAout ; ; ; ; Nu we in WINDOW2 zitten kunnen we het MAC-adres schrijven. ; ; ; a0123 0 ; movlw MAC0 ; call ISAout ; INCa0123 ; movlw MAC1 ; call ISAout ; INCa0123 ; movlw MAC2 ; call ISAout ; INCa0123 ; movlw MAC3 ; call ISAout ; INCa0123 ; movlw MAC4 ; call ISAout ; INCa0123 ; movlw MAC5 ; call ISAout ; ; ; ; ------------------------------------------------------------------- ; ------------------------------------------------------------------- ; ; ; We gaan 10BASE-T gebruiken, dus moeten we nu : ; ; ; ; Set Link Beat and Jabber enable bits ; ; in Media Type and Status register ; ; Stop transceiver ; ; ; ; Hiervoor zijn we in Window 4 nodig ; ; ; ; Kies eerst WINDOW 4 ; ; ; a0123 H'E' ; movlw 0x04 ; call ISAout ; INCa0123 ; movlw 0x08 ; call ISAout ; ; ; ; Set Link Beat and Jabber enable bits ; ; zie pdf blz 58 ; ; Bit 7 1 = Link beat enabled (writable). Defaults to 0 ; ; (disabled). Must be set by software only if the ; ; internal TP transceiver is in use. Link beat must be ; ; disabled in ENDEC loopback mode. ; ; Bit 6 1 = Jabber enabled (writable). Defaults to 0 (disabled). ; ; Must be set by software only if the internal TP ; ; transceiver is in use. This also enables the Polarity ; ; Reversal state machine. ; ; ; a0123 H'A' ; movlw B'11000000' ; call ISAout ; INCa0123 ; call ISAout0 ; ; ; ; ------------------------------------------------------------------- ; ------------------------------------------------------------------- ; ; ; Nu moeten we rx_enable en tx_enable uitvoeren. ; ; zie pdf blz. blz 36 en 38 ; ; ; a0123 H'E' ; call ISAout0 ; INCa0123 ; movlw 0x20 ; call ISAout ; DECa0123 ; call ISAout0 ; INCa0123 ; movlw 0x48 ; call ISAout ; ; ; ; Kies Window 1 ; ; ; DECa0123 ; movlw 0x01 ; call ISAout ; INCa0123 ; movlw 0x08 ; call ISAout ; ; ; ; ------------------------------------------------------------------- ;-) --- ; OK, de kaart is nu ingesteld. Nu gaan we over naar de lus waarin ; we pakketjes gaan ontvangen, analyseren en versturen. De_Lus: ; Vraag de TX Status op (PDF blz 50) a0123 H'0b' rcall ISAin ; w = TXstatus ; Bit 7 Complete (1 = TX is complete) ; Bit 6 Interrupt on Successful Transmission Completion Requested ; Bit 5 Jabber Error (TP only: TX Reset required) ; Bit 4 Underrun --> Network TX Reset and FIFO TX Reset required ; Bit 3 Maximum Collisions ; Bit 2 TX Status Overflow ; Bit 1 Undefined ; Bit 0 Undefined andlw B'00111000' ; Hou enkel rekening met deze bits iorlw D'0' btfsc STATUS, Z bra TXstatusOK ; TXstatus = 0 --> OK, ga verder bra TXreset TXstatusOK: ; ------------------------------------------------------------------- ; ; ; Vraag de RX Status op (PDF blz 48) ; a0123 8 ; rcall ISAin ; movwf Llow ; INCa0123 ; rcall ISAin ; movwf Lhigh ; ; ; btfsc Lhigh,7 ; Bit 15 hoog --> geen of onvolledig pakket ; bra De_Lus ; --> geen pakket -> lus ; btfsc Lhigh,6 ; Bit 14 hoog --> fouten in pakket! ; goto weg_ermee ; movlw B'00000111' ; andwf Lhigh, f ; Bit 10...0 = Lengte van pakket ; ; ; ; ------------------------------------------------------------------- ; Er staat een geldig pakket klaar! Doe er nu iets mee. ; ------------------------------------------------------------------- ; ; ; We gaan nu het pakket inlezen en in het RAM-geheugen plaatsen. ; ; ; lfsr 1, RAM ; Start RAM geheugen dat we gaan gebruiken ; ; ; movff Lhigh, FSR2H ; movff Llow, FSR2L ; gebruik FSR2L en FSR2H als teller ; ; ; Lees: ; a0123 0 ; rcall ISAin ; movwf POSTINC1 ; ; ; movf POSTDEC2, f ; teller FSR2H:FSR2L -1 ; tstfsz FSR2L ; bra Lees ; tstfsz FSR2H ; bra Lees ; Blijf lezen tot teller = 0 ; ; ; ; ------------------------------------------------------------------- ; Het pakket zit nu in het RAM-geheugen. ; We onderzoeken nu de ethernet-header | ; ----------------------------------------+ ; Byte 0 ... 5 : Destination MAC Address | ; Byte 6 ... B : Source MAC Address | ; Byte C D : Type | ; ----------------------------------------+ #define ETH_MAC_to RAM + H'0' #define ETH_MAC_from RAM + H'6' #define ETH_type RAM + H'C' ; ------------------------------------------------------------------- ; ; lfsr 1, ETH_type ; C = Type ; ; ; IFDEF LCD ; call cls ; call goto1 ; movf INDF1, w ; call DispDec ; ENDIF ; ; ; movlw D'008' ; cpfseq POSTINC1 ; Vergelijk met RAM (FSR1H FSR1L) ... ; bra weg_ermee ; ... en verhoog adres met 1 ; ; ; IFDEF LCD ; movf INDF1, w ; call DispDec ; ENDIF ; ; ; ; Type moet met 008 beginnen, anders is het geen geldig pakket. ; ; ; ; Als Type = 008 006 dan wil dit zeggen dat na de ethernet-header ; ; er een ARP-header volgt. ; movlw D'000' ; cpfsgt INDF1 ; bra IP ; Als Type = 008 000 dan gaat het om IP ; ; ; movlw D'006' ; cpfseq INDF1 ; Vergelijk met RAM (FSR1H FSR1L) ; bra weg_ermee ; Als Type 008 006 is, dan gaat het om ARP ; bra ARP ; Stuur een gepast ARP-reply terug ; ; ; ; ------------------------------------------------------------------- IP: ; IP-Header | Voorbeeld | Bytes | Offset t.o.v. RAM | ; ----------------------+-------------------------+---------+-------------------+ ; version/headerlength | 0100(*) 0101 | 1 | 0E | ; type of service | 000 | 1 | 0F | ; Total length: | 000 084 | 2 | 10 | ; Indentification: | 000 000 | 2 | 12 | ; 3-bit flags + | | | | ; 13-bit fragm.offset | | 2 | 14 | ; time to live TTL | 064 | 1 | 16 | ; protocol | 1 = ICMP | 1 | 17 | ; checksum | | 2 | 18 | ; Source IP address: | 192.168.2.2 | 4 | 1a | ; Destinati IP address: | 192.168.2.11 | 4 | 1e | ; options/data | | | | ; ----------------------+-------------------------+---------+-------------------+ ; (*) version = 4 = IP, Internet Protocol. #define IP_start RAM + H'0E' #define IP_id RAM + H'12' #define IP_protocol RAM + H'17' #define IP_from RAM + H'1A' #define IP_to RAM + H'1E' #define IP_checksum RAM + H'18' #define IP_length RAM + H'10' IFDEF LCD call goto3 lfsr 1, IP_from movf POSTINC1, w call DispDec movlw "." call SendCHAR movf POSTINC1, w call DispDec movlw "." call SendCHAR movf POSTINC1, w call DispDec movlw "." call SendCHAR movf POSTINC1, w call DispDec call goto2 movf POSTINC1, w call DispDec movlw "." call SendCHAR movf POSTINC1, w call DispDec movlw "." call SendCHAR movf POSTINC1, w call DispDec movlw "." call SendCHAR movf POSTINC1, w call DispDec ENDIF lfsr 1, IP_protocol movlw D'1' cpfseq INDF1 ; Vergelijk met RAM (FSR1H FSR1L) bra geenICMP bra ICMP ; Als protocol = 1, dan gaat het om ICMP geenICMP: movlw D'6' cpfseq INDF1 bra weg_ermee ; Als protocol = 6, dan gaat het om TCP TCP: ; TCP afhandelen ; TCP-Header | Voorbeeld | Bytes | Offset t.o.v. RAM | ; ----------------------+-------------------------+---------+-------------------+ ; Source Port | | 2 | 22 | ; Destination Port | | 2 | 24 | ; Sequence Number | | 4 | 26 | ; Acknowledgment Number | | 4 | 2A | ; Data Offset | | 1 | 2E | ; ECN + Control Bits | | 1 | 2F | ; Window | | 2 | 30 | ; checksum | | 2 | 32 | ; Urgent Pointer | | 4 | 34 | ; Options and padding | | 0...44 | 38 | ; Data | | | | ; ----------------------+-------------------------+---------+-------------------+ #define TCP_start RAM + H'22' #define TCP_from RAM + H'22' #define TCP_to RAM + H'24' #define TCP_control RAM + H'2F' #define TCP_checksum RAM + H'32' #define TCP_seqnum RAM + H'26' #define TCP_acknum RAM + H'2A' #define TCP_data_offset RAM + H'2E' ; TODO ; ; Control bits testen : ; - als enkel SYN = 1 dan reply op deze SYN versturen. ; | ; +--> = SYN + ACK versturen ; - als enkel ACK = 1 dan .... ? movlw D'000' cpfseq TCP_to bra weg_ermee movlw D'080' ; PORT 80 www? cpfseq TCP_to+1 bra weg_ermee ; alles wat niet PORT 80 is negeren. btfss TCP_control, D'0' ; Is FIN-bit = 1 bra FIN0 FIN1: ; Wissel Source en Desti.ports om : lfsr 0, delay ; delay + delay2 ff als hulpvar gebruiken. lfsr 1, TCP_to call MOVFF_POSTINC1_POSTINC0_2X ; delay, delay2 = to lfsr 1, TCP_from lfsr 0, TCP_to call MOVFF_POSTINC1_POSTINC0_2X ; TCP_to = from lfsr 1, delay lfsr 0, TCP_from call MOVFF_POSTINC1_POSTINC0_2X ; TCP_from = to ; OK, Source en Desti.ports zijn omgewisseld. ; normaal moeten we nu testen of dat de HTTP-port wordt aangesproken. ; voor lopig vergeten ; ZET ACK-Flag bsf TCP_control, D'4' ; CLEAR de FIN-Flag bcf TCP_control, D'0' bra SYNFIN ; Spring naar SYN-gedeelte dat ook ; bruikbaar is voor FIN-routine. Dit is slordig, later een mooiere oplossing ; zoeken FIN0: btfss TCP_control, D'1' ; Is SYN-bit = 1 bra SYNis0 SYN1: ; Een nieuw seq-nummer gebruiken. We verhogen het seq-nummer telkens ; met 1 zodat we steeds een uniek nummer hebben. Normaal zou hier een ; RANDOM-nummer gebruikt moeten worden. incf seq4, f movlw D'000' addwfc seq3,f addwfc seq2,f addwfc seq1,f ; Wissel Source en Desti.ports om : lfsr 0, delay ; delay + delay2 ff als hulpvar gebruiken. lfsr 1, TCP_to call MOVFF_POSTINC1_POSTINC0_2X ; delay, delay2 = to lfsr 1, TCP_from lfsr 0, TCP_to call MOVFF_POSTINC1_POSTINC0_2X ; TCP_to = from lfsr 1, delay lfsr 0, TCP_from call MOVFF_POSTINC1_POSTINC0_2X ; TCP_from = to ; OK, Source en Desti.ports zijn omgewisseld. ; normaal moeten we nu testen of dat de HTTP-port wordt aangesproken. ; voor lopig vergeten ; ZET ACK-Flag bsf TCP_control, D'4' SYNFIN: ; We moeten het ack-nummer nog mee sturen. ; ack-nummer = seqnummer + 1 lfsr 1, TCP_seqnum ; TCP_seqnum --> TCP_acknum lfsr 0, TCP_acknum call MOVFF_POSTINC1_POSTINC0_4X incf TCP_acknum+3,f ; TCP_acknum = TCP_acknum + 1 movlw D'000' addwfc TCP_acknum+2,f addwfc TCP_acknum+1,f addwfc TCP_acknum,f ; En gebruik een nieuw SEQ-nummer lfsr 1, seq1 lfsr 0, TCP_seqnum call MOVFF_POSTINC1_POSTINC0_4X ; En kopieer nieuw seq-nummer ; En we moeten in de ip-header het id op nul zetten. clrf IP_id clrf IP_id+1 call ip_set_to_from ; Zet From To in IP-header goed ; Geen options versturen, timestamp e.d. gebruiken wij niet! movlw B'00001111' andwf TCP_data_offset, f ; 4 hoogste bits = TCP_data_offset : reset movlw B'01010000' iorwf TCP_data_offset, f ; TCP_data_offset = 5 (5 32bitswords = 20 bytes) ; Lengte pakket naar 54 brengen (Ethernet-header 14 + tcp-header 40) movlw D'00' movwf Lhigh movwf IP_length movlw D'54' movwf Llow movlw D'40' ; IP-lengte = 40 (lengte zonder Ethernet-header (14)) movwf IP_length+1 ; call TCPIP_checksum ; checksums berekenen bra verzenden ; alles klaar, versturen... SYNis0: btfss TCP_control, D'4' ; Is ACK-bit = 1 bra weg_ermee ACK1: ; Zet de ACK en FIN bit ; Door FIN te zetten zeggen we ineens ; dat de verbinding verbroken moet ; worden. Dit werkt dus enkel als de ; data die verstuurd moet worden niet ; al te groot is! bsf TCP_control, D'4' bsf TCP_control, D'0' bcf TCP_control, D'1' bcf TCP_control, D'2' bcf TCP_control, D'3' ; bsf TCP_control, D'3' ; Zet PUSH flag bcf TCP_control, D'5' ; ACK en FIN vlag zijn gezet, al de rest is clear ; nu gaan we testen of dit packet wel data bevatte. movlw D'000' cpfseq IP_length bra With_Data movlw D'040' cpfseq IP_length+1 bra With_Data bra weg_ermee With_Data: ; Was het een GET aanvraag? ; TCP_data_offset bevat de lengte van de TCP-Header. ; Hiermee kunnen we dus ontdekken waar de DATA zich bevind. swapf TCP_data_offset, w ; de hoogste 4 bits zijn van tel andlw B'00001111' mullw 4 ; PRODH:PRODL bevat nu de lengte in bytes lfsr 2, TCP_start movf PRODL, w addwf FSR2L, f movf PRODH, w addwfc FSR2H, f ; FSRH:FSRL = TCP_start + header-lengte ; Vergelijk FSR2H:FSR2L met "GET /", smijt het pakket weg als het geen GET is. movlw LOW (GET) movwf TBLPTRL movlw HIGH (GET) movwf TBLPTRH movlw UPPER (GET) movwf TBLPTRU ; TBLPTR --> "GET /" g1: tblrd*+ ; Lees van adres TBLPTR in TABLAT / TBLPTR++ movf TABLAT, w ; w = het ingelezen karakter iorlw D'0' ; End Of Text? ASCII 0 btfsc STATUS, Z ; Als ASCII 0 dan ... bra g2 ; ... stop. cpfseq POSTINC2 bra weg_ermee ; Geen "GET /" --> weg ermee bra g1 g2: movlw " " cpfseq INDF2 ; Gaat het om "GET / "? bra g3 ; Als het gaat om "GET / " moeten we zorgen dat index.html getoond wordt movlw LOW (index) movwf TBLPTRL movlw HIGH (index) movwf TBLPTRH movlw UPPER (index) movwf TBLPTRU ; TBLPTR --> "index.html" index1: tblrd*+ ; "GET / " --> "GET /index.html " movf TABLAT, w iorlw D'0' btfsc STATUS, Z bra With_Data movwf POSTINC2 bra index1 g3: movff FSR2H, getfileH movff FSR2L, getfileL ; getfileH:getfileL --> filename ; Wissel Source en Desti.ports om : lfsr 0, delay ; delay + delay2 ff als hulpvar gebruiken. lfsr 1, TCP_to call MOVFF_POSTINC1_POSTINC0_2X ; delay, delay2 = to lfsr 1, TCP_from lfsr 0, TCP_to call MOVFF_POSTINC1_POSTINC0_2X ; TCP_to = from lfsr 1, delay lfsr 0, TCP_from call MOVFF_POSTINC1_POSTINC0_2X ; TCP_from = to ; OK, Source en Desti.ports zijn omgewisseld. ; We moeten het ack-nummer nog mee sturen. ; ack-nummer = seqnummer + TCP-lengte van ontvangen pakket lfsr 1, TCP_seqnum ; TCP_seqnum --> delay lfsr 0, delay call MOVFF_POSTINC1_POSTINC0_4X ; O ja, het Seq-nummer van dit pakket is het oude ack-nummer. lfsr 0, TCP_seqnum ; TCP_acknum --> TCP_seqnum lfsr 1, TCP_acknum call MOVFF_POSTINC1_POSTINC0_4X ; ga verder met aanpassen acknum lfsr 1, delay ; delay (orig TCP_seqnum) --> TCP_acknum lfsr 0, TCP_acknum call MOVFF_POSTINC1_POSTINC0_4X movff IP_length, delay ; High movff IP_length+1, delay+1 ; Low movlw D'40' bsf STATUS, C subwfb delay+1, f movlw D'0' subwfb delay, f ; IP-lengte - 40 = TCP-lengte (meestal toch ;-) movf delay+1,w addwf TCP_acknum+3,f ; TCP_acknum = TCP_acknum + TCP-lengte movf delay,w addwfc TCP_acknum+2,f movlw D'000' ; Carry's er bij-tellen addwfc TCP_acknum+1,f addwfc TCP_acknum,f IFDEF LCD call cls call goto1 lfsr 1, delay movf POSTINC1, w call DispDec movf POSTINC1, w call DispDec ENDIF ; Dataveld aanpassen : Webpagina in dataveld plaatsen lfsr 1, TCP_start + D'20' ; TCP-header = 20 movlw B'00001111' andwf TCP_data_offset, f ; 4 hoogste bits = TCP_data_offset : reset movlw B'01010000' iorwf TCP_data_offset, f ; TCP_data_offset = 5 (5 32bitswords = 20 bytes) ; Pseudo file system routine movlw LOW (web) movwf TBLPTRL movlw HIGH (web) movwf TBLPTRH movlw UPPER (web) movwf TBLPTRU ; TBLPTR --> web searchfile: movff getfileH, FSR2H movff getfileL, FSR2L tblrd*+ movff TABLAT, delay ; delay = lengte string tstfsz delay ; is delay = 0? bra search e404: ; Bestand niet gevonden, geef een 404 fout movlw LOW (htmlerr) movwf delay movlw HIGH (htmlerr) movwf delay2 movlw UPPER (htmlerr) movwf Hchecksum ; HTML error 404 movlw LOW (err) movwf TBLPTRL movlw HIGH (err) movwf TBLPTRH movlw UPPER (err) movwf TBLPTRU ; TBLPTR --> error bra header_lus search: tblrd*+ movf TABLAT, w cpfseq POSTINC2 bra next decfsz delay, f bra search movlw " " cpfseq POSTINC2 ; test of er na de bestandsnaam een spatie komt, ; om te vermijden dat bv. index.htmlblabla ; index.html zou weergeven. bra incnext bra gevonden incnext: incf delay, f ; Terug bijtellen wat er reeds afgetrokken was next: decf delay, w addwf TBLPTRL, f movlw D'0' addwfc TBLPTRH, f ; Tel het aantal niet gelezen chars bij TBLPTR movff TBLPTRL, delay movff TBLPTRH, delay2 tblrd*+ movf TABLAT, w addwf delay, f tblrd*+ movf TABLAT, w addwfc delay2, f movff delay, TBLPTRL movff delay2, TBLPTRH tblrd*+ tblrd*+ ; SKIP dit bestand en ga klaar staan op de volgende bestandsnaam bra searchfile gevonden: movff TBLPTRL, delay ; TBLPTR wijst naar inhoud 'bestand' , onthouden movff TBLPTRH, delay2 movff TBLPTRU, Hchecksum ; Plaats eerst de HTML-header in het geheugen movlw LOW (header) movwf TBLPTRL movlw HIGH (header) movwf TBLPTRH movlw UPPER (header) movwf TBLPTRU ; TBLPTR --> header header_lus tblrd*+ ; Lees van adres TBLPTR in TABLAT / TBLPTR++ movf TABLAT, w ; w = het ingelezen karakter iorlw D'0' ; End Of Text? ASCII 0 btfsc STATUS, Z ; Als ASCII 0 dan ... bra header_OK ; ... stop. movwf POSTINC1 ; kopieer karakter naar TCP_DATA / FSR1++ bra header_lus header_OK: movff delay, TBLPTRL ; Terughalen TBLPTR = inhoud 'bestand' movff delay2, TBLPTRH movff Hchecksum, TBLPTRU tblrd*+ movff TABLAT, delay tblrd*+ movff TABLAT, delay2 ; delay2:delay = lengte van de inhoud 'bestand' t1: tblrd*+ ; Lees van adres TBLPTR in TABLAT / TBLPTR++ movff TABLAT, POSTINC1 decfsz delay, f bra t1 tstfsz delay2 ; is delay2 = 0? bra t2 bra t3 ; Alle karakters zijn gekopieerd. t2: decf delay2, f bra t1 t3: clrf INDF1 ; Afsluiten met een 0, nodig indien het gaat om een ; oneven aantal bytes die verstuurd worden. ; zie : (*TCP_cheksum padding) in "call TCPIP_checksum" ; FSR1H:FSR1L = einde data lfsr 2, TCP_start + D'20' ; Wij versturen altijd een TCP-header van 20 bytes. movf FSR2L, w bsf STATUS, C subwfb FSR1L, f movf FSR2H, w subwfb FSR1H, f ; FSR1H:FSR1L = Lengte van de data. movlw D'40' addwf FSR1L, f movlw D'00' addwfc FSR1H, f ; FSR1H:FSR1L = Lengte data + 40 (TCP/IP-Header) movff FSR1H, IP_length movff FSR1L, IP_length+1 movlw D'14' addwf FSR1L, f movlw D'00' addwfc FSR1H, f ; FSR1H:FSR1L = Lengte data + 40 (TCP/IP-Header) + 14 (Ethernet-Header) movff FSR1H, Lhigh movff FSR1L, Llow call ip_set_to_from ; Zet From To in IP-header goed call TCPIP_checksum ; checksums berekenen bra verzenden ; alles klaar, versturen... ICMP: ; ICMP afhandelen ; ICMP-Header Bytes Offset RAM ; ; Type 1 22 ; Code 1 23 ; Checksum 2 24 ; #define ICMP_type RAM + H'22' #define ICMP_checksum RAM + H'24' lfsr 1, ICMP_type movlw D'8' cpfseq INDF1 ; Vergelijk met RAM (FSR1H FSR1L) bra weg_ermee ; Als type = 8, dan gaat het om een ECHO-request ECHO: ; ECHO afhandelen ; bsf LED1 ; ICMP echo lfsr 1, ICMP_type clrf POSTINC1 ; Type = 0 = Echo Reply call ip_set_to_from ; Zet From To in IP-header goed ; checksum herberekenen, nou ja, doe er gewoon 8 bij op ; ; Dank aan Gerard voor dit stukje code! :-) ; movlw 8 addwf ICMP_checksum,F btfsc STATUS,C incf ICMP_checksum + 1,F ; checksum_hi btfsc STATUS,Z incf ICMP_checksum,F bra verzenden ; en ECHO terugsturen ARP: ; We hebben dus een ARP-pakket ontvangen. ; ; Als uit het IP-adres blijkt dat dit pakket voor ons bedoeld ; was, dienen we dus een ARP-Reply te versturen om de PC die het ; ARP-pakketje verstuurde te vertellen welk HWadres we hebben. ; ARP-Header | Voorbeeld | Bytes | Offset t.o.v. RAM | ; ----------------------+-------------------------+---------+-------------------+ ; Hardware type: | 0x1 (Ethernet) | 2 | 0E | ; Protocol type: | 0x800 (IP) | 2 | 10 | ; Hardware length: | 6 | 1 | 12 | ; Protocol length: | 4 | 1 | 13 | ; Opcode: | 1 (request) 2 (reply) | 2 | 14 | ; Sender Ether address: | 07:00:00:00:00:00 | 6 | 16 | ; Sender IP address: | 192.168.2.1 | 4 | 1C | ; Target Ether address: | 00:00:00:00:00:00 | 6 | 20 | ; Target IP address: | 192.168.2.2 | 4 | 26 | ; ----------------------+-------------------------+---------+-------------------+ #define ARP_opcode RAM + H'14' #define ARP_MAC_from RAM + H'16' #define ARP_IP_from RAM + H'1C' #define ARP_MAC_to RAM + H'20' #define ARP_IP_to RAM + H'26' IFDEF LCD call goto3 lfsr 1, ARP_IP_from movf POSTINC1, w call DispDec movlw "." call SendCHAR movf POSTINC1, w call DispDec movlw "." call SendCHAR movf POSTINC1, w call DispDec movlw "." call SendCHAR movf POSTINC1, w call DispDec call goto2 lfsr 1, ARP_IP_to movf POSTINC1, w call DispDec movlw "." call SendCHAR movf POSTINC1, w call DispDec movlw "." call SendCHAR movf POSTINC1, w call DispDec movlw "." call SendCHAR movf POSTINC1, w call DispDec ENDIF lfsr 1, ARP_opcode ; Wat geeft Opcode ? movlw D'0' cpfseq POSTINC1 bra weg_ermee movlw D'1' cpfseq POSTINC1 bra weg_ermee ; 00 01 = Request : Smijt pakket weg als het ; iets anders is. ; Komt het "Target IP address" overeen met het ingestelde adres? lfsr 1, ARP_IP_to movlw IP0 cpfseq POSTINC1 bra weg_ermee movlw IP1 cpfseq POSTINC1 bra weg_ermee movlw IP2 cpfseq POSTINC1 ; Smijt alles wat geen juist bestemmings- bra weg_ermee ; IP-adres heeft weg movlw IP3 cpfseq POSTINC1 bra weg_ermee ; Ok, nu we weten dat dit pakket voor ons was bestemd, kunnen we ; een antwoord terugsturen. Dit terugsturen doen we door de ; ontvangen header aan te passen en dan te verzenden. ; Pas Opcode ARP aan lfsr 1, ARP_opcode clrf POSTINC1 movlw D'2' movwf POSTINC1 ; 00 02 = Reply ; Sender Ether address --> Target Ether address ; Opm FSR1H:FSR1L staat reeds goed voor Sender Ether address lfsr 0, ARP_MAC_to call MOVFF_POSTINC1_POSTINC0_6X ; Sender IP address --> Target IP address call MOVFF_POSTINC1_POSTINC0_4X ; Steek het MAC-adres in Sender Ether Address lfsr 0, ARP_MAC_from call MOV_MAC_POSTINC0 ; Steek het IP-adres in Sender IP Address ; Opm FSR0H:FSR0L staat reeds goed voor Target IP address call MOV_IP_POSTINC0 ; Niet alleen de ARP-header moeten we aanpassen, maar ook de ; Ethernetheader lfsr 0, ETH_MAC_to lfsr 1, ETH_MAC_from call MOVFF_POSTINC1_POSTINC0_6X call MOV_MAC_POSTINC0 ; Lengte van pakket instellen op 42. ; Waarom 42? ; Ethernet-header = 6 + 6 + 2 bytes (Source MAC + Destination MAC + type) ; ARP-header = 2 + 2 + 1 + 1 + 2 + 6 + 4 + 6 + 4 ( zie boven ) ; + -------------------------------------------------------------------- ; = 42 bytes movlw D'42' movwf Llow clrf Lhigh verzenden: call verzend weg_ermee: ; Smijt een ontvangen pakket weg en keer terug naar begin van lus a0123 H'E' rcall ISAout0 INCa0123 movlw 0x40 rcall ISAout goto De_Lus ;-) --- ; De subroutines i.v.m. ethernet. ISAout0: movlw 0 ; ISAout waarbij w = 0 ISAout: ; Schrijf een byte naar de ISA-kaart : ; PORT B staat standaard op OUTPUT movwf PORTB bcf iow rcall wacht160us bsf iow return ISAin: ; Lees een byte van de ISA-kaart : ; Zet PORT B eerst op INPUT setf TRISB bcf ior rcall wacht160us movf PORTB, w bsf ior ; Zet PORT B terug op OUTPUT clrf TRISB return CLEARa0123: ; Zet a0,a1,a2,a3 naar 0 ; ; a0 = PORTD,0 ; a1 = PORTD,1 ; a2 = PORTD,2 ; a3 = PORTD,3 ; movlw B'11110000' andwf PORTD, f return MOVL_E_a0123: ; Zet a0,a1,a2,a3 naar 0x0E ; movlw B'00001111' iorwf PORTD, f bcf a0 return verzend: a0123 0 movf Llow, w ; Pakket-lengte rcall ISAout movf Lhigh, w rcall ISAout rcall ISAout0 rcall ISAout0 lfsr 1, RAM ; Start RAM geheugen dat we gebruiken movff Lhigh, FSR2H movff Llow, FSR2L ; gebruik FSR2L en FSR2H als teller Schrijf: movf POSTINC1, W rcall ISAout movf POSTDEC2, f ; teller FSR2H:FSR2L -1 tstfsz FSR2L bra Schrijf tstfsz FSR2H bra Schrijf ; Blijf schrijven tot teller = 0 ; versturen van padding data pad: movlw B'00000011' andwf Llow, w bnz Schrijf_pad return Schrijf_pad: rcall ISAout0 incf Llow, f bra pad MOV_MAC_POSTINC0: movlw MAC0 movwf POSTINC0 movlw MAC1 movwf POSTINC0 movlw MAC2 movwf POSTINC0 movlw MAC3 movwf POSTINC0 movlw MAC4 movwf POSTINC0 movlw MAC5 movwf POSTINC0 return MOV_IP_POSTINC0: movlw IP0 movwf POSTINC0 movlw IP1 movwf POSTINC0 movlw IP2 movwf POSTINC0 movlw IP3 movwf POSTINC0 return MOVFF_POSTINC1_POSTINC0_6X: movff POSTINC1, POSTINC0 movff POSTINC1, POSTINC0 MOVFF_POSTINC1_POSTINC0_4X: movff POSTINC1, POSTINC0 movff POSTINC1, POSTINC0 MOVFF_POSTINC1_POSTINC0_2X: movff POSTINC1, POSTINC0 movff POSTINC1, POSTINC0 return ip_set_to_from: lfsr 0, ETH_MAC_to lfsr 1, ETH_MAC_from rcall MOVFF_POSTINC1_POSTINC0_6X rcall MOV_MAC_POSTINC0 lfsr 0, IP_to lfsr 1, IP_from rcall MOVFF_POSTINC1_POSTINC0_4X ; Steek ons IP in Source IP lfsr 0, IP_from rcall MOV_IP_POSTINC0 return Checksum: ; ------------------------------------------------------------------- ; Berekenen van "16-bit one's complement of the one's complement sum" ; Voor het aanroep, zet : ; ----------------------- ; FSR2H:FSR2l = lengte in bytes ; clear old checksum ; lfsr 1 = START RAM ; clrf Hchecksum, Lchecksum indien nodig ; Na de aanroep, bevat : ; ---------------------- ; Hchecksum,Lchecksum = checksum waarop comf nog moet worden ; uitgevoerd. ; ------------------------------------------------------------------- bcf STATUS, C ; Lengte is uitgedrukt in bytes, maar... rrcf FSR2H, f ; ...het berekenen van de checksum gaat... rrcf FSR2L, f ; per 16Bits, dus lengte/2 bcf STATUS, C ; reset C-flag CLus: movf POSTINC1, w addwfc Hchecksum, f movf POSTINC1, w addwfc Lchecksum, f movf POSTDEC2, w ; teller FSR2H:FSR2L -1 tstfsz FSR2L bra CLus tstfsz FSR2H bra CLus ; Blijf rekenen tot teller = 0 movlw D'000' addwfc Hchecksum, f ; Tel evt. carry van laatste optelling hierbij return TCPIP_checksum: ; ------------------------------------------------------------------- ; Berekenen van checksum voor de IP-header en de TCP-header ; ------------------------------------------------------------------- ; De TCP-checksum bestaat uit one compledingens van een pseudoheader en ; de one compledingens van de tcp-header + data. Voor de tcp-header ; + data kunnen we de normale Checksum routine gebruiken, omdat deze ; data mooi in het geheugen zit. De pseudo header is her en der ; verspreid, dus reken we eerst de pseudo-header uit en voegen er dan ; het deel van tcp-header+data aan toe. clrf Hchecksum ; checksum = 0 clrf Lchecksum lfsr 1, IP_from clrf FSR2H movlw D'8' movwf FSR2L ; FSR2H:FSR2L = 8 = lengte in bytes call Checksum ; calculate checksum for IP_from and IP_to ; movlw D'0' ; Normaal moeten we hier nul bijtellen, ; addwfc Hchecksum, f ; maar dit heeft toch geen effekt. movf IP_protocol, w addwfc Lchecksum, f ; add checksum IP_protocol movlw D'0' addwfc Hchecksum, f ; carry van hierboven overdragen movff IP_length, delay movff IP_length+1, delay2 ; delay, delay2 gebruiken als hulpvar movlw D'20' bsf STATUS, C subwfb delay2, f movlw D'0' subwfb delay,f ; Wij hebben lengte - 20 nodig lfsr 1, delay clrf FSR2H movlw D'2' movwf FSR2L ; FSR2H:FSR2L = 2 = lengte in bytes call Checksum ; calculate checksum for IP_length ; Hchecksum:Lchecksum bevat nu de checksum van de speudo-header. ; TCP-Header bijtellen. lfsr 1, TCP_start movff delay , FSR2H ; Lengte van TCP-header + DATA movff delay2, FSR2L ; gebruik FSR2L en FSR2H als teller ; (*TCP_cheksum padding) incf FSR2L, f ; Verhoog de lengte met 1 ; In call Cheksum wordt FSR2L / 2 ; Dus als FSR2L even was doet dit niets ( even + 1 ) / 2 = even / 2 ; bv ( 2 + 1 ) / 2 = 2 / 2 = 1 ; Maar als FSR2L oneven was wordt er een extra padding byte bijgevoegd. clrf TCP_checksum clrf TCP_checksum+1 ; clear TCP_checksum call Checksum ; Voeg checksum TCP-header+data toe ; comf nog uitvoeren op deze checksum comf Lchecksum, f comf Hchecksum, f ; one complemet ; en dan de checksum kopieren naar de gepaste lokatie movff Hchecksum, TCP_checksum movff Lchecksum, TCP_checksum+1 ; Checksum IP berekenen, nodig, want we hebben aanpassingen aan de ; ip-header gemaakt. clrf Hchecksum clrf Lchecksum clrf FSR2H ; Lengte van IP-header movlw D'20' movwf FSR2L ; gebruik FSR2L en FSR2H als teller clrf IP_checksum ; Oude checksum wissen clrf IP_checksum+1 lfsr 1, IP_start call Checksum ; comf nog uitvoeren op deze checksum comf Lchecksum, f comf Hchecksum, f ; en dan de checksum kopieren naar de gepaste lokatie movff Hchecksum, IP_checksum movff Lchecksum, IP_checksum+1 return ;-) --- ; text -------------------------------------------------------------- ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ; ; ! Lees Dit / Read This ! ; ------------------------ ; ; Wanneer db een oneven aantal karakters bevat wordt er automatisch een ; zero-padding byte toegevoegd. Zorg dat waar dit een rol speelt de regels ; uit een even aantal karakters bestaan. ; ; When db contains an odd number of expressions, a zero-padding byte will ; be added. So, where necessary, use a even number of characters to avoid ; problems. ; ; 5.13 DB � Declare Data of One Byte ; ; 5.13.1 Syntax ; ; [