;; wwwpic2 is a tcp/ip stack and www server in a PIC 16F84 ;; ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License ;; as published by the Free Software Foundation; either version 2 ;; of the License, or (at your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;; To contact V Sanders email ;; vince@kyllikki.fluff.org ;; The main web site for this program is ;; http://www.kyllikki.fluff.org/hardware/wwwpic2/ ;; ;; This program is based upon wwwpic by Denis Petrov ;; From and original idea by Shrikumar H. ;; ;; See the website and acompanying README for more details ;; Version 0.20 ; Title "WWWPic 2" Processor 16F84 ; PIC device type 16F84 or 16F84A ; ; include PIC register definitions and define config fuses ; depends upon processor selected ; IFDEF __16F84 __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_OFF & _HS_OSC INCLUDE ENDIF IFDEF __16F84A __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_OFF & _HS_OSC INCLUDE ENDIF ; set radix to decimal Radix DEC EXPAND ; settings and extra macros include "wwwpic2.inc" ;; Two vector locations _ResetVector set 0x00 _IntVector set 0x04 ;;======================================================================== ;; DATA RAM mapping ;;======================================================================== CBLOCK 0x0c RX_BYTE ; [soft uart] TX_BYTE ; [soft uart] TCPR_RPORT_H ; remote TCP port TCPR_RPORT_L ; TCPR_LPORT_H ; local TCP port, TCPR_LPORT_H==0 TCPR_LPORT_L ; TCPR_SEQ_L3 ; TCPR_SEQ_L2 ; TCPR_SEQ_L1 ; TCPR_SEQ_L0 ; TCPR_ACK_L3 ; TCPR_ACK_L2 ; TCPR_ACK_L1 ; TCPR_ACK_L0 ; TCPR_HLEN ; TCPR_FLAG ; TEMP_0 ; TEMP_1 ; TEMP_2 ; HTTP_UNITIDX ; HTTP_FILESIZE_H ; HTTP_FILESIZE_L ; HTTP_NAME_0 ; HTTP_NAME_1 ; HTTP_NAME_2 ; ; socket data, it's valid if tcp_online==1 TCPR_POS ; iterator 0 -->] 80..FF TCPS_ACK ; TCPS_SEQ ; TCPS_LEN ; for retransmit TCPS_FLAG ; for retransmit IP_POS ; iterator IP_HLEN ; IP header len (incoming only) IP_LEN ; IP packet len IP_SUM_0 ; TCP/IP chksum IP_SUM_1 ; --//-----//-- low octet IP_ADR_0 ; remote IP address IP_ADR_1 ; --//-- IP_ADR_2 ; --//-- IP_ADR_3 ; --//-- ENDC ;;======================================================================== ;; Reset Vector ;;======================================================================== ORG _ResetVector ; ; ; ; clrf INTCON ; Disables all interups clears GIE ; ; ; ; and all pending interupts movlw B'01001111' ; Sets options movwf OPTION_REG ; PORTB pulups on ; ; ; ; Rising edge trigger on RB0 ; ; ; ; TMR0 clock source internal ; ; ; ; TMR0 low to high edge ; ; ; ; prescaler asigned to WDT ; ; ; ; prescaler set to 1: 128 goto _init ; Goto start routine ; ; ; ; ;;======================================================================== ;; Interrupt Code ;;======================================================================== ORG _IntVector ; Called from main interupt vector as RBO edge is only active interupt source ; it came from there! ; Soft UART - simplex :( ; Recive a byte at the pre-set baud rate ; 'RS_DATA'(8) Data No Parity X stop _rx_byte: ; (5) Well 3-4 (interupt latency) call _delay4 ; (4) Delays 4 cycles total movlw RS_DATA ; (1) 8 data No parity x stop _rx_bit: bcf PORTA,B_RS232_CTS ; (1) Drop CTS to stop any more bytes ; ; ; ; being sent while dealing with ; ; ; ; this one call _delay_x_9 ; (2) RS_TICKS-9 bcf STATUS,C ; (1) Clear carry bit btfss PORTB,B_RS232_RxD ; (1) Set carry if rxd pin reads 0 bsf STATUS,C ; (1) rrf RX_BYTE,F ; (1) Rotate recived byte which shifts ; ; ; ; in the carry bit addlw -1 ; (1) Subtract one from the bit count bnz _rx_bit ; (3) Round for next bit ; ; ; ; ; RX SLIP code ;; RX_BYTE register contains recived byte movf RX_BYTE,W ; get recived byte into w xorlw 0C0h ; bnz _not_slip_end_char ; check for SLIP END char ; recived SLIP END bcf IP_HLEN,B_SLIP_OUTPKT ; clear discard data flag clrf IP_POS ; clear IP_POS clrf IP_SUM_0 ; clear ip checksup low byte clrf IP_SUM_1 ; clear ip checksup high byte goto _rx ; return to busy loop ; ; ; ; _not_slip_end_char: brclr IP_HLEN,B_SLIP_OUTPKT,_mode_slip ; is discard data flg set ; ; ; ; _mode_terminal: ; terminal mode - discarding data any 0xD char codes reply with ok xorlw (00Dh ^ 0C0h) ; Check for a 0xD char bnz _rx ; Not a 0xD return to busy loop TXLW 'O' ; This is for slip TXLW 'K' ; server sw that trys to issue TXLW 0Dh ; AT commands at startup goto _rx ; return to busy loop ; ; ; ; _mode_slip: ; slip mode - not discarding data brclr IP_HLEN,B_SLIP_ESCAPE,_no_slip_escape; check escape flag ; previous char was slip escape char ; PROTOCOL BUG - assumes its 0xDC or 0xDD - should pass thru if neither ; see RFC 1055 xorlw (0DCh ^ 0C0h) ; check for 0xDC movlw 0DBh ; Escaping in SLIP: skpnz ; 0xDB,0xDC --> 0xC0 movlw 0C0h ; 0xDB,0xDD --> 0xDB movwf RX_BYTE ; RX_BYTE=(RX_BYTE==0xDC?0xC0:0xDB) ; goto _end_slip_escape ; ok ,w either 0xdc or 0xdd so ; ; ; ; later xor fails ; ; ; ; _no_slip_escape: ; previous char was not an escape character - check this one bsf IP_HLEN,B_SLIP_ESCAPE ; set escape flag to true xorlw (0DBh ^ 0C0h) ; check for SLIP_escape bz _rx ; ret to busy loop with esc flg set ; ; ; ; _end_slip_escape: bcf IP_HLEN,B_SLIP_ESCAPE ; clear escape flag ; ; ; ; ; ; ; ; ; byte recived and slip de-escaped and framed movf RX_BYTE,W ; retrieve our original byte call _checksum_byte ; calculates the ip checksum ; as we go ; ; ; ; movf IP_POS,W ;(rus) addlw -20 ;(rus) SLIP.END (rus com) bc _xxxx ; IP (rus com) rlf IP_POS,W ; clrf PCLATH ; (rus) addwf PCL,F ; ; ; ; ; movf RX_BYTE,W ; IPhdr+ 0 Version & IHL movwf IP_HLEN ; rlf IP_HLEN,F ; IPhdr+ 1 Type of Service goto _01_ ; movlw 0 ; IPhdr+ 2 Total Length (hi) goto _rx_byte_must_equal_w ; movf RX_BYTE,W ; IPhdr+ 3 Total Length (lo) movwf IP_LEN ; goto _finish ; IPhdr+ 4 Identification (hi) ; ; ; ; _01_: bcf IP_HLEN,7 ; goto _finish ; IPhdr+ 5 Identification (lo) nop ; goto _finish ; IPhdr+ 6 Flags & Fragment Offset (hi) nop ; movlw 0 ; IPhdr+ 7 Fragment Offset (lo) goto _rx_byte_must_equal_w ; goto _finish ; IPhdr+ 8 Time to Live nop ; movlw 6 ; IPhdr+ 9 Protocol goto _rx_byte_must_equal_w ; goto _finish ; IPhdr+10 Header Checksum (hi) nop ; goto _finish ; IPhdr+11 Header Checksum (lo) nop ; movlw IP_ADR_0 ; IPhdr+12 Source Address goto _save_rx_byte ; movlw IP_ADR_1 ; IPhdr+13 goto _save_rx_byte ; movlw IP_ADR_2 ; IPhdr+14 goto _save_rx_byte ; movlw IP_ADR_3 ; IPhdr+15 goto _save_rx_byte ; movlw ADDR_MYSELF_0 ; IPhdr+16 Destination Address goto _rx_byte_must_equal_w ; movlw ADDR_MYSELF_1 ; IPhdr+17 goto _rx_byte_must_equal_w ; movlw ADDR_MYSELF_2 ; IPhdr+18 goto _rx_byte_must_equal_w ; movlw ADDR_MYSELF_3 ; IPhdr+19 _rx_byte_must_equal_w: xorwf RX_BYTE,W ; bnz _error ; recived byte wasnt correct ; ; ; ; discard the rest of the packet ; ; ; ; _xxxx: movf IP_HLEN,W ; IP_POS-IP_HLEN - (rus) subwf IP_POS,W ; (rus) IP (rus) bc _post_ip ; ... (rus)? ; ; ; ; _no_post_ip: xorlw 0FFh ; (rus) IP (rus) bnz _finish ; IP_SUM (rus) movf IP_SUM_0,W ; iorwf IP_SUM_1,W ; bnz _error ; (rus) ; ; ; ; _finish: incf IP_POS,F ; (rus) goto _rx ; ; ; ; ; _post_ip: addlw -14 ; (rus) TCP (rus) bnc _save_as_tcp_header ; bnz _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 ; (rus) TCP (rus) addlw -15 ; (rus) (W<14) - (rus) bc _no_save_rx_byte ; (rus) ; GET /xxx (rus) ­ (rus) telnet-(rus) ; (rus) ; (rus) www-browser. subwf TCPR_POS,W ; (rus) "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) bnc _no_save_rx_byte ; if ((HTTP_NAME_0 - (TCPR_RPORT_H + 14)) != 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 - (rus) movf RX_BYTE,W ; movwf INDF ; ; ; ; ; _no_save_rx_byte: incf IP_POS,W ; (rus) subwf IP_LEN,W ; IP ¯ (rus) ... bnz _finish ; ; ; ; ; movf IP_HLEN,W ; IP_LEN-=IP_HLEN; subwf IP_LEN,F ; call _chksum_pseudoheader ; (rus) movf IP_SUM_0,W ; TCP (rus) iorwf IP_SUM_1,W ; skpnz ; call _process_tcp ; goto _error ; ; ; ; ; ;=========================================================================== ; TX routines ;=========================================================================== ;_txhex: movwf FSR ; swapf FSR,W ; call _txhex0 ; movf FSR,W ;_txhex0:andlw 00001111b ; addlw -10 ; skipnc ; addlw 7 ; addlw 58 ; goto _tx ;------------------------------------------------ _slitx_csum: movf IP_SUM_0,W ; (rus) call _slitx ; (rus) movf IP_SUM_1,W ; goto _slitx ;;------------------------------------------------ ; ; ; ; _slitx4: movwf FSR ; (rus)  (W[0]..W[3]) call _slitx2 ; (rus) ; ; ; ; _slitx2: movf INDF,W ; (rus)  (FSR[0]..FSR[1]) call _checksum_hi call _slitx1 movf INDF,W call _checksum_lo ; ; ; ; _slitx1: movf INDF,W ; (rus) (*FSR++) incf FSR,F ; goto _slitx ;;------------------------------------------------ ; ; ; ; _tx_0_0: call _tx_0 ; (rus) ; ; ; ; _tx_0: movlw 000h ; (rus) ; ; ; ; _slitx: xorlw 0C0h ; (rus) SLIP bnz _ne_C0 ; (rus) TXLW 0DBh ; 0xC0 --> 0xDB,0xDC movlw 0DCh ; 0xDB --> 0xDB,0xDD goto _tx ; ; ; ; ; _ne_C0: xorlw (0DBh ^ 0C0h) ; <0DBh xor 0C0h> bnz _tx11 ; call _tx11 ; movlw (0DDh ^ 0DBh) ; <0DDh xor 0DBh> ; ; ; ; _tx11: ; xorlw 0DBh ; ; ; ; ; _tx: bsf PORTA,B_RS232_TxD ; rus com movwf TX_BYTE ; IN: W movlw ((-(RS_DATA+1))<< 4) & 0xff ; <(-(RS_DATA+1))shl 4> ; OUT: TX_BYTE:=W ; ; ; ; _tx_loop_c: bsf STATUS,C ; 1 ; ; ; ; _tx_loop: call _delay_x_9 rrf TX_BYTE,F ; 1 ; 1 bnc _c_is_clear ; 2 ; 3 addlw 10h ; 1 bcf PORTA,B_RS232_TxD ; 1 bnz _tx_loop_c ; 3 ; ; ; ; Warning - falls thru to _delay_x_9 ; ; ; ; which returns also. ; ; ; ; saves a call and return ;; Delays for RS_TICKS less a fixed value (9 is the current value) ;; currently depends on 6Mhz clock! - possible bug in that it delays for ;; 70 cycles (total 79) where RS_TICKS is 78 (see next bit for reason) ;; For 10Mhz operation : ;; RS_TICKS will be 130.2 hence we either creep back by 0.2 or add an extra ;; cycle and creep forward 0.8. ;; Given how close Denis starts to the bits leading edge, I suspect that he ;; delibarately added the extra cycle at 6Mhz to cause forward creep rather ;; than back. ;; I shall do likewise and cause a delay for 122 cycles after 8 bits this only ;; puts us 6/1/2 cycles futher along along (8%) anyway. ;; I wont do this here tho! i shall add it to RS_TICKS at the top _delay_x_9: ;; Smallest delay possible with this routine is 19 cycles (38400 @ 4Mhz clock ;; is possible using 26 cycles so i dont think its an issue ) ;; Uses TEMP_0 and TEMP_1 and 7 instrctions ;; Delay comprises of ;; 9 - static value ;; 2 - call to get here ;; 6 - routine overhead ;; (n*3) - where n is number of loops required ;; -1 - (-1 coz last time round loop only executes 2 cycles not 3) ;; r - where r is (n mod 3) to get number of extras leftover ;; ;; We need to calculate sumber of times round loop which is RS_TICKS less the ;; static values (9+2+6-1)=16 ; ; ; ; WAIT_CYCLES set (RS_TICKS - 16) WAIT_LOOPS set (WAIT_CYCLES / 3) ; ; ; ; if (WAIT_LOOPS < 1) ;{ error "wait time too short" endif ; } ; ; ; ; movwf TEMP_1 ; (1) store w to temp_1 movlw WAIT_LOOPS ; (1) get number of loops to do WAIT_CYCLES set (WAIT_CYCLES - (WAIT_LOOPS*3)); calc number of spare cycles movwf TEMP_0 ; (1) store literal in TEMP_0 movf TEMP_1,W ; (1) recover w from TEMP_1 _tx_delay: decfsz TEMP_0,F ; (1) decrement and goto if zero goto _tx_delay ; (2(1 if skipped)) go back round loop ; ; ; ; one cycle down coz the goto got ; ; ; ; missed have to account for it ; ; ; ; with a nop if (WAIT_CYCLES == 1) ; { nop ; ; (1) endif ; ; } if (WAIT_CYCLES == 2) ; { goto _delay_x_9_next2 ; (2) ; ; ; ; _delay_x_9_next2: endif ; ; } ; ; ; ; _delay4: return ; ; (2) ; ; ; ; _c_is_clear: bsf PORTA,B_RS232_TxD ; 1 addlw 10h ; 1 bcf STATUS,C ; 1 =nop goto _tx_loop ; 2 ; ; ; ; ;;======================================================================== ;; Primary initialisation - and main loop ;;======================================================================== ; ; ; ; RS232_TxD:=0, RS232_CTS:=0 _init: clrf PORTB ; Initialise PORTB to off clrf PORTA ; Initialise PORTA to off movlw B'00000000' ; porta, ___ooooo tris 5 ; (depreciated) set PORTA data ; ; ; ; direction to all output movlw B'00000001' ; portb, oooooooi tris 6 ; (depreciated) set PORTB to ; ; ; ; output except for RB0 ; ; ; ; bcf TCPS_FLAG,B_TCP_ONLINE ; clear tcp_online flag ; return here upon recipt of error ; ; ; ; _error: clrf IP_HLEN ; clear IP_HLEN reg bsf IP_HLEN,B_SLIP_OUTPKT ; set discard data flag ;; return here to continue to wait for next byte ; ; ; ; _rx: bsf PORTA,B_RS232_CTS ; turn on CTS movlw B'10010000' ; enable GIE and INTE movwf INTCON ; ; ; ; ; _busy_loop: ; The interupt routine doesnt use RETIE it simply gotos back to either of the ; _rx or _error entry points goto _busy_loop ; infinite busy loop ; ; ; ; ;======================================================================== ; (rus)  TCP/IP (rus)  ;======================================================================== _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)) ; (rus) IP (rus) 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 ; (rus) SEQ (rus) subwf TCPS_ACK,W ; (rus) TCP (rus) bc _no_correct_hi_seq ; incf TCPR_SEQ_L1,F ; skpnz ; incf TCPR_SEQ_L2,F skpnz 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 ; (rus) TCP (rus)  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 B'00010011' ; 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 ; (rus) xorwf IP_POS,W ; (rus) TCP (rus)  bz _loop_break0 call _file_read call _checksum_byte incf IP_POS,F goto _loop_top0 _loop_break0: call _slitx_csum call _tx_0_0 ; ; ; ; clrf IP_POS ; (rus) TCP (rus)  _loop_top1: movf TCPS_LEN,W xorwf IP_POS,W bz _loop_break1 call _file_read call _slitx incf IP_POS,F goto _loop_top1 _loop_break1: ; ; ; ; _tx_slip_end: movlw 0C0h ; (rus) SLIP.END goto _tx ; ; ; ; ;======================================================================== ; (rus) TCP/IP (rus) ;======================================================================== _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)<<8)+(ADDR_MYSELF_1+ADDR_MYSELF_3)) call _checksum_hi SUM1 (6+((ADDR_MYSELF_0+ADDR_MYSELF_2)<<8)+(ADDR_MYSELF_1+ADDR_MYSELF_3)) goto _checksum_lo ;------------------------------------------ _checksum_byte: brset IP_POS,0,_checksum_lo _checksum_hi: subwf IP_SUM_0,F ; (rus) movlw 1 skipc _checksum_lo: subwf IP_SUM_1,F ; (rus) 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 ; (rus) xorlw TCP_PORT_HTTP iorwf TCPR_LPORT_H,W skipz return ; ; ; ; skip0 TCPR_FLAG,2 ; RST bcf TCPS_FLAG,B_TCP_ONLINE brset TCPR_FLAG,0,_tcp_fin ; FIN brset 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 bz _my_transmit_is_acked subwf TCPS_LEN,W ; -TCPR_ACK_L0+TCPS_SEQ bz _tcp_send ; (rus)... RETRANSMIT !!!! return ; (rus) TCPR_ACK_L0 = (rus) _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 ; bnz _tcp_send ; (rus)... 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 (rus) ******************* movlw B'00010001' ; http_state = * ; b_tcp_online = 0 ; tcps_flag = FIN+ACK brset TCPS_FLAG,B_HTTP_STATE_1,_set_flag_and_send brset TCPS_FLAG,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 bnc _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' ; bz _cgi_a ; HTTP_NAME_0 == 'a' sublw ('a'-'0') ;<'a'-'0'> ; addlw -10 ; bnc _cgi_digit ; HTTP_NAME_0 in ['0'..'9'] movlw 3 ; movwf HTTP_UNITIDX ; HTTP_UNITIDX = 3 clrf HTTP_FILESIZE_H ; movlw 06Fh ; HTTP_FILESIZE = 0x6F goto _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 TCPS_FLAG,B_HTTP_STATE_0; http_state=1 goto _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 bnz _transmit_80 movf HTTP_FILESIZE_L,W addlw 7Fh bc _transmit_80 bsf TCPS_FLAG,B_HTTP_STATE_1; http_state=3 movf HTTP_FILESIZE_L,W ; <== TRANSMIT less than TCP_SND_WINDOW bytes goto _transmit_not_80 _transmit_80: movlw TCP_SND_WINDOW ; <== TRANSMIT TCP_SND_WINDOW bytes _transmit_not_80: movwf TCPS_LEN goto _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 B'00010000' ; tcps_flag = 0x11; // SYN+ACK ; ; ; ; tcp_online=0; ; ; ; ; http_state=*; _set_flag_and_send: movwf TCPS_FLAG goto _tcp_send_empty ; tcp_send_empty() ; ; ; ; _tcp_syn: ; brset TCPS_FLAG,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 B'10010010' ; http_state=0; // just connected movwf TCPS_FLAG ; tcps_flag = 0x12; // SYN+ACK call _tcp_send_empty ; tcp_send_empty(); // (rus) 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 ,_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 >= 2); { skip0 HTTP_UNITIDX,1 bsf PCLATH,0 endif ; } movf IP_POS,W if (FS_INTERNAL_ROM_UNITS >= 1) ; { skip0 HTTP_UNITIDX,0 iorlw 80h endif ; } movwf PCL ;======================================================================== ; Simple CGI support ;======================================================================== _cgi_portb_hi: swapf PORTB,W goto _lo4bit_as_hexdigit ; skip0 ; retlw '1' ; retlw '0' _cgi_portb_lo: movf PORTB,W _lo4bit_as_hexdigit: andlw B'00001111' addlw -10 skipnc addlw 7 addlw 58 return ; ; ; ; ORG 0x200 ;======================================================================== ; JavaScript program for PortB control ;======================================================================== dt "HTTP/1.0" dt " 200\r\n\r\n" ; "Content-Type: %s", "blah-blah-blah" ; "Content-Length: %d", blah_blah_blah ; "Refresh: %d", blah_blah_blah dt "P" dt "ort B</t" dt "itle><bo" dt "dy onLoa" dt "d=\"for(v" dt "ar i=0;i" dt "<7;i++)d" dt "ocument." dt "forms[0]" dt ".element" dt "s[i].che" dt "cked=0x" goto _cgi_portb_hi ; SIC! goto _cgi_portb_lo dt "&(2<<i)" dt "\"><form " dt "action=a" dt "><script" dt ">for(var" dt " i=1;i<8" dt ";i++)doc" dt "ument.wr" dt "ite(\"B.\"" dt "+i+\"<INP" dt "UT TYPE=" dt "checkbox" dt "><BR>\")<" dt "/script>" dt "<input t" dt "ype=subm" dt "it value" dt "=Read><i" dt "nput typ" dt "e=button" dt " value=W" dt "rite onC" dt "lick=\"fo" dt "r(var v=" dt "400,i=0;" dt "i<7;v+=d" dt "ocument." dt "forms[0]" dt ".element" dt "s[i].che" dt "cked<<++" dt "i);top.l" dt "ocation." dt "href=v\">" ;======================================================================== ; Index Page ;======================================================================== dt "HTTP/1.0" dt " 200\r\n\r\n" dt "<a href=" dt "a>PortB " dt "control<" dt "/a><hr><" dt "a href=h" dt "ttp://ky" dt "llikki.f" dt "luff.org" dt "/hardwar" dt "e/>wwwpi" dt "c2 homep" dt "age</a> " dt " " dt " " endif ; } if (FS_USE_EXTERNAL_ROM); { _file_read: retlw 0 endif ; } end