;; 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 <zhengxi@operamail.com>
;; From and original idea by Shrikumar H. <shri@cs.umass.edu>
;;
;; 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 <p16f84.inc>
ENDIF
IFDEF __16F84A
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_OFF & _HS_OSC
INCLUDE <p16f84a.inc>
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 <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 >= 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 <PORTA,4>
; 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 "<title>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
syntax highlighted by Code2HTML, v. 0.9