;;========================================================================
;;
;; 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
|