;;======================================================================== ;; ;; Program: TCP/IP stack and HTTP-server in a chip ;; Idea: Shrikumar H. <shri@cs.umass.edu> ;; Author: Denis Petrov <zhengxi@operamail.com> ;; Platform: Microchip PIC16F84 ;; Date: 17.09.99 ;; LastDate: 25.09.99 ;; ;;======================================================================== ;; todo: watching tcp_online ;; use WDT ;; more than 1 socket include masmpic.inc .386 ;;======================================================================== ;; General settings ;;======================================================================== QUARTZ_FREQ = 6000000 RS_BAUD = 19200 RS_DATA = 8 RS_TICKS = (QUARTZ_FREQ/4)/RS_BAUD ; [non-volatile] ADDR_MYSELF_0 = 219 ; 219.192.55.208 ( ~my phone# :) ADDR_MYSELF_1 = 192 ADDR_MYSELF_2 = 55 ADDR_MYSELF_3 = 208 TCP_PORT_HTTP = 80 ; 1..255 TCP_RCV_WINDOW = 128;!sic!; [non-volatile] TCP_SND_WINDOW = 128 ; [non-volatile] RS_MONITOR = 1 ; monitor works over raw RS232 FS_UNIT_SIZE = 128 ; [non-volatile] FS_ROOT_DIR_ENTRIES = 8 ; min 2: INDEX and ERROR. FS_USE_INTERNAL_ROM = 1 FS_INTERNAL_ROM_UNITS = 4 ; number of 128-byte pages FS_USE_INTERNAL_EEPROM = 0 ; FS_USE_EXTERNAL_ROM = 0 ;;======================================================================== ;; DATA RAM mapping ;;======================================================================== TCPR_RPORT_H = SRAM0 ; remote TCP port TCPR_RPORT_L = SRAM1 TCPR_LPORT_H = SRAM2 ; local TCP port, TCPR_LPORT_H==0 TCPR_LPORT_L = SRAM3 TCPR_SEQ_L3 = SRAM4 TCPR_SEQ_L2 = SRAM5 TCPR_SEQ_L1 = SRAM6 TCPR_SEQ_L0 = SRAM7 TCPR_ACK_L3 = SRAM8 TCPR_ACK_L2 = SRAM9 TCPR_ACK_L1 = SRAM10 TCPR_ACK_L0 = SRAM11 TCPR_HLEN = SRAM12 ; Is not used when sending не используется при посылке TCPR_FLAG = SRAM13 ; ÎÅ ÉÓÐÏÌØÚÕÅÔÓÑ ÐÒÉ ÐÏÓÙÌËÅ TEMP_0 = SRAM2 TEMP_1 = SRAM12 TEMP_2 = SRAM13 HTTP_UNITIDX = SRAM14 ;*** HTTP_FILESIZE_H = SRAM15 ;*** HTTP_FILESIZE_L = SRAM16 ;*** HTTP_NAME_0 = SRAM14 HTTP_NAME_1 = SRAM15 HTTP_NAME_2 = SRAM16 if RS_MONITOR MON_ADDR_H = SRAM14 MON_ADDR_L = SRAM15 MON_TAG = SRAM16 ; like (as) 'R', 'W', 'A' ×ÒÏÄÅ 'R','W','A' endif ; socket data, it's valid if tcp_online==1 TCPR_POS = SRAM17 ; iterator 0 -->] 80..FF ; bytes received from the time communication opened ; ÐÒÉÎÑÔÏ ÂÁÊÔ Ó ÏÔËÒÙÔÉÑ ÓÏÅÄÉÎÅÎÉÑ TCPS_ACK = SRAM18 TCPS_SEQ = SRAM19 TCPS_LEN = SRAM20 ; for retransmit TCPS_FLAG = SRAM21 ; for retransmit RX_BYTE = SRAM22 ; [soft uart] TX_BYTE = RX_BYTE ; [soft uart] IP_POS = SRAM23 ; iterator IP_HLEN = SRAM24 ; IP header len (incoming only) IP_LEN = SRAM25 ; IP packet len IP_SUM_0 = SRAM26 ; TCP/IP chksum IP_SUM_1 = SRAM27 ; --//-----//-- low octet IP_ADR_0 = SRAM28 ; remote IP address IP_ADR_1 = SRAM29 ; --//-- IP_ADR_2 = SRAM30 ; --//-- IP_ADR_3 = SRAM31 ; --//-- DefBit B_HTTP_STATE_0, TCPS_FLAG, 5 DefBit B_HTTP_STATE_1, TCPS_FLAG, 6 DefBit B_TCP_ONLINE, TCPS_FLAG, 7 ;DefBit B_LED_1, PORTA, 3 ;DefBit B_LED_2, PORTA, 2 DefBit B_RS232_RxD, PORTB, 0 DefBit B_RS232_TxD, PORTA, 3 DefBit B_RS232_CTS, PORTA, 2 DefBit B_SLIP_OUTPKT, IP_HLEN, 7 DefBit B_SLIP_ESCAPE, IP_HLEN, 6 ;;======================================================================== ;; Useful macros ;;======================================================================== TXLW macro k movlw (k) call _tx endm SLITXLW macro k movlw (k) call _slitx endm SUM0 MACRO x:req __TMPSUM=(((x)+((x) shr 16)) shr 8) movlw __TMPSUM ENDM SUM1 MACRO x:req __TMPSUM=(((x)+((x) shr 16)) shr 0) movlw __TMPSUM ENDM ;;======================================================================== ;; Code ;;======================================================================== _start: clrf INTCON ; Disable Interrupts ÚÁÐÒÅÔÉÔØ ×ÓÅ ÐÒÅÒÙ×ÁÎÉÑ ? movlw 01001111b ; "_-", WDT/128 option jump _init _interrupt: ; ; Soft UART ( simplex :( ) ; ; S01234567T ; ; 115.2 ; ; 57.6 ; ; 38.4 ; ; 19.2 ; _________ ; ; _^_"þ" ; _interrupt_b0: ; 5 ; Interrupt ÏÂÒÁÂÏÔÞÉÔ ÐÒÅÒÙ×ÁÎÉÑ INT call _delay4 ; 4 ; Delay 4 (ÍÏÍÅÎÔ "þ") movlw 8 ; 1 ; 8Nx _rx_next: bcf B_RS232_CTS ; 1 ; fall CTS call _delay_x_9 ; x-9 ; bcf C ; 1 ; skip1 B_RS232_RxD ; 1 ; bsf C ; 1 ; C:=RS232_RxD rrf RX_BYTE,F ; 1 ; addlw -1 ; 1 ; jnz _rx_next ; 3 ; movf RX_BYTE,w ; xorlw 0C0h ; jnz _no_C0 ; Starting to recieve ÎÁÞÉÎÁÅÍ ÐÒÉÅÍ bcf B_SLIP_OUTPKT ; New package (SLIP END) ÎÏ×ÏÇÏ ÐÁËÅÔÁ (SLIP END) clrf IP_POS ; clrf IP_SUM_0 ; clrf IP_SUM_1 ; jump _rx ; _no_C0: j0 B_SLIP_OUTPKT,_mode_slip; if the symbol being revieved is not in the package ; ÅÓÌÉ ÐÒÉÎÉÍÁÅÍÙÊ ÓÉÍ×ÏÌ ×ÎÅ ÐÁËÅÔÁ _mode_terminal: xorlw <00Dh xor 0C0h> ; jnz _rx ; Modem emulation ÜÍÕÌÑÃÉÑ ÍÏÄÅÍÁ: TXLW 'O' ; Respond to AT command ÏÔ×ÅÔ ÎÁ AT-ËÏÍÁÎÄÙ TXLW 'K' ; TXLW 0Dh ; jump _rx ; _mode_slip: j0 B_SLIP_ESCAPE,_no_slip_escape xorlw <0DCh xor 0C0h> ; Treatment of the 2nd byte ; ÏÔÒÁÂÏÔËÁ ×ÔÏÒÏÇÏ ÂÁÊÔÁ movlw 0DBh ; Special order SLIP ÓÐÅÃ.ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÓÔÅÊ SLIP: skipnz ; 0xDB,0xDC --> 0xC0 movlw 0C0h ; 0xDB,0xDD --> 0xDB movwf RX_BYTE ; RX_BYTE=(RX_BYTE==0xDC?0xC0:0xDB) ; jump _end_slip_escape ; _no_slip_escape: ; bsf B_SLIP_ESCAPE ; if OxDB is recieved, then ÅÓÌÉ ÐÒÉÎÑÔ 0xDB, ÚÎÁÞÉÔ xorlw <0DBh xor 0C0h> ; this is the first byte ÜÔÏ ÐÅÒ×ÙÊ ÂÁÊÔ jz _rx ; special order SLIP ÓÐÅÃ.ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÓÔÉ SLIP: _end_slip_escape: bcf B_SLIP_ESCAPE ; movf RX_BYTE,W call _checksum_byte ; control sum refreshement (renewal?) ; ÏÂÎÏ×ÌÅÎÉÅ ËÏÎÔÒÏÌØÎÏÊ ÓÕÍÍÙ ; of the package being recieved ; ÐÒÉÎÉÍÁÅÍÏÇÏ ÐÁËÅÔÁ movf IP_POS,W ; treatment of the first 0x13 bytes ; ÏÂÒÁÂÏÔËÁ ÐÅÒ×ÙÈ 0x13 ÂÁÊÔ addlw -20 ; after SLIP END as a header ; ÐÏÓÌÅ SLIP.END ËÁË ÚÁÇÏÌÏ×ÏË jc _xxxx ; of the IP package IP ÐÁËÅÔÁ rlf IP_POS,W ; clrf PCLATH ; usefull but not required ; ÜÔÏ ÐÏÌÅÚÎÏ, ÎÏ ÎÅ ÎÅÏÂÈÏÄÉÍÏ addwf PCL,F ; movf RX_BYTE,W ; IPhdr+ 0 Version & IHL movwf IP_HLEN ; rlf IP_HLEN,F ; IPhdr+ 1 Type of Service jump _01_ ; movlw 0 ; IPhdr+ 2 Total Length (hi) jump _rx_byte_must_equal_w ; movf RX_BYTE,W ; IPhdr+ 3 Total Length (lo) movwf IP_LEN ; jump _finish ; IPhdr+ 4 Identification (hi) _01_: bcf IP_HLEN,7 ; jump _finish ; IPhdr+ 5 Identification (lo) nop ; jump _finish ; IPhdr+ 6 Flags & Fragment Offset (hi) nop ; movlw 0 ; IPhdr+ 7 Fragment Offset (lo) jump _rx_byte_must_equal_w ; jump _finish ; IPhdr+ 8 Time to Live nop ; movlw 6 ; IPhdr+ 9 Protocol jump _rx_byte_must_equal_w ; jump _finish ; IPhdr+10 Header Checksum (hi) nop ; jump _finish ; IPhdr+11 Header Checksum (lo) nop ; movlw IP_ADR_0 ; IPhdr+12 Source Address jump _save_rx_byte ; movlw IP_ADR_1 ; IPhdr+13 jump _save_rx_byte ; movlw IP_ADR_2 ; IPhdr+14 jump _save_rx_byte ; movlw IP_ADR_3 ; IPhdr+15 jump _save_rx_byte ; movlw ADDR_MYSELF_0 ; IPhdr+16 Destination Address jump _rx_byte_must_equal_w ; movlw ADDR_MYSELF_1 ; IPhdr+17 jump _rx_byte_must_equal_w ; movlw ADDR_MYSELF_2 ; IPhdr+18 jump _rx_byte_must_equal_w ; movlw ADDR_MYSELF_3 ; IPhdr+19 _rx_byte_must_equal_w: xorwf RX_BYTE,W ; jnz _error ; _xxxx: movf IP_HLEN,W ; IP_POS-IP_HLEN - on which position ÎÁ ËÁËÏÍ ÍÅÓÔÅ subwf IP_POS,W ; after the IP header, the recieved byte can be found ; ÐÒÉÎÑÔÙÊ ÂÁÊÔ ÎÁÈÏÄÉÔÓÑ ÐÏÓÌÅ IP ÚÁÇÏÌÏ×ËÁ jc _post_ip ; ... or is this still an IP header? ; ... ÉÌÉ ÜÔÏ ×ÓÅ ÅÝÅ IP ÚÁÇÏÌÏ×ÏË? _no_post_ip: xorlw 0FFh ; and if this is the last byte of the IP header ; Á ÅÓÌÉ ÜÔÏ ÐÏÓÌÅÄÎÉÊ ÂÁÊÔ IP ÚÁÇÏÌÏ×ËÁ jnz _finish ; IP_SUM should be 0 IP_SUM ÄÏÌÖÎÁ ÂÙÔØ ÒÁ×ÎÁ 0 movf IP_SUM_0,W ; iorwf IP_SUM_1,W ; jnz _error ; wrong sum for monitoring ; ÎÅÐÒÁ×ÉÌØÎÁÑ ËÏÎÔÒÏÌØÎÁÑ ÓÕÍÍÁ... _finish: incf IP_POS,F ; Next! ÓÌÅÄÕÀÝÉÊ! jump _rx ; _post_ip: addlw -14 ; saving the first 14 bytes of the TCP header ; ÓÏÈÒÁÎÑÅÍ ÐÅÒ×ÙÅ 14 ÂÁÊÔ TCP ÚÁÇÏÌÏ×ËÁ jnc _save_as_tcp_header ; jnz _no_correct_tcp_hlen ; rrf TCPR_HLEN,F ; if(IP_POS-IP_HLEN==14) rrf TCPR_HLEN,F ; { bcf TCPR_HLEN,7 ; TCPR_HLEN=(TCPR_HLEN<<2)&0x3F; bcf TCPR_HLEN,6 ; } _no_correct_tcp_hlen: subwf TCPR_HLEN,W ; saving bytes 5, 6 and 7 of the TCP _connection_ ; ÓÏÈÒÁÎÑÅÍ 5,6É7 ÂÁÊÔÙ TCP _ÓÏÅÄÉÎÅÎÉÑ_. addlw -15 ; if now (W<14) - than the name of the file ; ÅÓÌÉ ÓÅÊÞÁÓ (W<14) - ÚÎÁÞÉÔ ÉÍÑ ÆÁÊÌÁ jc _no_save_rx_byte ; came in multiple packages, for example, ; ÐÒÉÛÌÏ × ÎÅÓËÏÌØËÉÈ ÐÁËÅÔÁÈ, ÎÁÐÒÉÍÅÒ, ; GET /xxx was typed in the telnet-client ; GET /xxx ÂÙÌÏ ÎÁÂÒÁÎÏ × telnet-ËÌÉÅÎÔÅ ; so this check is not necessary ; ÔÁË ÞÔÏ ÜÔÁ ÐÒÏ×ÅÒËÁ ÎÅ Ñ×Ì. ÎÅÏÂÈÏÄÉÍÏÊ, ; if only www-browser will be used ; ÅÓÌÉ ÂÕÄÅÔ ÐÏÌØÚÏ×ÁÔØÓÑ ÔÏÌØËÏ www-browser. subwf TCPR_POS,W ; like first symbols of the file name in "GET /" ; ËÁË ÐÅÒ×ÙÅ ÓÉÍ×ÏÌÙ ÉÍÅÎÉ ÆÁÊÌÁ × "GET /.." addlw (-1-(5+3)) ; W=TCPR_POS-(TCPR_HLEN-(IP_POS-IP_HLEN-14)) addlw 3 ; (5.7)->(FD.FF) (5.7)->(0.2) jnc _no_save_rx_byte if (HTTP_NAME_0-(TCPR_RPORT_H+14)) ne 0 addlw (HTTP_NAME_0-(TCPR_RPORT_H+14)) endif _save_as_tcp_header: addlw TCPR_RPORT_H+14 _save_rx_byte: movwf FSR ; [W]:=RX_BYTE - is often used ÞÁÓÔÏ ÉÓÐÏÌØÚÕÅÔÓÑ movf RX_BYTE,W ; movwf INDR ; _no_save_rx_byte: incf IP_POS,W ; ÅÓÌÉ ÐÒÉÎÑÔ ÐÏÓÌÅÄÎÉÊ ÂÁÊÔ subwf IP_LEN,W ; if the last byte of the IP package is recieved... ; IP ÐÁËÅÔÁ... jnz _finish ; movf IP_HLEN,W ; IP_LEN-=IP_HLEN; subwf IP_LEN,F ; call _chksum_pseudoheader ; control check sum of the TCP package's header/body ; ÐÒÏ×ÅÒËÁ ËÏÎÔÒÏÌØÎÏÊ ÓÕÍÍÙ TCP ÚÁÇÏÌÏ×ËÁ/ÔÅÌÁ ÐÁËÅÔÁ movf IP_SUM_0,W ; iorwf IP_SUM_1,W ; skipnz ; call _process_tcp ; jump _error ; ;=========================================================================== ; TX routines ;=========================================================================== ;_txhex: movwf FSR ; swapf FSR,W ; call _txhex0 ; movf FSR,W ;_txhex0:andlw 00001111b ; addlw -10 ; skipnc ; addlw 7 ; addlw 58 ; jump _tx ;;------------------------------------------------ _slitx_csum: movf IP_SUM_0,W ; pass (or deliver) the control sum ; ÐÅÒÅÄÁÔØ ËÏÎÔÒÏÌØÎÕÀ ÓÕÍÍÕ call _slitx ; (2 bytes) (Ä×Á ÂÁÊÔÁ) movf IP_SUM_1,W ; jump _slitx ;;------------------------------------------------ _slitx4: movwf FSR ; pass (or deliver) 4 bytes (W[0]...W[3]) ; ÐÅÒÅÄÁÔØ 4 ÂÁÊÔÁ (W[0]..W[3]) call _slitx2 ; with the control sum correction ; Ó ËÏÒÒÅËÃÉÅÊ ËÏÎÔÒÏÌØÎÏÊ ÓÕÍÍÙ _slitx2: movf INDR,W ; pass (or deliver) 2 bytes (FSR[0]...FSR[1]) ; ÐÅÒÅÄÁÔØ 2 ÂÁÊÔÁ (FSR[0]..FSR[1]) call _checksum_hi call _slitx1 movf INDR,W call _checksum_lo _slitx1: movf INDR,W ; pass (or deliver) 1 byte (*FSR++) ; ÐÅÒÅÄÁÔØ 1 ÂÁÊÔ (*FSR++) incf FSR,F ; jump _slitx ;;------------------------------------------------ _tx_0_0: call _tx_0 ; pass (or deliver) 2 zeros ; ÐÅÒÅÄÁÔØ Ä×Á ÎÕÌÑ _tx_0: movlw 000h ; pass (or deliver) a zero ; ÐÅÒÅÄÁÔØ ÎÕÌØ _slitx: xorlw 0C0h ; pass (deliver) a byte by (using) SLIP protocol ; ÐÅÒÅÄÁÔØ ÂÁÊÔ ÐÏ ÐÒÏÔÏËÏÌÕ SLIP jnz _ne_C0 ; i.e. ( = that is) with substitutions ; Ô.Å. Ó ÚÁÍÅÎÁÍÉ TXLW 0DBh ; 0xC0 --> 0xDB,0xDC movlw 0DCh ; 0xDB --> 0xDB,0xDD jump _tx ; _ne_C0: xorlw <0DBh xor 0C0h> ; jnz _tx11 ; call _tx11 ; movlw <0DDh xor 0DBh> ; _tx11: ; xorlw 0DBh ; _tx: bsf B_RS232_TxD ; just pass (deliver) one byte ; ÐÒÏÓÔÏ ÐÅÒÅÄÁÔØ ÏÄÉÎ ÂÁÊÔ movwf TX_BYTE ; IN: W movlw <(-(RS_DATA+1))shl 4> ; OUT: TX_BYTE:=W _tx_loop_c: bsf C ; 1 _tx_loop: call _delay_x_9 rrf TX_BYTE,F ; 1 ; 1 jnc _c_is_clear ; 2 ; 3 addlw 10h ; 1 bcf B_RS232_TxD ; 1 jnz _tx_loop_c ; 3 _delay_x_9: ; upon technical-delay it is not allowed: ; ÐÒÉ TX-ÚÁÄÅÒÖËÅ ÎÅÌØÚÑ: ; 1. to change flag STATUS.C ; 1. ÉÚÍÅÎÑÔØ ÆÌÁÇ STATUS.C ; 2. to overload the stream of returns ; 2. ÓÉÌØÎÏ ÐÅÒÅÇÒÕÖÁÔØ ÓÔÅË ×ÏÚ×ÒÁÔÏ× if ((RS_TICKS)-11) eq 28 ; 38400 and 6MHz call _x2 ;28=2+2*13 _x2: nop call _x1 ;12=2+2*5 _x1: nop brake elseif ((RS_TICKS)-11) eq 67 ; 19200 and 6MHz if 0 nop call _x1 ;66=2*3+4*15 call _x1 ; call _x1 ;66=2*5+10+10+10+10+10+6 call _x1 ; call _x2 ; _x1: brake brake _x2: brake brake else TEMP_DELAY = TEMP_0 clrf TEMP_DELAY bsf TEMP_DELAY,4 _tx_delay: nop decfsz TEMP_DELAY,F jump _tx_delay endif else error endif _delay4: return _c_is_clear: bsf B_RS232_TxD ; 1 addlw 10h ; 1 bcf C ; 1 =nop jump _tx_loop ; 2 ;======================================================================== ; ;======================================================================== _init: ;movlw 00000000b ; RS232_TxD:=0, RS232_CTS:=0 clrf PORTB ; clrf PORTA movlw 00000000b ; porta, ___ooooo tris 5 movlw 00000001b ; portb, oooooooi tris 6 bcf B_TCP_ONLINE ; tcp_online=0 _error: clrf IP_HLEN ; bsf B_SLIP_OUTPKT ; at first outside of the package ; ÓÎÁÞÁÌÁ ÓÎÁÒÕÖÉ ÐÁËÅÔÁ _rx: bsf B_RS232_CTS ; raise CTS ÐÏÄÎÑÔØ CTS movlw 10010000b ; GIE+INTE movwf INTCON _rxl: ; clrwdt ;???? jump _rxl ;======================================================================== ; Sending of the TCP/IP package ÐÅÒÅÄÁÞÁ TCP/IP ÐÁËÅÔÁ ;======================================================================== _just_ack: _tcp_send_empty_10: bcf TCPS_FLAG,0 ; TCPS_FLAG=xxxxxxx0 bcf TCPS_FLAG,1 ; TCPS_FLAG=xxxxxx0x _tcp_send_empty: clrf TCPS_LEN _tcp_send: call _tx_slip_end SUM0 <-(4500h+4000h+8000h)> ; calculation of the IP header control sum ; ÒÁÓÞÅÔ ËÏÎÔÒÏÌØÎÏÊ ÓÕÍÍÙ IP ÚÁÇÏÌÏ×ËÁ movwf IP_SUM_0 SUM1 <-(4500h+4000h+8000h)> movwf IP_SUM_1 TXLW 045h call _tx_0_0 movf TCPS_LEN,W addlw 14h+14h movwf IP_LEN ; IP_LEN = TCPS_LEN+14h+14h call _slitx call _chksum_pseudoheader call _tx_0_0 TXLW 040h call _tx_0 TXLW 080h TXLW 006h call _slitx_csum SLITXLW ADDR_MYSELF_0 SLITXLW ADDR_MYSELF_1 SLITXLW ADDR_MYSELF_2 SLITXLW ADDR_MYSELF_3 movlw IP_ADR_0 call _slitx4 movf TCPR_SEQ_L0,W ; SEQ formatting for the TCP package which is ; being sent ; ÆÏÒÍÉÒÏ×ÁÎÉÅ SEQ ÄÌÑ subwf TCPS_ACK,W ; ÏÔÐÒÁ×ÌÑÅÍÏÇÏ TCP ÐÁËÅÔÁ jc _no_correct_hi_seq ; incf TCPR_SEQ_L1,F ; skipnz ; incf TCPR_SEQ_L2,F skipnz incf TCPR_SEQ_L3,F _no_correct_hi_seq: addwf TCPR_SEQ_L0,F ; TCPR_SEQ_L0+=TCPS_ACK-TCPR_SEQ_L0 SUM0 <-(5000h+TCP_RCV_WINDOW-0014h)> movwf IP_SUM_0 ; calculation of the TCP headers control sum ; ÒÁÓÞÅÔ ËÏÎÔÒÏÌØÎÏÊ ÓÕÍÍÙ TCP ÚÁÇÏÌÏ×ËÁ SUM1 <-(5000h+TCP_RCV_WINDOW-0014h)> movwf IP_SUM_1 call _chksum_pseudoheader movlw TCPR_LPORT_H movwf FSR call _slitx2 movlw TCPR_RPORT_H movwf FSR call _slitx2 movlw TCPR_ACK_L3 call _slitx4 movlw TCPR_SEQ_L3 call _slitx4 TXLW 050h movf TCPS_FLAG,W andlw 00010011b ; 0x10,0x11,0x12 call _tx movf TX_BYTE,W call _checksum_lo call _tx_0 TXLW TCP_RCV_WINDOW clrf IP_POS _loop_top0: movf TCPS_LEN,W ; calculation of the TCP package's body ; ÒÁÓÞÅÔ ËÏÎÔÒÏÌØÎÏÊ ÓÕÍÍÙ xorwf IP_POS,W ; ÔÅÌÁ TCP ÐÁËÅÔÁ jz _loop_break0 call _file_read call _checksum_byte incf IP_POS,F jump _loop_top0 _loop_break0: call _slitx_csum call _tx_0_0 clrf IP_POS ; delivery of the TCP package's body ; ÐÅÒÅÄÁÞÁ ÔÅÌÁ TCP ÐÁËÅÔÁ _loop_top1: movf TCPS_LEN,W xorwf IP_POS,W jz _loop_break1 call _file_read call _slitx incf IP_POS,F jump _loop_top1 _loop_break1: _tx_slip_end: movlw 0C0h ; deliver SLIP.END ÐÅÒÅÄÁÔØ SLIP.END jump _tx ;======================================================================== ; calculation/check of control sums of TCP/IP headers/packages ; ÒÁÓÞÅÔ/ÐÒÏ×ÅÒËÁ ËÏÎÔÒÏÌØÎÙÈ ÓÕÍÍ TCP/IP ÚÁÇÏÌÏ×ËÏ×/ÐÁËÅÔÏ× ;======================================================================== _chksum_pseudoheader: movf IP_LEN,W call _checksum_lo movf IP_ADR_0,W call _checksum_hi movf IP_ADR_1,W call _checksum_lo movf IP_ADR_2,W call _checksum_hi movf IP_ADR_3,W call _checksum_lo SUM0 <6+((ADDR_MYSELF_0+ADDR_MYSELF_2)shl 8)+(ADDR_MYSELF_1+ADDR_MYSELF_3)> call _checksum_hi SUM1 <6+((ADDR_MYSELF_0+ADDR_MYSELF_2)shl 8)+(ADDR_MYSELF_1+ADDR_MYSELF_3)> jump _checksum_lo ;------------------------------------------ _checksum_byte: j1 <IP_POS,0>,_checksum_lo _checksum_hi: subwf IP_SUM_0,F ; correct high byte of the control sum ; ËÏÒÒÅËÔÉÒÏ×ÁÔØ ÓÔ.ÂÁÊÔ ËÏÎÔÒ.ÓÕÍÍÙ movlw 1 skipc _checksum_lo: subwf IP_SUM_1,F ; correct low byte of the control sum ; ËÏÒÒÅËÔÉÒÏ×ÁÔØ ÍÌ.ÂÁÊÔ ËÏÎÔÒ.ÓÕÍÍÙ movlw 1 skipc subwf IP_SUM_0,F skipc subwf IP_SUM_1,F return ;======================================================================== ; UDP handler ;======================================================================== _process_udp: ; ... to do ... ;======================================================================== ; TCP handler ;======================================================================== _process_tcp: movf TCPR_LPORT_L,W ; testing the number of the local port ; ÐÒÏ×ÅÒËÁ ÎÏÍÅÒÁ ÌÏËÁÌØÎÏÇÏ ÐÏÒÔÁ xorlw TCP_PORT_HTTP iorwf TCPR_LPORT_H,W skipz return skip0 <TCPR_FLAG,2> ; RST bcf B_TCP_ONLINE j1 <TCPR_FLAG,0>,_tcp_fin ; FIN j1 <TCPR_FLAG,1>,_tcp_syn ; SYN skip1 <TCPR_FLAG,4> ; ACK ???? return ;_tcp_ack: movf TCPS_SEQ,W subwf TCPR_ACK_L0,W subwf TCPS_LEN,W ; TCPS_LEN-TCPR_ACK_L0+TCPS_SEQ jz _my_transmit_is_acked subwf TCPS_LEN,W ; -TCPR_ACK_L0+TCPS_SEQ jz _tcp_send ; if client did not confirm recieve... RETRANSMIT!! ; ÅÓÌÉ ËÌÉÅÎÔ ÎÅ ÐÏÄÔ×ÅÒÄÉÌ ÐÒÉÅÍ... RETRANSMIT !!!! return ; completely wrong TCPR_ACK_L0 = we're not responding ; ÓÏ×ÓÅÍ ÎÅÐÒÁ×ÉÌØÎÙÊ TCPR_ACK_L0 = ÎÅ ÏÔ×ÅÞÁÅÍ _my_transmit_is_acked: movf TCPR_ACK_L0,W ; tcps_seq=LO(tcpr.ack); movwf TCPS_SEQ ; movf TCPR_SEQ_L0,W ; if(tcpr.seq==tcps_ack1) xorwf TCPS_ACK,W ; jnz _tcp_send ; if we havn't RX'd what we expected... RETRANSMIT! ; ÅÓÌÉ ÍÙ ÐÏÌÕÞÉÌÉ ÎÅ ÔÏ, ÞÔÏ ÖÄÁÌÉ... RETRANSMIT !!!! ;_new_data_was_rvcd: movf TCPR_HLEN,W subwf IP_LEN,W addwf TCPS_ACK,F ; tcps_ack1 += ip_len-tcpr.hlen; addwf TCPR_POS,F skipnc bsf TCPR_POS,7 ; 0-->](128..255) ;;****** HTTP server ËÁË ËÏÎÅÞÎÙÊ Á×ÔÏÍÁÔ ******************* movlw 00010001b ; http_state = * ; b_tcp_online = 0 ; tcps_flag = FIN+ACK j1 B_HTTP_STATE_1,_set_flag_and_send j1 B_HTTP_STATE_0,_http_state_1 _http_state_0: movf TCPR_POS,W ; if(tcpr_pos<*) goto _tcp_send_empty_10 addlw -8 ; *** ; strlen("GET / HTTP/0.9\r\n\r\n")=18 jnc _tcp_send_empty_10 ; ??? todo: file system functions ;=set http_unitidx ;=set http_filesize_h ;=set http_filesize_l if FS_USE_INTERNAL_ROM ;------------------------ ; CGI ;------------------------ movf HTTP_NAME_0,W sublw 'a' ; jz _cgi_a ; HTTP_NAME_0 == 'a' sublw <'a'-'0'> ; addlw -10 ; jnc _cgi_digit ; HTTP_NAME_0 in ['0'..'9'] movlw 3 ; movwf HTTP_UNITIDX ; HTTP_UNITIDX = 3 clrf HTTP_FILESIZE_H ; movlw 068h ; HTTP_FILESIZE = 0x6E jump _cgi_done ; _cgi_digit: rlf HTTP_NAME_1,F ; status.c=0 movf HTTP_NAME_1,W ; rlf HTTP_NAME_1,F ; rlf HTTP_NAME_1,F ; addwf HTTP_NAME_1,W ; addwf HTTP_NAME_2,W ; W := 10*HTTP_NAME_0+HTTP_NAME_1 addlw -16 ; W := 10*(HTTP_NAME_0-'0')+(HTTP_NAME_1-'0') skip0 <HTTP_NAME_0,0> addlw 100 skip0 <HTTP_NAME_0,1> addlw 200 movwf PORTB ; ; andlw 11110b ; movwf PORTB ; _cgi_a: clrf HTTP_UNITIDX ; HTTP_UNITIDX = 0 movlw 1 ; movwf HTTP_FILESIZE_H ; HTTP_FILESIZE = 0x180 movlw 080h ; _cgi_done: movwf HTTP_FILESIZE_L ; endif if FS_USE_EXTERNAL_ROM ...todo... endif bsf B_HTTP_STATE_0 ; http_state=1 jump _send_portion_of_file _http_state_1: incf HTTP_UNITIDX,F ; http_unitidx++ movf TCPS_LEN,W ; http_filesize -= tcps_len; subwf HTTP_FILESIZE_L,F skipc decf HTTP_FILESIZE_H,F _send_portion_of_file: movf HTTP_FILESIZE_H,F jnz _transmit_80 movf HTTP_FILESIZE_L,W addlw 7Fh jc _transmit_80 bsf B_HTTP_STATE_1 ; http_state=3 movf HTTP_FILESIZE_L,W ; <== TRANSMIT less than TCP_SND_WINDOW bytes jump _transmit_not_80 _transmit_80: movlw TCP_SND_WINDOW ; <== TRANSMIT TCP_SND_WINDOW bytes _transmit_not_80: movwf TCPS_LEN jump _tcp_send _tcp_fin: incf TCPR_SEQ_L0,W ; tcps_ack1 = B3(tcpr.seq)+1; movwf TCPS_ACK incf TCPS_SEQ,F ; tcps_seq1++; movlw 00010000b ; tcps_flag = 0x11; // SYN+ACK ; tcp_online=0; ; http_state=*; _set_flag_and_send: movwf TCPS_FLAG jump _tcp_send_empty ; tcp_send_empty(); // 0 byte ÐÅÒÅÄÁÅÍ 0 ÂÁÊÔ _tcp_syn: ;; j1 B_TCP_ONLINE,_return ; if( 0==tcp_online ) { incf TCPR_SEQ_L0,W ; tcps_ack1 = B3(tcpr.seq)+1; movwf TCPS_ACK clrf TCPR_POS ; tcpr_pos=0; clrf TCPS_SEQ ; tcps_seq1=ISS=0; movlw 10010010b ; http_state=0; // just connected movwf TCPS_FLAG ; tcps_flag = 0x12; // SYN+ACK call _tcp_send_empty ; tcp_send_empty(); // ÐÅÒÅÄÁÅÍ 0 ÂÁÊÔ incf TCPS_SEQ,F ; tcps_seq1++; return ; } if FS_USE_INTERNAL_ROM ;======================================================================== ; Internal ROM/EEPROM File (max 512/64 bytes) ;======================================================================== ; UNIT0: ROM 0x0200..0x027F ; UNIT1: ROM 0x0280..0x02FF ; UNIT2: ROM 0x0300..0x037F ; UNIT3: ROM 0x0380..0x03FF ; UNIT4: EEPROM 0x0000..0x003F ;======================================================================== _file_read: if FS_USE_INTERNAL_EEPROM j0 <HTTP_UNITIDX,2>,_ir_read _ie_read: movf IP_POS,W movwf EEADR ; Address to read bsf RP0 bsf EECON1,0 ; EE Read bcf RP0 movf EEDATA,W ; W = EEDATA return endif _ir_read: clrf PCLATH bsf PCLATH,1 if FS_INTERNAL_ROM_UNITS ge 2 skip0 <HTTP_UNITIDX,1> bsf PCLATH,0 endif movf IP_POS,W if FS_INTERNAL_ROM_UNITS ge 1 skip0 <HTTP_UNITIDX,0> iorlw 80h endif movwf PCL ;======================================================================== ; Simple CGI support :) ;======================================================================== _cgi_portb_hi: swapf PORTB,W jump _lo4bit_as_hexdigit ; skip0 <PORTA,4> ; retlw '1' ; retlw '0' _cgi_portb_lo: movf PORTB,W _lo4bit_as_hexdigit: andlw 00001111b addlw -10 skipnc addlw 7 addlw 58 return .org 800h ;======================================================================== ; JavaScript program for PortB control ;======================================================================== .db 'H','T','T','P','/','1','.','0',' ','2','0','0', 13, 10, 13, 10 ; "Content-Type: %s", "blah-blah-blah" ; "Content-Length: %d", blah_blah_blah ; "Refresh: %d", blah_blah_blah .db '<','t','i','t','l','e','>','P','o','r','t',' ','B','<','/','t' .db 'i','t','l','e','>','<','b','o','d','y',' ','o','n','L','o','a' .db 'd','=','"','f','o','r','(','v','a','r',' ','i','=','0',';','i' .db '<','7',';','i','+','+',')','d','o','c','u','m','e','n','t','.' .db 'f','o','r','m','s','[','0',']','.','e','l','e','m','e','n','t' .db 's','[','i',']','.','c','h','e','c','k','e','d','=','0','x' jump _cgi_portb_hi ; SIC! jump _cgi_portb_lo .db '&','(','2','<','<','i',')','"','>','<','f','o','r','m',' ' .db 'a','c','t','i','o','n','=','a','>','<','s','c','r','i','p','t' .db '>','f','o','r','(','v','a','r',' ','i','=','1',';','i','<','8' .db ';','i','+','+',')','d','o','c','u','m','e','n','t','.','w','r' .db 'i','t','e','(','"','B','.','"','+','i','+','"','<','I','N','P' .db 'U','T',' ','T','Y','P','E','=','c','h','e','c','k','b','o','x' .db '>','<','B','R','>','"',')','<','/','s','c','r','i','p','t','>' .db '<','i','n','p','u','t',' ','t','y','p','e','=','s','u','b','m' .db 'i','t',' ','v','a','l','u','e','=','R','e','a','d','>','<','i' .db 'n','p','u','t',' ','t','y','p','e','=','b','u','t','t','o','n' .db ' ','v','a','l','u','e','=','W','r','i','t','e',' ','o','n','C' .db 'l','i','c','k','=','"','f','o','r','(','v','a','r',' ','v','=' .db '4','0','0',',','i','=','0',';','i','<','7',';','v','+','=','d' .db 'o','c','u','m','e','n','t','.','f','o','r','m','s','[','0',']' .db '.','e','l','e','m','e','n','t','s','[','i',']','.','c','h','e' .db 'c','k','e','d','<','<','+','+','i',')',';','t','o','p','.','l' .db 'o','c','a','t','i','o','n','.','h','r','e','f','=','v','"','>' ; .db 'H','T','T','P','/','1','.','0',' ','4','0','4', 13, 10, 13, 10 ; .db 'N','o','t',' ','f','o','u','n','d','<','h','r','>','<','a',' ' ; .db 'h','r','e','f','=','i','>','M','a','i','n',' ','P','a','g','e' ; .db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; .db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; .db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; .db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; .db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .db 'H','T','T','P','/','1','.','0',' ','2','0','0', 13, 10, 13, 10 .db '<','a',' ','h','r','e','f','=','a','>','P','o','r','t','B',' ' .db 'c','o','n','t','r','o','l','<','/','a','>','<','h','r','>','<' .db 'a',' ','h','r','e','f','=','h','t','t','p',':','/','/','z','h' .db 'e','n','g','x','i','.','d','a','.','r','u','>','D','e','n','i' .db 's',' ','P','e','t','r','o','v',27h,'s',' ','h','o','m','e',' ' .db 'p','a','g','e','<','/','a','>', 0, 0, 0, 0, 0, 0, 0, 0 .db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 endif if FS_USE_EXTERNAL_ROM _file_read: retlw 0 endif end |