	list      p=16f877            ; list directive to define processor

	#include <p16f877.inc>        ; processor specific variable definitions
	
;
;		PICNIC - PIC Network Interface Controller
;		Copyright (c) 2002 SHINSHU UNIVERSITY KISO LAB
;		 All Rights Reserved.
;
;		1-SEP-2002	Version 1.2.0.0
;
;


;-----------------------------------------------------------------------------------
	
	__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC & _LVP_OFF


;-----------------------------------------------------------------------------------
HTTP_PORT		EQU	.80			; HTTP port number (80=default)
LCD_PORT		EQU	.0			; LCD control port number (0=unused)
PARALLEL_PORT		EQU	.10001			; Parallel port number (0=unused)
SERIAL_PORT		EQU	.10002			; Serial port number (0=unused)

BOOTPC_PORT		EQU	.68			; BOOTP port number (client)
BOOTPS_PORT		EQU	.67			; BOOTP port number (server)

BAUD_RATE		EQU	.129	;10		; RS232C baud rate on reset
							; 129=9600bps
							; 10=115200bps

PARALLEL_PACKET_SIZE	EQU	.8			; Parallel Tx packet size
SERIAL_PACKET_SIZE	EQU	(.2 + .6 + .4 + .2 + .1 + .1)		; Serial status packet size
							; type:mac:ip:port:baud:flow
CH_BACKSPACE		EQU	.8			; Backspace character code
SOCKETS			EQU	.4			; Number of sockets (no changes)


;-----------------------------------------------------------------------------------

		ORG	0x2100
		
		DE	.192, .168, 0, .200	; IP address(0.0.0.0=DHCP)
		DE	.255 , .255 , .255 , 0	; Net mask
		DE	0,0,0,0		; GateWay
		DE	1,2,0,0		; Firmware Version x,x,x,x
		
		
		DE	HTTP_PORT / .256 , HTTP_PORT & .255				; HTTP port number
		DE	LCD_PORT / .256 , LCD_PORT & .255				; LCD port number
		DE	PARALLEL_PORT / .256 , PARALLEL_PORT & .255			; PARALLEL port number
		DE	SERIAL_PORT / .256 , SERIAL_PORT & .255			; SERIAL port number

;
;-----------------------------------------------------------------------------------

;
;		Protocol numbers, etc.
;
COM_PROTO	EQU	08H			; HIGH BYTE (common)
IP_PROTO	EQU	00H			; LOW BYTE (0800h means IP packet)
ARP_PROTO	EQU	06H			; LOW BYTE (0806h means ARP packet)


TCP_PROTO	EQU	.6
UDP_PROTO	EQU	.17
ICMP_PROTO	EQU	.1

;
;		RTL8019AS configuration parameters
;
PAGE_BEGIN	EQU	40H			; Memory starting address
PAGE_START	EQU	46H			; Rx buffer starting address
PAGE_STOP	EQU	80H			; Rx buffer ending address

DATA_SIZE	EQU	.18

;
;		Ethernet configuration parameters
;
NE_SIZE		EQU	.4			; RTL8019 status area size
PACKET_SIZE	EQU	.6 + .6 + .2			; Ethernet header size
ARP_SIZE	EQU	.28			; ARP packet size
IP_SIZE		EQU	.20			; IP (basic) header size
UDP_SIZE	EQU	.8			; UDP header size
TCP_SIZE	EQU	.20			; TCP (basic) header size
DHCP_SIZE	EQU	.308
;
;		TCP/IP state
;
LISTEN		EQU	00			; Idle
SYN_RCVD	EQU	80H			; SYN,ACK sent, waiting for ACK
ESTAB		EQU	81H			; Communication established
CLOSE_WAIT	EQU	82H
LAST_ACK	EQU	83H
FIN_WAIT_1	EQU	84H
FIN_WAIT_2	EQU	85H
CLOSING		EQU	86H
TIME_WAIT	EQU	87H

;		Socket structure
;------------------------------------------
;		org	0
;so_job		ds	2
;so_ip		ds	4
;so_port	ds	2
;so_seq_no	ds	4
;so_ack_no	ds	4
;------------------------------------------



;-----------------------------------------------------------------------------------
;		I/O port configuration
;-----------------------------------------------------------------------------------
SA		EQU	PORTC			; NE2000 address bus
SA0		EQU	0			;rc.0
SA1		EQU	1
SA2		EQU	2
SA3		EQU	3
SA4		EQU	4			;rc.4

SD		EQU	PORTD
SD0		EQU	0			;rd.0
SD1		EQU	1
SD2		EQU	2
SD3		EQU	3
SD4		EQU	4
SD5		EQU	5
SD6		EQU	6
SD7		EQU	7			;rd.7

RDY		EQU	5			;rc.5		; ~IOCHRDY


CNT		EQU	PORTE
RD		EQU	0			;re.0	; RTL8019AS ~RD
WR		EQU	1			;re.1	; RTL8019AS ~WR


;
;		LCD I/O configuration (for optional LCD)
;
D7		EQU	7			;rb.7			; for LCD
D6		EQU	6
D5		EQU	5
D4		EQU	4
E		EQU	3			; LCD enable
RS		EQU	2			;rb.2 ; LCD RS pin



;-----------------------------------------------------------------------------------
;		Global variables
;-----------------------------------------------------------------------------------
;		PAGE 0 
;		org	20h

;	LCD variables
wait_cn		EQU	20H	
wait_cn2	EQU	21H	
d4		EQU	22H	
d8		EQU	23H	

cd		EQU	24H
tmp		EQU	24H	
use		EQU	25H	
;-----------------------------------------------------------------------------------
gcn1		EQU	26H	
sum		EQU	27H		; check sum for TCP,...
sum1		EQU	28H
bytes		EQU	29H			; current ptr for calculate above
ptr		EQU	2AH	


cn_l		EQU	2BH		; fan free
cn_h		EQU	2CH	

remote_adr	EQU	2DH			; Remote
remote_adr1	EQU	2EH
remote_len	EQU	2FH	
remote_len1	EQU	30H
curr		EQU	31H			; Current page address


val		EQU	32H	
val1		EQU	33H	
val2		EQU	34H	
val3		EQU	35H	
val_m		EQU	36H			; for DECIMAL
val_cn		EQU	37H
proto		EQU	37H			; Protocol number
state		EQU	38H			; TCP flag

;-----------------------------------------------------------------------------------
;
;		IP protocol
;
ip_header	EQU	39H
ip_ver_len	EQU	39H		; VERSION:4,DATA SIZE:5
ip_tos		EQU	3AH		; service type
ip_length	EQU	3BH		; data length
ip_length1	EQU	3CH
ip_ident	EQU	3DH	
ip_ident1	EQU	3EH
ip_flagment	EQU	3FH		
ip_flagment1	EQU	40H
ip_ttl		EQU	41H		; time to live
ip_proto	EQU	42H		; protocol 1:ICMP,6:TCP,17:UDP
ip_sum		EQU	43H		; header checksum
ip_sum1		EQU	44H
ip_src		EQU	45H	
ip_src1		EQU	46H
ip_src2		EQU	47H
ip_src3		EQU	48H
ip_dest		EQU	49H	
ip_dest1	EQU	4AH
ip_dest2	EQU	4BH
ip_dest3	EQU	4CH


;-----------------------------------------------------------------------------------
;		TCP protocol
;
tcp_header	EQU	4DH	
tcp_src_port	EQU	4DH	
tcp_src_port1	EQU	4EH
tcp_tar_port	EQU	4FH	
tcp_tar_port1	EQU	50H
tcp_seq_no	EQU	51H	
tcp_seq_no1	EQU	52H
tcp_seq_no2	EQU	53H
tcp_seq_no3	EQU	54H
tcp_ack_no	EQU	55H	
tcp_ack_no1	EQU	56H
tcp_ack_no2	EQU	57H
tcp_ack_no3	EQU	58H
tcp_header_size	EQU	59H	
tcp_flags	EQU	5AH	
TCP_URG		EQU	5	
TCP_ACK		EQU	4	
TCP_PSH		EQU	3	
TCP_RST		EQU	2
TCP_SYN		EQU	1	
TCP_FIN		EQU	0	

tcp_window	EQU	5BH	
tcp_window1	EQU	5CH
tcp_sum		EQU	5DH	
tcp_sum1	EQU	5DH
tcp_		EQU	5FH	
tcp_1		EQU	60H	

;-----------------------------------------------------------------------------------
;		UDP protocol
;
udp_header	SET	tcp_header
udp_src_port	SET	tcp_header+0
udp_src_port1	SET	tcp_header+1
udp_tar_port	SET	tcp_header+2
udp_tar_port1	SET	tcp_header+3
udp_length	SET	tcp_header+4
udp_length1	SET	tcp_header+5
udp_sum		SET	tcp_header+6
udp_sum1	SET	tcp_header+7
udp_data	SET	tcp_header+8
udp_data1	SET	tcp_header+9
udp_data2	SET	tcp_header + .10
udp_data3	SET	tcp_header + .11
udp_data4	SET	tcp_header + .12
udp_data5	SET	tcp_header + .13
udp_data6	SET	tcp_header + .14
udp_data7	SET	tcp_header + .15


;-----------------------------------------------------------------------------------
;		ARP protocol
;
arp_header	SET	ip_header
arp_hard_type	SET	ip_header+0
arp_prot_type	SET	ip_header+2
arp_hard_len	SET	ip_header+4
arp_prot_len	SET	ip_header+5
arp_ope		SET	ip_header+6
arp_ope1	SET	ip_header+7
arp_src_mac	SET	ip_header+8
arp_src_ip	SET	ip_header + .14
arp_dest_mac	SET	ip_header + .18
arp_dest_ip	SET	ip_header + .24
arp_dest_ip1	SET	ip_header + .25
arp_dest_ip2	SET	ip_header + .26
arp_dest_ip3	SET	ip_header + .27
;		=	ip_header + .28


;-----------------------------------------------------------------------------------
;		ICMP protocol
;
icmp_header	SET	tcp_header
icmp_type	SET	tcp_header+0
icmp_code	SET	tcp_header+1
icmp_sum	SET	tcp_header+2
icmp_mes	SET	tcp_header+4


;-----------------------------------------------------------------------------------
;		DHCP protocol
;
dhcp_header	SET	udp_data
dhcp_ope	SET	udp_data+0
dhcp_type	SET	udp_data+1
dhcp_phylen	SET	udp_data+2
dhcp_hop	SET	udp_data+3
dhcp_trans	SET	udp_data+4
dhcp_sec	SET	udp_data+8
dhcp_dummy	SET	udp_data + .10
dhcp_client_ip	SET	udp_data + .12
dhcp_user_ip	SET	udp_data + .16
dhcp_user_ip1	SET	udp_data + .17
dhcp_user_ip2	SET	udp_data + .18
dhcp_user_ip3	SET	udp_data + .19
dhcp_server_ip	SET	udp_data + .20
dhcp_server_ip1	SET	udp_data + .21
dhcp_server_ip2	SET	udp_data + .22
dhcp_server_ip3	SET	udp_data + .23
dhcp_router_ip	SET	udp_data + .24


;-----------------------------------------------------------------------------------
;		Environment configuration variables
;
;		PAGE 1
;		org	0a0h
this_ip		EQU	0A0H		; own IP address
this_ip1	EQU	0A1H		
this_ip2	EQU	0A2H		
this_ip3	EQU	0A3H		
mymac		EQU	0A4H		; own MAC address
mymac1		EQU	0A5H
mymac2		EQU	0A6H
mymac3		EQU	0A7H
mymac4		EQU	0A8H
mymac5		EQU	0A9H
seq_no		EQU	0AAH			; own sequence number
seq_no1		EQU	0ABH		
seq_no2		EQU	0ACH		
seq_no3		EQU	0ADH
ident		EQU	0AEH		
ident1		EQU	0AFH
timer		EQU	0B0H		
timer_cn	EQU	0B1H		
dhcp_done	EQU	0B2H		
http_port	EQU	0B3H			; port number copy from EEPROM
http_port1	EQU	0B4H
lcd_port	EQU	0B5H		
lcd_port1	EQU	0B6H
para_port	EQU	0B7H		
para_port1	EQU	0B8H
serial_port	EQU	0B9H		
serial_port1	EQU	0BAH

fifo_poi	EQU	0BBH		; (GET) pointer used by routines
fifo_buff	EQU	0BCH		; (SET) pointer used in interrupts
fifo_cn		EQU	0BDH		; number of Rx bytes
fifo_top	EQU	0BEH		; buffer
fifo_bottom	EQU	0DCH

fifo_line	EQU	0DCH		
fifo_line_cn	EQU	0DDH	


;-----------------------------------------------------------------------------------
;		Ethernet header
;
ne_header	EQU	0DEH		; NE2000 Status
ne_stat		EQU	0DEH		; Rx status (RSR)
ne_next		EQU	0DFH		; Next Boundary pointer
ne_cn_l		EQU	0E0H		; Data size (L)
ne_cn_h		EQU	0E1H		; Data size (H)

eth_header	EQU	0E2H			; Ethernet Header
eth_dest	EQU	0E2H			; Destination MAC address
eth_dest1	EQU	0E3H
eth_dest2	EQU	0E4H
eth_dest3	EQU	0E5H
eth_dest4	EQU	0E6H
eth_dest5	EQU	0E7H
eth_src		EQU	0E8H		; Source MAC address
eth_src1	EQU	0E9H
eth_src2	EQU	0EAH
eth_src3	EQU	0EBH
eth_src4	EQU	0ECH
eth_src5	EQU	0EDH
eth_type	EQU	0EEH		; Packet type
eth_type1	EQU	0EFH
null		EQU	0F0H


bs_ptr		SET	ne_header
bs_ptr2		SET	ne_header+1
save_line	SET	ne_header+2
save_cn		SET	ne_header+3




;-----------------------------------------------------------------------------------
;		Common variables
;

;		org	70h		; COMMON MEMORY PAGE
; BEGIN -- register saves for interrupts
w_save		EQU	070H	
pclath_save	EQU	071H	
status_save	EQU	072H	
fsr_save	EQU	073H		
save_fsr	EQU	074H		
; END

mul10		EQU	075H
mul101		EQU	076H
getmes_wk	EQU	075H		
getmes_wk1	EQU	076H
com_cn		EQU	077H		
byte_cn		EQU	078H		
com_fsr		EQU	078H		
ind		EQU	079H		
dest		EQU	07AH		
dest1		EQU	07BH
data0		EQU	07CH		; a data for transmit to ethernet chip
wk		EQU	07DH	
wk1		EQU	07EH
wk2		EQU	07FH
common		EQU	07FH	

;-----------------------------------------------------------------------------------
;	Decimal conversion area
;-----------------------------------------------------------------------------------
;		PAGE 2
;		
			; for binary to decimal conversion
decimal_top	EQU	120H	


;-----------------------------------------------------------------------------------
;	RS232C destination data
;-----------------------------------------------------------------------------------
;		PAGE 3
;		org	190h
on_ether	EQU	190H			; Destination Ethernet address
on_ether1	EQU	191H
on_ether2	EQU	192H
on_ether3	EQU	193H
on_ether4	EQU	194H
on_ether5	EQU	195H
on_ip		EQU	196H		; Destination IP address
on_ip1		EQU	197H
on_ip2		EQU	198H
on_ip3		EQU	199H
on_port		EQU	19AH				; Destinatin port number
on_port1	EQU	19AH
on_rate		EQU	19CH				; Configured baud rate
on_flow		EQU	19DH				; =0
transmitted	EQU	19EH
skb		EQU	1A0H
;-----------------------------------------------------------------------------------
;		Program entry
;-----------------------------------------------------------------------------------
		ORG	0			; Reset vector (=0000h)
		MOVLW	HIGH (start)		; Go to startup routine

		MOVWF	PCLATH
		GOTO	start

;-----------------------------------------------------------------------------------
;		Interrupt processing
;
;		No calls in interrupt routine to avoid using up the stack.
;-----------------------------------------------------------------------------------

		org	4		; Interrupt vector(=0004h)
interrupt
;-----------------------------------------------------------------------------------
;		Context save processing
		movwf	w_save		; Save W register
		swapf	STATUS, 0	; Save STATUS register
		clrf	STATUS				; Set STATUS to 0
		movwf	status_save
		movf	PCLATH,0		; Save PCLATH
		movwf	pclath_save
		clrf	PCLATH			; Set PCLATH=0
		bcf	STATUS,IRP	
		movf	FSR, 0		
		movwf	fsr_save	; Save FSR
;-------------------------------------------------------------------------------;		RB0 Interruption
		btfss	INTCON,INTE
		GOTO	int_next2
		BTFSS	INTCON,INTF
		GOTO	int_next2

		bcf	INTCON,INTF
		BSF	STATUS,RP0
		BSF	STATUS,RP1
		BSF	on_flow,7
		BCF	STATUS,RP1
		BCF	STATUS,RP0
;-------------------------------------------------------------------------------;
int_next2
		BTFSC	PIR1,TMR1IF
		goto	int_tmr1
		goto	int_next1
int_tmr1
		bcf	PIR1,TMR1IF
		BSF	STATUS,RP0
		MOVF	dhcp_done,0
		andlw	7FH
		btfss	STATUS,Z
		DECF	dhcp_done,1
		bcf	STATUS,RP0
int_tmr2
		bsf	STATUS,RP0
		MOVLW	1
		ADDWF	timer,1
		btfsc	STATUS,C
		GOTO	dec_tm
dec_tm9		CLRF	STATUS
;-------------------------------------------------------------------------------
int_next1
		btfss	INTCON, PEIE	
		goto	int2
		btfss	PIR1,RCIF			; RS232C Rx?
		goto	int2
;-----------------------------------------------------------------------------------
;		Serial Rx Interrupt Processing
		bsf	STATUS,RP0	
		
		MOVLW	fifo_bottom - fifo_top
		SUBWF	fifo_cn,0
		BTFSC	3,0
		GOTO	rec_over

		movf	fifo_buff,0		; Current ring
		movwf	FSR		;Get buffer pointer to fsr
		bcf	STATUS,RP0	;
		MOVF	RCREG,0			; Save Rx data in ring buffer
		MOVWF	INDF		
		bsf	STATUS,RP0	
		incF	fifo_buff,1	; Go to next address...

		MOVLW	fifo_bottom
		SUBWF	fifo_buff,0
		BTFSS	3,0
		GOTO	int1_1

		MOVLW	fifo_top	
		movwf	fifo_buff
int1_1		incf	fifo_cn,1		; Increment number of bytes in ring buffer
;-----------------------------------------------------------------------------------
		MOVLW	(fifo_bottom - fifo_top) / 2	; [2004/10/30]
		subwf	fifo_cn,0
		btfss	3,0
		goto	int2
		bsf	STATUS,RP1
		BTFSS	on_flow,0
		GOTO	int2
		CLRF	STATUS
		BSF	PORTB,1
int2
		CLRF	STATUS
;-------------------------------------------------------------------------------;		Context return processing
		MOVF	fsr_save,0			; Restore fsr
		MOVWF	FSR
		MOVF	pclath_save,0		; Restore pclath
		MOVWF	PCLATH
		swapf	status_save,0
		movwf	STATUS					; Restore status
		swapf	w_save,1
		swapf	w_save,0		; Restore W
;	End of ISR
		retfie				; Return from interrupt service routine


;		RS232C Rx buffer overflow
rec_over
		bcf	STATUS, RP0	
		MOVF	RCREG, 0				; Read data and discard
		bcf	STATUS, RP0	
		goto	int2


;-----------------------------------------------------------------------------------
;		Socket timeout check
;
dec_tm
		bsf	STATUS, IRP
		MOVLW	SOCKETS
		MOVWF	timer_cn
		MOVLW	(skb + 1) & 0FFH	
		MOVWF	FSR
dec_tm0
		MOVF	INDF,0		
		andlw	0f0h
		btfsc	STATUS, Z	
		goto	dec_tm1
		MOVLW	10H		
		SUBWF	INDF, 1
		movF	INDF, 0		
		andlw	0f0h
		btfss	STATUS, Z	
		goto	dec_tm1
		DECF	FSR, 1		
		CLRF	INDF		
		INCF	FSR,1		
dec_tm1
		MOVLW	10H		
		ADDWF	FSR, 1
		DECFSZ	timer_cn, 1
		GOTO	dec_tm0
		bcf	STATUS, IRP	
		goto	dec_tm9



;-----------------------------------------------------------------------------------
;		Get hexadecimal routine
;
getascii
		andlw	0fh
		ADDWF	PCL, 1		
		DT	"0123456789ABCDEF"
;-----------------------------------------------------------------------------------
;		Increment TCP seq_no
;
next_seq_no
		bsf	STATUS,RP0	
		movLW	1				; +65536
		ADDWF	seq_no2,1
		btfsc	STATUS,	C	
		ADDWF	seq_no3,1	
		bcf	STATUS,RP0	
		RETURN


;-----------------------------------------------------------------------------------
;		Increment TCP seq_no
;
inc_seq_no
		bsf	STATUS,IRP	
		movLW	.3		
		ADDWF	FSR,1
		movLW	.1		
		ADDWF	INDF,1
		DECF	FSR,1		
		btfsc	STATUS,C	
		addwf	INDF,1		
		DECF	FSR,1	 
		btfsc	STATUS,C	
		addwf	INDF,1		
		DECF	FSR,1		
		btfsc	STATUS,C	
		addwf	INDF,1		
		bcf	STATUS,IRP	
		retURN

;-----------------------------------------------------------------------------------
;		Add ip_length to TCP seq_no
;
add_seq_no
		bsf	STATUS,IRP	
		movLW	.3		
		ADDWF	FSR,1

		MOVF	ip_length1,0	
		addwf	INDF,1		
		DECF	FSR,1		
		movlw	1
		btfsc	STATUS,C	
		addwf	INDF,1		
		DECF	FSR,1		
		btfsc	STATUS,C	
		addwf	INDF,1		
		DECF	FSR,1		
		btfsc	STATUS,C	
		addwf	INDF,1		
	
		movLW	.2		
		ADDWF	FSR,1
		MOVF	ip_length,0	
		addwf	INDF,1		
		DECF	FSR,1		
		movlw	1
		btfsc	STATUS,C	
		addwf	INDF,1		
		DECF	FSR,1		
		btfsc	STATUS,C	
		addwf	INDF,1		
		bcf	STATUS,IRP	
		retURN

;-----------------------------------------------------------------------------------
;		Increment TCP ack_no
;
inc_ack_no
		movLW	1		
		ADDWF	tcp_seq_no3,1
		btfsc	STATUS,C	
		addwf	tcp_seq_no2,1	
		btfsc	STATUS,C	
		addwf	tcp_seq_no1,1	
		btfsc	STATUS,C	
		addwf	tcp_seq_no,1	

		goto	copy_ack_no
;		ret

;-----------------------------------------------------------------------------------
;		Add ip_length to TCP ack_no
;
add_ack_no
		MOVLW	.20 + .20	
		SUBWF	ip_length1,1
		movlw	1
		btfss	STATUS,C	
		subwf	ip_length,1	

		MOVF	ip_length1,0	
		ADDWF	tcp_seq_no3,1
		movlw	1
		btfsc	STATUS,C	
		addwf	tcp_seq_no2,1	
		btfsc	STATUS,C	
		addwf	tcp_seq_no1,1	
		btfsc	STATUS,C	
		addwf	tcp_seq_no,1	

		MOVF	ip_length,0	
		ADDWF	tcp_seq_no2,1
		movlw	1
		btfsc	STATUS,C	
		addwf	tcp_seq_no1,1	
		btfsc	STATUS,C	
		addwf	tcp_seq_no,1	
copy_ack_no
		MOVF	com_fsr,0	
		MOVWF	FSR
		MOVLW	.12		
		ADDWF	FSR,1
		bsf	STATUS,IRP	
		MOVF	tcp_seq_no,0	
		MOVWF	INDF
		INCF	FSR,1		
		MOVF	tcp_seq_no1,0	
		MOVWF	INDF
		INCF	FSR,1		
		MOVF	tcp_seq_no2,0	
		MOVWF	INDF
		INCF	FSR,1		
		MOVF	tcp_seq_no3,0	
		MOVWF	INDF
		bcf	STATUS,IRP	
		retURN


;-----------------------------------------------------------------------------------
;		Clear checksum value.
;
clear_sum
		clrF	sum		
		clrF	sum1		
		clrF	bytes		; For distinguishing HI byte/LO byte
		retURN


;-----------------------------------------------------------------------------------
;		Error recovery routine
;-----------------------------------------------------------------------------------
overflow2
overflow
		clrF	STATUS		
		
		clrF	PORTC		
		movlw	21h			; RTL8019AS STOP
		call	assert_wr0
		
		MOVLW	HIGH (wait_ms)	
		MOVWF	PCLATH
		MOVLW	.2		
		MOVWF	wait_cn
		call	wait_ms			; 10ms Wait
		clrF	PCLATH		
		
		MOVLW	0AH		
		MOVWF	PORTC		
		DB	01,00		
		call	assert_wr0
		
		MOVLW	0BH		
		MOVWF	PORTC		
		DB	01,00		
		call	assert_wr0
		
		call	initialize		; Initialize RTL8019
		
		MOVLW	0CH
		MOVWF	PORTC					; RCR
		movlw	B'000100'			; MONITOR disable
		call	assert_wr0
		
		MOVLW	0DH		
		MOVWF	PORTC					; TCR
		DB	01,00		;clrw				; L/B disable
		call	assert_wr0
		
		goto	main0			; Return to regular processing

;===================================================================================
;		Main routine
;===================================================================================
main

		CLRF	PORTC					;rc
		movlw	22h
		call	assert_wr0		; Return to PAGE0

		MOVLW	0CH		
		MOVWF	PORTC
		movlw	B'000100'
		call	assert_wr0
		MOVLW	0DH		
		MOVWF	PORTC
		DB	01,00						; L/B disable
		call	assert_wr0
		
		MOVLW	HIGH (wait_ms)	
		MOVWF	PCLATH
		MOVLW	.100		
		MOVWF	wait_cn
		call	wait_ms			; 100ms Wait
		clrF	PCLATH		
		
		MOVLW	this_ip		
		MOVWF	FSR
		MOVF	INDF,0		
		INCF	FSR,1		
		iorwf	INDF,0		
		INCF	FSR,1		
		iorwf	INDF,0		
		INCF	FSR,1		
		iorwf	INDF,0		
		btfss	STATUS,2	
		goto	main0			; Own IP address is 0.0.0.0?
do_dhcp
		CLRF	STATUS
		MOVLW	HIGH (dhcp)	
		MOVWF	PCLATH
		call	dhcp
		MOVLW	$ >> 8		
		MOVWF	PCLATH
;===================================================================================
;		Main loop
;===================================================================================
main0

		bsf	STATUS,RP0	
	 			; RS232C Rx?
		MOVLW	0
		SUBWF	fifo_cn,0
		BTFSS	3,2
		GOTO	receive232c
		MOVLW	80h
		SUBWF	dhcp_done,0
		BTFSC	3,2
		GOTO	do_dhcp
		bcf	STATUS,RP0	

		CLRF	PCLATH		
		MOVLW	.7		
		MOVWF	PORTC
		call	assert_rd		; RCR read
		
		btfsc	data0,4		
		goto	overflow
		btfsc	data0,3		
		goto	overflow
		btfsc	data0,2		
		goto	overflow
		goto	get_packet		; Packet received
main99		goto	main0

receive232c
		bcf	STATUS,RP0	
		MOVLW	serial_tx >> 8	
		MOVWF	PCLATH		; To receive232c processing
		goto	serial_tx



;-----------------------------------------------------------------------------------
;	Packet Rx processing
;-----------------------------------------------------------------------------------
get_packet
;	PAGE 1
		CLRF	PORTC		
		movlw	B'01100010'
		call	assert_wr0		; Set to PAGE1
		
		MOVLW	.7		
		MOVWF	PORTC
		call	assert_rd
		MOVF	data0,0				; Get current page
		MOVWF	curr
;	PAGE 0
		CLRF	PORTC		
		movlw	B'00100010'
		call	assert_wr0		; Return to PAGE0
		
		MOVLW	.3		
		MOVWF	PORTC
		call	assert_rd		; Read BNDY
		
		INCF	data0,1					; BNDY++
		MOVLW	PAGE_STOP		; overlap calculation
		SUBWF	data0,0
		BTFSS	3,0
		GOTO	packet1

		MOVLW	PAGE_START	
		MOVWF	data0
packet1
		MOVF	curr,0				; if (BNDY+1)==CURR, no new data
		SUBWF	data0,0
		BTFSC	3,2
		goto	main0			; quit


;-----------------------------------------------------------------------------------
; Reading out of RTL8019 status + Ethernet header
		CLRF	remote_adr	
		MOVF	data0,0		
		MOVWF	remote_adr1
		MOVLW	NE_SIZE + PACKET_SIZE	
		MOVWF	remote_len
		CLRF	remote_len1		
		call	remote_read
		
		MOVLW	NE_SIZE + PACKET_SIZE		; Loop Counter
		MOVWF	gcn1
		bcf	STATUS,IRP		
		MOVLW	ne_header					; Read out to address ne_header
		MOVWF	FSR
		MOVLW	10H			
		MOVWF	PORTC
get_packet0
		bcf	PORTE,0				;RD
		btfss	PORTC,RDY				; ~Wait
		goto	$-1
		MOVF	PORTD,0		
		
		bsf	PORTE,0		;RD
		movwf	INDF		;INDF			; Set *INDF = data to buffer
		INCF	FSR,1		
		DECFSZ	gcn1,1		
		GOTO	get_packet0
;
;		Branch processing based on Ethernet header
		bsf	STATUS,RP0	
		btfss	ne_stat,0	
		goto	main9
		MOVLW	COM_PROTO		; Skip if high 8 bits of type not equal to 8
		SUBWF	eth_type,0
		BTFSS	3,2
		GOTO	main9
		MOVLW	IP_PROTO		; Branch to IP protocol processing
		SUBWF	eth_type1,0
		BTFSC	3,2
		GOTO	do_ip
		MOVLW	ARP_PROTO		; Branch to ARP protocol processing
		SUBWF	eth_type1,0
		BTFSC	3,2
		GOTO	do_arp			; Branch to ARP protcol processing
;		goto	main9				; other
;-----------------------------------------------------------------------------------
main9
		bcf	STATUS,IRP	
		bcf	STATUS,RP1	
		bsf	STATUS,RP0	
		MOVLW	PAGE_START		; Error Check and Recovery
		SUBWF	ne_next,0
		BTFSS	3,0
		GOTO	overflow2
		MOVLW	PAGE_STOP		; Error Check and Recovery
		SUBWF	ne_next,0
		BTFSC	3,0
		GOTO	overflow2

		DECF	ne_next,1					; Calculate next boundary
		MOVLW	PAGE_START	
		SUBWF	ne_next,0
		BTFSC	3,0
		GOTO	packet11

		MOVLW	PAGE_STOP-1	
		MOVWF	ne_next
packet11
		bcf	STATUS,RP0	
		
		CLRF	PORTC		
		movlw	B'00100010'
		call	assert_wr0
		
		MOVLW	.3		
		MOVWF	PORTC
		MOVLW	ne_next		
		MOVWF	FSR
		MOVF	INDF,0			; Set boundary pointer
		call	assert_wr0
		goto	main99



;-----------------------------------------------------------------------------------
;		ARP protocol processing
;-----------------------------------------------------------------------------------
do_arp
		bcf	STATUS,RP0	
		MOVLW	NE_SIZE + PACKET_SIZE	
		MOVWF	remote_adr
		MOVLW	ne_cn_l			
		MOVWF	FSR
		MOVF	INDF,0			
		MOVWF	remote_len
		INCF	FSR,1			
		MOVF	INDF,0			
		MOVWF	remote_len1

		MOVLW	NE_SIZE + PACKET_SIZE	
		SUBWF	remote_len,1
		movlw	1
		btfss	STATUS,C		
		subwf	remote_len1,1		
		call	remote_read

		MOVLW	ip_header				; Read out data to area starting from address ip_header
		MOVWF	FSR
get_packet10
		movf	remote_len,0		
		iorwf	remote_len1,0		
		btfsc	STATUS,Z		
		goto	get_packet2		; Read in complete?
		
		bcf	PORTE,0			
		btfss	PORTC,5						; ~Wait
		goto	$-1
		MOVF	PORTD,0			
		bsf	PORTE,0			
		movwf	INDF			
		INCF	FSR,1			
		
		movlw	1			; Decrement register
		SUBWF	remote_len,1		
		btfss	STATUS,C		
		SUBWF	remote_len1,1		
		
		btfss	FSR,7						; over flow?
		goto	get_packet10
;	after 80h
get_packet20
		movf	remote_len,0		
		iorwf	remote_len1,0		
		btfsc	STATUS,Z		
		goto	get_packet2		; Read in complete
		
		bcf	PORTE,0			
		btfss	PORTC,5						; ~Wait
		goto	$-1
	;	MOVF	PORTD,0			
		bsf	PORTE,0			
	;	movwf	INDF

		movlw	1
		subwf	remote_len,1		
		btfss	STATUS,C		
		subwf	remote_len1,1		
		goto	get_packet20
;
;		Analysis of ARP header
get_packet2
		MOVLW	0					; If arp_code not 0001, discard
		SUBWF	arp_ope,0
		BTFSS	3,2
		GOTO	main9

		MOVLW	1			
		SUBWF	arp_ope1,0
		BTFSC	3,2
		GOTO	arp_req

		MOVLW	2			
		SUBWF	arp_ope1,0
		BTFSC	3,2
		GOTO	arp_reply
		
		goto	main9
arp_reply
		MOVLW	HIGH (ser_arp)		
		MOVWF	PCLATH
		goto	ser_arp
arp_req
arp
		MOVLW	this_ip				; this_ip in BANK 1
		MOVWF	FSR
		MOVF	arp_dest_ip,0			; ARP IP address same as own?
		SUBWF	INDF,0
		BTFSS	3,2
		GOTO	main9
		INCF	FSR,1			

		MOVF	arp_dest_ip1,0		
		SUBWF	INDF,0
		BTFSS	3,2
		GOTO	main9
		INCF	FSR,1			

		MOVF	arp_dest_ip2,0		
		SUBWF	INDF,0
		BTFSS	3,2
		GOTO	main9
		INCF	FSR,1			
		MOVF	arp_dest_ip3,0		
		SUBWF	INDF,0
		BTFSS	3,2
		GOTO	main9


;	Own ARP request
		call	prepare_ether2		

		movlw	COM_PROTO		
		call	assert_wr
		movlw	ARP_PROTO		
		call	assert_wr

		MOVLW	arp1 >> 8
		movwf	PCLATH
		call	arp1			
		CLRF	PCLATH
		CLRF	PORTC			
		movlw	B'00100010'
		call	assert_wr0
		
		MOVLW	.4			
		MOVWF	PORTC
		movlw	PAGE_BEGIN		 
		call	assert_wr0
		
		MOVLW	.5			
		MOVWF	PORTC
		movlw	.60			
		call	assert_wr0
		
		MOVLW	.6			
		MOVWF	PORTC
		DB	01,00		
		call	assert_wr0
		
		call	transmit			; Send ARP response
		goto	main9


;-----------------------------------------------------------------------------------
;		IP protocol Rx processing
;-----------------------------------------------------------------------------------
do_ip
		bcf	STATUS,RP0	
		MOVLW	NE_SIZE + PACKET_SIZE	
		MOVWF	remote_adr
		MOVLW	ne_cn_l			
		MOVWF	FSR
	;	mov	fsr,#ip_length
		MOVF	INDF,0			
		MOVWF	remote_len
		INCF	FSR,1			
		MOVF	INDF,0			
		MOVWF	remote_len1

		MOVLW	NE_SIZE + PACKET_SIZE				; Subtract Ether header length from number of Rx bytes
		SUBWF	remote_len,1
		movlw	1
		btfss	STATUS,C		
		subwf	remote_len1,1		
		call	remote_read
;
;	Rx of IP packet
		MOVLW	ip_header				; Read in data to address ip_header
		MOVWF	FSR

		bcf	PORTE,0			
		btfss	PORTC,5						; ~Wait
		goto	$-1
		MOVF	PORTD,0			
		bsf	PORTE,0			
		movwf	INDF					; Read 1 byte!
		INCF	FSR,1			

		movlw	1			
		subwf	remote_len,1		
		btfss	STATUS,C		
		subwf	remote_len1,1		

		MOVF	ip_ver_len,0		; Calculate remaining number of bytes
		MOVWF	gcn1
		MOVLW	0FH			
		ANDWF	gcn1,1

		BCF	3,0			
		RLF	gcn1,1			
		RLF	gcn1,1			
		DECF	gcn1,1				; Calculate IP header size from IP header
		call	copy_toram		; Transfer to RAM

ip_get_packet2
		MOVLW	45H			; IP Version 4 ?
		SUBWF	ip_ver_len,0
		BTFSS	3,2
		GOTO	ip_get_packet9
		MOVLW	TCP_PROTO			; To TCP Rx processing
		SUBWF	ip_proto,0
		BTFSC	3,2
		GOTO	tcp
		MOVLW	UDP_PROTO			; To UDP Rx processing
		SUBWF	ip_proto,0
		BTFSC	3,2
		GOTO	udp
		MOVLW	ICMP_PROTO		; To ICMP Rx processing
		SUBWF	ip_proto,0
		BTFSC	3,2
		GOTO	icmp
ip_get_packet9
		call	abort				; Abort remote DMA
		goto	main9

;-----------------------------------------------------------------------------------
;		Read in gcn1 items of data
;-----------------------------------------------------------------------------------
copy_toram
		bcf	PORTE,0		
		btfss	PORTC,5					; ~Wait
		goto	$-1
		MOVF	PORTD,0		
		bsf	PORTE,0		
		movwf	INDF				; *INDF = data
		INCF	FSR,1					; fsr++
		
		movlw	1		
		subwf	remote_len,1	
		btfss	STATUS,C	
		subwf	remote_len1,1	
		
		DECFSZ	gcn1,1		
		GOTO	copy_toram
		retURN



;-----------------------------------------------------------------------------------
;		Put remaining packets in RAM buffer
;-----------------------------------------------------------------------------------
get_remain
get_remain0
		movf	remote_len,0	
		iorwf	remote_len1,0	
		btfsc	STATUS,Z	
		goto	get_remain9	
		
		bcf	PORTE,0		
		btfss	PORTC,5					; ~Wait
		goto	$-1
		MOVF	PORTD,0		
		bsf	PORTE,0		
		movwf	INDF				; Set in front
		INCF	FSR,1		
		
		movlw	1		
		subwf	remote_len,1	
		btfss	STATUS,C	
		subwf	remote_len1,1	
		
		movlw	.16+.128
		addwf	FSR,0		
		btfss	STATUS,C	
		goto	get_remain0

		MOVLW	20H				; Change banks and continue read in
		MOVWF	FSR
		bsf	STATUS,IRP	
get_remain20
		movf	remote_len,0	
		iorwf	remote_len1,0	
		btfsc	STATUS,Z	
		goto	get_remain9		; End of read in
		
		bcf	PORTE,0		
		btfss	PORTC,5					; ~Wait
		goto	$-1
		MOVF	PORTD,0		
		bsf	PORTE,0		
		movwf	INDF				; Set in back
		INCF	FSR,1		
		
		movlw	1
		subwf	remote_len,1	
		btfss	STATUS,C	
		subwf	remote_len1,1	
		
		movlw	.16+.128
		addwf	FSR,0		
		btfss	STATUS,C	
		goto	get_remain20

get_remain30
		call	abort
		
;		movf	remote_len,0	
;		iorwf	remote_len[1],0
;		btfsc	z
;		goto	get_remain9		; Read in complete
;		
;		bcf	RD
;		btfss	RDY			; ~Wait
;		goto	$-1
;		bsf	RD
;
;		movlw	1
;		subwf	remote_len[0],1
;		btfss	STATUS,C
;		subwf	remote_len[1],1
;		goto	get_remain30
get_remain9
		bcf	STATUS,IRP	
		retURN




;-----------------------------------------------------------------------------------
;		ICMP protocol processing
;-----------------------------------------------------------------------------------
icmp
		call	get_remain			; Transfer data from RTL8019
		MOVLW	.8			; If type is not 08h, discard
		SUBWF	icmp_type,0
		BTFSS	3,2
		GOTO	main9
		MOVLW	0				; If code is not 08h, discard
		SUBWF	icmp_code,0
		BTFSS	3,2
		GOTO	main9
ping
		MOVLW	ICMP_PROTO			; protocol=ICMP
		MOVWF	proto
		call	prepare_ip			; preparation of IP packet
;
		MOVLW	PACKET_SIZE + IP_SIZE	
		MOVWF	remote_adr
		MOVLW	PAGE_BEGIN		
		MOVWF	remote_adr1
		MOVF	ip_length1,0				;ne_cn_l
		MOVWF	remote_len
		MOVLW	IP_SIZE - 1		
		SUBWF	remote_len,1
		CLRF	remote_len1		
		call	remote_write
		
		call	clear_sum			; clear checksum value
		
		MOVLW	10H			
		MOVWF	PORTC
		call	assert_wr2times			; type : code
		call	assert_wr2times			; sum High : Low
		
		MOVF	ip_length1,0				;ne_cn_l
		MOVWF	gcn1
		MOVLW	IP_SIZE + 4		;sub	gcn1,#IP_SIZE + 4
		SUBWF	gcn1,1
		MOVLW	icmp_header + 4		
		MOVWF	FSR
icmp10
		MOVF	INDF,0			
		INCF	FSR,1			
		call	assert_wr
		
		movlw	.16 + .128
		addwf	FSR,0			
		btfsc	STATUS,C		
		goto	icmp20
icmp19		DECFSZ	gcn1,1			
		GOTO	icmp10
		bcf	STATUS,IRP		

		DB	01,00		;clrw
		call	assert_wr

		MOVLW	PACKET_SIZE + IP_SIZE + 2	
		MOVWF	remote_adr
		MOVLW	PAGE_BEGIN		
		MOVWF	remote_adr1
		call	set_checksum
		
		MOVLW	4H			
		MOVWF	PORTC
		movlw	PAGE_BEGIN			; transmit page is start page 
		call	assert_wr0
		
		MOVLW	.5			
		MOVWF	PORTC
		MOVLW	ne_cn_l			
		MOVWF	FSR
		MOVF	INDF,0			
		call	assert_wr0
		
		MOVLW	.6			
		MOVWF	PORTC
		INCF	FSR,1			
		MOVF	INDF,0			
		call	assert_wr0
		
		call	transmit			; send PING response
		goto	main9
icmp20
		MOVLW	20H			
		MOVWF	FSR
		bsf	STATUS,IRP		
		goto	icmp19



;-----------------------------------------------------------------------------------
;		UDP
;-----------------------------------------------------------------------------------
udp
		MOVLW	.8			
		MOVWF	gcn1
		call	copy_toram
		
;	BOOTP port check
		MOVLW	BOOTPC_PORT / .256	
		SUBWF	udp_tar_port,0
		BTFSS	3,2
		GOTO	udp_1
		MOVLW	BOOTPC_PORT & 0FFH		; To BOOTP processing
		SUBWF	udp_tar_port1,0
		BTFSC	3,2
		GOTO	bootp_res

		MOVLW	this_ip			
		MOVWF	FSR
		MOVF	INDF,0				; Tx data to own address?
		SUBWF	ip_dest,0
		BTFSS	3,2
		GOTO	main9

		INCF	FSR,1			
		MOVF	INDF,0			
		SUBWF	ip_dest1,0
		BTFSS	3,2
		GOTO	main9

		INCF	FSR,1			
		MOVF	INDF,0			
		SUBWF	ip_dest2,0
		BTFSS	3,2
		GOTO	main9
		INCF	FSR,1			
		MOVF	INDF,0			
		SUBWF	ip_dest3,0
		BTFSS	3,2
		GOTO	main9

;	LCD port check
udp_1
		MOVLW	lcd_port & 0FFH		
		MOVWF	FSR
		MOVF	INDF,0			
		SUBWF	udp_tar_port,0
		BTFSS	3,2
		GOTO	udp_2
		INCF	FSR,1			
		MOVF	INDF,0			
		SUBWF	udp_tar_port1,0
		BTFSC	3,2
		GOTO	udp_lcd_tag
udp_2
		MOVLW	para_port & 0FFH	
		MOVWF	FSR
		MOVF	INDF,0			
		SUBWF	udp_tar_port,0
		BTFSS	3,2
		GOTO	udp_3

		INCF	FSR,1			
		MOVF	INDF,0			
		SUBWF	udp_tar_port1,0
		BTFSC	3,2
		GOTO	udp_parallel_tag
udp_3
		MOVLW	serial_port & 0FFH	
		MOVWF	FSR
		MOVF	INDF,0			
		SUBWF	udp_tar_port,0
		BTFSS	3,2
		GOTO	udp_4
		INCF	FSR,1			
		MOVF	INDF,0			
		SUBWF	udp_tar_port1,0
		BTFSC	3,2
		GOTO	udp_serial_tag
udp_4
;
;		add new funciton this
;
		goto	main9
udp_lcd_tag
		movlw	udp_lcd >> 8
		movwf	PCLATH
		GOTO	udp_lcd
;
;		Parallel I/O processing (UDP)
;
udp_parallel_tag
		MOVLW	udp_data		
		MOVWF	FSR
		call	get_remain
		MOVLW	HIGH (udp_parallel)	
		MOVWF	PCLATH
		goto	udp_parallel
udp_serial_tag
		MOVLW	HIGH (udp_serial)	
		MOVWF	PCLATH
		goto	udp_serial

;-----------------------------------------------------------------------------------
get_dgram
		movf	remote_len,0		
		iorwf	remote_len1,0		
		btfsc	STATUS,Z		
		goto	get_dgram9
		
		bcf	PORTE,0			
		btfss	PORTC,5						; ~Wait
		goto	$-1
		MOVF	PORTD,0			
		bsf	PORTE,0			
		movwf	data0
		
		movlw	1
		subwf	remote_len,1		
		btfss	STATUS,C		
		subwf	remote_len1,1		
		
		BCF	3,0							; OK
		retURN
get_dgram9
		BSF	3,0							; EOT
		RETURN


;-----------------------------------------------------------------------------------
;		BOOTP response
;-----------------------------------------------------------------------------------
bootp_res
		call	get_remain

		MOVLW	this_ip		
		MOVWF	FSR
		MOVF	INDF,0		
		INCF	FSR,1
		iorwf	INDF,0
		INCF	FSR,1
		iorwf	INDF,0
		INCF	FSR,1
		iorwf	INDF,0
		btfss	STATUS,Z
		goto	main9
		
		MOVLW	HIGH (bootp)	
		MOVWF	PCLATH
		call	bootp
		MOVLW	HIGH (bootp_res)
		MOVWF	PCLATH
		
		movlw	35h	; 
		call	assert_wr
		movlw	01h
		call	assert_wr
		movlw	3		; request
		call	assert_wr
		
		movlw	3dh	; 
		call	assert_wr
		movlw	07h
		call	assert_wr
		movlw	01h
		call	assert_wr
		MOVLW	mymac		
		MOVWF	FSR
		movlw	6
		call	transmit_nbytes			; Own MAC
		
		movlw	.54	; 
		call	assert_wr
		movlw	04h
		call	assert_wr
		movlw	0c0h
		call	assert_wr
		movlw	0a8h
		call	assert_wr
		movlw	0h
		call	assert_wr
		movlw	3h
		call	assert_wr

		movlw	.50	; 
		call	assert_wr
		movlw	4
		call	assert_wr
		
		MOVLW	dhcp_user_ip		
		MOVWF	FSR
		movlw	4
		call	transmit_nbytes
		
		
		movlw	0ffh
		call	assert_wr
		
		MOVLW	.64 - .7 - .9 - .1 - .6 - .6
		MOVWF	gcn1
bootp_40
		DB	01,00		;clrw
		call	assert_wr
		DECFSZ	gcn1,1		
		GOTO	bootp_40
		MOVLW	HIGH (bootp_tx)
		MOVWF	PCLATH
		call	bootp_tx
		MOVLW	HIGH (bootp_40)
		MOVWF	PCLATH
;
;	Here we register the IP from the DHCP server as our own
		MOVLW	this_ip		
		MOVWF	FSR
		MOVF	dhcp_user_ip,0	
		MOVWF	INDF
		INCF	FSR,1
		MOVF	dhcp_user_ip1,0	
		MOVWF	INDF
		INCF	FSR,1
		MOVF	dhcp_user_ip2,0	
		MOVWF	INDF
		INCF	FSR,1
		MOVF	dhcp_user_ip3,0	
		MOVWF	INDF
		bsf	STATUS,RP0
		CLRF	dhcp_done
		BCF	STATUS,RP0

;
;	Display received IP address on LCD
		bcf	PORTB,2
		MOVLW	0C0H		
		MOVWF	d4
		MOVLW	HIGH (write_lcd4)
		MOVWF	PCLATH
		call	write_lcd4			; Go to second line
		
		MOVLW	HIGH(print_ip)
		MOVWF	PCLATH
		call	print_ip			; Display!
		CLRF	PORTB
		CLRF	PCLATH
		goto	main9




;-----------------------------------------------------------------------------------
;		TCP
;-----------------------------------------------------------------------------------
tcp
		MOVLW	.20			; Read in 20 bytes
		MOVWF	gcn1
		call	copy_toram
		
		MOVLW	http_port & 0ffh		
		MOVWF	FSR
		MOVF	INDF,0		; Matches http port on EEPROM?
		SUBWF	tcp_tar_port,0
		BTFSS	3,2
		GOTO	tcp9

		INCF	FSR,1
				
		MOVF	INDF,0
		SUBWF	tcp_tar_port1,0
		BTFSC	3,2
		GOTO	tcp_www

tcp9		goto	main9				; Nothing besides http responding to TCP
;
;	http processing
tcp_www
		MOVLW	this_ip		
		MOVWF	FSR
		MOVF	INDF,0
		INCF	FSR,1
		iorwf	INDF,0
		INCF	FSR,1
		iorwf	INDF,0
		INCF	FSR,1
		iorwf	INDF,0
		btfsc	STATUS,Z
		goto	main9			; if the IP address is 0.0.0.0, stop processing
		
		btfsc	tcp_flags,5	;TCP_URG			; URG
		goto	main9			; discard
		
		MOVLW	HIGH(search_socket)
		MOVWF	PCLATH
		call	search_socket		; search socket
		MOVLW	HIGH (tcp_www)
		MOVWF	PCLATH
		btfsc	STATUS,C
		goto	state1			; state exists?
		
		call	no_socket		; socket creation
		goto	main9
;
;	socket state1
state1
		MOVLW	.12		;add	FSR,#12
		ADDWF	FSR,1
	;	mov	pclath,#print_hex>>8
	;	mov	pclath,#$>>8
;
		MOVF	INDF,0		
		SUBWF	tcp_seq_no,0
		BTFSS	3,2
		GOTO	state12
		INCF	FSR,1
		MOVF	INDF,0		
		SUBWF	tcp_seq_no1,0
		BTFSS	3,2
		GOTO	state12
		INCF	FSR,1
		MOVF	INDF,0		
		SUBWF	tcp_seq_no2,0
		BTFSS	3,2
		GOTO	state12
		INCF	FSR,1
		MOVF	INDF,0		
		SUBWF	tcp_seq_no3,0
		BTFSS	3,2
		GOTO	state12
		MOVLW	.15		
		SUBWF	FSR,1
		call	state2
state12		CLRF	PCLATH
		goto	main9
		
state2
		MOVLW	HIGH(state_table)
		MOVWF	PCLATH

		MOVF	INDF,0
		andlw	7fh
		ADDWF	2,1		
state_table
		goto	job_SYN_RCVD		;
		goto	job_ESTAB		;
		goto	job_CLOSE_WAIT		;
	;	nop	;goto	job_LAST_ACK	;
		goto	main9
		goto	job_FIN_WAIT_1		;
		goto	job_FIN_WAIT_2		;
	;	nop	;goto	job_CLOSING	;
		goto	main9
	;	nop	;goto	job_TIME_WAIT	;
		goto	main9
		goto	main9		;ACK,PSH,RST,SYN,FIN





;-----------------------------------------------------------------------------------
;		receive SYN, 
;		send SYN,ACK, wait for ACK
job_SYN_RCVD
		btfsc	tcp_flags,TCP_RST
		goto	recv_rst
		btfsc	tcp_flags,TCP_FIN
		goto	recv_fin
		btfss	tcp_flags,TCP_ACK
		RETURN

		MOVLW	ESTAB	;mov	INDF,#ESTAB
		MOVWF	INDF
		bcf	STATUS,IRP
		RETURN
recv_rst
		clrF	INDF
		bcf	STATUS,IRP
		RETURN

;-----------------------------------------------------------------------------------
;
;
job_FIN_WAIT_1
		btfsc	tcp_flags,TCP_RST
		goto	recv_rst
		btfss	tcp_flags,TCP_ACK
		RETURN
		
		MOVLW	FIN_WAIT_2
		MOVWF	INDF
		bcf	STATUS,IRP
		RETURN

;-----------------------------------------------------------------------------------
;
;
job_FIN_WAIT_2
		btfsc	tcp_flags,TCP_RST
		goto	recv_rst
		btfss	tcp_flags,TCP_FIN
		RETURN
		
		clrF	INDF
		bcf	STATUS,IRP

		call	inc_ack_no
		call	send_ack
		RETURN

;-----------------------------------------------------------------------------------
;
;
		nop
job_ESTAB
		btfsc	tcp_flags,TCP_RST
		goto	recv_rst
		btfsc	tcp_flags,TCP_FIN
		goto	recv_fin
		
		INCF	FSR,1
		MOVLW	HIGH (job_ESTAB)
		MOVWF	PCLATH
		MOVF	INDF,0
		andlw	0fh
		ADDWF	2,1		;jmp	pc+w
		goto	ESTAB_00
		goto	ESTAB_01
		goto	ESTAB_02
		goto	ESTAB_03
		goto	ESTAB_99


recv_fin
		MOVLW	0
		MOVWF	INDF
		bcf	STATUS,IRP
		
		call	inc_ack_no
		call	send_ack
		RETURN

;-----------------------------------------------------------------------------------
;
;
job_CLOSE_WAIT
		MOVLW	0
		MOVWF	INDF
		bcf	STATUS,IRP
		
		call	send_fin
		RETURN
ESTAB_99
		decF	FSR,1
		MOVLW	FIN_WAIT_1
		MOVWF	INDF
		bcf	STATUS,IRP
		
		call	send_fin
		
		MOVF	com_fsr,0
		MOVWF	FSR
		MOVLW	.8
		ADDWF	FSR,1
		call	inc_seq_no
		RETURN

;-----------------------------------------------------------------------------------
;		ESTABLISH
;
ESTAB_00
		incF	INDF,1
		bcf	STATUS,IRP
estab0
		MOVLW	HIGH(get_nextbyte)
		MOVWF	PCLATH

		call	get_nextbyte		; get data from buffer
		MOVLW	HIGH (estab0)
		MOVWF	PCLATH
		
		MOVLW	0			; end?
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	estab1
			; newline character?
		MOVLW	0AH
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	estab1
			; found '?' character? (=GET command processing)
		MOVLW	'?'
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	parse_cgi_tag
		goto	estab0
parse9

;-----------------------------------------------------------------------------------
;
;
estab1
		call	abort			; abort buffer transfer
		call	add_ack_no		; increment ACK number
;		call	send_ack		; send ACK
		
		MOVLW	014H			; bank address = 14h fan
		MOVWF	wk
		goto	send_mes		; send message
;
;		for jumping between banks
parse_cgi_tag
		MOVLW	HIGH(parse_cgi)
		MOVWF	PCLATH

		goto	parse_cgi




ESTAB_01
		incF	INDF,1
		bcf	STATUS,IRP
	;	call	send_ack
	;
		MOVLW	017H	
		MOVWF	wk
		goto	send_mes		; send message
ESTAB_02
		incF	INDF,1
		bcf	STATUS,IRP
	;	call	send_ack
		
		;mov	wk,#01Ah		; bank address = 19h
		MOVLW	01AH
		MOVWF	wk
		goto	send_mes		; send message
ESTAB_03
		incF	INDF,1
		bcf	STATUS,IRP
	;	call	send_ack
		
		;mov	wk,#01Dh		; bank address = 1bh
		MOVLW	01DH
		MOVWF	wk
		goto	send_mes		; send message
;
;		abort remote DMA transfer
abort
		CLRF	PORTC	 
		movlw	22h
		call	assert_wr0		; return to PAGE0
		
		MOVLW	0ah
		MOVWF	PORTC
		DB	01,00		;clrw
		call	assert_wr0
		
		MOVLW	0bh
		MOVWF	PORTC
		DB	01,00		;clrw
		call	assert_wr0
		RETURN





;-----------------------------------------------------------------------------------
;		Tx RST packet
send_rst
		MOVLW	B'000100'		; RST
		MOVWF	state
		goto	send_common


;-----------------------------------------------------------------------------------
;		Tx FIN packet
send_fin
		MOVLW	B'010001'		; ACK+FIN
		MOVWF	state
		goto	send_common


;-----------------------------------------------------------------------------------
;		Tx ACK packet
send_ack
		MOVLW	B'010000'		; ACK
		MOVWF	state
;		goto	send_common
send_common
		MOVLW	0		
		MOVWF	ip_length
		;mov	ip_length[1],#IP_SIZE + TCP_SIZE
		MOVLW	IP_SIZE + TCP_SIZE
		MOVWF	ip_length1
		
		MOVLW	TCP_PROTO	
		MOVWF	proto
		call	prepare_ip
		
		MOVLW	PACKET_SIZE + IP_SIZE	
		MOVWF	remote_adr
		;mov	remote_adr[1],#PAGE_BEGIN
		MOVLW	PAGE_BEGIN
		MOVWF	remote_adr1

		;mov	remote_len[0],#20		; 20 bytes
		MOVLW	.20
		MOVWF	remote_len
		;mov	remote_len[1],#0
		MOVLW	0
		MOVWF	remote_len1
		call	remote_write
		
		call	clear_sum			; clear checksum value
		
		MOVLW	http_port & 0ffh
		MOVWF	FSR
		movlw	2
		call	transmit_nbytes			; own port number
		
		MOVLW	tcp_src_port
		MOVWF	FSR
		movlw	2
		call	transmit_nbytes			; destination port number

		MOVF	com_fsr,0
		MOVWF	FSR
		MOVLW	.8
		ADDWF	FSR,1
		bsf	STATUS,IRP
		movlw	4+4
		call	transmit_nbytes			; own SEQNO
		bcf	STATUS,IRP
		
		movlw	50h			; 20bytes
		call	assert_wr
		MOVF	state,0			;mov	w,state
		call	assert_wr
		
		movlw	08h			; window(high)
		call	assert_wr
		movlw	00h			; window(low)
		call	assert_wr
		
		call	assert_wr2times			; tcp sum
		call	assert_wr2times			; exception pointer
		
		call	calc_tcp_sum			; calculation of TCP SUM
		
		MOVLW	4h
		MOVWF	PORTC
		movlw	PAGE_BEGIN			; transmit page is start page 
		call	assert_wr0
		
		MOVLW	5
		MOVWF	PORTC
		movlw	.60				; Tx 60 bytes
		call	assert_wr0
		
		MOVLW	6
		MOVWF	PORTC
		DB	01,00		;clrw					; Upper transfer byte = 0
		call	assert_wr0
		call	transmit			; Send!!
		RETURN

;-----------------------------------------------------------------------------------
;
;
send_mes
		MOVLW	assert_wr2x & 0ffh	; Send job to RTL8019
		MOVWF	dest
		MOVLW	HIGH (assert_wr2x)	
		MOVWF	dest1		
send_mes_head
				; temporarily set for 65535 byte transfer
;-------
		MOVLW	PACKET_SIZE + IP_SIZE
		MOVWF	remote_adr
		MOVLW	PAGE_BEGIN
		MOVWF	remote_adr1

		MOVLW	0FFH
		MOVWF	remote_len
		MOVLW	0FFH
		MOVWF	remote_len1

;-------		

		;mov	remote_len[1],#0ffh		; 
		call	remote_write
		
		;clr	remote_len[0]
		;clr	remote_len[1]
		CLRF	remote_len
		CLRF	remote_len1
		
		call	clear_sum			; clear checksum value
		
		MOVLW	http_port & 0ffh
		MOVWF	FSR
		movlw	2
		call	transmit_nbytes2		; own port number
		
		MOVLW	tcp_src_port
		MOVWF	FSR
		movlw	2
		call	transmit_nbytes2		; destination port number

		bsf	STATUS,IRP
		MOVF	com_fsr,0
		MOVWF	FSR
		MOVLW	.8
		ADDWF	FSR,1
		movlw	4
		call	transmit_nbytes2		; own SEQNO
		bcf	STATUS,IRP
	
		MOVLW	tcp_seq_no
		MOVWF	FSR
		movlw	4
		call	transmit_nbytes2		; destination SEQNO+1
		
		movlw	50h		; 20bytes
		call	assert_wr2
		movlw	B'011000'
		call	assert_wr2
		
		movlw	08h		; window(high)
		call	assert_wr2
		movlw	00h		; window(low)
		call	assert_wr2
		
		DB	01,00		;clrw
		call	assert_wr2		; tcp sum
		DB	01,00		;clrw
		call	assert_wr2		; tcp sum
		DB	01,00		;clrw
		call	assert_wr2		; exception pointer
		DB	01,00		;clrw
		call	assert_wr2		; exception pointer
	
		CLRF	ind
		bsf	STATUS,RP1
		bcf	STATUS,RP0
		MOVF	wk,0		; Read out address=[wk:ind]
		MOVWF	EEADRH
send_mes0
		bsf	STATUS,RP1
		bcf	STATUS,RP0
		MOVF	ind,0		
		MOVWF	EEADR
		bsf	STATUS,RP0
		bsf	EECON1,7		;eepgd
		bsf	EECON1,0	;eecon1.0 ; read out data from code area
		nop				; dummy cycle
		nop
		bcf	STATUS,RP0
		MOVF	EEDATH,0		; move (read out data) to work area
		MOVWF	getmes_wk
		MOVF	EEDATA,0	
		MOVWF	getmes_wk1

		bcf	STATUS,RP1
		
		RLF	getmes_wk1,0		
		RLF	getmes_wk,1		
		MOVF	getmes_wk,0		; upper 7 bits equal to 0?
		MOVWF	data0
		MOVLW	7FH		
		ANDWF	data0,1
		MOVF	data0,1		
		btfsc	STATUS,Z
		goto	send_mes9		; if the upper 7 bits are 0, quit
;
;		if the upper 7 bits are metacharacters, branch operation
		MOVLW	'$'  
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	ctrl_code2
 		MOVLW	'@'
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	ctrl_code3
 		MOVLW	'%'
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	ctrl_code4

		MOVLW	'~'
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	ctrl_code5
		
		MOVF	data0,0			;
		call	assert_wr2
		
		MOVF	getmes_wk1,0		; transfer lower 7 bits to RTL8019 buffer
		andlw	7fh
		call	assert_wr2
		
		MOVLW	1					; ind++
		ADDWF	ind,1
		bsf	STATUS,RP1
		bcf	STATUS,RP0
		btfsc	STATUS,C
		INCF	EEADRH,1
		goto	send_mes0
send_mes9

send_mes_foot
		call	abort			; abort remote DMA transfer
		
	
		MOVF	remote_len,0
		MOVWF	ip_length1
	
		MOVF	remote_len1,0
		MOVWF	ip_length

		call	calc_tcp_sum		; calculate TCP SUM
		
		MOVLW	.20		;add	ip_length[1],#20; add 20
		ADDWF	ip_length1,1
		movlw	1
		btfsc	STATUS,C
		addwf	ip_length,1		;addwf	ip_length[0]
		
		MOVLW	TCP_PROTO	; TCP packet
		MOVWF	proto
		call	prepare_ip		; preparation for IP protocol
		
		MOVLW	4h
		MOVWF	PORTC
		movlw	PAGE_BEGIN			; transmit page is start page 
		call	assert_wr0
		
		MOVLW	PACKET_SIZE			; add 1 to number of Tx bytes packet size 6+6+2
		addWF	ip_length1,1
		movlw	1
		btfsc	STATUS,C
		addwf	ip_length,1	
		
		MOVLW	6
		MOVWF	PORTC
		MOVF	ip_length,0		
		call	assert_wr0
		MOVF	ip_length,1		
		btfsc	STATUS,Z
		goto	send_mes_foot1
send_mes_foot2
		MOVLW	5
		MOVWF	PORTC
		MOVF	ip_length1,0	
		call	assert_wr0
		call	transmit			; Send!!
		
;
;	Additional Code
send_mes_foot3
		MOVLW	PACKET_SIZE+IP_SIZE+TCP_SIZE
		SUBWF	ip_length1,1	
	
		movlw	1
		btfss	STATUS,C
	
		SUBWF	ip_length,1	
		
		MOVF	com_fsr,0
		MOVWF	FSR
		MOVLW	.8
		ADDWF	FSR,1
		call	add_seq_no			; add to seq no
		RETURN

send_mes_foot1
 		MOVLW	.60
		SUBWF	ip_length1,0
		BTFSC	3,0
		GOTO	send_mes_foot2
		MOVLW	5
		MOVWF	PORTC
		movlw	.60				; MINIMUM 60bytes
		call	assert_wr0
		call	transmit
		goto	send_mes_foot3

;-----------------------------------------------------------------------------------
;		A/D conversion
;
ad_in
		RLF	getmes_wk1,1	
		RLF	getmes_wk1,1		
		RLF	getmes_wk1,1		
		MOVLW	B'00111000'	 
		ANDWF	getmes_wk1,1
		MOVLW	B'10000001'	
		IORWF	getmes_wk1,1
		MOVF	getmes_wk1,0		; set value in ADCON1
		MOVWF	ADCON1
		MOVLW	1	
		MOVWF	wait_cn
		MOVLW	HIGH (wait_ms)
		MOVWF	PCLATH

		call	wait_ms				; sampling time 20 us wait
		MOVLW	HIGH (ad_in)
		MOVWF	PCLATH
		
		bsf	ADCON1,2		; A/D conversion start
		btfsc	ADCON1,2		; A/D conversion wait
		goto	$-1
		
		MOVF	ADRESH,0			; conversion result in val[1]:val[0]
		MOVWF	val1
		bsf	STATUS,RP0
		MOVF	ADRESL,0	
		bcf	STATUS,RP0
		movwf	val		
		
		btfss	getmes_wk1,5				; RA5 or not?
		goto	ad_in1				; not RA5
	;
	; Multiply A/D conversion result by 5
	;
		BCF	3,0		
		RLF	val,1		
		RLF	val1,1		
		BCF	3,0	
		RLF	val,1		
		RLF	val1,1		
		
		MOVF	ADRESH,0	
		ADDWF	val1,1
		bsf	STATUS,RP0
		MOVF	ADRESL,0
		bcf	STATUS,RP0
		addwf	val,1
		btfsc	STATUS,C
		INCF	val1,1	

		MOVLW	decimal_top & 0ffh	; initial value of storage space
		MOVWF	FSR
		bsf	STATUS,IRP			; IRP=1
		MOVLW	HIGH (divide16)
		MOVWF	PCLATH

		call	divide16
ad_in1
		MOVLW	HIGH (put_decimal16)
		MOVWF	PCLATH

		call	put_decimal16			; convert to decimal
		MOVLW	HIGH (ad_in1)
		MOVWF	PCLATH
		goto	ctrl_next



;-----------------------------------------------------------------------------------
;	SOCKET STATUS
ctrl_code5
		MOVLW	7FH		
		ANDWF	getmes_wk1,1
		swapf	getmes_wk1,1	
		movf	getmes_wk1,0	
		movwf	FSR
		bsf	STATUS,IRP
		
;		movlw	put_socket_stat >> 8	
;		MOVWF	PCLATH
;		call	put_socket_stat			; show socket status
		bcf	STATUS,IRP
		goto	ctrl_next
;--------------------------------------------------------------------------
;	TRIS
;	Display of input/output
ctrl_code4
		MOVLW	7FH		
		ANDWF	getmes_wk1,1
		MOVF	getmes_wk1,0
		MOVWF	FSR
		SWAPF	FSR,1		
		MOVLW	0FH		
		ANDWF	FSR,1
		MOVLW	PORTA | 80H	
		ADDWF	FSR,1
		
		MOVF	getmes_wk1,0
		call	getbitpos
		MOVF	INDF,0		
		ANDWF	data0,1
		BTFSC	3,2		
		GOTO	ctrl_out
		goto	ctrl_in
;
;		return bit position
;
getbitpos
		movwf	wk
		MOVLW	1	
		MOVWF	data0
		MOVLW	07H		
		ANDWF	wk,1
		BTFSC	3,2		
		GOTO	getbitpos9
getbitpos0
		BCF	3,0	
		RLF	data0,1	
		DECFSZ	wk,1		
		GOTO	getbitpos0
getbitpos9	RETURN


;-----------------------------------------------------------------------------------
;	PARALLEL
;	display of current High/Low
ctrl_code3
		MOVLW	7FH		
		ANDWF	getmes_wk1,1
		MOVF	getmes_wk1,0
		MOVWF	FSR
		SWAPF	FSR,1		
		MOVLW	0FH		
		ANDWF	FSR,1
		BTFSS	3,2		
		GOTO	ctrl_code31

		MOVLW	80h | PORTA
		ADDWF	FSR,1
		MOVF	getmes_wk1,0
		call	getbitpos
		
		MOVF	INDF,0
		andwf	data0,0				; check of TRIS_RA
		BTFSC	3,2			; output pin?
		GOTO	ctrl_code32

		MOVLW	1FH		
		MOVWF	PCLATH
		call	getadtable
		MOVWF	wk	
		MOVLW	HIGH (ctrl_code3)
		MOVWF	PCLATH
		
		MOVF	wk,0		
		ANDWF	data0,1
		BTFSS	3,2		; if 1, analog input
		GOTO	ad_in
;
;
ctrl_code32
		CLRF	FSR		
ctrl_code31	MOVLW	PORTA				; + 05h
		ADDWF	FSR,1

		MOVF	getmes_wk1,0
		call	getbitpos
		MOVF	INDF,0		
		ANDWF	data0,1
		BTFSC	3,2		
		GOTO	ctrl_low
		goto	ctrl_high

;-----------------------------------------------------------------------------------
;	get short message
get_short_mes
		MOVLW	1FH		; bank = 1h
		MOVWF	PCLATH
		MOVF	wk,0			
		MOVWF	PCL
ctrl_out
		movlw	mes_out & .255	; 'OUT'
		goto	put_short_mes10
ctrl_in
		movlw	mes_in & .255	; 'IN'
		goto	put_short_mes10
ctrl_high
		movlw	mes_high & .255	; 'HIGH'
		goto	put_short_mes10
ctrl_low
		movlw	mes_low & .255	; 'LOW'
		goto	put_short_mes10
put_short_mes10
		MOVWF	wk		
put_short_mes0
		call	get_short_mes
		MOVWF	data0		
		MOVLW	HIGH (put_short_mes0)
		MOVWF	PCLATH		; modification of PCLATH
		
		MOVLW	0			; NULL?
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	ctrl_next
		MOVF	data0,0
		call	assert_wr2		; transfer to RTL8019
		
		INCF	wk,1		;			; wk++
		goto	put_short_mes0
;
;		META CHARACTER
ctrl_code2
		MOVLW	HIGH (ctrl_code1)
		MOVWF	PCLATH

		MOVF	getmes_wk1,0
		andlw	7fh
		addlw	-'0'			; unknown
		
		call	ctrl_code1			; to control character output routine
		MOVLW	HIGH (ctrl_code2)
		MOVWF	PCLATH
ctrl_next
		MOVLW	1			; ind++
		ADDWF	ind,1
		bsf	STATUS,RP1
		bcf	STATUS,RP0
		btfsc	STATUS,C
		INCF	EEADRH,1
		goto	send_mes0

;-----------------------------------------------------------------------------------
;		creation of socket
;
no_socket
		btfss	tcp_flags,TCP_SYN
		RETURN
;
;	SYN packet Rx → SYN+ACK Tx
;
recv_syn
		MOVLW	HIGH (socket_entry)
		MOVWF	PCLATH

		call	socket_entry			; search socket entry
		MOVLW	HIGH (recv_syn)
		MOVWF	PCLATH
		btfsc	STATUS,C
		goto	send_rst			; no open sockets
		
				;
		MOVLW	0
		MOVWF	ip_length
				; IP header = 20+24
		MOVLW	.20 + .24
		MOVWF	ip_length1
		
		MOVLW	TCP_PROTO		; TCP packet
		MOVWF	proto
		call	prepare_ip
;
	
;-------
		MOVLW	PACKET_SIZE + IP_SIZE	;mov	remote_adr[0],#PACKET_SIZE + IP_SIZE
		MOVWF	remote_adr
		MOVLW	PAGE_BEGIN
		MOVWF	remote_adr1

		MOVLW	.20 + .4
		MOVWF	remote_len
		MOVLW	0
		MOVWF	remote_len1

;-------		
		
		call	remote_write
		
		call	clear_sum			; clear checksum value
		
		MOVLW	http_port & 0ffh
		MOVWF	FSR
		movlw	2
		call	transmit_nbytes			; own port number
		
		MOVLW	tcp_src_port
		MOVWF	FSR
		movlw	2
		call	transmit_nbytes			; destination port number

		MOVLW	seq_no
		MOVWF	FSR
		movlw	4
		call	transmit_nbytes			; own SEQNO
		
		
		call	inc_ack_no		; tcp_seq_no++;
		
		MOVF	com_fsr,0
		MOVWF	FSR
		MOVLW	.8
		ADDWF	FSR,1

		bsf	STATUS,IRP
		bsf	STATUS,RP0
		MOVF	seq_no,0	; own SEQ NO to own socket + 8
		MOVWF	INDF
		INCF	FSR,1
		MOVF	seq_no1,0
		MOVWF	INDF
		INCF	FSR,1
		MOVF	seq_no2,0
		MOVWF	INDF
		INCF	FSR,1
		MOVF	seq_no3,0	
		MOVWF	INDF
		INCF	FSR,1
		bcf	STATUS,RP0
		
		MOVF	tcp_seq_no,0	
		MOVWF	INDF
		INCF	FSR,1
		MOVF	tcp_seq_no1,0
		MOVWF	INDF
		INCF	FSR,1
		MOVF	tcp_seq_no2,0
		MOVWF	INDF
		INCF	FSR,1
		;mov	INDF,tcp_seq_no[3]
		MOVF	tcp_seq_no3,0
		MOVWF	INDF
		bcf	STATUS,IRP
	
		MOVF	com_fsr,0
		MOVWF	FSR
		MOVLW	.8
		ADDWF	FSR,1
		call	inc_seq_no
		
		MOVLW	tcp_seq_no
		MOVWF	FSR
		movlw	4
		call	transmit_nbytes		; destination SEQNO + 1
		
		movlw	60h			; option available
		call	assert_wr
		movlw	B'010010'			; ACK+SYN
		call	assert_wr
		
		movlw	08h			; window(high)
		call	assert_wr
		movlw	00h			; window(low)
		call	assert_wr
		
		call	assert_wr2times		; tcp sum
		call	assert_wr2times		; exception pointer
		
		movlw	2h
		call	assert_wr		
		movlw	4h
		call	assert_wr		
		movlw	5h
		call	assert_wr		
		movlw	0b4h
		call	assert_wr		
		
		call	calc_tcp_sum		; calculation of TCP SUM
		
		MOVLW	4h
		MOVWF	PORTC
		movlw	PAGE_BEGIN		; transmit page is start page 
		call	assert_wr0
		
		MOVLW	5
		MOVWF	PORTC
		movlw	.60			; Tx 60 bytes
		call	assert_wr0
		
		MOVLW	6
		MOVWF	PORTC
		DB	01,00		;clrw
		call	assert_wr0
		call	transmit		; Send!

		call	next_seq_no		; seq_no++
		RETURN

;-----------------------------------------------------------------------------------
;		calculation of checksum
calc_tcp_sum
		CLRF	bytes		;clr	bytes	; adjustment for 2 byte alignment
		
		MOVLW	this_ip		;mov	fsr,#this_ip; add own IP address
		
		MOVWF	FSR
		MOVF	INDF,0
		call	calc_sum
		INCF	FSR,1
		MOVF	INDF,0
		call	calc_sum
		INCF	FSR,1
		MOVF	INDF,0
		call	calc_sum
		INCF	FSR,1
		MOVF	INDF,0
		call	calc_sum
	
		MOVF	ip_src,0		; add destination IP address
		call	calc_sum
		MOVF	ip_src1,0
		call	calc_sum
		MOVF	ip_src2,0
		call	calc_sum
		MOVF	ip_src3,0
		call	calc_sum
		
		DB	01,00		;clrw				; add protocol number
		call	calc_sum
		MOVLW	TCP_PROTO
		call	calc_sum
		
		MOVF	remote_len1,0	; add number of bytes
		call	calc_sum
		MOVF	remote_len,0
		call	calc_sum
		
	
;-------
		MOVLW	PACKET_SIZE + IP_SIZE + .16
		MOVWF	remote_adr
		MOVLW	PAGE_BEGIN
		MOVWF	remote_adr1

;-------		
		
		call	set_checksum		; set in RTL8019 buffer
		RETURN



;===================================================================================
;		NIC initialization routine
;===================================================================================
initialize
		call	init_nic			; NIC reset
		call	getmac				; get MAC address
		call	setmac				; set MAC address
				; initialization of ring buffer [2004/10/30]
		bsf	STATUS,RP0
		MOVLW	fifo_top		
		MOVWF	fifo_buff
		MOVWF	fifo_poi			
		MOVWF	fifo_line		 
		
		clrF	fifo_cn
		clrF	fifo_line_cn
		bcf	STATUS,RP0
		
		RETURN



;-----------------------------------------------------------------------------------
;		RTL8019 reset
;-----------------------------------------------------------------------------------
reset_nic
		clrF	PORTC
		movlw	21h
		call	assert_wr0		; STOP OPERATION
		
		MOVLW	1Fh
		MOVWF	PORTC
		call	assert_rd		; read 1eh
		
		MOVLW	1Fh
		MOVWF	PORTC
		MOVF	data0,0
		call	assert_wr0		; write it out(RESET)
reset_nic0
		MOVLW	07h
		MOVWF	PORTC
		call	assert_rd		; read status
		
		btfss	data0,7			;data.7	; RESET end check
		goto	reset_nic0
		RETURN


;-----------------------------------------------------------------------------------
;		RTL8019 initialization
;-----------------------------------------------------------------------------------
init_nic
		call	reset_nic
		
		MOVLW	0eh			; DCR(Data Conifguration Register)
		MOVWF	PORTC
		movlw	68h
		call	assert_wr0
		
		MOVLW	0ah
		MOVWF	PORTC
		DB	01,00		;clrw
		call	assert_wr0		; for over flow
		
		MOVLW	0bh
		MOVWF	PORTC
		DB	01,00		;clrw
		call	assert_wr0		; for over flow
		
		MOVLW	01h
		MOVWF	PORTC
		movlw	PAGE_START		; PAGE START
		call	assert_wr0
		
		MOVLW	02h
		MOVWF	PORTC
		movlw	PAGE_STOP		; PAGE STOP
		call	assert_wr0
		
		MOVLW	03h
		MOVWF	PORTC
		movlw	PAGE_START		; BDRY
		call	assert_wr0
		
		MOVLW	0ch			; RCR
		MOVWF	PORTC
		movlw	0h	;	20h
		call	assert_wr0
		
		MOVLW	0dh			; TCR
		MOVWF	PORTC
		movlw	2			; LOOPBACK
		call	assert_wr0

		MOVLW	0fh			; IMR
		MOVWF	PORTC
		movlw	B'11111'
		call	assert_wr0
		
		MOVLW	7			; ISR
		MOVWF	PORTC
		movlw	0ffh
		call	assert_wr0

		clrF	PORTC			; CR(Command Regster)
		movlw	22h			; START OPERATION with L/B
		call	assert_wr0
		RETURN

;-----------------------------------------------------------------------------------
;		get MAC address
;-----------------------------------------------------------------------------------
getmac
		clrF	PORTC
		movlw	22h
		call	assert_wr0
		
		CLRF	remote_adr 
		CLRF	remote_adr1	 
		MOVLW	.12	 	; transfer 12 bytes
		MOVWF	remote_len
		clrF	remote_len1	 
		call	remote_read

		MOVLW	6			; MAC address is 6 bytes
		MOVWF	gcn1
		MOVLW	mymac		; set address in mymac
		MOVWF	FSR
get_mac0
		MOVLW	10h
		MOVWF	PORTC
		call	assert_rd		; read from here
		call	assert_rd		; 
		
		MOVF	data0,0	;mov	INDF,data		; read MAC address to PIC
		MOVWF	INDF
		INCF	FSR,1
		DECFSZ	gcn1,1	 
		GOTO	get_mac0
		RETURN



;-----------------------------------------------------------------------------------
;		MAC address setup
;-----------------------------------------------------------------------------------
setmac
;	PAGE 1
		clrF	PORTC
		movlw	B'01100010'
		call	assert_wr0
;
		MOVLW	01h
		MOVWF	PORTC
		MOVLW	mymac
		MOVWF	FSR
		MOVLW	6			; MAC address is 6 bytes
		MOVWF	gcn1
setmac0
		MOVF	INDF,0
		call	assert_wr0		; MAC address setup
		INCF	FSR,1
		INCF	PORTC,1
		DECFSZ	gcn1,1	 
		GOTO	setmac0
		MOVLW	7
		MOVWF	PORTC
		movlw	PAGE_START + 1		
		call	assert_wr0		; also set current page
		
		MOVLW	8
		MOVWF	PORTC
		DB	01,00		;clrw
		call	assert_wr0
		INCF	PORTC,1	 
		DB	01,00		;clrw
		call	assert_wr0
		INCF	PORTC,1	 
		DB	01,00		;clrw
		call	assert_wr0
		INCF	PORTC,1	 
		DB	01,00		;clrw
		call	assert_wr0
		INCF	PORTC,1	 
		DB	01,00		;clrw
		call	assert_wr0
		INCF	PORTC,1	 
		DB	01,00		;clrw
		call	assert_wr0
		INCF	PORTC,1	 
		DB	01,00		;clrw
		call	assert_wr0
		INCF	PORTC,1	 
		DB	01,00		;clrw
		call	assert_wr0
		
		clrF	PORTC
		movlw	22h
		call	assert_wr0
		RETURN



;-----------------------------------------------------------------------------------
;		preparation for remote DMA write 
;-----------------------------------------------------------------------------------
remote_write
		MOVLW	8
		MOVWF	PORTC
		MOVF	remote_adr,0
		call	assert_wr0
		
		MOVLW	9
		MOVWF	PORTC
		MOVF	remote_adr1,0
		call	assert_wr0
		
		MOVLW	0ah
		MOVWF	PORTC
		MOVF	remote_len,0
		call	assert_wr0
		
		MOVLW	0bh
		MOVWF	PORTC
		MOVF	remote_len1,0
		call	assert_wr0
		
		clrF	PORTC
		movlw	B'00010010'
		call	assert_wr0		; write now!
		MOVLW	10h
		MOVWF	PORTC
		RETURN


;-----------------------------------------------------------------------------------
;		preparation for remote DMA read in
;-----------------------------------------------------------------------------------
remote_read
		MOVLW	8
		MOVWF	PORTC
		MOVF	remote_adr,0
		call	assert_wr0
		
		MOVLW	9
		MOVWF	PORTC
		MOVF	remote_adr1,0
		call	assert_wr0
		
		MOVLW	0ah
		MOVWF	PORTC
		MOVF	remote_len,0
		call	assert_wr0
		
		MOVLW	0bh
		MOVWF	PORTC
		MOVF	remote_len1,0
		call	assert_wr0
		
		clrF	PORTC
		movlw	B'00001010'
		call	assert_wr0		; read now!
		MOVLW	10h
		MOVWF	PORTC
		RETURN

;-----------------------------------------------------------------------------------
;		calculation of checksum
;-----------------------------------------------------------------------------------
calc_sum
		BTFSS	bytes,0		;btfss	bytes.0	; alignment check
		goto	calc_sum_high
;	LOW byte
		ADDWF	sum,1	 ; add data to (sum[1],sum[0])
		movlw	1
		btfsc	STATUS,C
		addwf	sum1,1		 

		btfsc	STATUS,C			; calculation of 1's complement
		addwf	sum,1	 
		btfsc	STATUS,C
		addwf	sum1,1	 
		INCF	bytes,1	 	; to next alignment
		RETURN
;	HIGH byte
calc_sum_high
		ADDWF	sum1,1		  ; add data to (sum[1],sum[0])
		movlw	1
		
		btfsc	STATUS,C			; calculation of 1's complement
		ADDWF	sum,1		 
		btfsc	STATUS,C
		ADDWF	sum1,1		 
	
		INCF	bytes,1	 			; to next alignment
		RETURN



assert_wr2times
		DB	01,00		;clrw
		call	assert_wr
		DB	01,00		;clrw
		goto	assert_wr
;-----------------------------------------------------------------------------------
;	Tx data = data
assert_wr2x
		MOVLW	1	 	; remote_len++
		ADDWF	remote_len,1
		btfsc	STATUS,C
		INCF	remote_len1,1	 
		MOVF	data0,0			; transmit data variable
		goto	assert_wr
;	Tx data = W
assert_wr2	movwf	data0		; store away once
		MOVLW	1	 	; remote_len++
		ADDWF	remote_len,1
		btfsc	STATUS,C
		INCF	remote_len1,1	 
		MOVF	data0,0
;-----------------------------------------------------------------------------------
;		write to RTL8019 (considering checksum)
;-----------------------------------------------------------------------------------HAVE
assert_wr
		MOVWF	PORTD	 
assert_wr_2	btfss	bytes,0		 
		goto	asser_wr_high
		
		ADDWF	sum,1		 
		movlw	1
		btfsc	STATUS,C
		ADDWF	sum1,1		 

		btfsc	STATUS,C
		ADDWF	sum,1	 
		btfsc	STATUS,C
		ADDWF	sum1,1	 
		
		INCF	bytes,1		 
		goto	assert_wr0_2
asser_wr_high
		ADDWF	sum1,1	 
		movlw	1
		
		btfsc	STATUS,C
		ADDWF	sum,1	 
		btfsc	STATUS,C
		ADDWF	sum1,1	 
	
		INCF	bytes,1	 
		goto	assert_wr0_2


;-----------------------------------------------------------------------------------
;		plain write to RTL8019
;-----------------------------------------------------------------------------------
assert_wr0
		movwf	PORTD	 
assert_wr0_2	bsf	STATUS,RP0
		clrF	PORTD	 			; output to RD port
		bcf	STATUS,RP0
		
		bcf	PORTE,1	 
		

		btfss	PORTC,5
		goto	$-1
		
		bsf	PORTE,1	 
		
		bsf	STATUS,RP0
		MOVLW	0FFH		 	; input to RD port
		MOVWF	PORTD
		bcf	STATUS,RP0
		RETURN


assert_rd
		bcf	PORTE,0
		
		btfss	PORTC,5			; ~Wait
		goto	$-1
		
		MOVF	PORTD,0		 
		MOVWF	data0
		bsf	PORTE,0
		RETURN



;-----------------------------------------------------------------------------------
;		Processing for packet Tx
;-----------------------------------------------------------------------------------
transmit_this_ip
		MOVLW	this_ip	 
		MOVWF	FSR
		movlw	4

transmit_nbytes
		movwf	gcn1
		MOVLW	10h
		MOVWF	PORTC
transmit0	MOVF	INDF,0
		call	assert_wr
		INCF	FSR,1
		DECFSZ	gcn1,1	 
		GOTO	transmit0
		RETURN


transmit_nbytes2
		movwf	gcn1
		MOVLW	10h
		MOVWF	PORTC
transmit2_0	MOVF	INDF,0
		call	assert_wr2
		INCF	FSR,1
		DECFSZ	gcn1,1		 
		GOTO	transmit2_0
		RETURN

;-----------------------------------------------------------------------------------
;		packet Tx
;-----------------------------------------------------------------------------------
transmit
retry
		clrF	PORTC
		call	assert_rd
		
		BTFSC	data0,2	 	; check Tx bit
		goto	transmit			; Tx wait
		
		clrF	PORTC
		movlw	B'00100110'			; set Tx bit
		call	assert_wr0			; Send!
trans100
		MOVLW	4
		MOVWF	PORTC
		call	assert_rd
		
		btfsc	data0,0	 
		goto	transmit9			; Send complete?
		btfsc	data0,3	 
		goto	retry
		
		goto	trans100
transmit9	RETURN


 
;-----------------------------------------------------------------------------------
;		Construct Ethernet header.
;-----------------------------------------------------------------------------------
prepare_ether2
		movlw	PACKET_SIZE + ARP_SIZE
		MOVWF	remote_len
		GOTO	prepare_ether1
prepare_ether
	;	call	wait_transmit			; wait during Tx
		movlw	PACKET_SIZE + IP_SIZE
		MOVWF	remote_len
prepare_ether1
		CLRF	remote_len1
		CLRF	remote_adr
		MOVLW	PAGE_BEGIN
		MOVWF	remote_adr1


 
		call	remote_write
		
		MOVLW	10h			; MAC of packet sender
		MOVWF	PORTC
		MOVLW	eth_src
		MOVWF	FSR
		movlw	6
		call	transmit_nbytes
		
		MOVLW	mymac		; set own MAC address
		MOVWF	FSR
		movlw	6
		call	transmit_nbytes
		RETURN


;-----------------------------------------------------------------------------------
;		construction of IP header
;-----------------------------------------------------------------------------------
prepare_ip
		call	prepare_ether
		movlw	COM_PROTO
		call	assert_wr
		movlw	IP_PROTO
		call	assert_wr
		
		call	ip_common
		
 
		MOVLW	ip_sum - ip_header + PACKET_SIZE
		MOVWF	remote_adr
		MOVLW	PAGE_BEGIN
		MOVWF	remote_adr1


 		
	;	goto	set_checksum
set_checksum
		COMF	sum,1	 
		COMF	sum1,1	 
		
		MOVLW	2	 	; checksum is 2 bytes
		MOVWF	remote_len
		CLRF	remote_len1	 
		call	remote_write
		
		MOVLW	10h
		MOVWF	PORTC
		MOVF	sum1,0
		call	assert_wr0			; write checksum (must call assert_wr0)
		MOVF	sum,0
		call	assert_wr0
		RETURN



;-----------------------------------------------------------------------------------
;		construct IP protocol header
;-----------------------------------------------------------------------------------
ip_common
		call	clear_sum			; clear checksum value
		
		MOVLW	10h
		MOVWF	PORTC
		movlw	45h			; ID
		call	assert_wr
		movlw	00h			; TOS
		call	assert_wr
		
		MOVF	ip_length,0			; length high
		call	assert_wr
		MOVF	ip_length1,0			; length low
		call	assert_wr
		
		MOVLW	ident
		MOVWF	FSR
		MOVF	INDF,0			; Seq No High
		call	assert_wr
		INCF	FSR,1
		
		MOVF	INDF,0			; Seq No Low
		call	assert_wr
		MOVLW	1		 
		ADDWF	INDF,1
		decF	FSR,1
		btfsc	STATUS,C
		addwf	INDF,1

		movlw	00h			; flagment(2bytes)
		call	assert_wr
		movlw	00h			;
		call	assert_wr
		
		movlw	0ffh			; TTL
		call	assert_wr
		
		MOVF	proto,0			; PROTOCOL = anything
		call	assert_wr
		
		call	assert_wr2times			; sum is zero
		
		call	transmit_this_ip
		
		MOVLW	ip_src			; to IP
		MOVWF	FSR
		movlw	4
		call	transmit_nbytes
		RETURN




;-----------------------------------------------------------------------------------
;		control of parallel I/F
;-----------------------------------------------------------------------------------
		org	820h
udp_parallel
		MOVLW	$ >> 8
		MOVWF	PCLATH
		MOVLW	udp_data
		MOVWF	FSR
		
		MOVLW	6	 
		SUBWF	INDF,0
		BTFSC	3,0
		GOTO	main90
		MOVF	INDF,0
		INCF	FSR,1
		ADDWF	2,1	 
		goto	para_get_status			; get status
		goto	para_set_high			; High setting
		goto	para_set_low			; Low setting
		goto	para_set_whole			; all configuration settings
		goto	para_get_adc			; A/D conversion
		goto	para_set_rbpu			; On/Off of internal pullup
;
;	set to HIGH/INPUT
para_set_high
		call	para_set_common
		MOVF	wk1,0	 
		IORWF	INDF,1
		goto	para_get_status
;
;	set to LOW/OUTPUT
para_set_low
		call	para_set_common
		COMF	wk1,1	 
		MOVF	wk1,0	 
		ANDWF	INDF,1
		goto	para_get_status
;
;	calculation of bit position
para_set_common
		INCF	FSR,1
		MOVF	INDF,0	 	; bit position (0-7)
		MOVWF	wk
		MOVLW	1 
		MOVWF	wk1
para_set_common0
		MOVLW	0 
		SUBWF	wk,0
		BTFSC	3,2
		GOTO	para_set_common9
		BCF	3,0	 
		RLF	wk1,1 
		DECF	wk,1 
		goto	para_set_common0
para_set_common9
		decF	FSR,1
		MOVF	INDF,0		; I/O port number
		MOVWF	FSR
		RETURN
;
;	SET WHOLE mode
para_set_whole
		MOVF	INDF,0	 	; port
		MOVWF	ptr
		INCF	FSR,1
		MOVF	INDF,0 		; size
		MOVWF	gcn1
		INCF	FSR,1
para_set_whole0
		MOVF	INDF,0	 		; Mask
		MOVWF	wk
		INCF	FSR,1
		MOVF	INDF,0 
		MOVWF	wk1
		INCF	FSR,1
		
		MOVF	FSR,0 		; save FSR
		MOVWF	wk2
		MOVF	ptr,0
		MOVWF	FSR
		MOVF	INDF,0
		ANDWF	wk,0 
		IORWF	wk1,0	 
		movwF	INDF		; *ptr = (*ptr & Mask) | Value
		MOVF	wk2,0		; restore FSR
		MOVWF	FSR
		
		INCF	ptr,1 
		DECFSZ	gcn1,1	 
		GOTO	para_set_whole0
		goto	para_get_status


;
; internal pullup On/Off
para_set_rbpu
		bsf	STATUS,RP0
		MOVLW	0 
		SUBWF	INDF,0
		BTFSS	3,2
		GOTO	para_set_rbpu1
		BSF	OPTION_REG,7     ; do not pull up
		goto	para_set_rbpu9
para_set_rbpu1
		BCF	OPTION_REG,7   ; pull up
para_set_rbpu9	bcf	STATUS,RP0
		goto	para_get_status



;-----------------------------------------------------------------------------------
para_get_adc
		MOVF	INDF,0 		; ADCON1 setting
		MOVWF	ADCON1
		BSF	ADCON1,0 
		INCF	FSR,1
		
		MOVF	INDF,0 		; acquisition time wait
		MOVWF	wait_cn
para_get_aqu0
		MOVLW	8	 
		MOVWF	wait_cn2
		DECFSZ	wait_cn2,1 
		GOTO	$-1
		DECFSZ	wait_cn,1 		; 25μs×WaitTime
		GOTO	para_get_aqu0
		BSF	ADCON1,2 	 ; A/D conversion start
		BTFSC	ADCON1,2 	; A/D conversion wait (synchronized)
		goto	$-1 		; we would really like to make it asynchronized(^_^;
		
		CLRF	PCLATH
para_get_status
		MOVLW	para_port	 ; source port number
		MOVWF	wk2
common_get_status
		CLRF	ip_length	 
	 
		MOVLW	IP_SIZE + UDP_SIZE + PARALLEL_PACKET_SIZE
		MOVWF	ip_length1
		
		CLRF	PCLATH
		
		MOVLW	UDP_PROTO		; UDP packet
		MOVWF	proto
		call	prepare_ip			; construct IP packet
		
		call	clear_sum			; clear checksum value
		
 
		MOVLW	PACKET_SIZE+IP_SIZE
		MOVWF	remote_adr
		MOVLW	PAGE_BEGIN
		MOVWF	remote_adr1

		MOVLW	(UDP_SIZE + PARALLEL_PACKET_SIZE) & 0ffh
		MOVWF	remote_len
		MOVLW	HIGH (UDP_SIZE + PARALLEL_PACKET_SIZE)
		MOVWF	remote_len1
 
		call	remote_write
		
		MOVLW	10h
		MOVWF	PORTC
		
		MOVF	wk2,0		;para_port
		MOVWF	FSR
		MOVF	INDF,0			; From PORT #(HIGH)
		call	assert_wr
		INCF	FSR,1
		MOVF	INDF,0			; From PORT #(LOW)
		call	assert_wr
		
		MOVF	udp_src_port,00		; To PORT #
		call	assert_wr
		MOVF	udp_src_port1,0
		call	assert_wr
		
 		MOVLW	HIGH (UDP_SIZE + PARALLEL_PACKET_SIZE)
		call	assert_wr
		movlw	(UDP_SIZE + PARALLEL_PACKET_SIZE) & 0ffh ; UDP DATAGRAM SIZE
		call	assert_wr
		
		call	assert_wr2times			; sum(not fixed)
 		
		MOVF	PORTA,0
		call	assert_wr			; 
		MOVF	PORTB,0
		call	assert_wr			; 
		
		MOVLW	80h + PORTA			;ra
		MOVWF	FSR
		MOVF	INDF,0
		call	assert_wr			; 
		INCF	FSR,1
		MOVF	INDF,0
		call	assert_wr			; 
		
		MOVF	ADRESH,0 
		MOVWF	val1			; put conversion result in val[1]:val[0]
		bsf	STATUS,RP0
		MOVF	ADRESL,0			;adres,0; page1 is lower byte
		bcf	STATUS,RP0
		MOVWF	val		 
		
		MOVF	val1,0
		call	assert_wr			; A/D conversion result (H)
		MOVF	val,0
		call	assert_wr			; A/D conversion result (L)
		
		bsf	STATUS,RP0
		MOVF	ADCON1,0
		bcf	STATUS,RP0
		call	assert_wr			;
		movlw	0				; Reserved
		call	assert_wr			;
		
		MOVLW	HIGH (calc_udp_sum)
		MOVWF	PCLATH

		call	calc_udp_sum
		MOVLW	HIGH (transmit_60bytes)
		MOVWF	PCLATH

		call	transmit_60bytes
main90		
		MOVLW	HIGH (main9)
		MOVWF	PCLATH

		goto	main9


;-----------------------------------------------------------------------------------
;		calculation and Tx of UDP checksum
;
calc_udp_sum
		CLRF	PCLATH
		CLRF	bytes		;clr	bytes ; adjustment for 2 byte alignment
		MOVLW	this_ip	 	; add own IP address
		MOVWF	FSR
		
		MOVF	INDF,0
		call	calc_sum
		INCF	FSR,1
		MOVF	INDF,0
		call	calc_sum
		INCF	FSR,1
		MOVF	INDF,0
		call	calc_sum
		INCF	FSR,1
		MOVF	INDF,0
		call	calc_sum
	
		MOVF	ip_src,0		; add destination IP address
		call	calc_sum
		MOVF	ip_src1,0
		call	calc_sum
		MOVF	ip_src2,0
		call	calc_sum
		MOVF	ip_src3,0
		call	calc_sum
	
		DB	01,00		;clrw				; add protocol number
		call	calc_sum
		MOVLW	UDP_PROTO
		call	calc_sum
		
		MOVF	remote_len1,0		;#PARALLEL_PACKET_SIZE>>8
		call	calc_sum
		MOVF	remote_len,0		;#PARALLEL_PACKET_SIZE & 0ffh
		call	calc_sum

	 	; checksum set position
 
		MOVLW	PACKET_SIZE+IP_SIZE + 6
		MOVWF	remote_adr
		MOVLW	PAGE_BEGIN
		MOVWF	remote_adr1

 		call	set_checksum
		RETURN

transmit_60bytes
		CLRF	PCLATH
		
		MOVLW	4h
		MOVWF	PORTC
		movlw	PAGE_BEGIN			; transmit page is start page 
		call	assert_wr0
		
		MOVLW	5
		MOVWF	PORTC
		movlw	.60		; basically set to 60. (PARALLEL_PACKET_SIZE+IP_SIZE+PACKET_SIZE) & 0ffh
		call	assert_wr0
		
		MOVLW	6
		MOVWF	PORTC
		movlw	0		; (PARALLEL_PACKET_SIZE+IP_SIZE+PACKET_SIZE) >> 8
		call	assert_wr0
		
		call	transmit
		RETURN

;-----------------------------------------------------------------------------------
;		serial port processing
;
udp_serial
		bsf	STATUS,RP0
		BSF	STATUS,RP1
		movlw	.16
		MOVwf	transmitted & 0ffh
		clrf	STATUS

		MOVF	udp_length,0 
		MOVWF	remote_len1
		MOVF	udp_length1,0 
		MOVWF	remote_len

		MOVLW	8	 
		SUBWF	remote_len,1
		btfss	STATUS,C
		DECF	remote_len1,1 
		
		MOVLW	HIGH (get_dgram)
		MOVWF	PCLATH

		call	get_dgram
		MOVLW	$>>8		;HIGH (udp_serial)
		MOVWF	PCLATH
		
		btfsc	STATUS,C
		goto	main90
		
		MOVF	data0,0	 
		MOVWF	udp_data
		MOVLW	4	 
		SUBWF	data0,0
		BTFSC	3,0
		GOTO	main90
		MOVF	data0,0
		ADDWF	2,1 
		goto	ser_get_status		; status display
		goto	ser_register_tag	; address registration
		goto	ser_unregister_tag	; address deletion
		goto	ser_transmit		; data Tx
;
;		ARP response Rx processing
ser_arp
		bcf	STATUS,IRP
		MOVLW	arp_src_mac & 0ffh
		MOVWF	FSR

		bsf	STATUS,RP0
		bsf	STATUS,RP1
		MOVF	INDF,0	 
		MOVWF	on_ether & 0FFH	; set hardware address
		INCF	FSR,1
		MOVF	INDF,0	 
		MOVWF	on_ether1 & 0FFH
		INCF	FSR,1
		MOVF	INDF,0 
		MOVWF	on_ether2 & 0FFH
		INCF	FSR,1
		MOVF	INDF,0 
		MOVWF	on_ether3 & 0FFH
		INCF	FSR,1
		MOVF	INDF,0	 
		MOVWF	on_ether4 & 0FFH
		INCF	FSR,1
		MOVF	INDF,0	 
		MOVWF	on_ether5 & 0FFH
		CLRF	STATUS	 
 
		
		bsf	RCSTA,4		;cren
		bsf	INTCON,6	;peie			; permission for use
		MOVLW	HIGH (main9)
		MOVWF	PCLATH

		goto	main9

;-----------------------------------------------------------------------------------
;		send serial status to host
;-----------------------------------------------------------------------------------
ser_get_status
		CLRF	ip_length 
 		MOVLW	IP_SIZE + UDP_SIZE + SERIAL_PACKET_SIZE
		MOVWF	ip_length1

		CLRF	PCLATH
		
		MOVLW	UDP_PROTO		; UDP packet
		MOVWF	proto
		call	prepare_ip			; construct IP packet
		
		call	clear_sum			; clear checksum value
		
 
		MOVLW	PACKET_SIZE+IP_SIZE
		MOVWF	remote_adr
		MOVLW	PAGE_BEGIN
		MOVWF	remote_adr1

		MOVLW	(UDP_SIZE + SERIAL_PACKET_SIZE) & 0ffh
		MOVWF	remote_len
		MOVLW	HIGH (UDP_SIZE + SERIAL_PACKET_SIZE)
		MOVWF	remote_len1

;-------		
		call	remote_write
		
		MOVLW	10h
		MOVWF	PORTC
		
		MOVLW	serial_port
		MOVWF	FSR
		MOVF	INDF,0			; From PORT #(HIGH)
		call	assert_wr
		INCF	FSR,1
		MOVF	INDF,0			; From PORT #(LOW)
		call	assert_wr
		
		MOVF	udp_src_port,0		; To PORT #
		call	assert_wr
		MOVF	udp_src_port1,0
		call	assert_wr
		
		movlw	HIGH (UDP_SIZE + SERIAL_PACKET_SIZE)
		call	assert_wr
		movlw	(UDP_SIZE + SERIAL_PACKET_SIZE) & 0ffh ; UDP DATAGRAM SIZE
		call	assert_wr
		
		call	assert_wr2times			; sum(not fixed)
;
;		DGRAM
;
		CLRF	PCLATH
		
		MOVF	udp_data,0
		call	assert_wr			; sum(not fixed)
		
		bsf	STATUS,IRP
		MOVLW	transmitted & 0ffh
		movwf	FSR
		movf	INDF,0
		call	assert_wr
		MOVLW	on_ether & 0ffh
		MOVWF	FSR
		movlw	SERIAL_PACKET_SIZE-2
		call	transmit_nbytes
		bcf	STATUS,IRP
		
		MOVLW	HIGH (calc_udp_sum)
		MOVWF	PCLATH

		call	calc_udp_sum
		MOVLW	HIGH (transmit_60bytes)
		MOVWF	PCLATH

		call	transmit_60bytes

		MOVLW	HIGH (main9)
		MOVWF	PCLATH

		goto	main9

;-----------------------------------------------------------------------------------
ser_transmit
		bsf	STATUS,RP0
		bsf	STATUS,RP1
		CLRF	transmitted & 0ffh
		clrf	STATUS
ser_transmit0
		MOVLW	get_dgram >> 8
		movwf	PCLATH
		CALL	get_dgram
		MOVLW	$ >> 8
		MOVWF	PCLATH
		BTFSC	STATUS,C
		GOTO	ser_transmit9
		
		BSF	STATUS,RP0
		BSF	STATUS,RP1
		BTFSS	on_flow,0
		GOTO	ser_transmit1

		CLRF	STATUS
		BTFSC	PORTB,0
		GOTO	ser_transmit9
ser_transmit1
		CLRF	STATUS
		CALL	async_transmit
		bsf	STATUS,RP0
		BSF	STATUS,RP1
		INCF	transmitted,1
		clrf	STATUS
		GOTO	ser_transmit0
ser_transmit9
		MOVLW	HIGH (ser_get_status)
		MOVWF	PCLATH

		goto	ser_get_status

;-----------------------------------------------------------------------------------
ser_register_tag
		MOVLW	4+2			; read in 6 bytes
		MOVWF	gcn1
		MOVLW	udp_data+1
		MOVWF	FSR
		MOVLW	HIGH (copy_toram)
		MOVWF	PCLATH

		call	copy_toram
		
		MOVLW	HIGH (ser_register)
		MOVWF	PCLATH

		goto	ser_register

;-----------------------------------------------------------------------------------
ser_unregister_tag
		MOVLW	HIGH (ser_unregister)
		MOVWF	PCLATH

		goto	ser_unregister


;-----------------------------------------------------------------------------------
;		check for socket of received packet
;-----------------------------------------------------------------------------------
search_socket
		bsf	STATUS,IRP
		MOVLW	SOCKETS		;mov	com_cn,#SOCKETS
		MOVWF	com_cn
		MOVLW	skb & 0ffh		;mov	com_fsr,#0a0h
		MOVWF	com_fsr
search_socket0
		MOVF	com_fsr,0
		MOVWF	FSR
		BTFSS	INDF,7	 
		goto	search_socket9
		
		MOVLW	.2
		ADDWF	FSR,1
		MOVF	ip_src,0 
		SUBWF	INDF,0
		BTFSS	3,2
		GOTO	search_socket9
		INCF	FSR,1
		MOVF	ip_src1,0 
		SUBWF	INDF,0
		BTFSS	3,2
		GOTO	search_socket9
		INCF	FSR,1
		MOVF	ip_src2,0 
		SUBWF	INDF,0
		BTFSS	3,2
		GOTO	search_socket9
		INCF	FSR,1
		MOVF	ip_src3,0 
		SUBWF	INDF,0
		BTFSS	3,2
		GOTO	search_socket9
		INCF	FSR,1
		
 
		MOVF	tcp_src_port,0
		SUBWF	INDF,0
		BTFSS	3,2
		GOTO	search_socket9
		INCF	FSR,1
 
		MOVF	tcp_src_port1,0	
		SUBWF	INDF,0
		BTFSS	3,2
		GOTO	search_socket9
		INCF	FSR,1
		
		MOVLW	.7
		SUBWF	FSR,1
		MOVLW	0F0H 
		IORWF	INDF,1
		decF	FSR,1
		BSF	3,0	 
		RETURN
search_socket9
		MOVLW	10H	 
		ADDWF	com_fsr,1
		DECFSZ	com_cn,1 
		GOTO	search_socket0
		bcf	STATUS,IRP
		BCF	3,0	 
		RETURN


;-----------------------------------------------------------------------------------
;		construction of new socket
;-----------------------------------------------------------------------------------
socket_entry
		bsf	STATUS,IRP
		MOVLW	skb & 0ffh
		MOVWF	FSR
		MOVF	FSR,0	 
		MOVWF	com_fsr
		MOVLW	SOCKETS	 
		MOVWF	com_cn
entry0
		BTFSC	INDF,7	 
		goto	entry9
		
		MOVLW	SYN_RCVD
		MOVWF	INDF
		INCF	FSR,1
		MOVLW	0f0h
		MOVWF	INDF
		INCF	FSR,1
		MOVF	ip_src,0 
		MOVWF	INDF
		INCF	FSR,1
		MOVF	ip_src1,0 
		MOVWF	INDF
		INCF	FSR,1
		MOVF	ip_src2,0 
		MOVWF	INDF
		INCF	FSR,1
		MOVF	ip_src3,0 
		MOVWF	INDF
		INCF	FSR,1
		
		MOVF	tcp_src_port,0 
		MOVWF	INDF
		INCF	FSR,1
		MOVF	tcp_src_port1,0 
		MOVWF	INDF
		INCF	FSR,1
		
		MOVF	tcp_seq_no,0 
		MOVWF	INDF
		INCF	FSR,1
		MOVF	tcp_seq_no1,0 
		MOVWF	INDF
		INCF	FSR,1
		MOVF	tcp_seq_no2,0 
		MOVWF	INDF
		INCF	FSR,1
		MOVF	tcp_seq_no3,0 
		MOVWF	INDF
		INCF	FSR,1

		MOVF	tcp_ack_no,0 
		MOVWF	INDF
		INCF	FSR,1
		MOVF	tcp_ack_no1,0 
		MOVWF	INDF
		INCF	FSR,1
		MOVF	tcp_ack_no2,0 
		MOVWF	INDF
		INCF	FSR,1
		MOVF	tcp_ack_no3,0 
		MOVWF	INDF
		INCF	FSR,1
		bcf	STATUS,IRP
		BCF	3,0	 
		RETURN
entry9
		MOVLW	10h
		ADDWF	FSR,1

		MOVLW	10H	 
		ADDWF	com_fsr,1
		DECFSZ	com_cn,1 
		GOTO	entry0
		
socket_entry_99	bcf	STATUS,IRP
		BSF	3,0 
		RETURN


;-----------------------------------------------------------------------------------
;		processing for broadcast Tx of Ethernet packets
;-----------------------------------------------------------------------------------
broad_cast
		CLRF	PCLATH
 
		MOVLW	0
		MOVWF	remote_adr
		MOVLW	PAGE_BEGIN
		MOVWF	remote_adr1

		MOVLW	IP_SIZE + PACKET_SIZE
		MOVWF	remote_len
		MOVLW	0
		MOVWF	remote_len1
 
		call	remote_write
		
		MOVLW	10h			; destination: send to ff-ff-ff-ff-ff-ff
		MOVWF	PORTC
		movlw	0ffh
		call	assert_wr
		movlw	0ffh
		call	assert_wr
		movlw	0ffh
		call	assert_wr
		movlw	0ffh
		call	assert_wr
		movlw	0ffh
		call	assert_wr
		movlw	0ffh
		call	assert_wr
		
		MOVLW	mymac		; source: set own MAC address
		MOVWF	FSR
		movlw	6
		call	transmit_nbytes
		RETURN

bootp2
		call	broad_cast
		CLRF	PCLATH
		
		movlw	COM_PROTO
		call	assert_wr
		movlw	IP_PROTO
		call	assert_wr

		movlw	.255
		movwf	ip_src 	; send own IP as 255.255.255.255
		movwf	ip_src1	 
		movwf	ip_src2	 
		movwf	ip_src3	 
		
  
		MOVLW	HIGH (DHCP_SIZE+20)
		MOVWF	ip_length
 
		MOVLW	(DHCP_SIZE + .20) & 0FFH
		MOVWF	ip_length1
		
		MOVLW	UDP_PROTO
		MOVWF	proto
		call	ip_common
 
		MOVLW	ip_sum - ip_header + PACKET_SIZE
		MOVWF	remote_adr
		MOVLW	PAGE_BEGIN
		MOVWF	remote_adr1
 		
		goto	set_checksum

bootp
		call	bootp2
		CLRF	PCLATH
		
		call	clear_sum			; clear checksum value
 
		MOVLW	PACKET_SIZE+IP_SIZE
		MOVWF	remote_adr
		MOVLW	PAGE_BEGIN
		MOVWF	remote_adr1

		MOVLW	DHCP_SIZE & 0ffh
		MOVWF	remote_len
		MOVLW	HIGH (DHCP_SIZE)
		MOVWF	remote_len1

;-------		
		call	remote_write
		
		MOVLW	10h
		MOVWF	PORTC
		
		movlw	0				; client BOOTP port
		call	assert_wr
		movlw	BOOTPC_PORT			; client BOOTP port
		call	assert_wr
		
		movlw	0				; server BOOTP port
		call	assert_wr
		movlw	BOOTPS_PORT			; server BOOTP port
		call	assert_wr
		
		movlw	HIGH (DHCP_SIZE)	;DHCP_SIZE>>8
		call	assert_wr
		movlw	DHCP_SIZE & 0ffh		; length
		call	assert_wr
		
		call	assert_wr2times			; sum
		
		movlw	1
		call	assert_wr			; Requare:1,Reply:2
		movlw	1
		call	assert_wr			; 10Mbps Ethernet:1
		movlw	6
		call	assert_wr			; EthernetLength:6
		DB	01,00		;clrw
		call	assert_wr			; Hop Count
		
		
		MOVLW	mymac + 2
		MOVWF	FSR
		MOVF	INDF,0
		call	assert_wr
		INCF	FSR,1
		MOVF	INDF,0
		call	assert_wr
		INCF	FSR,1
		MOVF	INDF,0
		call	assert_wr
		INCF	FSR,1
		MOVF	INDF,0
		call	assert_wr
		
		call	assert_wr2times
		call	assert_wr2times
		
		
		MOVLW	4*4
		MOVWF	gcn1
bootp_10	
		MOVLW	HIGH (assert_wr)
		MOVWF	PCLATH

		DB	01,00		;clrw
		call	assert_wr
		MOVLW	HIGH (bootp_10)
		MOVWF	PCLATH
		DECFSZ	gcn1,1		;djnz	gcn1,bootp_10
		GOTO	bootp_10
;
;	client hardware address
;
		MOVLW	mymac
		MOVWF	FSR
		MOVLW	HIGH (transmit_nbytes)
		MOVWF	PCLATH

		movlw	6
		call	transmit_nbytes
		MOVLW	HIGH (bootp_10)
		MOVWF	PCLATH
		
		MOVLW	.16 - .6
		MOVWF	gcn1
bootp_10_0
		MOVLW	HIGH (assert_wr)
		MOVWF	PCLATH

		DB	01,00		;clrw
		call	assert_wr
		MOVLW	HIGH (bootp_10_0)
		MOVWF	PCLATH
		DECFSZ	gcn1,1	 
		GOTO	bootp_10_0
;
;		startup file name
;
		MOVLW	.128 + .64
		MOVWF	gcn1
bootp_20
		MOVLW	HIGH (assert_wr)
		MOVWF	PCLATH

		DB	01,00		;clrw
		call	assert_wr
		MOVLW	HIGH (bootp_20)
		MOVWF	PCLATH
		DECFSZ	gcn1,1	 
		GOTO	bootp_20
	;
	;	Magic
	;
		MOVLW	HIGH (assert_wr)
		MOVWF	PCLATH

		movlw	63h	; 99
		call	assert_wr
		movlw	82h	; 130
		call	assert_wr
		movlw	53h	; 83
		call	assert_wr
		movlw	63h	; 99
		call	assert_wr
		RETURN


bootp_tx
		CLRF	PCLATH
		DB	01,00		;clrw
		call	calc_sum
		DB	01,00		;clrw
		call	calc_sum
		DB	01,00		;clrw
		call	calc_sum
		DB	01,00		;clrw
		call	calc_sum
		
		MOVLW	0ffh
		call	calc_sum
		MOVLW	0ffh
		call	calc_sum
		MOVLW	0ffh
		call	calc_sum
		MOVLW	0ffh
		call	calc_sum
		
		DB	01,00	 
		call	calc_sum
		MOVLW	.17
		call	calc_sum
		
		MOVLW	HIGH (DHCP_SIZE)
		call	calc_sum
		MOVLW	DHCP_SIZE & 0ffh
		call	calc_sum

 
 		MOVLW	PACKET_SIZE+IP_SIZE + 6
		MOVWF	remote_adr
		MOVLW	PAGE_BEGIN
		MOVWF	remote_adr1
 		call	set_checksum
		
		
		MOVLW	4h
		MOVWF	PORTC
		movlw	PAGE_BEGIN			; transmit page is start page 
		call	assert_wr0
		
		MOVLW	5
		MOVWF	PORTC
		movlw	(DHCP_SIZE+IP_SIZE+PACKET_SIZE) & 0ffh
		call	assert_wr0
		
		MOVLW	6
		MOVWF	PORTC
		movlw	HIGH (DHCP_SIZE+IP_SIZE+PACKET_SIZE)
		call	assert_wr0
		
		call	transmit
;		setb	rb.5
		RETURN
;-----------------------------------------------------------------------------------
;		write in of EEPROM data
;		automatically increment address
;--------------------------------------------------------------------------------- 
;		org	0a00h

		goto	$		;unknown
write_eeprom16
		MOVLW	'b'	 
		MOVWF	ind
		MOVF	wk2,0	 
		XORWF	wk1,1
		MOVF	wk1,0	 
		XORWF	wk2,1
		MOVF	wk2,0	 
		XORWF	wk1,1
		call	write_eeprom
		MOVF	wk2,0	 
		MOVWF	wk1
write_eeprom
		MOVLW	'w'	 
		SUBWF	ind,0
		BTFSC	3,2
		GOTO	write_eeprom16
write_eeprom0	bsf	STATUS,RP1
		bcf	STATUS,RP0
		MOVF	wk,0	 	;addr
		MOVWF	EEADR
		MOVF	wk1,0 
		MOVWF	EEDATA
		bsf	STATUS,RP0
		bcf	EECON1,7			;eepgd
		bsf	EECON1,2		;wren
		
		bcf	INTCON,7		;gie
		MOVLW	55H	 
		MOVWF	EECON2
		MOVLW	0AAH	 
		MOVWF	EECON2
		bsf	EECON1,1		;wr
		
		btfsc	EECON1,1		;wr
		goto	$-1
		
		bcf	EECON1,2		;wren
		bcf	STATUS,RP0
		bcf	STATUS,RP1
		INCF	wk,1 
		bsf	INTCON,7		;gie
		RETURN




get_nextbyte
		MOVF	remote_len,0 
		iorwf	remote_len1,0 
		btfsc	STATUS,Z
		goto	get_nextbyte9
		
		bcf	PORTE,0
		btfss	PORTC,5			; ~Wait
		goto	$-1
		MOVF	PORTD,0
		bsf	PORTE,0
		
		MOVWF	data0	 
		MOVLW	0AH	 
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	get_nextbyte9
		movlw	1			; LENGTH--
		subwf	remote_len,1 
		btfss	STATUS,C
		subwf	remote_len1,1	 
		RETURN
get_nextbyte9
		CLRF	data0		 
		RETURN





;-----------------------------------------------------------------------------------
;		parsing of CGI (GET method)
;		00b=192.168.0.200
;-----------------------------------------------------------------------------------
parse_cgi
		call	get_nextbyte
		MOVLW	0	 
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	parse9_tag
 
		MOVLW	0AH
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	parse9_tag
 	; Initial value
		MOVLW	'I'
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	initial_values_tag
	 		; pin change
		MOVLW	'R'
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	modify_pin
		

		MOVLW	'0'	 
		SUBWF	data0,1
		MOVF	data0,0	 
		MOVWF	wk
		SWAPF	wk,1 
		
		call	get_nextbyte
	 
		MOVLW	0
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	parse9_tag
		
		MOVLW	'0'	 
		SUBWF	data0,1
		MOVF	data0,0	 
		IORWF	wk,1
		
		call	get_nextbyte
	 
		MOVLW	0
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	parse9_tag
		MOVF	data0,0	 
		MOVWF	ind
 	; byte units
		MOVLW	'b'
		SUBWF	ind,0
		BTFSC	3,2
		GOTO	parse4
 		; word units
		MOVLW	'w'
		SUBWF	ind,0
		BTFSC	3,2
		GOTO	parse4
		goto	parse9_tag				; if not b|w, end
parse4
		CLRF	wk1  			; initial value = 0
		CLRF	wk2	 
		
		call	get_nextbyte			; skip '='
	 
		MOVLW	0
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	parse9_tag
 
		MOVLW	'&'
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	parse_cgi

parse_cgi0
		call	get_nextbyte
 
		MOVLW	0
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	parse9_tag
 
		MOVLW	' '
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	parse91_tag
	 		MOVLW	9
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	parse91_tag
	 
		MOVLW	'&'
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	parse_cgi2
		
 
		MOVLW	'.'
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	parse_cgi3
 
		MOVLW	','
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	parse_cgi3
 
		MOVLW	'0'
		SUBWF	data0,0
		BTFSS	3,0
		GOTO	parse_cgi3
 
		MOVLW	'9' ^ 0FFH
		ADDWF	data0,0
		BTFSC	3,0
		GOTO	parse_cgi3
		
		call	multiply_added
		goto	parse_cgi0
parse_cgi2
		call	write_eeprom
		goto	parse_cgi
parse_cgi3
		call	write_eeprom
		CLRF	wk1	 
		CLRF	wk2	 
		goto	parse_cgi0
parse91_tag
		call	write_eeprom
parse9_tag
		MOVLW	HIGH (parse9)
		MOVWF	PCLATH

		goto	parse9


;-----------------------------------------------------------------------------------
;		multiply by 10 and add data
;-----------------------------------------------------------------------------------
multiply_added
		MOVLW	'0'	 	
		SUBWF	data0,1		; since data is in ASCII characters
		
		BCF	3,0 
		RLF	wk1,1	 
		RLF	wk2,1	 		;
		
		MOVF	wk1,0 	;
		MOVWF	mul10
		MOVF	wk2,0	 
		MOVWF	mul101
		BCF	3,0 
		RLF	wk1,1	 
		RLF	wk2,1	 
		BCF	3,0	 
		RLF	wk1,1	 
		RLF	wk2,1	 
		MOVF	mul10,0	  
		ADDWF	wk1,1
		btfsc	STATUS,C
		INCF	wk2,1	 
		MOVF	mul101,0  
		ADDWF	wk2,1
		MOVF	data0,0	 	;add
		ADDWF	wk1,1
		btfsc	STATUS,C			; check CARRY
		INCF	wk2,1	 
		RETURN



;-----------------------------------------------------------------------------------
;		return EEPROM data to initial values
;-----------------------------------------------------------------------------------
		goto	$	 
initial_values_tag
		call	initial_values
		goto	parse9_tag

initial_values
		MOVLW	default_values_end - default_values_begin
		MOVWF	gcn1
		CLRF	wk	 
initial_values0
		call	get_initial_value
		MOVWF	wk1 
		
		MOVLW	HIGH (write_eeprom0)
		MOVWF	PCLATH

		call	write_eeprom0
		MOVLW	HIGH (initial_values0)
		MOVWF	PCLATH
		
		DECFSZ	gcn1,1	 
		GOTO	initial_values0
		RETURN

;-----------------------------------------------------------------------------------
;		pin changes from CGI
;		RA0=H
;-----------------------------------------------------------------------------------HAVE
modify_pin
		call	get_nextbyte			; get port information
		MOVLW	'A' ; out of range error
		SUBWF	data0,0
		BTFSS	3,0
		GOTO	parse9_tag
		MOVLW	'B' ^ 0FFH	 
		ADDWF	data0,0
		BTFSC	3,0
		GOTO	parse9_tag
		MOVLW	'A'	 	; subtract 'A'
		SUBWF	data0,1
		MOVLW	PORTA	 
		ADDWF	data0,1
		MOVF	data0,0
		MOVWF	FSR

		call	get_nextbyte			; get bit position
		MOVLW	'0'	 	; out of range error
		SUBWF	data0,0
		BTFSS	3,0
		GOTO	parse9_tag
		MOVLW	'9' ^ 0FFH		 	; 
		ADDWF	data0,0
		BTFSC	3,0
		GOTO	parse9_tag
		MOVLW	'0'		 
		SUBWF	data0,1
		INCF	data0,1		 
		CLRF	wk		 
		BSF	3,0	 
modify_pin0
		RLF	wk,1	 
		DECFSZ	data0,1	 
		GOTO	modify_pin0
		call	get_nextbyte
		MOVLW	'='		 
		SUBWF	data0,0		;; missing '=' means error
		BTFSS	3,2
		GOTO	parse9_tag
		call	get_nextbyte
		MOVLW	'H'	 
		SUBWF	data0,0		; High/Low output?
		BTFSC	3,2
		GOTO	modify_pin_h
		COMF	wk,1		 
		MOVF	wk,0		 
		ANDWF	INDF,1		; output 'L' to I/O port
		goto	parse9_tag

modify_pin_h
		MOVF	wk,0	 
		IORWF	INDF,1		;; output 'H' to I/O port
		goto	parse9_tag


get_initial_value
		MOVLW	1FH	 ; get initial values
		MOVWF	PCLATH
		MOVF	wk,0	 
		MOVWF	PCL




;===================================================================================
;		start up routine
;===================================================================================
;		org	0c00h

start

		CLRF	PORTA			; initialization of each port
		CLRF	PORTB
		clrF	PORTC			; RC =  RTL8019AS SA0-SA5
		clrF	PORTD			; RD = 00h
		MOVLW	B'111'		; each control port = H
		MOVWF	PORTE
		bsf	STATUS,RP0
		MOVLW	B'10000110'	 
		DB	00,62	 		; interrupt setting
		MOVLW	B'10000010' 
		MOVWF	ADCON1		; RE0-2 are Digital Pin
		MOVLW	B'00111111' 
		MOVWF	TRISA		; RA0-4 to be A/D input pins
		MOVLW	B'000'	 	; RE0-2 to be output pins
		MOVWF	TRISE
		bcf	STATUS,RP0

		CLRF	use	 
				; clear LCD port/serial port valid flag

		call	get_ip_address		; read out EEPROM IP address to file register.
		call	get_port_no		; read out EEPROM port number to file register.
;
;	check LCD port
;	if port is not 0, output rb7-2
;
		bsf	STATUS,RP0
		MOVF	lcd_port,0	; check if LCD port number is 0
		iorwf	lcd_port1,0 
		movlw	B'00001111'		; if LCD port is 0, output RB7-4, input RB3-0
		btfss	STATUS,Z
		movlw	B'00000011'		; if LCD port is not 0, output RB7-2, input RB1-0
		MOVWF	TRISB	 
		bcf	STATUS,RP0
		
		btfss	STATUS,Z
		bsf	use,0	 
			; if LCD port is not 0, enable use.LCD.


;	SERIAL port check

		call	clear_seq_no		; set TCP sequence number to 0
		
		call	init_lcd		; initialize LCD module
		
		MOVLW	B'11' 
		MOVWF	PORTE		; each control port = H
		
		MOVLW	5	 	; wait 5 ms
		MOVWF	wait_cn
		call	wait_ms
		
		bsf	STATUS,RP0
		MOVLW	B'11100000'
		MOVWF	TRISC
		MOVLW	B'11111111' 
		MOVWF	TRISD
		MOVLW	B'000'	 
		MOVWF	TRISE
		bcf	STATUS,RP0
		
		call	init_socket		; initialization of socket buffer
		CLRF	PCLATH
		
		call	initialize		; initialization of RTL8019AS
		
		MOVLW	$>>8
		MOVWF	PCLATH
		
		MOVLW	this_ip	 
		MOVWF	FSR
		;mov	FSR,#this_ip		; check if own IP is 0.0.0.0
		MOVF	INDF,0
		INCF	FSR,1
		iorwf	INDF,0
		INCF	FSR,1
		iorwf	INDF,0
		INCF	FSR,1
		iorwf	INDF,0
		btfsc	STATUS,Z
		goto	start1			; if IP is 0.0.0.0, go to start1
		
		MOVLW	HIGH (print_ip)	; display IP address on LCD
		MOVWF	PCLATH
		call	print_ip
		goto	start2
start1
		MOVLW	HIGH (write_lcd4)
		MOVWF	PCLATH
		
		bsf	PORTB,2
		MOVLW	'D'			; display 'DHCP' on LCD
		MOVWF	d4
		call	write_lcd4
		MOVLW	'H'
		MOVWF	d4
		call	write_lcd4
		MOVLW	'C'
		MOVWF	d4
		call	write_lcd4
		MOVLW	'P'
		MOVWF	d4
		call	write_lcd4
		
		MOVLW	$ >> 8
		MOVWF	PCLATH
start2
		bsf	STATUS,RP0
		MOVLW	B'11110000'		; change rc.4 to input pin
		MOVWF	PORTC
		bcf	STATUS,RP0
		
		MOVLW	HIGH (wait_us)
		MOVWF	PCLATH

		MOVLW	.100 	; 100us待つ
		MOVWF	wait_cn
		call	wait_us
		
		MOVLW	HIGH (start2)
		MOVWF	PCLATH
		btfss	PORTC,4		 	; check rc.4 pin
		goto	bootstrap		; if 'L', go to bootstrap mode
		
		bsf	STATUS,RP0
		MOVLW	B'10100000'		; restore rc to original state
		MOVWF	TRISC
		MOVLW	B'00100110' 
		MOVWF	TXSTA			; initialize ASYNC module on Tx side
		MOVLW	BAUD_RATE 
		MOVWF	SPBRG			; baud rate setting
		BSF	PIE1,5			; rcie; Rx interrupts enabled
		bcf	STATUS,RP0
		MOVLW	B'10000000'	 
		MOVWF	RCSTA			; initialize ASYNC module on Rx side
		bcf	STATUS,RP0
		bcf	INTCON,6	;peie		; peripheral device interrupts enabled
		
		CLRF	PCLATH
		
		;mov	dest[0],#assert_wr2x & 0ffh
		;mov	dest[1],#assert_wr2x >>8
		MOVLW	assert_wr2x & 0ffh 
		MOVWF	dest
		MOVLW	HIGH (assert_wr2x) 
		MOVWF	dest1		
		bsf	STATUS,RP0
		CLRF	dhcp_done
		bcf	STATUS,RP0
		CLRF	PORTB			; initial state RB=00h
		CLRF	TMR1L
		CLRF	TMR1H
		MOVLW	B'000101'
		MOVWF	T1CON
		BSF	STATUS,RP0

		BSF	PIE1,TMR1IE
		BCF	STATUS,RP0
		BSF	INTCON,PEIE	 
		BSF	INTCON,GIE	 
		BSF	INTCON,GIE		;gie; global interrupts enabled
		goto	main
;-----------------------------------------------------------------------------------
;		clear socket buffer
;-----------------------------------------------------------------------------------
init_socket
		bsf	STATUS,IRP
		MOVLW	skb & 0FFh
		MOVWF	FSR

		MOVLW	SOCKETS * .16	 
		MOVWF	com_cn
init_socket0	clrF	INDF
		INCF	FSR,1
		DECFSZ	com_cn,1	 
		GOTO	init_socket0
;
;		clear serial registration address
;
;		bsf	STATUS,IRP	; already irp set
		MOVLW	on_ether & 0ffh
		MOVWF	FSR

		MOVLW	SERIAL_PACKET_SIZE - 2	 
		MOVWF	com_cn
init_on_ether0	clrF	INDF
		INCF	FSR,1
		DECFSZ	com_cn,1		 
		GOTO	init_on_ether0
		
		bcf	STATUS,IRP
		RETURN

;-----------------------------------------------------------------------------------
;		if PIC16F877 EEPROM, get IP address
;-----------------------------------------------------------------------------------
get_ip_address
		bsf	STATUS,RP0
		
		MOVLW	this_ip	 
		MOVWF	FSR
		MOVLW	4		 
		MOVWF	common
		bsf	STATUS,RP1
		bcf	STATUS,RP0
		CLRF	EEADR	 
get_ip_address0
		bsf	STATUS,RP1
		bsf	STATUS,RP0
		bcf	EECON1,7			;eepgd
		BSF	EECON1,0 
		bcf	STATUS,RP0
		MOVF	EEDATA,0	 
		INCF	EEADR,1	 
		bcf	STATUS,RP1
		
		movwf	INDF
		INCF	FSR,1
		DECFSZ	common,1 
		GOTO	get_ip_address0
		
		MOVLW	ident
		MOVWF	FSR
		clrF	INDF
		INCF	FSR,1
		clrF	INDF
		RETURN
;-----------------------------------------------------------------------------------
;		get port number from PIC16F877 EEPROM
;-----------------------------------------------------------------------------------
get_port_no
		MOVLW	http_port & 0ffh
		MOVWF	FSR
		MOVLW	.4 * .2	 
		MOVWF	common
		bsf	STATUS,RP1
		bcf	STATUS,RP0
		MOVLW	.16	 
		MOVWF	EEADR
get_port_no0
		bsf	STATUS,RP0
		bcf	EECON1,7	;eepgd
		bsf	EECON1,0 
		bcf	STATUS,RP0
		MOVF	EEDATA,0 
		MOVWF	INDF
		INCF	FSR,1
		INCF	EEADR,1	 
		
		DECFSZ	common,1 
		GOTO	get_port_no0
		bcf	STATUS,RP1
		RETURN
;-----------------------------------------------------------------------------------
;		initialization of TCP sequence number
;-----------------------------------------------------------------------------------
clear_seq_no
		bsf	STATUS,RP0
		CLRF	seq_no	 
		CLRF	seq_no1	 
		CLRF	seq_no2	 
		CLRF	seq_no3	 
		bcf	STATUS,RP0
		RETURN


;-----------------------------------------------------------------------------------
;		initialization of LCD
;-----------------------------------------------------------------------------------HAVE
init_lcd
		MOVLW	.15	 	; wait 15ms
		MOVWF	wait_cn
		call	wait_ms
		
		BCF	PORTB,2			; RS='L'
		MOVLW	B'00110000'
		MOVWF	d8
		call	write_lcd8
		MOVLW	.5		; wait 4.1ms
		MOVWF	wait_cn
		call	wait_ms
		
		MOVLW	B'00110000'
		MOVWF	d8
		call	write_lcd8
		MOVLW	.100		; wait 100us
		MOVWF	wait_cn
		call	wait_us
		
		MOVLW	B'00110000'
		MOVWF	d8
		call	write_lcd8		; 0 0 0011 (3)
		
		MOVLW	B'00100000'
		MOVWF	d8
		call	write_lcd8		; 0 0 0010 (4bit)
	;
		MOVLW	B'00101000'		; duty,font set9
		MOVWF	d4
		call	write_lcd4
		
		MOVLW	B'00000001'		; clear command
		MOVWF	d4
		call	write_lcd4
		MOVLW	.2		; wait until clear ends
		MOVWF	wait_cn
		call	wait_ms
		
		MOVLW	B'00000110'		; entry mode set
		MOVWF	d4
		call	write_lcd4
		
		MOVLW	B'00001110'		; display on,cursor on
		MOVWF	d4
		call	write_lcd4
		RETURN



;-----------------------------------------------------------------------------------
;		LCD write routine for 8 bit mode
;-----------------------------------------------------------------------------------
write_lcd8
		BTFSS	use,0		;btfss	use.0; do not write to RB port unless LCD is on
		goto	lcd_skip
		
		MOVF	PORTB,0	 
		MOVWF	tmp
		MOVLW	0FH	 
		ANDWF	tmp,1
		MOVLW	0F0H	 
		ANDWF	d8,1
		MOVF	d8,0	 
		IORWF	tmp,1
		MOVF	tmp,0	 	; output to RB port
		MOVWF	PORTB

		goto	$+1
		BSF	PORTB,3	 	; set E pin to 'H'
		GOTO	$+1			;jmp	$+1
		BCF	PORTB,3	 
lcd_skip
		MOVLW	.40
		MOVWF	wait_cn
		call	wait_us
		RETURN




;-----------------------------------------------------------------------------------
;		LCD write routine for 4 bit mode
;-----------------------------------------------------------------------------------
write_lcd4
		MOVF	d4,0	 
		MOVWF	d8
		call	write_lcd8
		
		MOVF	d4,0	 
		MOVWF	d8
		SWAPF	d8,1	 
		call	write_lcd8
		RETURN

;-----------------------------------------------------------------------------------
;		hexadecimal LCD output routine
;-----------------------------------------------------------------------------------
print_hex
		bsf	PORTB,2
		swapf	cd,0
		CLRF	PCLATH
		call	getascii
		MOVWF	d4	 
		call	write_lcd4
	;
		MOVF	cd,0
		CLRF	PCLATH
		call	getascii
		MOVWF	d4	 
		call	write_lcd4
		RETURN


;-----------------------------------------------------------------------------------
;		waits on the order of ms
;-----------------------------------------------------------------------------------
wait_ms
wait_ms0
		MOVLW	0	 
		MOVWF	wait_cn2
wait_ms1	GOTO	$+1	 
		GOTO	$+1 
		GOTO	$+1	 
		GOTO	$+1	 
		GOTO	$+1	 
		GOTO	$+1	 
		GOTO	$+1	 
		DECFSZ	wait_cn2,1 
		GOTO	wait_ms1
		DECFSZ	wait_cn,1 
		GOTO	wait_ms0
		RETURN

;-----------------------------------------------------------------------------------
;		waits on the order of μs
;-----------------------------------------------------------------------------------
wait_us
wait_us0
		GOTO	$+1 
	 
		DECFSZ	wait_cn,1
		GOTO	wait_us0
		RETURN


;-----------------------------------------------------------------------------------
;		32 bit binary to decimal conversion routine
;-----------------------------------------------------------------------------------
put_decimal32
		MOVF	FSR,0	 
		MOVWF	save_fsr
		MOVLW	decimal_top & 0ffh	; initialization of storage area
		MOVWF	FSR
		bsf	STATUS,IRP			; IRP=1
		call	divide32		; lowest conversion
		call	divide32
		call	divide32
		call	divide32
		call	divide32
		
		call	divide32
		call	divide32
		call	divide32
		call	divide32
		call	divide32		; highest conversion
		
		MOVLW	.10 - .1		;mov	val_cn,#10-1
		MOVWF	val_cn
		goto	put_decimal_ent


;-----------------------------------------------------------------------------------
;		16 bit binary to decimal conversion routine
;-----------------------------------------------------------------------------------
put_decimal16
		MOVF	FSR,0 
		MOVWF	save_fsr
		MOVLW	decimal_top & 0ffh	; initialization of storage area
		MOVWF	FSR
		bsf	STATUS,IRP			; IRP=1
		call	divide16		; lowest conversion
		call	divide16
		call	divide16
		call	divide16
		call	divide16		; highest conversion
		
		MOVLW	.5 - .1	 
		MOVWF	val_cn
		goto	put_decimal_ent

;-----------------------------------------------------------------------------------
;		8 bit binary to decimal conversion routine
;-----------------------------------------------------------------------------------
put_decimal
		movwf	val
		
		MOVF	FSR,0	 
		MOVWF	save_fsr
		MOVLW	decimal_top & 0ffh	; initialization of storage area
		MOVWF	FSR
		bsf	STATUS,IRP			; IRP=1
		call	divide			; lowest conversion
		call	divide
		call	divide			; highest conversion
		
		MOVLW	.3 - .1	 
		MOVWF	val_cn
put_decimal_ent	CLRF	val_m	 
put_decimal0
		MOVLW	0	 
		SUBWF	val_m,0
		BTFSS	3,2
		GOTO	put_decimal1
		MOVLW	'0'	 
		SUBWF	INDF,0
		BTFSC	3,2
		GOTO	put_decimal2
put_decimal1	MOVF	INDF,0	 
		MOVWF	data0
		call	puttty
			; output (destination will change depending on dest)
		MOVLW	HIGH (put_decimal1)
		MOVWF	PCLATH
		
		INCF	val_m,1	 
put_decimal2	INCF	FSR,1
		DECFSZ	val_cn,1 
		GOTO	put_decimal0
		MOVF	INDF,0	 	; lowest digit
		MOVWF	data0
		call	puttty			; output (destination will change depending on dest)
		MOVLW	HIGH (put_decimal2)
		MOVWF	PCLATH

		bcf	STATUS,IRP
		MOVF	save_fsr,0
		MOVWF	FSR
		RETURN


;-----------------------------------------------------------------------------------
;		LCD display of 8 bit binary in decimal format
;-----------------------------------------------------------------------------------
print_dec
		movwf	val
		
		MOVF	FSR,0	 	; save fsr
		MOVWF	save_fsr
		MOVLW	decimal_top & 0ffh	; initialization of storage area
		MOVWF	FSR
		bsf	STATUS,IRP			; IRP=1
		call	divide			; lowest conversion
		call	divide
		call	divide			; highest conversion
		
		bsf	PORTB,2
		MOVF	INDF,0 
		MOVWF	d4
		call	write_lcd4
		INCF	FSR,1
		MOVF	INDF,0	 
		MOVWF	d4
		call	write_lcd4
		INCF	FSR,1
		MOVF	INDF,0 
		MOVWF	d4
		call	write_lcd4
		
		bcf	STATUS,IRP
		MOVF	save_fsr,0
		MOVWF	FSR
		RETURN






;-----------------------------------------------------------------------------------
;		8 bit division routine
;-----------------------------------------------------------------------------------
divide
		MOVLW	8
		MOVWF	gcn1
		CLRF	val_m 
divide0
		BCF	3,0 
		RLF	val,1	 
		RLF	val_m,1	 
		
		movlw	B'11110110'
		addwf	val_m,0
		btfsc	STATUS,C
		MOVWF	val_m	 
		btfsc	STATUS,C
		INCF	val,1 
		
		DECFSZ	gcn1,1
		GOTO	divide0
		decF	FSR,1
		MOVF	val_m,0	 	; remainder
		MOVWF	INDF
		MOVLW	'0'	 
		ADDWF	INDF,1
		RETURN


;-----------------------------------------------------------------------------------
;		16 bit division routine
;-----------------------------------------------------------------------------------
divide16
		MOVLW	.16
		MOVWF	gcn1
		clrF	val_m
divide16_0
		BCF	3,0	 
		RLF	val,1	 
		RLF	val1,1	 
		RLF	val_m,1	 
		
		movlw	B'11110110'
		addwf	val_m,0
		btfsc	STATUS,C
		MOVWF	val_m	 
		btfsc	STATUS,C
		INCF	val,1	 
		
		DECFSZ	gcn1,1	 
		GOTO	divide16_0
		decF	FSR,1
		MOVF	val_m,0 	; remainder
		MOVWF	INDF
		MOVLW	'0'	 
		ADDWF	INDF,1
		RETURN


;-----------------------------------------------------------------------------------
;		32 bit division routine
;-----------------------------------------------------------------------------------
divide32
		MOVLW	.32
		MOVWF	gcn1
		CLRF	val_m	 
divide32_0
		BCF	3,0	 
		RLF	val,1	 
		RLF	val1,1	 
		RLF	val2,1	 
		RLF	val3,1		 
		RLF	val_m,1	 
		
		movlw	B'11110110'
		addwf	val_m,0
		btfsc	STATUS,C
		MOVWF	val_m	 
		btfsc	STATUS,C
		INCF	val,1	 
		
		DECFSZ	gcn1,1	 
		GOTO	divide32_0
		decF	FSR,1
		MOVF	val_m,0	 	; remainder
		MOVWF	INDF
		MOVLW	'0'	 
		ADDWF	INDF,1
		RETURN

;===================================================================================
;		bootstrap main routine
;===================================================================================
get_lcdmes
		MOVLW	lcd_mes >> 8	 
		MOVWF	PCLATH
		MOVF	wk,0 
		MOVWF	PCL
;
;	BOOTSTRAP MODE Entry
;
bootstrap
		MOVLW	$ >> 8	 
		MOVWF	PCLATH
		MOVLW	B'11000000' 
		MOVWF	d4
		bcf	PORTB,2			;RS
		call	write_lcd4		; move cursor to second line

		MOVLW	.16	 
		MOVWF	gcn1
		MOVLW	lcd_mes & 0ffh
		MOVWF	wk
bootstrap10
		call	get_lcdmes		; display 'Bootstrap Mode' on LCD
		MOVWF	d4 
		
		MOVLW	$ >> 8	 
		MOVWF	PCLATH

		bsf	PORTB,2		;RS
		call	write_lcd4
		MOVLW	$ >> 8	 
		MOVWF	PCLATH

		
		INCF	wk,1	 
		DECFSZ	gcn1,1
		GOTO	bootstrap10	 
;
;		ASYNCの初期化
;
		bsf	STATUS,RP0 
		MOVLW	B'10100000' 
		MOVWF	TRISC
		MOVLW	B'00100110'	 	; setting on Tx side
		MOVWF	TXSTA
		MOVLW	BAUD_RATE 	; baud rate setting
		MOVWF	SPBRG
		BSF	PIE1,RCIE 		; Rx interrupts enabled
		bcf	STATUS,RP0	 
		MOVLW	B'10010000' 
		MOVWF	RCSTA
		MOVLW	async_transmit & 0ffh ; Tx routine setting
		MOVWF	dest
		MOVLW	async_transmit >> 8  
		MOVWF	dest1
		bsf	INTCON,PEIE	 			; peripheral device interrupts enabled
		bsf	INTCON,GIE 			; (global) interrupts enabled

		MOVLW	bs_1 & 00ffh 		; start up message
		MOVWF	com_cn
		call	put_bs_text
		
		MOVLW	bs_config & 00ffh 
		MOVWF	com_cn			; display of current settings
		call	put_bs_text
		
		MOVLW	bs_prompt & 00ffh 	; prompt display
		MOVWF	com_cn
		call	put_bs_text
;-----------------------------------------------------------------------------------
;		Bootstrap main loop
;-----------------------------------------------------------------------------------
		bsf	STATUS,RP0	 
bootstrap0
 			; Rx wait (fifo_cn!=0 on receive)
		MOVLW	0
		SUBWF	fifo_cn,0
		BTFSC	3,2
		GOTO	bootstrap0		
		MOVF	fifo_poi,0	 
		MOVWF	FSR			; get Rx pointer
		MOVF	INDF,0		 
		MOVWF	data0			; get received character
		
		incF	fifo_poi,1				; increment Rx buffer
 
		MOVLW	fifo_bottom
		SUBWF	fifo_poi,0
		BTFSS	3,0
		GOTO	ring1_1
		MOVLW	fifo_top 
		MOVWF	fifo_poi
ring1_1		DECF	fifo_cn,1	 	; decrement number of Rx bytes
		
 		; Case of backspace character...
		MOVLW	CH_BACKSPACE
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	boots_bs
		bcf	STATUS,RP0 
		call	async_transmit				; To echo back, send!!
		bsf	STATUS,RP0 
		
 			; Case of CR...
		MOVLW	.13
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	boots_cr			
		incF	fifo_line_cn,1
		goto	bootstrap0				; return to main loop


;-----------------------------------------------------------------------------------
;		backspace Rx processing
;-----------------------------------------------------------------------------------
boots_bs
 				; if there are no characters to delete, do nothing
		MOVLW	0
		SUBWF	fifo_line_cn,0
		BTFSC	3,2
		GOTO	bootstrap0
		MOVF	fifo_poi,0 
		MOVWF	FSR
		DECF	FSR,1	 
		
 		MOVLW	fifo_top
		SUBWF	FSR,0
		BTFSC	3,0
		GOTO	boots_bs1
		MOVLW	fifo_bottom - 1	 
		MOVWF	FSR
boots_bs1	clrF	INDF	 	; clear BS character just typed
		
		MOVF	fifo_line,0	 
		MOVWF	FSR
		MOVF	fifo_line_cn,0	 
		ADDWF	FSR,1
		DECF	FSR,1		 
		
	 
		MOVLW	fifo_bottom
		SUBWF	FSR,0
		BTFSS	3,0
		GOTO	boots_bs2
		MOVLW	fifo_top	 
		SUBWF	FSR,1
boots_bs2	clrF	INDF	 	; clear character typed prior
		bcf	STATUS,IRP		 
		
		bcf	STATUS,RP0	 
		call	async_transmit				; for echo back, echo BS character
		MOVLW	' '	 
		MOVWF	data0
		call	async_transmit				; output space
		MOVLW	CH_BACKSPACE 
		MOVWF	data0
		call	async_transmit				; echo BS again
		bsf	STATUS,RP0 
		
		decF	fifo_line_cn,1
		goto	bootstrap0


;-----------------------------------------------------------------------------------
;		CR Rx processing
;-----------------------------------------------------------------------------------
boots_cr
		MOVLW	.10	 
		MOVWF	data0
		bcf	STATUS,RP0	 
		call	async_transmit				; echo new line
		bsf	STATUS,RP0	 
	 	; Is nothing inputted?
		MOVLW	0
		SUBWF	fifo_line_cn,0
		BTFSS	3,2
		goto	bs_job					; divide work
bootstrap9
		bcf	STATUS,RP0		;rp0
		MOVLW	bs_prompt & 00ffh	;mov	com_cn,#bs_prompt & 00ffh
		MOVWF	com_cn			; prompt display
		call	put_bs_text
		
		bsf	STATUS,RP0	 
		MOVF	fifo_poi,0		 
		MOVWF	fifo_line
		clrF	fifo_line_cn
		goto	bootstrap0				; to main loop

;
;		when an invalid command is input
;
bootstrap99
		bcf	STATUS,RP0		 
		MOVLW	bs_invalid & 00ffh 
		MOVWF	com_cn
		call	put_bs_text
		goto	bootstrap9



get_bs_str
		MOVLW	1FH		 
		MOVWF	PCLATH
		MOVF	bs_ptr,0	 
		goto	get_bs_job
get_bs_str2
		MOVLW	1FH		 
		MOVWF	PCLATH
		MOVF	bs_ptr2,0	 
		MOVWF	PCL


;-----------------------------------------------------------------------------------
;		command analysis processing
;-----------------------------------------------------------------------------------
bs_job
		movf	fifo_line,0 
		MOVWF	save_line
		MOVF	fifo_line_cn,0	 
		MOVWF	save_cn
		clrF	bs_ptr
bs_job10
		call	get_bs_str
		MOVWF	bs_ptr2	 
		MOVLW	$ >> 8	 
		MOVWF	PCLATH

		
 				; no match
		MOVLW	0
		SUBWF	bs_ptr2,0
		BTFSC	3,2
		GOTO	bootstrap99
bs_job0
		call	get_bs_str2
		MOVWF	wk	 
		MOVLW	$ >> 8	 
		MOVWF	PCLATH

	 	; OK to end
		MOVLW	0
		SUBWF	wk,0
		BTFSC	3,2
		GOTO	bs_job1			
		call	getterm				; get 1 character from buffer
		bsf	STATUS,RP0	 
		
 		MOVLW	.13
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	bs_job2	
 		; wrong character?
		MOVF	data0,0
		SUBWF	wk,0
		BTFSS	3,2
		GOTO	bs_job2			
		incF	bs_ptr2,1				; advance 1 character
		goto	bs_job0

bs_job2
		MOVLW	2		 
		ADDWF	bs_ptr,1
		MOVF	save_line,0	 
		MOVWF	fifo_line
		MOVF	save_cn,0	 
		MOVWF	fifo_line_cn
		goto	bs_job10
bs_job1
		incF	bs_ptr,1
		call	get_bs_str
		MOVWF	wk	 
		
		bcf	STATUS,RP0	 
		MOVLW	0EH		 
		MOVWF	PCLATH
		MOVF	wk,0	 
		MOVWF	PCL


;		org	0e00h


;-----------------------------------------------------------------------------------
;		'initialize' execution routine
bsj_init
		call	initial_values
bsj_config	MOVLW	bs_config & 00ffh    
		MOVWF	com_cn			; display of current settings

		call	put_bs_text
		goto	bootstrap9
;-----------------------------------------------------------------------------------
;		'help' execution routine
bsj_help
		MOVLW	bs_help & 00ffh	 
		MOVWF	com_cn			; help
		call	put_bs_text
		goto	bootstrap9
;-----------------------------------------------------------------------------------
;		read past space characters
skip_space
		call	getterm
 
		MOVLW	' '
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	skip_space
 
		MOVLW	9
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	skip_space	
		retURN
;-----------------------------------------------------------------------------------
;		'lcd=xxxxx' execution routine
bsj_lcd
		MOVLW	.16 + .2 
		MOVWF	 wk
		goto	bs_set_word
;-----------------------------------------------------------------------------------
;		'para=xxxxx' execution routine
bsj_para
		MOVLW	.16 + .2 + .2
		MOVWF	 wk
;		mov	wk[0],#16+2+2
		goto	bs_set_word
;-----------------------------------------------------------------------------------
;		'serial=xxxxx' execution routine
bsj_serial
;		mov	wk[0],#16+2+2+2
		MOVLW	.16 + .2 +.2 + .2
		MOVWF	 wk
		goto	bs_set_word
;-----------------------------------------------------------------------------------
;		'http=xxxxx' execution routine
bsj_http
;		mov	wk[0],#16
		MOVLW	.16
		MOVWF	 wk
		
bs_set_word	MOVLW	'w'	 
		MOVWF	ind
		MOVLW	1	 
		MOVWF	byte_cn
		goto	bs_set_common
;-----------------------------------------------------------------------------------
;		'net=xxxxx' execution routine
bsj_net
		;mov	wk[0],#4
		MOVLW	4
		MOVWF	wk
		goto	bs_set_byte
;-----------------------------------------------------------------------------------
;		'gate=xxxxx' execution routine
bsj_gate
 
		MOVLW	8
		MOVWF	wk
		goto	bs_set_byte
;-----------------------------------------------------------------------------------
;		'ip=xxx.xxx.xxx.xxx' execution routine
bsj_ip
 		; EEPROM ADR=0
		MOVLW	0
		MOVWF	wk
		
bs_set_byte 
		MOVLW	'b'
		MOVWF	ind
	 
		MOVLW	4
		MOVWF	byte_cn
		
bs_set_common
		call	skip_space
	 
		MOVLW	.13
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	put_bs_err	
	 
		MOVLW	'='
		SUBWF	data0,0
		BTFSS	3,2
		GOTO	put_bs_err			
		
		call	skip_space
	 
		MOVLW	.13
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	put_bs_err			
		CLRF	wk1		 ; initial value = 0
		CLRF	wk2	 	; initial value = 0
		goto	bs_getnumber
bs_getnumber0
		call	getterm
bs_getnumber
	 				; if CR, end
		MOVLW	.13
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	bs_write9			
 		MOVLW	'.'
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	bs_write
 		MOVLW	','
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	bs_write
 		MOVLW	'0'
		SUBWF	data0,0
		BTFSS	3,0
		GOTO	bs_write
 		MOVLW	'9' ^ 0FFH
		ADDWF	data0,0
		BTFSC	3,0
		GOTO	bs_write

		call	multiply_added
		goto	bs_getnumber0
bs_write
		call	write_eeprom
		decF	byte_cn,1
 				; specified number of bytes written?
		MOVLW	0
		SUBWF	byte_cn,0
		BTFSC	3,2
		GOTO	bootstrap9
		CLRF	wk1		;clr	wk[1]; initial value = 0
		CLRF	wk2		;clr	wk[2]	; initial value = 0

		goto	bs_getnumber0
bs_write9
		call	write_eeprom
		goto	bootstrap9

;-----------------------------------------------------------------------------------
;		read 1 character from line buffer (terminating character is CR)
;-----------------------------------------------------------------------------------
getterm
		bsf	STATUS,RP0		;rp0
getterm0	MOVF	fifo_line,0		;mov	fsr,fifo_line
		MOVWF	FSR
		MOVF	INDF,0			;mov	data,indirect	
		MOVWF	data0			; command analysis
		
		incF	fifo_line,1
 		MOVLW	fifo_bottom
		SUBWF	fifo_line,0
		BTFSS	3,0
		GOTO	getterm1
		MOVLW	fifo_top 
		MOVWF	fifo_line
getterm1	decF	fifo_line_cn,1				; decrement number of Rx bytes
		
			; skip NULL characters
		MOVLW	0
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	getterm0
		bcf	STATUS,RP0		;rp0
		retURN 

put_bs_err
		MOVLW	bs_err & 00ffh	 
		MOVWF	com_cn			; Syntax error display
		call	put_bs_text
		goto	bootstrap9




;-----------------------------------------------------------------------------------
;		Text output routine for bootstrap routine
;-----------------------------------------------------------------------------------
put_bs_text
		bsf	STATUS,RP1
		bcf	STATUS,RP0
		MOVLW	13H	 	; BANK 10h fan
		MOVWF	EEADRH
		MOVF	com_cn,0	 
		MOVWF	EEADR
		bsf	STATUS,RP0
		bsf	EECON1,7	;eepgd
		BSF	EECON1,0 
		nop
		nop
		bcf	STATUS,RP0
		;mov	getmes_wk[0],eedath
		;mov	getmes_wk[1],eedata
		MOVF	EEDATH,0
		MOVWF	getmes_wk
		MOVF	EEDATA,0 
		MOVWF	getmes_wk1
		bcf	STATUS,RP1
		
		RLF	getmes_wk1,0	 
		RLF	getmes_wk,1	 
		MOVF	getmes_wk,0
		andlw	7fh
		btfsc	STATUS,Z
		goto	put_bs_text9
		MOVWF	data0		 
		MOVLW	'$'		 
		SUBWF	data0,0
		BTFSC	3,2
		GOTO	ctrl_code
		call	async_transmit
		
		MOVF	getmes_wk1,0
		andlw	7fh
		btfsc	STATUS,Z
		goto	put_bs_text9
		MOVWF	data0		 
		call	async_transmit
		
		INCF	com_cn,1	 
		goto	put_bs_text
put_bs_text9	RETURN



;-----------------------------------------------------------------------------------
;		232C output routine
;-----------------------------------------------------------------------------------
async_transmit
		BTFSS	PIR1,4		;btfss	pir1.4
		goto	async_transmit
		MOVF	data0,0		 
		MOVWF	TXREG
		RETURN


;-----------------------------------------------------------------------------------
;		control code output (1)
;-----------------------------------------------------------------------------------
;		org	0f00h
ctrl_code
		MOVLW	HIGH (ctrl_code1)
		MOVWF	PCLATH
		MOVF	getmes_wk1,0
		andlw	7fh
		addlw	-'0'
		call	ctrl_code1
		INCF	com_cn,1		 
		goto	put_bs_text
		
;		nop	10
ctrl_code1
		ADDWF	2,1	 
		goto	put_mac_address		; 0:MAC address
		goto	put_ip_address		; 1:IP address
		goto	put_netmask		; 2:net mask
		goto	put_gateway_address	; 3:gateway
		goto	put_http_port		; 4:http port
		goto	put_lcd_port		; 5:lcd port
		goto	put_io_port		; 6:parallel port
		goto	put_232_port		; 7:232c port
		goto	put_version		; 8:version display
		
		goto	put_send_packet		; 9:number of Tx packets
		goto	put_this_ip		; A:display own IP
		goto	put_ptop		; B:display PtoP IP address

put_send_packet
		MOVLW	ident
		MOVWF	FSR
		MOVF	INDF,0		 
		MOVWF	val1
		INCF	FSR,1
		MOVF	INDF,0		 
		MOVWF	val
		INCF	FSR,1	
		MOVLW	0		 
		MOVWF	val2
		INCF	FSR,1
		MOVLW	0	 
		MOVWF	val3
		goto	put_decimal32		; display number of Tx packets

put_http_port
		bsf	STATUS,RP1
		MOVLW	.16		 
		MOVWF	EEADR
		goto	putcom16
put_lcd_port
		bsf	STATUS,RP1
		MOVLW	.16 + .2	 
		MOVWF	EEADR
		goto	putcom16
put_io_port
		bsf	STATUS,RP1
		MOVLW	.16 + .4	 
		MOVWF	EEADR
		goto	putcom16
put_232_port
		bsf	STATUS,RP1
		MOVLW	.16 + .6	 
		MOVWF	EEADR
putcom16	goto	put_number16
	;	RETURN


put_this_ip
		MOVLW	this_ip	 
		MOVWF	FSR
		MOVLW	4
		MOVWF	common
		call	put_number_fr
		RETURN
put_ptop
		bsf	STATUS,RP1
		MOVLW	.24	 
		MOVWF	EEADR
		goto	putcom32
put_ip_address
		bsf	STATUS,RP1
		CLRF	EEADR		 
		goto	putcom32
put_netmask
		bsf	STATUS,RP1
		MOVLW	.4
		MOVWF	EEADR
		goto	putcom32
put_gateway_address
		bsf	STATUS,RP1
		MOVLW	.8
		MOVWF	EEADR
		goto	putcom32
put_version
		bsf	STATUS,RP1
		MOVLW	.12
		MOVWF	EEADR
putcom32	MOVLW	.4	 
		MOVWF	common
		goto	put_number
		RETURN

;-----------------------------------------------------------------------------------
;		output to external port
;-----------------------------------------------------------------------------------
puttty
		MOVF	dest1,0	 
		MOVWF	PCLATH
		MOVF	dest,0	 
		MOVWF	PCL


;-------------------------------------------------------------------------------

;-----------------------------------------------------------------------------------
;		send socket status to web browser (namely, netstat -n)
;-----------------------------------------------------------------------------------
;put_socket_stat
;		bsf	STATUS,IRP 
;		MOVF	INDF,0	 
;		MOVWF	cd
;		incF	FSR,1		;fsr
;		call	put_hexadecimal
;		MOVF	INDF,0	 
;		MOVWF	cd
;		incF	FSR,1		;fsr
;		call	put_hexadecimal
;		
;		MOVLW	' '	 
;		MOVWF	data0
;		call	puttty
;		MOVLW	$ >> 8	 
;		MOVWF	PCLATH
;		bsf	STATUS,IRP	;irp
;		MOVF	INDF,0	 
;		incF	FSR,1		;fsr
;		call	put_decimal
;		MOVLW	'.'	 
;		MOVWF	data0
;		call	puttty
;		MOVLW	 $ >> 8	 
;;		MOVWF	PCLATH
;		
;		bsf	STATUS,IRP		;irp
;		MOVF	INDF,0		 
;		INCF	FSR,1	 
;		call	put_decimal
;		MOVLW	'.'	 
;		MOVWF	data0
;		call	puttty
;		MOVLW	$ >> 8	 
;		MOVWF	PCLATH
;		
;		bsf	STATUS,IRP
;		MOVF	INDF,0	 
;		INCF	FSR,1		;inc	fsr
;		call	put_decimal
;		MOVLW	'.'	 
;		MOVWF	data0
;		call	puttty
;		MOVLW	$ >>8	 
;		MOVWF	PCLATH
;		bsf	STATUS,IRP	;irp
;		MOVF	INDF,0	 
;		incF	FSR,1
;		call	put_decimal
;		
;;		MOVLW	' '	 
;		MOVWF	data0
;		call	puttty
;		MOVLW	$ >>8	 
;		MOVWF	PCLATH		
;		
;		bsf	STATUS,IRP	;irp
;		MOVF	INDF,0	 
;		MOVWF	val1
;		incF	FSR,1		;fsr
;		MOVF	INDF,0	 
;		MOVWF	val
;		INCF	FSR,1	 
;		call	put_decimal16
;		
;		MOVLW	' ' 
;		MOVWF	data0
;		call	puttty
;		MOVLW	$ >> 8	 
;		MOVWF	PCLATH
;		
;		bsf	STATUS,IRP	;irp
;		MOVF	INDF,0	 
;		MOVWF	val3
;		INCF	FSR,1	 
;		MOVF	INDF,0 
;		MOVWF	val2
;		INCF	FSR,1	 
;		MOVF	INDF,0	 
;		MOVWF	val1
;		INCF	FSR,1	 
;		MOVF	INDF,0	 
;		MOVWF	val
;		INCF	FSR,1	 
;		call	put_decimal32
;		
;		MOVLW	' '	 
;		MOVWF	data0
;		call	puttty
;		MOVLW	$ >>8	 
;		MOVWF	PCLATH
;		
;		bsf	STATUS,IRP	;irp
;		MOVF	INDF,0	 
;		MOVWF	val3
;		INCF	FSR,1	 
 ;		MOVF	INDF,0
;		MOVWF	val2
;		INCF	FSR,1	 
 ;		MOVF	INDF,0
;		MOVWF	val1
;		INCF	FSR,1		 
 ;		MOVF	INDF,0	
;		MOVWF	val
;		goto	put_decimal32
 ;


;-----------------------------------------------------------------------------------
;		get 8 bit '.' -delimited decimal values from EEPROM and display
;-----------------------------------------------------------------------------------
put_number0
		MOVLW	'.'	 
		MOVWF	data0
		call	puttty
		MOVLW	$ >> 8
		MOVWF	PCLATH
put_number
		bsf	STATUS,RP1
		bsf	STATUS,RP0
		bcf	EECON1,7	;eepgd
		BSF	EECON1,0 
		bcf	STATUS,RP0
		MOVF	EEDATA,0 
		MOVWF	data0
		INCF	EEADR,1	 
		bcf	STATUS,RP1
		
		MOVF	data0,0
		call	put_decimal
		DECFSZ	common,1 
		GOTO	put_number0
		RETURN


;-----------------------------------------------------------------------------------
;		display 8 big '.'-delimited decimal values
;-----------------------------------------------------------------------------------
put_number_fr0
		MOVLW	'.' 
		MOVWF	data0
		call	puttty
		MOVLW	HIGH (put_number_fr0)
		MOVWF	PCLATH
put_number_fr
		MOVF	INDF,0
		INCF	FSR,1
		call	put_decimal
		DECFSZ	common,1 
		GOTO	put_number_fr0
		RETURN


;-----------------------------------------------------------------------------------
;		get hexadecimal value from EEPROM and display in decimal
;-----------------------------------------------------------------------------------
put_number16
		bsf	STATUS,RP1
		bsf	STATUS,RP0
		bcf	EECON1,7	;eepgd
		BSF	EECON1,0 
		bcf	STATUS,RP0
		MOVF	EEDATA,0 
		INCF	EEADR,1	 
		bcf	STATUS,RP1
		MOVWF	val1	 
		
		bsf	STATUS,RP1
		bsf	STATUS,RP0
		bcf	EECON1,7	;eepgd
		BSF	EECON1,0 
		bcf	STATUS,RP0
		MOVF	EEDATA,0		;mov	w,eedata
		INCF	EEADR,1	 
		bcf	STATUS,RP1
		MOVWF	val 
		
		call	put_decimal16
		RETURN





;-----------------------------------------------------------------------------------
;		hexadecimal output routine
;-----------------------------------------------------------------------------------
put_hexadecimal
		CLRF	PCLATH
		swapf	cd,0
		call	getascii
		MOVWF	data0	 
		MOVLW	HIGH (puttty)
		MOVWF	PCLATH

		call	puttty
	;	mov	pclath,#$>>8
	;
		CLRF	PCLATH
		MOVF	cd,0
		call	getascii
		MOVWF	data0	 
		MOVLW	HIGH (puttty)
		MOVWF	PCLATH

		call	puttty
		MOVLW	HIGH (put_hexadecimal)
		MOVWF	PCLATH
		RETURN

;-----------------------------------------------------------------------------------
;		output MAC address
;-----------------------------------------------------------------------------------
put_mac_address
		MOVLW	mymac
		MOVWF	FSR
		MOVF	INDF,0	 
		MOVWF	cd
		INCF	FSR,1
		call	put_hexadecimal
		
		MOVLW	'-'	 
		MOVWF	data0
		call	puttty
		MOVLW	HIGH (put_hexadecimal)
		MOVWF	PCLATH
		
		MOVF	INDF,0	 
		MOVWF	cd
		INCF	FSR,1
		call	put_hexadecimal
		
		MOVLW	'-'	 
		MOVWF	data0
		call	puttty
		MOVLW	HIGH (put_hexadecimal)
		MOVWF	PCLATH

		MOVF	INDF,0	 
		MOVWF	cd
		INCF	FSR,1
		call	put_hexadecimal
		
		MOVLW	'-'	 
		MOVWF	data0
		call	puttty
		MOVLW	HIGH (put_hexadecimal)
		MOVWF	PCLATH 
		MOVF	INDF,0	 
		MOVWF	cd
		INCF	FSR,1
		call	put_hexadecimal
		
		MOVLW	'-' 
		MOVWF	data0
		call	puttty
		MOVLW	HIGH (put_hexadecimal)
		MOVWF	PCLATH

		MOVF	INDF,0 
		MOVWF	cd
		INCF	FSR,1
		call	put_hexadecimal
		
		MOVLW	'-' 
		MOVWF	data0
		call	puttty
		MOVLW	HIGH (put_hexadecimal)
		MOVWF	PCLATH

		MOVF	INDF,0	 
		MOVWF	cd
		INCF	FSR,1
		call	put_hexadecimal
		RETURN


;-----------------------------------------------------------------------------------
;		output IP address to LCD
;-----------------------------------------------------------------------------------
print_ip
		MOVLW	HIGH (print_dec)
		MOVWF	PCLATH

		MOVLW	this_ip	 
		MOVWF	FSR
		
		MOVF	INDF,0
		INCF	FSR,1
		call	print_dec
		
		MOVLW	'.'
		MOVWF	d4
		call	write_lcd4
		
		MOVF	INDF,0
		INCF	FSR,1
		call	print_dec
		
		MOVLW	'.'
		MOVWF	d4
		call	write_lcd4
		
		MOVF	INDF,0
		INCF	FSR,1
		call	print_dec
		
		MOVLW	'.'
		MOVWF	d4
		call	write_lcd4
		
		MOVF	INDF,0
		INCF	FSR,1
		call	print_dec
		RETURN



;-----------------------------------------------------------------------------------
;		Register serial Rx data destination
;-----------------------------------------------------------------------------------
		org	1000h

ser_register
		;mov	wk,#SERIAL_PACKET_SIZE-2
		MOVLW	SERIAL_PACKET_SIZE - 2
		MOVWF	wk
		CLRF	wk1	 
		bsf	STATUS,IRP
		MOVLW	on_ether & 0ffh
		MOVWF	FSR
ser_register0
		MOVF	INDF,0	 
		IORWF	wk1,1
		INCF	FSR,1
		DECFSZ	wk,1	 
		GOTO	ser_register0
		bcf	STATUS,IRP

		MOVLW	0 
		SUBWF	wk1,0		; if already registered, do nothing but 
		BTFSS	3,2		; send status only.
		GOTO	ser_register9
;	register destination
		bsf	STATUS,IRP
		MOVLW	on_ip & 0ffh
		MOVWF	FSR
 		
		MOVF	udp_data1,0 
		MOVWF	INDF
		INCF	FSR,1
		MOVF	udp_data2,0 
		MOVWF	INDF
		INCF	FSR,1
		MOVF	udp_data3,0 
		MOVWF	INDF
		INCF	FSR,1
		MOVF	udp_data4,0 
		MOVWF	INDF
		INCF	FSR,1
		
		MOVF	udp_src_port,0 
		MOVWF	INDF
		INCF	FSR,1
		MOVF	udp_src_port1,0 
		MOVWF	INDF
		INCF	FSR,1

		MOVF	udp_data5,0 
		MOVWF	INDF
		bsf	STATUS,RP0
		MOVF	INDF,0 ; set baud rate
		MOVWF	SPBRG
		bcf	STATUS,RP0
		
		INCF	FSR,1
		MOVF	udp_data6,0 
		MOVWF	INDF
		MOVLW	0
		SUBWF	INDF,0
		BTFSS	3,2
		BSF	INTCON,INTE
		bcf	STATUS,IRP
;
;		send ARP request
;
		CLRF	PCLATH				; Important!
		
 		CLRF	remote_adr
		MOVLW	PAGE_BEGIN
		MOVWF	remote_adr1

		MOVLW	PACKET_SIZE + ARP_SIZE
		MOVWF	remote_len
		CLRF	remote_len1

 		call	remote_write
		
		MOVLW	10h		; send to destination:"ff-ff-ff-ff-ff-ff"
		MOVWF	PORTC
		movlw	0ffh
		call	assert_wr
		movlw	0ffh
		call	assert_wr
		movlw	0ffh
		call	assert_wr
		movlw	0ffh
		call	assert_wr
		movlw	0ffh
		call	assert_wr
		movlw	0ffh
		call	assert_wr
		
		MOVLW	mymac		; source : set own MAC address
		MOVWF	FSR
		movlw	6
		call	transmit_nbytes
		
		movlw	COM_PROTO			; 08 Etherframe type
		call	assert_wr
		movlw	ARP_PROTO			; ARP
		call	assert_wr
		
		MOVLW	$ >> 8	
		MOVWF	PCLATH
		call	arp2				; ARP header write
		CLRF	PCLATH				; Important!
		
		clrF	PORTC
		movlw	B'00100010'
		call	assert_wr0
		
		MOVLW	4h
		MOVWF	PORTC
		movlw	PAGE_BEGIN		; transmit page is start page 
		call	assert_wr0
		
		MOVLW	.5
		MOVWF	PORTC
		movlw	.60				; minimum packet = 60
		call	assert_wr0
		
		MOVLW	6
		MOVWF	PORTC
		DB	01,00		;clrw					; adr high
		call	assert_wr0
		call	transmit			; send ARP response
ser_register9
		MOVLW	HIGH (ser_get_status)
		MOVWF	PCLATH
		goto	ser_get_status

;-----------------------------------------------------------------------------------
;		delete registration of serial Rx data destination
;-----------------------------------------------------------------------------------
ser_unregister
		bcf	RCSTA,4		;cren
		bcf	INTCON,6	;peie				; not to be used
		
 		MOVLW	SERIAL_PACKET_SIZE - 2
		MOVWF	wk
		CLRF	wk1		;clr	wk[1]
		bsf	STATUS,IRP
		MOVLW	on_ether & 0ffh
		MOVWF	FSR
ser_unregister0
		clrF	INDF
		INCF	FSR,1
		DECFSZ	wk,1	 
		GOTO	ser_unregister0
		bcf	STATUS,IRP
		
		goto	ser_register9





;
;	DHCP protocol processing
;
dhcp
		BSF	STATUS,RP0
		MOVLW	0FFH
		MOVWF	dhcp_done
		BCF	STATUS,RP0

		MOVLW	HIGH (bootp)
		MOVWF	PCLATH

		call	bootp			; get address by DHCP
		CLRF	PCLATH

		movlw	35h	; 
		call	assert_wr
		movlw	01h
		call	assert_wr
		movlw	1
		call	assert_wr
		
		movlw	3dh	; 
		call	assert_wr
		movlw	07h
		call	assert_wr
		movlw	01h
		call	assert_wr
		MOVLW	mymac
		MOVWF	FSR
		movlw	6
		call	transmit_nbytes			; own MAC
		
		movlw	0ffh
		call	assert_wr
		
		MOVLW	.64 - .7 - .9 - .1
		MOVWF	gcn1
bootp_30
		CLRF	PCLATH
		DB	01,00		;clrw
		call	assert_wr
		
		MOVLW	HIGH (bootp_30)
		MOVWF	PCLATH
		DECFSZ	gcn1,1		;djnz	gcn1,bootp_30
		GOTO	bootp_30
		MOVLW	HIGH (bootp_tx)
		MOVWF	PCLATH

		call	bootp_tx
		RETURN



;-----------------------------------------------------------------------------------
;	construct ARP header
arp1
		CLRF	PCLATH
		
		DB	01,00		;clrw
		call	assert_wr
		movlw	01h			; Ethernet fixed at 1
		call	assert_wr

		movlw	COM_PROTO
		call	assert_wr
		movlw	IP_PROTO		; IP OK
		call	assert_wr
		movlw	06h
		call	assert_wr
		movlw	04h
		call	assert_wr
		movlw	00h
		call	assert_wr
		movlw	02h
		call	assert_wr
		movlw	mymac
		movwf	FSR
		movlw	6
		call	transmit_nbytes
		call	transmit_this_ip
		movlw	arp_src_mac
		movwf	FSR
		movlw	.10
		call	transmit_nbytes
		return
arp2	
		clrf	PCLATH
		db	01,00
		call	assert_wr
		movlw	01h
		call	assert_wr
		movlw	COM_PROTO
		call	assert_wr
		movlw	IP_PROTO
		call	assert_wr
		
		movlw	06h			; number of Ethernet address bytes = 6
		call	assert_wr
		movlw	04h			; number of IP address bytes = 4
		call	assert_wr

		movlw	00h
		call	assert_wr
		movlw	01h			; ARP request (=1)
		call	assert_wr
		
		MOVLW	mymac
		MOVWF	FSR
		movlw	6
		call	transmit_nbytes		; send own MAC
		call	transmit_this_ip	; send own IP
		
		movlw	00h
		call	assert_wr
		movlw	00h
		call	assert_wr
		movlw	00h
		call	assert_wr
		movlw	00h
		call	assert_wr
		movlw	00h
		call	assert_wr
		movlw	00h
		call	assert_wr
		
		bsf	STATUS,IRP
		MOVLW	on_ip & 0ffh
		MOVWF	FSR
check_netid
		MOVLW	HIGH (check_netid)
		MOVWF	PCLATH
		bsf	STATUS,RP1
		bcf	STATUS,RP0
		MOVLW	.4		; address=16
		MOVWF	EEADR
		bcf	STATUS,RP1
		
		call	getnetmask
		bsf	STATUS,RP0
		MOVF	this_ip,0 
		MOVWF	wk1
		MOVF	wk,0	 	; [1] = this
		ANDWF	wk1,1
		MOVF	INDF,0	 	;on_ip[0]
		ANDWF	wk,1
	; [0] = host
		INCF	FSR,1
		MOVF	wk1,0
		SUBWF	wk,0 
		BTFSS	3,2
		GOTO	gateway

		call	getnetmask
		bsf	STATUS,RP0
		MOVF	this_ip1,0
		MOVWF	wk1
		MOVF	wk,0
		ANDWF	wk1,1
		MOVF	INDF,0	 	;on_ip[0]	
		ANDWF	wk,1

		INCF	FSR,1
		MOVF	wk1,0	 
		SUBWF	wk,0
		BTFSS	3,2
		GOTO	gateway
		call	getnetmask
		bsf	STATUS,RP0
		;mov	wk[1],this_ip[2]
		;and	wk[1],wk[0]		; [1] = this
		;and	wk[0],INDF		;on_ip[0]	; [0] = host
		MOVF	this_ip2,0
		MOVWF	wk1
		MOVF	wk,0
		ANDWF	wk1,1
		MOVF	INDF,0
		ANDWF	wk,1
		INCF	FSR,1
		MOVF	wk1,0	 
		SUBWF	wk,0
		BTFSS	3,2
		GOTO	gateway

		call	getnetmask
		bsf	STATUS,RP0
		;mov	wk[1],this_ip[3]
		;and	wk[1],wk[0]		; [1] = this
		;and	wk[0],INDF		;on_ip[0]	; [0] = host
		MOVF	this_ip3,0
		MOVWF	wk1
		MOVF	wk,0
		ANDWF	wk1,1
		MOVF	INDF,0
		ANDWF	wk,1

		MOVF	wk1,0	 
		SUBWF	wk,0
		BTFSS	3,2
		GOTO	gateway

direct
		bcf	STATUS,RP0
		bcf	STATUS,RP1
		CLRF	PCLATH
		MOVLW	on_ip & 0ffh
		MOVWF	FSR
		movlw	4			; send destination IP
		call	transmit_nbytes
		
		bcf	STATUS,IRP
		MOVLW	$ >> 8
		MOVWF	PCLATH
		RETURN

gateway
		bsf	STATUS,RP1
		bcf	STATUS,RP0
		MOVLW	.8		; address=16
		MOVWF	EEADR
		bsf	STATUS,RP0
		bcf	STATUS,RP1

		MOVLW	$ >> 8
		MOVWF	PCLATH
		call	getnetmask
		CLRF	PCLATH
		MOVF	wk,0
		call	assert_wr

		MOVLW	$ >> 8
		MOVWF	PCLATH
		call	getnetmask
		CLRF	PCLATH
		MOVF	wk,0
		call	assert_wr

		MOVLW	$ >> 8
		MOVWF	PCLATH
		call	getnetmask
		CLRF	PCLATH
		MOVF	wk,0
		call	assert_wr

		MOVLW	$ >> 8
		MOVWF	PCLATH
		call	getnetmask
		CLRF	PCLATH
		MOVF	wk,0
		call	assert_wr
		
		bcf	STATUS,IRP
		MOVLW	$ >> 8
		MOVWF	PCLATH
		RETURN

getnetmask
		bsf	STATUS,RP1
		bsf	STATUS,RP0
		bcf	EECON1,7	;eepgd
		BSF	EECON1,0		;bsf	eecon1,0
		bcf	STATUS,RP0
		MOVF	EEDATA,0		;mov	wk[0],eedata
		MOVWF	wk
		INCF	EEADR,1		;inc	eeadr
		bcf	STATUS,RP1
		RETURN


;-----------------------------------------------------------------------------------
;		send 232C data to host
;-----------------------------------------------------------------------------------
serial_tx
		bsf	STATUS,IRP		;irp
		MOVLW	on_ether & 0ffh	 
		MOVWF	FSR
		bsf	STATUS,RP0		;rp0
		MOVF	INDF,0	 
		MOVWF	eth_src
		INCF	FSR,1	 
		MOVF	INDF,0
		MOVWF	eth_src1
		INCF	FSR,1	 
		MOVF	INDF,0
		MOVWF	eth_src2
		;mov	eth_src[2],INDF
		INCF	FSR,1	 
		MOVF	INDF,0
		MOVWF	eth_src3
		INCF	FSR,1		 
		;mov	eth_src[4],INDF
		MOVF	INDF,0
		MOVWF	eth_src4

		INCF	FSR,1	 
	 
		MOVF	INDF,0
		MOVWF	eth_src5

		INCF	FSR,1	 
		bcf	STATUS,RP0		;rp0
		
		;mov	ip_src[0],INDF
		MOVF	INDF,0
		MOVWF	ip_src
		INCF	FSR,1	 
		;mov	ip_src[1],INDF
		MOVF	INDF,0
		MOVWF	ip_src1

		INCF	FSR,1 
		;mov	ip_src[2],INDF
		MOVF	INDF,0
		MOVWF	ip_src2

		INCF	FSR,1 
		MOVF	INDF,0
		MOVWF	ip_src3

		INCF	FSR,1	 
		bcf	STATUS,IRP		;irp
;
;	preparation
;
		bsf	STATUS,RP0		;rp0
		MOVF	fifo_cn,0 
		movwf	wk
;skip1
		bcf	STATUS,RP0		;rp0
		
		MOVLW	0	 
		MOVWF	ip_length
		MOVLW	IP_SIZE + UDP_SIZE 
		MOVWF	ip_length1
		MOVF	wk,0	 
		ADDWF	ip_length1,1		; Tx byte size
		MOVLW	SERIAL_PACKET_SIZE    ; common header size
		ADDWF	ip_length1,1
		CLRF	PCLATH	 
		
		MOVLW	UDP_PROTO	 
		MOVWF	proto			; UDP packet
		call	prepare_ip			; construct IP packet
		
		call	clear_sum			; clear checksum value
		
 		MOVLW	PACKET_SIZE+IP_SIZE
		MOVWF	remote_adr
		MOVLW	PAGE_BEGIN
		MOVWF	remote_adr1
		
		;mov	remote_len[0],#UDP_SIZE
		MOVLW	UDP_SIZE
		MOVWF	remote_len

 		MOVLW	SERIAL_PACKET_SIZE
		ADDWF	remote_len,1
		MOVF	wk,0
		ADDWF	remote_len,1
		MOVLW	0	 
		MOVWF	remote_len1
		call	remote_write
		
		
		MOVLW	10H	 
		MOVWF	PORTC
	
		MOVLW	serial_port	 
		MOVWF	FSR
		MOVF	INDF,0	 		; From PORT #(HIGH)
		call	assert_wr
		INCF	FSR,1	 
		MOVF	INDF,0	 			; From PORT #(LOW)
		call	assert_wr
		
		bsf	STATUS,IRP	;irp
		MOVLW	on_port & 0ffh 
		MOVWF	FSR			; To Port#
		MOVF	INDF,0	 
		call	assert_wr
		INCF	FSR,1	 
		MOVF	INDF,0	 
		call	assert_wr
		bcf	STATUS,IRP	;irp
		
		movlw	0
		call	assert_wr
		movlw	UDP_SIZE+SERIAL_PACKET_SIZE
		ADDWF	wk,0 
		call	assert_wr
		
		call	assert_wr2times

		movlw	4
		call	assert_wr
		MOVF	wk,0 
		addlw	SERIAL_PACKET_SIZE
		call	assert_wr			; sum(not fixed)
;
;		status part
		bsf	STATUS,IRP	;irp
		MOVLW	on_ether & 0ffh	 
		MOVWF	FSR
		movlw	SERIAL_PACKET_SIZE - 2
		call	transmit_nbytes
		bcf	STATUS,IRP	;irp
;
;		send
serial_tx0
		MOVLW	$ >> 8	 
		MOVWF	PCLATH
		bsf	STATUS,RP0		;rp0
		MOVF	fifo_poi,0 
		MOVWF	FSR		;; Rx pointer (GET)
		MOVF	INDF,0	 
		MOVWF	data0		; get received character
		
		incF	fifo_poi,1			; increment Rx buffer
 		MOVLW	fifo_bottom
		SUBWF	fifo_poi,0
		BTFSS	3,0
		GOTO	tx100
		MOVLW	fifo_top 
		MOVWF	fifo_poi
tx100		decF	fifo_cn,1				; decrement number of Rx bytes
		bcf	STATUS,RP0		;rp0
		
		clrF	PCLATH
		MOVF	data0,0	 
		call	assert_wr
		
		MOVLW	$ >> 8	 
		MOVWF	PCLATH
 		DECFSZ	wk,1
		GOTO	serial_tx0
		bcf	PORTB,1

;
;	UDP sum calculation and send
		MOVLW	calc_udp_sum >> 8 
		MOVWF	PCLATH
		call	calc_udp_sum
		
		clrF	PCLATH		;pclc,#4hath
		MOVLW	4		 
		MOVWF	PORTC
		movlw	PAGE_BEGIN 
		call	assert_wr0

		MOVLW	PACKET_SIZE 
		ADDWF	ip_length1,1	; add packet size 6+6+2 to number of Tx bytes plus 1
		movlw	1
		btfsc	STATUS,C 
		ADDWF	ip_length,1 
		
		MOVLW	6	 
		MOVWF	PORTC
		MOVF	ip_length,0 	; HIGH
		call	assert_wr0
		
		MOVLW	$ >> 8	 
		MOVWF	PCLATH
		MOVF	ip_length,1 
		btfsc	STATUS,Z 
		goto	serial_tx1
serial_tx2
		clrF	PCLATH	 
		MOVLW	5	 
		MOVWF	PORTC
		MOVF	ip_length1,0 
		call	assert_wr0
		call	transmit			; Send!!
		
		clrF	PCLATH		;pclath
		goto	main0
serial_tx1
 		MOVLW	.60	
		SUBWF	ip_length1,0
		BTFSC	3,0
		GOTO	serial_tx2

		CLRF	PCLATH	 
		MOVLW	5	 
		MOVWF	PORTC
		movlw	.60				; MINIMUM 60bytes
		call	assert_wr0
		call	transmit
		
		CLRF	PCLATH	 
		goto	main0
udp_lcd9
		clrf	PCLATH
		GOTO	main9
;-------------------------------------------------------------------------------
;  output of characters to LCD
;-------------------------------------------------------------------------------
udp_lcd
		MOVF	udp_length,0
		movwf	remote_len1
		movf	udp_length1,0
		movwf	remote_len
		movlw	8
		subwf	remote_len,1
		btfss	STATUS,C
		
		decF	remote_len1,1
		MOVLW	get_dgram >> 8
		movwf	PCLATH
		CALL	get_dgram
		MOVLW	$ >> 8
		MOVWF	PCLATH
		BTFSC	STATUS,C
		GOTO	udp_lcd9
		
		MOVLW	1
		SUBWF	data0,0
		BTFSS	3,2
		GOTO	udp_lcd_0
		MOVLW	get_dgram >>8
		MOVWF	PCLATH
		CALL	get_dgram
		MOVLW	$ >> 8
		MOVWF	PCLATH
		BTFSC	STATUS,C
		GOTO	udp_lcd9

		MOVF	PORTB,0
		MOVWF	wk
		BCF	PORTB,2
		MOVF	data0,0
		MOVWF	d4
		
		MOVLW	write_lcd4 >> 8
		MOVWF	PCLATH
		CALL	write_lcd4
		MOVLW	$ >> 8
		MOVWF	PCLATH
		
		MOVF	wk,0
		MOVWF	PORTB
		MOVLW	B'11111100'
		ANDWF	d4,1
		BTFSS	STATUS,Z
		GOTO	udp_lcd_0
		
		MOVLW	2
		MOVWF	wait_cn
		MOVLW	wait_ms >> 8
		MOVWF	PCLATH
		CALL	wait_ms
		MOVLW	$ >> 8
		MOVWF	PCLATH
udp_lcd_0
		MOVLW	get_dgram >> 8
		MOVWF	PCLATH
		CALL	get_dgram
		MOVLW	$ >> 8
		MOVWF	PCLATH
		BTFSC	STATUS,C
		GOTO	udp_lcd91
		MOVF	PORTB,0
		MOVWF	wk
		BSF	PORTB,2
		MOVF	data0,0
		MOVWF	d4
		MOVLW	write_lcd4 >> 8
		MOVWF	PCLATH
		CALL	write_lcd4
		MOVLW	$ >> 8
		MOVWF	PCLATH
		MOVF	wk,0
		MOVWF	PORTB

		GOTO	udp_lcd_0
udp_lcd91
		MOVLW	lcd_port
		MOVWF	wk2
		MOVLW	para_get_status >> 8
		MOVWF	PCLATH
		GOTO	common_get_status


;-----------------------------------------------------------------------------------
;		bootstrap mode message
;-----------------------------------------------------------------------------------
		org	1300h
lcd_mes		DT	"Bootstrap Mode  "
bs_1		DB	06,8A,06,8A		;.13,.10,.13,.10,
		DA	"PIC Network Interface Card - Bootstrap Mode Version $8"
		DB	06,8A		;,.13,.10
		DB	0,0
bs_prompt	DA	"PICNIC>"
bs_config	DA	"***** Configuration ***** "
		DB	06,8A		;,.13,.10
		DA	"MAC Addr.  :$0"
		DB	06,8A		;,.13,.10
		DA	"[I]P Addr. :$1"
		DB	06,8A		;,.13,.10
		DA	"[N]etMask  :$2"
		DB	06,8A		;.13,.10
		DA	"[G]ateWay  :$3"
		DB	06,8A		;,.13,.10
		DA	"[H]ttpPort     #$4"
		DB	06,8A		;,.13,.10
		DA	"[L]CD Port     #$5"
		DB	06,8A		;,.13,.10
		DA	"[P]arallelPort #$6"
		DB	06,8A		;,.13,.10
		DA	"[S]erialPort   #$7"
		DB	06,8A		;,.13,.10
		DB	0,0
bs_err		DA	"Syntax Error"
		DB	17,0D,05,00		;(,and 13),(10,0)
bs_invalid	DA	"Invalid Command."
		DB	06,8A,00,00		;,.13,.10,0,0
bs_help
		DA	"***** Bootstrap Mode Help ***** "
		DB	06,8A		;,.13,.10
		DA	"config         - Print Board Configuration and Status."
		DB	06,8A		;,.13,.10
		DA	"{str}={value}  - Update System Configuration. "
		DB	06,8A		;,.13,.10
		DA	"initialize     - All registers set Initial Values."
		DB	06,8A		;,.13,.10
		DB	0,0


;-----------------------------------------------------------------------------------
;		message for web browser
;-----------------------------------------------------------------------------------

		org	1400h
		DA	"HTTP/1.0 200 O"
		DB	25,8D		;'K',13
		DB	05,43		;10,C 
		DA	"onnection: close"
		DB	06,8A		;, .13, .10, 
		DA	"Content-type: text/htm"
		DB	36,0D,05,0D,05,3C		;'l', .13, .10, .13, .10, '<'
		DA	"HTML><HEAD><TITLE>PIC Network Interface Card</TITLE></HEAD><BODY"
		DB	1F,0A			;'>',.10
		DA	"<FONT SIZE=+2>PIC Network Interface Card Version  $8 </FONT>"
		DA	"<HR>"

		DA	"<h3>I/O Ports</h3>"
		DA	"<DL><DD><FORM ACTION=\"modify.cgi\" METHOD=\"GET\""
		DB	1F,0A		;'>',10
		DA	"<TABLE BORDER>"
		DA	"<TR><TD>Port</TD><TD>Value</TD></TR>"
		
		DA	"<TR><TD>RA0 "
		DB	12,80		;"%",0000_0000b,
		DA	" </TD>"
		DA	"<TD ALIGN=\"right\">"
		DB	20,00		;'@",00000000b,
		DA	"</TD></TR>"
		
		DA	"<TR><TD>RA1 "
		DB	12,81		;"%",0000_0001b,
		DA	" </TD>"
		DA	"<TD ALIGN=\"right\">"
		DB	20,01		;@",00000001b,
		DA	"</TD></TR>"
		
		DA	"<TR><TD>RA2 "
		DB	12,82		;%",0000_0010b,
		DA	" </TD>"
		DA	"<TD ALIGN=\"right\">"
		DB	20,02		;@",00000010b,
		DA	"</TD></TR>"
		
		DA	"<TR><TD>RA3 "
		DB	12,83		;%",0000_0011b,
		DA	" </TD>"
		DA	"<TD ALIGN=\"right\">"
		DB	20,03		;"@",00000011b,
		DA	"</TD></TR>"
		
		DA	"<TR><TD>RA5 "
		DB	12,84		;%",0000_0100b,
		DA	" </TD>"
		DA	"<TD ALIGN=\"right\">"
		DB	20,04		;@",00000100b,
		DA	" Celsius</TD></TR>"
		DB	0,0


		org	01700h
		DA	"<TR><TD>RB0 "
		DB	12,90		;%",0001_0000b,
		DA	" </TD>"
		DA	"<TD><INPUT TYPE=\"submit\" NAME=\"RB0\" VALUE=\"H\">"
		DB	20,10		;'@',0001_0000b,
		DA	"<INPUT TYPE=\"submit\" NAME=\"RB0\" VALUE=\"L\"></TD></TR>"
		DA	"<TR><TD>RB1 "
		DB	12,91		;%",0001_0001b,
		DA	" </TD>"
		DA	"<TD><INPUT TYPE=\"submit\" NAME=\"RB1\" VALUE=\"H\">"
		DB	20,11		;'@',0001_0001b,
		DA	"<INPUT TYPE=\"submit\" NAME=\"RB1\" VALUE=\"L\"></TD></TR>"
		DA	"<TR><TD>RB2 "
		DB	12,92		;%",0001_0010b,
		DA	" </TD>"
		DA	"<TD><INPUT TYPE=\"submit\" NAME=\"RB2\" VALUE=\"H\">"
		DB	20,12		;'@',0001_0010b,
		DA	"<INPUT TYPE=\"submit\" NAME=\"RB2\" VALUE=\"L\"></TD></TR>"
		DA	"<TR><TD>RB3 "
		DB	12,93		;%",0001_0011b,
		DA	" </TD>"
		DA	"<TD><INPUT TYPE=\"submit\" NAME=\"RB3\" VALUE=\"H\">"
		DB	20,13		;'@',0001_0011b,
		DA	"<INPUT TYPE=\"submit\" NAME=\"RB3\" VALUE=\"L\"></TD></TR>"
		
		
		DA	"<TR><TD>RB4 "
		DB	12,94		;%",0001_0100b,
		DA	" </TD>"
		DA	"<TD><INPUT TYPE=\"submit\" NAME=\"RB4\" VALUE=\"H\">"
		DB	20,14		;'@',0001_0100b,
		DA	"<INPUT TYPE=\"submit\" NAME=\"RB4\" VALUE=\"L\"></TD></TR>"
		DA	"<TR><TD>RB5 "
		DB	12,95		;%",0001_0101b,
		DA	" </TD>"
		DA	"<TD><INPUT TYPE=\"submit\" NAME=\"RB5\" VALUE=\"H\">"
		DB	20,15		;'@',0001_0101b,
		DA	"<INPUT TYPE=\"submit\" NAME=\"RB5\" VALUE=\"L\"></TD></TR>"
		DA	"<TR><TD>RB6 "
		DB	12,96		;%",0001_0110b,
		DA	" </TD>"
		DA	"<TD><INPUT TYPE=\"submit\" NAME=\"RB6\" VALUE=\"H\">"
		DB	20,16		;'@',0001_0110b,
		DA	"<INPUT TYPE=\"submit\" NAME=\"RB6\" VALUE=\"L\"></TD></TR>"
		DA	"<TR><TD>RB7 "
		DB	12,97		;%",0001_0111b,
		DA	" </TD>"
		DA	"<TD><INPUT TYPE=\"submit\" NAME=\"RB7\" VALUE=\"H\">"
		DB	20,17		;'@',0001_0111b,
		DA	"<INPUT TYPE=\"submit\" NAME=\"RB7\" VALUE=\"L\"></TD></TR>"
		DA	"<TR><TD> </TD>"
		DA	"<TD><INPUT TYPE=\"submit\" VALUE=\"Reload\"></TD></TR>"
		DA	"</TABLE>"
		DA	"</FORM></DL>"
		db	0,0
		
		org	1A00h
		DA	"<FORM METHOD=\"GET\" ACTION=\"submit.cgi\""
		DB	1F,0A	;>",10
		DA	"<h3>Configuration</h3>"

		DA	"<DL><DD><TABLE BORDER>"
		
		DA	"<TR><TD>MAC Address</TD>"
		DA	"<TD>$0</TD></TR>"
		
		DA	"<TR><TD>IP Addr</TD>"
		DA	"<TD><INPUT TYPE=\"text\" NAME=\"00b\"  VALUE=\""
		DA	"$1\"></TD></TR>"
		
		DA	"<TR><TD>NetMask</TD>"
		DA	"<TD><INPUT TYPE=\"text\" NAME=\"04b\"  VALUE=\""
		DA	"$2\"></TD></TR>"
		
		DA	"<TR><TD>GateWay</TD>"
		DA	"<TD><INPUT TYPE=\"text\" NAME=\"08b\"  VALUE=\""
		DA	"$3\"></TD></TR>"
		
;		DA	"<TR><TD>RS232C Conv</TD>"
;		DA	"<TD><INPUT TYPE=\"text\" NAME=\"18b\"  VALUE=\""
;		DA	'$','9'+2,""></TD></TR>"
		
		DA	"<TR><TD>http Port TCP:#</TD>"
		DA	"<TD><INPUT TYPE=\"text\" NAME=\"10w\"  VALUE=\""
		DA	"$4\"></TD></TR>"
		
		DA	"<TR><TD>LCD  Port UDP:#</TD>"
		DA	"<TD><INPUT TYPE=\"text\" NAME=\"12w\"  VALUE=\""
		DA	"$5\"></TD></TR>"
		
		DA	"<TR><TD>Parallel Port UDP:#</TD>"
		DA	"<TD><INPUT TYPE=\"text\" NAME=\"14w\"  VALUE=\""
		DA	"$6\"></TD></TR>"
		
		DA	"<TR><TD>Serial Port UDP:#</TD>"
		DA	"<TD><INPUT TYPE=\"text\" NAME=\"16w\"  VALUE=\""
		DA	"$7\"></TD></TR>"
		DA	"<TR><TD> </TD>"
		DA	"<TD><INPUT TYPE=\"submit\" VALUE=\"Save\">"
		DA	"<INPUT TYPE=\"submit\" NAME=\"INIT\" VALUE=\"Default\" ></TD></TR>"
		DA	"</TABLE>"
		DA	"</FORM></DL>"
		db	0,0
		
		
		org	1D00h
		
		DA	"<h3>Status </h3>"
		DA	"<DL><DD><TABLE BORDER>"
		DA	"<TR><TD>Sent Packets </TD>"
		DA	"<TD>$9</TD></TR>"
		DA	"<TR><TD>This IP</TD>"
		DA	"<TD>"
		DB	12,3A		;$",'9'+1, 
		DA	"</TD></TR>"
;		DA	"<TR><TD>Socket #1</TD>"
;		DA	"<TD>"
;		DB	3F,0A		;~",0ah,
;		DA	"</TD></TR>"
;		DA	"<TR><TD>Socket #2</TD>"
;		DA	"<TD>"
;		DB	3F,0B		;~",0bh,
;		DA	"</TD></TR>"
;		DA	"<TR><TD>Socket #3</TD>"
;		DA	"<TD>"
;		DB	3F,0C	;~",0ch,
;		DA	"</TD></TR>"
;		DA	"<TR><TD>Socket #4</TD>"
;		DA	"<TD>"
;		DB	3F,0D		;~",0dh,
;		DA	"</TD></TR>"
;		DA	"<TR><TD>Socket #5</TD>"
;		DA	"<TD>"
;		DB	3F,0E		;~",0eh,
;		DA	"</TD></TR>"
		DA	"</TABLE></DL> "
		
		DA	"<P><HR>Copyright (c) 2000-2001 by <A HREF=\"http://www.tristate.ne.jp\">TriState Co.,Ltd.</A> "
		DB	06,8A		;,13,10
		DA	"</BODY></HTML>"
		db	0,0




;-----------------------------------------------------------------------------------
;		EEPROM data initialization
;-----------------------------------------------------------------------------------
		org	1F00h
default_values_begin
		DT	.192,.168,0,.200
		DT	.255,.255,.255,0
		DT	0,0,0,0
		DT	1,2,0,0		; Firmware Version x,x,x,x
		
		DT	HTTP_PORT / .256,HTTP_PORT & .255				; HTTP port number
		DT	LCD_PORT / .256,LCD_PORT & .255				; LCD port number
		DT	PARALLEL_PORT / .256,PARALLEL_PORT & .255			; PARALLEL port number
		DT	SERIAL_PORT / .256,SERIAL_PORT & .255			; SERIAL port number
default_values_end

getadtable
		bsf	STATUS,RP0		;rp0
		MOVF	ADCON1,0		;adcon1,0
		bcf	STATUS,RP0
		andlw	0fh
		ADDWF	2,1		;jmp	pc+w
		retLw	B'11111111'
		retLw	B'11111111'
		retLw	B'00011111'
		retLw	B'00011111'
		retLw	B'00001011'
		retLw	B'00000011'
		retLw	B'00000000'
		retLw	B'00000000'
		retLw	B'11110011'
		retLw	B'00111111'
		retLw	B'00110111'
		retLw	B'00110011'
		retLw	B'00010011'
		retLw	B'00000011'
		retLw	B'00000001'
		retLw	B'00000001'


mes_low		DT	" Low  ",0
mes_high	DT	" High ",0
mes_in		DT	"In ",0
mes_out		DT	"Out",0

;-----------------------------------------------------------------------------------
;		for bootstrap mode command parsing
;-----------------------------------------------------------------------------------
get_bs_job
		ADDWF	2,1		;jmp	pc+w
		DT	str_init & 0ffh,	bsj_init & 0ffh
		DT	str_init2 & 0ffh,	bsj_init & 0ffh
		
		DT	str_config & 0ffh,	bsj_config & 0ffh
		DT	str_config2 & 0ffh,	bsj_config & 0ffh
		
		DT	str_help & 0ffh,	bsj_help & 0ffh
		DT	str_help2 & 0ffh,	bsj_help & 0ffh
		
		DT	str_ip & 0ffh,		bsj_ip & 0ffh
		DT	str_ip2 & 0ffh,		bsj_ip & 0ffh
		
		DT	str_net & 0ffh,		bsj_net & 0ffh
		DT	str_net2 & 0ffh,	bsj_net & 0ffh
		
		DT	str_gate & 0ffh,	bsj_gate & 0ffh
		DT	str_gate2 & 0ffh,	bsj_gate & 0ffh
		
		DT	str_http & 0ffh,	bsj_http & 0ffh
		DT	str_http2 & 0ffh,	bsj_http & 0ffh

		DT	str_lcd & 0ffh,		bsj_lcd & 0ffh
		DT	str_lcd2 & 0ffh,	bsj_lcd & 0ffh

		DT	str_para & 0ffh,	bsj_para & 0ffh
		DT	str_para2 & 0ffh,	bsj_para & 0ffh

		DT	str_serial & 0ffh,	bsj_serial & 0ffh
		DT	str_serial2 & 0ffh,	bsj_serial & 0ffh

		DT	0,0		; Terminator


str_config	DT	"config",0
str_config2	DT	"ls",0

str_init	DT	"initialize",0
str_init2	DT	"init",0

str_help	DT	"help",0
str_help2	DT	'?',0

str_ip		DT	"ip",0
str_ip2		DT	'i',0

str_net		DT	"net",0
str_net2	DT	"n",0

str_gate	DT	"gate",0
str_gate2	DT	'g',0

str_http	DT	"http",0
str_http2	DT	'h',0

str_lcd		DT	"lcd",0
str_lcd2	DT	'l',0

str_para	DT	"parallel",0
str_para2	DT	'p',0

str_serial	DT	"serial",0
str_serial2	DT	's',0



		end

