;**********************************************************************
;                                                                     *
;    Filename:	  PicTree       xxx.asm                          *
;    Date:        2007,3/16  ～　4/3                                  *
;    File Version:  1.0 2007,4/3                                      *
;                                                                     *
;    Author:      S.Nishioka                                          *
;    Company:     NS KIKAKU                                           *
;                                                                     *
;                                                                     *
;**********************************************************************

	list      p=16f648A		; list directive to define processor
	#include <p16F648A.inc>		; processor specific variable definitions

	#include <pic16macro_1.txt> 	;マクロ定義

	errorlevel  -302		; suppress message 302 from list file

	__CONFIG   _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_OFF & _PWRTE_ON &_WDT_OFF &  _HS_OSC 


	list	mm=on,st=on,n=60	;memory map,symbol table,lines per page
	noexpand
	radix	dec 

;	page

;***** DEFINITIONS

#DEFINE CY	STATUS,C	;Carry
#DEFINE	ds	res

bank0	macro
	bcf	STATUS,RP1
	bcf	STATUS,RP0
	endm

bank1	macro
	bcf	STATUS,RP1
	bsf	STATUS,RP0
	endm

bank2	macro
	bsf	STATUS,RP1
	bcf	STATUS,RP0
	endm

bank3	macro
	bsf	STATUS,RP1
	bsf	STATUS,RP0
	endm


;	page

;***** VARIABLE DEFINITIONS ******************************************

;a common memory 16 bytes (0x70 - 0x7f)
;interupts
w_temp        EQU     0x71        ; variable used for context saving 
status_temp   EQU     0x72        ; variable used for context saving
pclath_temp   EQU     0x73        ; variable used for context saving
		
				
;***** DEFINITIONS ******************************************

;*	version no.
#define		version_no	'1','.','0'	;1.0 ****

;*      terminator
CR		=		0x0d
LF		=		0x0a

;*	header of command
xx_command	=		'#'		;****

;*	terminator of ルートコマンド　＋　データ
terminator_route =		','		;****
	

;*      i/o ports
#define		b_Tx1		PORTB,0		;-1
#define		b_Rx1		PORTB,1

#define		b_Tx2		PORTB,2		;-2
#define		b_Rx2		PORTB,3			

#define		b_Tx3		PORTB,4		;-3
#define		b_Rx3		PORTB,5

#define		b_Tx4		PORTB,6		;-4
#define		b_Rx4		PORTB,7	


#define		b_OUT		PORTA,0		;outputs
#define		b_INP		PORTA,1		;inputs

#define		b_LED		PORTA,2		;outputs　

#define		b_SELECT	PORTA,5		;select inputs 1:PicTree 0:RS232 inputs/outputs


;***** bank0 (0x20 - 0x6f)
		org	0x20	;ファイルアドレス20h番地から変数を割り当てる
mode		ds	1
pcflag		ds	1
pcsw		ds	1

acc		ds	1

pnt         	ds      1               ;pointer for tbuf(rx,tx data buffer)
xbuf_size   	=       16		;受信バッファサイズ、最大受信文字数を決定する****************
xbuf_cnt    	ds      1               ;必ずxbufの前に置く事！
xbuf        	ds      xbuf_size       ;buffer

command_max_length =	xbuf_size	;コマンド最大受信文字数

id_max_length	=	8		;ID 最大文字数*************************************
id_cnt		ds	1		;ID length
id_save		ds	id_max_length	;ID save

from_route	ds	1		;*元ルート番号
from_route_dec	ds	1		;	   -1
to_route	ds	1		;*先ルート番号
to_route_dec	ds	1		;	   -1

crlf_code_save	ds	1		;**** CR LF code save,terminator

wk1_routing	ds	1		;*routing処理

wk1_mrx_command	ds	1		;*コマンドを改行まで受信する

wk1_mex		ds	1		;*コマンドを調べ実行する
wk2_mex		ds	1
wk_mex_route	ds	1
wk_mex_route_time ds	1
wk1_mex_rom	ds	1
wk2_mex_rom	ds	1

wk1_mta		ds	1		;*アンサーを処理する



;
;*	subroutines

wk_tx_xbuf	ds	1		;*所定のルート へ　xbuf　の内容を送信する (binaryでもasciiでも良い)

wk_txstring	ds	1		;txstring_from_route
movstring_length  ds	1		;*move string
from_pnt	ds	1
to_pnt		ds	1

wk_h		ds	1		;hex > ascii
wk_l		ds	1
wk_getdt_hex	ds	1		;ascii > hex




;*	TMR0処理
t_TMR0		=		200	;Rtcc kihon count(10.24ms)          
T10ms		ds		1	;10.24ms UP Count
t_T10ms		=		10	;10.24ms*10=102.4ms
invalid_command_timeout	ds	1	;102.4ms Down Count
command_timeout	ds		1	;102.4ms Down Count
routing_timeout	ds		1	;102.4ms Down Count

t_invalid_command_time	=	8	;0.8s (102.4ms*x);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
t_command_time		=	50	;5s ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

t_routing_time_minus	=	5	;0.5s  - 初期値;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
t_routing_time_plus	=	50	;5s  + 初期値;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


invalid_command_time	ds	1
command_time		ds	1
routing_time		ds	1

;
answer			ds	1
answer_no     		=      	0	;no answer
answer_ok     		=    	1       ;ok answer and jmp to コマンド待ち処理(#受信）
answer_ng      		=   	2	;ng answer and jmp to コマンド待ち処理(#受信）
answer_ng_invalid_timeout  =   	3	;ng answer and jmp to invalid timeout処理へ
answer_ng_id		=	4	;ng answer+ID and jump to コマンド待ち処理(#受信）
answer_ok_id		=	5	;ok answer+ ID and jump to コマンド待ち処理(#受信）
answer_busy_id		=	6	;ok answer+ ID and jump to コマンド待ち処理(#受信）

;*	subroutines
b_96		=       24*5
b_48        	=       50*5
b_dly       	=       b_48            ;4800 bps
hb_dly     	=       b_dly/2
bitcnt		ds      1               ;bit count 
rbyte		ds      1               ;rx,tx buffer
dlycnt      	ds      1               ;tx,rx delay count


rom_pnt		ds	1		;eeprom addr
rom_rbyte	ds	1		;eeprom data

;*		flag
flag		ds	1
#define		f_mcheck_command	flag,7
#define		f_mrx_command		flag,6
#define		f_mexecute_command	flag,5
#define		f_mtx_answer		flag,4
#define		f_minvalid_command	flag,3

;*
flag1		ds	1
#define		f_routing		flag1,7	;0:none  1:routeが確立している

#define		f_routing_1		flag1,6	;-1 0:none  1:routing portである
#define		f_routing_2		flag1,5	;-2
#define		f_routing_3		flag1,4	;-3
#define		f_routing_4		flag1,3	;-4

#define		bit_saver		flag1,2	;bit saver for routing処理

#define		from_bit_save		flag1,1	;from_route bit for routing timeout処理　0:リセット
#define		to_bit_save		flag1,0	;to_route bit for routing timeout処理   0:リセット


;*
flag2		ds	1
#define		f_ok			flag2,7	;0:ng   1:ok
#define		f_hex_ok		flag2,6	;0:ng   1:ok

;*	bank1 (0xa0 - 0xef)
		org	0xa0

;*	bank2 (0x120 - 0x16f)
		org	0x120

;*
		ORG     0x000             ; processor reset vector
		goto    start             ; go to beginning of program

	
;**********************************************************************
;
;	interrupt
;
;**********************************************************************
	
	ORG     0x004             ; interrupt vector location
	movwf   w_temp            ; save off current W register contents
	movf	STATUS,w          ; move status register into W register
	movwf	status_temp       ; save off contents of STATUS register
	movf	PCLATH,w          ; move pclath register into W register
	movwf	pclath_temp       ; save off contents of PCLATH register

; isr code can go here or be located as a call subroutine elsewhere


	movf    pclath_temp,w     ; retrieve copy of PCLATH register
	movwf	PCLATH            ; restore pre-isr PCLATH register contents
	movf    status_temp,w     ; retrieve copy of STATUS register
	movwf	STATUS            ; restore pre-isr STATUS register contents
	swapf   w_temp,f
	swapf   w_temp,w          ; restore pre-isr W register contents
	retfie                    ; return from interrupt


;*	Version
ver_string	jmppcw
		retw	12
		retw	'P','i','c','T','r','e','e',' ','v',version_no

;
;*	routing処理をする
;       entry	f_routing:		0:none  1:routeが確立している
;		from_route_dec:		元ルート番号　0 1 2 3 (from_route-1)
;               to_route_dec:		先ルート番号 0 1 2 3 (to_route-1)
; 
execute_routing
		jb	f_routing,routing_start
		movr#	wk1_routing,13		;調整の必要がある;;;;;;;;;;;;;;;;;;;;;;;;;;;
routing_dly					;ルート処理のある無しにかかわらずほぼ同じ処理時間にする
		djnz	wk1_routing,routing_dly
		nop
		ret

routing_start					;ルート処理をする
		nop
		movwr	w,from_route_dec
		jmppcw
		jmp	a1
		jmp	a2
		jmp	a3
		jmp	a4

a1
		movb_b	bit_saver,b_Rx1
		movb_b	from_bit_save,bit_saver	;from_bit_save は　routing timeout処理用

		movwr	w,to_route_dec
		jmppcw
		jmp	b1
		jmp	b2
		jmp	b3
		jmp	b4
	

a2
		movb_b	bit_saver,b_Rx2
		movb_b	from_bit_save,bit_saver

		movwr	w,to_route_dec
		jmppcw
		jmp	b1
		jmp	b2
		jmp	b3
		jmp	b4

a3
		movb_b	bit_saver,b_Rx3
		movb_b	from_bit_save,bit_saver

		movwr	w,to_route_dec
		jmppcw
		jmp	b1
		jmp	b2
		jmp	b3
		jmp	b4

a4
		movb_b	bit_saver,b_Rx4
		movb_b	from_bit_save,bit_saver
	
		movwr	w,to_route_dec
		jmppcw
		jmp	b1
		jmp	b2
		jmp	b3
		jmp	b4

b1
		movb_b	b_Tx1,bit_saver

		movb_b	bit_saver,b_Rx1
		movb_b	to_bit_save,bit_saver	;to_bit_save は　routing timeout処理用

		movwr	w,from_route_dec
		jmppcw
		jmp	c1
		jmp	c2
		jmp	c3
		jmp	c4



b2
		movb_b	b_Tx2,bit_saver

		movb_b	bit_saver,b_Rx2
		movb_b	to_bit_save,bit_saver

		movwr	w,from_route_dec
		jmppcw
		jmp	c1
		jmp	c2
		jmp	c3
		jmp	c4

b3
		movb_b	b_Tx3,bit_saver

		movb_b	bit_saver,b_Rx3
		movb_b	to_bit_save,bit_saver

		movwr	w,from_route_dec
		jmppcw
		jmp	c1
		jmp	c2
		jmp	c3
		jmp	c4

b4
		movb_b	b_Tx4,bit_saver

		movb_b	bit_saver,b_Rx4
		movb_b	to_bit_save,bit_saver

		movwr	w,from_route_dec
		jmppcw
		jmp	c1
		jmp	c2
		jmp	c3
		jmp	c4

c1
		movb_b	b_Tx1,bit_saver
		ret

c2
		movb_b	b_Tx2,bit_saver
		ret

c3
		movb_b	b_Tx3,bit_saver
		ret

c4
		movb_b	b_Tx4,bit_saver
		ret

;**********************************************************************
;	main
;**********************************************************************
start
;*	ハード関係の初期化
		clr	PORTA
		movr#	CMCON,b'00000111'

		bank1	
		movr#	TRISA,b'11111010'	;0:outputs 1:inputs
		movr#	TRISB,b'10101010'
		movr#	OPTION_REG,b'01010111'	; RBPU=0 PORTB pull up,T0CS=1 TMR source internal clock,1/256 prescaler 		
		bank0

		movr#	PORTB,0xff

		setb	b_OUT			;reset 0;;;;;;;;;;;;;;;;;;;;;;;;;;
		setb	b_LED			;LED OFF when 1

;*	Timer関係の初期化
		clr	TMR0
		clr	T10ms
		movr#	invalid_command_time,t_invalid_command_time
		movr#	command_time,t_command_time

		movr#	rom_pnt,t_routing_time_eeprom_minus ;in the EEPROM data memory
		call	rom_getdt
		movrr	routing_time,rbyte		;routing timeout

		clr	invalid_command_timeout
		clr	command_timeout
		clr	routing_timeout


;*	ID関係の初期化
		movr#	pnt,id_save
		movr#	rom_pnt,id_string_eeprom
		call	rom_getdt
		movrr	id_cnt,rbyte
		movrr	acc,rbyte
id0
		call	rom_getdt
		call	putdt
		djnz	acc,id0

;
		clr	mode
		clr	pcflag
		clr	pcsw

		clr	flag
		clr	flag1
		clr	flag2

		clrb	f_routing
		setb	from_bit_save		;from_route bit for routing timeout処理
		setb	to_bit_save		;to_route bit for routing timeout処理

		setb	f_mcheck_command	;*コマンド待ち処理(#受信）へ


;*	main loop
main
;*
		call	minvalid_command
                call    mtx_answer
                call    mexecute_command
                call    mrx_command
		call    mcheck_command

;
;*	common処理
common
;*	TMR0処理
		csaer#	TMR0,t_TMR0
                jmp	routing
                clr     TMR0
		inc	T10ms		;10.24msごとに T10ms UP count
		csaer#	T10ms,t_T10ms
		jmp	routing
		clr	T10ms

;*	timeout処理  102.4ms ごとに以下を実行する　if t_T10ms = 10
		cser#	invalid_command_timeout,0
                dec     invalid_command_timeout
		cser#	command_timeout,0
		dec	command_timeout
		cser#	routing_timeout,0
		dec	routing_timeout


;*	routing処理
routing
		jnb	f_routing,main
		clrb	b_LED			;LED on

		call	routing_start

;*      routing timeout処理

		cjer#	routing_timeout,0,routing_exit

		jnb	from_bit_save,reset_timeout	;start bit は　0　で、通常は　1　のまま
		jnb	to_bit_save,reset_timeout
                jmp     main
reset_timeout
		movrr	routing_timeout,routing_time
		jmp	main
routing_exit
;		clrb	f_routing
		clr	flag1		;以下をリセットする
;		f_routing		flag1,7	;0:none  1:routeが確立している
;		f_routing_1		flag1,6	;-1 0:none  1:routing portである
;		f_routing_2		flag1,5	;-2
;		f_routing_3		flag1,4	;-3
;		f_routing_4		flag1,3	;-4
;		bit_saver		flag1,2	;bit saver for routing処理
;		from_bit_save		flag1,1	;from_route bit for routing timeout処理　0:リセット
;		to_bit_save		flag1,0	;to_route bit for routing timeout処理   0:リセット

		setb	from_bit_save		;bit をリセットしておく
		setb	to_bit_save

		setb	b_LED			;LED off
		jmp	main


;**********************************************************************
;*	コマンド待ち処理(#受信）
mcheck_command
		jnb	f_routing,mcheck_1
		ret				;ルート確立中は受信処理しないとする

		jb	f_routing_1,mc_r2	;-1 routing? (routing when f_routing_1 is 1)
		jnb	b_Rx1,mc1
mc_r2
		jb	f_routing_2,mc_r3	;-2 routing?
		jnb	b_Rx2,mc2
mc_r3
		jb	f_routing_3,mc_r4	;-3 routing?
		jnb	b_Rx3,mc3
mc_r4
		jb	f_routing_4,mc_exit	;-4 routing?
		jnb	b_Rx4,mc4
mc_exit
		ret

mcheck_1
		sb	f_mcheck_command
		ret
		jnb	b_Rx1,mc1	;コマンド信号？
		jnb	b_Rx2,mc2
		jnb	b_Rx3,mc3
		jnb	b_Rx4,mc4
		ret
mc1
		movr#	from_route,1
		movr#	from_route_dec,0
		call	rxdata_1
		cjer#	rbyte,xx_command,mc11
mc10						;#が無い、不正なコマンドである
		clrb	f_mcheck_command
		setb	f_minvalid_command	;invalid command timeout処理へ（無視する）
		clr	pcflag
		ret
mc11						;#あり
		clrb	f_mcheck_command
		setb	f_mrx_command		;*コマンドを改行まで受信する へ
		clr	pcflag
		ret		
mc2
		movr#	from_route,2
		movr#	from_route_dec,1
		call	rxdata_2
		cjer#	rbyte,xx_command,mc11
		jmp	mc10
mc3
		movr#	from_route,3
		movr#	from_route_dec,2
		call	rxdata_3
		cjer#	rbyte,xx_command,mc11
		jmp	mc10
mc4
		movr#	from_route,4
		movr#	from_route_dec,3
		call	rxdata_4
		cjer#	rbyte,xx_command,mc11
		jmp	mc10

;**********************************************************************
;*	コマンドを　改行　まで受信する 　　xbuf　に保存する
mrx_command
		sb	f_mrx_command
		ret
		test	pcflag
		jnz	mrx1

		clr	xbuf_cnt			;受信文字数
		movr#	pnt,xbuf
		movr#	wk1_mrx_command,command_max_length ;最大受信文字数

		movrr	command_timeout,command_time	;timeout初期化
		inc	pcflag
		ret
mrx1
		call	rxdata_from_route	;１文字受信 exit f_ok 1:ok 0:ng
		jb	f_ok,mrx2
		test	command_timeout		;command_timeout?
		sz
		ret

		clrb	f_mrx_command		;エラー,command timeoutである
		setb	f_mtx_answer		;アンサーを処理する へ
		movr#	answer,answer_ng	;ng
		clr	pcflag
		ret
mrx2
		call	putdt
		inc	xbuf_cnt
		cjer#	rbyte,CR,mrx3		;terminator?改行？
		cjer#	rbyte,LF,mrx3		;terminator?
		movrr	command_timeout,command_time	;timeout初期化
		dec	wk1_mrx_command
		sz
		ret	

		clrb	f_mrx_command		;エラー,最大文字数を超えた
		setb	f_mtx_answer		;アンサーを処理する へ
		movr#	answer,answer_ng_invalid_timeout ;ngアンサ　and 最大文字数を超えた,invalid command timeout処理へ
		clr	pcflag
		ret
mrx3
		movrr	crlf_code_save,rbyte	;CRLF code save
		cjer#	xbuf_cnt,1,mrx4		;#改行のみ？	
		clrb	f_mrx_command		;コマンドを全て受信した
		setb	f_mexecute_command	;コマンドを調べ実行する　へ
		clr	pcflag
		ret
mrx4
		clrb	f_mrx_command		;#改行のみのコマンド,OKアンサ
		setb	f_mtx_answer		;アンサーを処理する へ
		movr#	answer,answer_ok	;ok
		clr	pcflag
		ret

;**********************************************************************
;*	コマンドを調べ実行する
;**********************************************************************
mexecute_command
		sb	f_mexecute_command
		ret
		test	pcflag
		jnz	mex_1	

		inc	pcflag
		clr	pcsw
		ret
mex_1
		movr#	pnt,xbuf
		call	getdt
		cjer#	rbyte,'V',mex_version	;Version command?
		cjer#	rbyte,'I',mex_2		;ID or INP command?
		cjer#	rbyte,'O',mex_out	;OUT command?
		cjer#	rbyte,'T',mex_route_time;route time command?+-
		cjer#	rbyte,'R',mex_rom	;ROM command?

		jb	f_routing,mex_busy	;ルート確立中はルートコマンドを受け付けない
		cjer#	rbyte,'-',mex_route_m	;-route command?
		cjer#	rbyte,'+',mex_route_p	;+route command?

mex_ng						;アンサ　NG
		clrb	f_mexecute_command
		setb	f_mtx_answer		;アンサーを処理する へ
		movr#	answer,answer_ng
		clr	pcflag
		ret
mex_busy					;アンサBUSY +ID 
		clrb	f_mexecute_command
		setb	f_mtx_answer		;アンサーを処理する へ
		movr#	answer,answer_busy_id
		clr	pcflag
		ret
	

mex_2						;*ID or INP command?
		call	getdt
		cjer#	rbyte,'D',mex_id
		cjer#	rbyte,'N',mex_3
		jmp	mex_ng
mex_3
		call	getdt
		cjer#	rbyte,'P',mex_inp
		jmp	mex_ng

;*	route time command
mex_route_time
		call	getdt
		cjer#	rbyte,'-',mex_route_time_m	;-
		cjer#	rbyte,'+',mex_route_time_p	;+
		jmp	mex_ng
;	RT-
mex_route_time_m
		call	getdt
		cjerr	rbyte,crlf_code_save,mex_route_time_m1	;IDの確認へ
		cjner#	rbyte,'=',mex_ng

		call	getdt_hex
		jnb	f_hex_ok,mex_ng
		movrr	wk_mex_route_time,rbyte
		call	getdt
		cjnerr	rbyte,crlf_code_save,mex_ng		;改行？

		movrr	rbyte,wk_mex_route_time
		movr#	rom_pnt,t_routing_time_eeprom_minus	;EEPROMへ書き込む
		call	rom_putdt
		jmp	mex_out_ok		;アンサOK and jmp to アンサーを処理する へ	
;
mex_route_time_m1				;IDの確認へ
		movr#	rom_pnt,t_routing_time_eeprom_minus ;in the EEPROM data memory
mex_route_time_com
		call	rom_getdt
		movrr	acc,rbyte
		call	hex_to_ascii

		movrr	rbyte,wk_h
		call	txdata_from_route	;*元ルート from_route へ１文字送信する
		movrr	rbyte,wk_l
		call	txdata_from_route	;*元ルート from_route へ１文字送信する

		movrr	rbyte,crlf_code_save	;CR　LF codeを取り出す
		call	txdata_from_route
		jmp	mex_exit
		

;	RT+
mex_route_time_p
		call	getdt
		cjerr	rbyte,crlf_code_save,mex_route_time_p1	;IDの確認へ
		cjner#	rbyte,'=',mex_ng

		call	getdt_hex
		jnb	f_hex_ok,mex_ng
		movrr	wk_mex_route_time,rbyte
		call	getdt
		cjnerr	rbyte,crlf_code_save,mex_ng		;改行？

		movrr	rbyte,wk_mex_route_time
		movr#	rom_pnt,t_routing_time_eeprom_plus	;EEPROMへ書き込む
		call	rom_putdt
		jmp	mex_out_ok		;アンサOK and jmp to アンサーを処理する へ
;
mex_route_time_p1				;IDの確認へ
		movr#	rom_pnt,t_routing_time_eeprom_plus ;in the EEPROM data memory
		jmp	mex_route_time_com


;*	EEPROM command
mex_rom
		call	getdt
		cjner#	rbyte,'O',mex_ng
		call	getdt
		cjner#	rbyte,'M',mex_ng

		call	getdt_hex
		jnb	f_hex_ok,mex_ng
		movrr	rom_pnt,rbyte		;rom_pntを設定しておく
		call	getdt
		cjerr	rbyte,crlf_code_save,mex_rom_check	;改行？
		cjner#	rbyte,'=',mex_ng

		movrr	wk1_mex_rom,pnt		;data pnt in xbuf
		clr	wk2_mex_rom		;データ数
mex_rom_0
		call	getdt
		cjerr	rbyte,crlf_code_save,mex_rom_1	;改行？data終了？
		inc	wk2_mex_rom		;データ数+1
		jmp	mex_rom_0

mex_rom_1
		cjer#	wk2_mex_rom,0,mex_ng	;空データ、エラーである

		movrr	acc,wk2_mex_rom		;データ数、EEPROMへ書き込む
		movrr	rbyte,wk2_mex_rom
		call	rom_putdt
		movrr	pnt,wk1_mex_rom
mex_rom_2
		call	getdt
		call	rom_putdt
		djnz	acc,mex_rom_2
		jmp	mex_out_ok		;アンサOK and jmp to アンサーを処理する へ


;
mex_rom_check					;eepromデータの確認
		call	rom_getdt
		cjaer#	rbyte,xbuf_size,mex_ng	;最大文字数は xbuf_size-1
		movrr	wk1_mex_rom,rbyte
mex_rom_check_1
		call	rom_getdt
		call	txdata_from_route	;*元ルート from_route へ１文字送信する
		djnz	wk1_mex_rom,mex_rom_check_1

		movrr	rbyte,crlf_code_save	;CR　LF codeを取り出す
		call	txdata_from_route
		jmp	mex_exit



;*	OUT comand
mex_out
		call	getdt
		cjner#	rbyte,'U',mex_ng
		call	getdt
		cjner#	rbyte,'T',mex_ng
		call	getdt
		cjerr	rbyte,crlf_code_save,mex_out_check
		cjner#	rbyte,'=',mex_ng
		call	getdt
		cjer#	rbyte,'0',mex_out_0
		cjer#	rbyte,'1',mex_out_1
		nop
		jmp	mex_ng
mex_out_0
		call	getdt
		cjnerr	rbyte,crlf_code_save,mex_ng

		clrb	b_OUT
mex_out_ok
		clrb	f_mexecute_command	
		setb	f_mtx_answer		;アンサーを処理する へ
		movr#	answer,answer_ok	;ok
		clr	pcflag
		ret
mex_out_1
		call	getdt
		cjnerr	rbyte,crlf_code_save,mex_ng

		setb	b_OUT
		jmp	mex_out_ok
mex_out_check
		jb	b_OUT,mex_out_check_1
		movr#	rbyte,'0'		;アンサ 0　
		call	txdata_from_route	;*元ルート from_route へ１文字送信する
		movrr	rbyte,crlf_code_save	;CR　LF codeを取り出す
		call	txdata_from_route
		jmp	mex_exit
mex_out_check_1
		movr#	rbyte,'1'		;アンサ 1　
		call	txdata_from_route	;*元ルート from_route へ１文字送信する
		movrr	rbyte,crlf_code_save	;CR　LF codeを取り出す
		call	txdata_from_route
		jmp	mex_exit



;*	INP command
mex_inp		
		call	getdt
		cjnerr	rbyte,crlf_code_save,mex_ng

		jb	b_INP,mex_inp_1
		movr#	rbyte,'0'		;アンサ 0　
		call	txdata_from_route	;*元ルート from_route へ１文字送信する
		movrr	rbyte,crlf_code_save	;CR　LF codeを取り出す
		call	txdata_from_route
mex_exit					;コマンド待ち処理(#受信）へ
		clrb	f_mexecute_command
		setb	f_mcheck_command
		clr	pcflag
		ret		
mex_inp_1
		movr#	rbyte,'1'		;アンサ 1　
		call	txdata_from_route	;*元ルート from_route へ１文字送信する
		movrr	rbyte,crlf_code_save	;CR　LF codeを取り出す
		call	txdata_from_route
		jmp	mex_exit

;*	ID command
mex_id
		call	getdt
		cjerr	rbyte,crlf_code_save,mex_id_0	;IDの確認へ
		cjner#	rbyte,'=',mex_ng

		clr	movstring_length
		clr	wk1_mex

		movrr	from_pnt,pnt
		movr#	to_pnt,id_save

mex_id_set1					;IDの登録
		call	getdt
		cjerr	rbyte,crlf_code_save,mex_id_set2

		movrr	acc,rbyte
		call	mex_id_check		;IDが有効な文字か調べる
		jnb	f_ok,mex_ng

		inc	movstring_length
		cjaer#	movstring_length,id_max_length+1,mex_ng	
		jmp	mex_id_set1
mex_id_set2
		test	movstring_length
		jz	mex_ng
		movrr	id_cnt,movstring_length
		call	movstring
;
		movrr	acc,id_cnt		;EEPROMへ書き込む
		movrr	rbyte,id_cnt
		movr#	rom_pnt,id_string_eeprom
		call	rom_putdt
		movr#	pnt,id_save
mex_id_set3
		call	getdt
		call	rom_putdt
		djnz	acc,mex_id_set3
		jmp	mex_out_ok		;アンサOK and jmp to アンサーを処理する へ
;*
mex_id_0					;IDの確認	
		movrr	wk1_mex,id_cnt
		movr#	pnt,id_save
mex_id_1
		call	getdt
		call	txdata_from_route	;*元ルート from_route へ１文字送信する
		djnz	wk1_mex,mex_id_1

		movrr	rbyte,crlf_code_save	;CR　LF codeを取り出す
		call	txdata_from_route
		jmp	mex_exit

;
mex_id_check						;IDが有効な文字か調べるacc : 0~9 A~Z a~z
		cjer#	acc,'_',mex_id_check_ok		;'_'は有効である
		cjer#	acc,'.',mex_id_check_ok		;'.'は有効である
		cjbr#	acc,0x30,mex_id_check_ng	;0~9
		cjber#	acc,0x39,mex_id_check_ok

		cjbr#	acc,0x41,mex_id_check_ng	;A~Z
		cjber#	acc,0x5A,mex_id_check_ok

		cjbr#	acc,0x61,mex_id_check_ng	;a~z
		cjber#	acc,0x7A,mex_id_check_ok
mex_id_check_ng
		clrb	f_ok
		ret
mex_id_check_ok
		setb	f_ok
		ret


;*	Version command
mex_version
		call	getdt
		cjnerr	rbyte,crlf_code_save,mex_ng

		clw
                call    ver_string
                movrw   wk1_mex,w		;string length
                clr     wk2_mex
mex_v1
                inc     wk2_mex			;w
                movwr   w,wk2_mex
                call    ver_string
                movrw	rbyte,w
                call    txdata_from_route	;*元ルート from_route へ１文字送信する
                djnz    wk1_mex,mex_v1

		movrr	rbyte,crlf_code_save	;CR　LF codeを取り出す
		call	txdata_from_route
                jmp	mex_exit		; コマンド待ち処理(#受信）へ


;*	route command (-)
mex_route_m					;-route command?
		call	getdt			;route番号？
		movrr	acc,rbyte
		call	check_route_no
		jb	f_ok,mex_route_m1	;正しい番号か？
mex_route_ng					;アンサNG + ID
		clrb	f_mexecute_command	
		setb	f_mtx_answer		;アンサーを処理する へ
		movr#	answer,answer_ng_id	;NGアンサ + ID,　jump to コマンド待ち処理(#受信）
		clr	pcflag
		ret
mex_route_m1
		subr#	acc,0x30
		movrr	to_route,acc		;to_route　を設定する
		dec	acc
		movrr	to_route_dec,acc	;to_route_dec　を設定する

		cjerr	from_route,to_route,mex_route_ng ;fromと　to　が同じルートである

		movr#	rom_pnt,t_routing_time_eeprom_minus ;in the EEPROM data memory
		call	rom_getdt
		movrr	routing_time,rbyte		;routing time準備
		movrr	routing_timeout,routing_time	;routing timeout リセット
mex_route_common
		call	getdt			;改行？
		cjerr	rbyte,crlf_code_save,mex_route_command		;ルートコマンド？
		cjer#	rbyte,terminator_route,mex_route_data_command	;','? ルートコマンド　+　データ？		
		jmp	mex_route_ng
;*
mex_route_command				;ルートコマンド
		clrb	f_mexecute_command	
		setb	f_mtx_answer		;アンサーを処理する へ
		movr#	answer,answer_ok_id	;OKアンサ + ID + ルート確立,　jump to コマンド待ち処理(#受信）へ
		clr	pcflag
		ret
;*
mex_route_data_command 				;ルートコマンド　+　データ
		call	getdt
		movrr	wk_mex_route,rbyte
		call	txdata_to_route		;to_route へデータ送信
		cjnerr	wk_mex_route,crlf_code_save,mex_route_data_command

		call	setup_f_routing		;*確立したルートに対応する　フラグ　をセットる

		setb	f_routing		;ルートを確立、routing処理実行

		clrb	f_mexecute_command	
		setb	f_mtx_answer		;アンサーを処理する へ
		movr#	answer,answer_no	;NOアンサ jump to コマンド待ち処理(#受信）
		clr	pcflag
		ret		


;*	route command (+)
mex_route_p					;+route command?
		call	getdt
		movrr	acc,rbyte
		call	check_route_no
		jnb	f_ok,mex_route_ng	;ng

		subr#	acc,0x30
		movrr	to_route,acc		;to_route　を設定する
		dec	acc
		movrr	to_route_dec,acc	;to_route_dec　を設定する

		cjerr	from_route,to_route,mex_route_ng ;fromと　to　が同じルートである

		movr#	rom_pnt,t_routing_time_eeprom_plus ;in the EEPROM data memory
		call	rom_getdt
		movrr	routing_time,rbyte		;routing time準備
		movrr	routing_timeout,routing_time	;routing timeout リセット
		jmp	mex_route_common


;
check_route_no					;IDが有効なルート番号か調べる　acc : 1~4
		cjbr#	acc,0x31,check_ng
		cjber#	acc,0x34,check_ok
check_ng
		clrb	f_ok
		ret
check_ok
		setb	f_ok
		ret




;**********************************************************************
;*	アンサーを処理する
mtx_answer
		sb	f_mtx_answer
		ret
		test	pcflag
		jnz	mta1	

		inc	pcflag
		ret
mta1
		cjer#	answer,answer_no,mta_no				;no answer
		cjer#	answer,answer_ok,mta_ok				;ok answer and jmp to コマンド待ち処理(#受信）
		cjer#	answer,answer_ng,mta_ng				;ng answer and jmp to コマンド待ち処理(#受信）
		cjer#	answer,answer_ng_invalid_timeout,mta_ng_invalid ;ng answer and jmp to invalid timeout処理へ
		cjer#	answer,answer_ng_id,mta_ng_id			;ng answer+ID and jump to コマンド待ち処理(#受信）
		cjer#	answer,answer_ok_id,mta_ok_id			;ok answer+ID and jump to コマンド待ち処理(#受信）
		cjer#	answer,answer_busy_id,mta_busy_id		;busy answer+ID and jump to コマンド待ち処理(#受信）
;*
mta_no
		clrb	f_mtx_answer
		setb	f_mcheck_command	;コマンド待ち処理(#受信）へ
		clr	pcflag
		ret
;*
mta_ok
		movr#	rbyte,'O'
		call	txdata_from_route
		movr#	rbyte,'K'
		call	txdata_from_route
		movrr	rbyte,crlf_code_save	;CR　LF codeを取り出す
		call	txdata_from_route
		jmp	mta_no			;コマンド待ち処理(#受信）へ
;*
mta_ng
		movr#	rbyte,'N'
		call	txdata_from_route
		movr#	rbyte,'G'
		call	txdata_from_route

		movrr	rbyte,crlf_code_save	;CR　LF codeを取り出す
		call	txdata_from_route
		jmp	mta_no			;コマンド待ち処理(#受信）へ
;*
mta_ng_invalid
		movr#	rbyte,'N'
		call	txdata_from_route
		movr#	rbyte,'G'
		call	txdata_from_route
		movrr	rbyte,crlf_code_save	;CR　LF codeを取り出す
		call	txdata_from_route

		clrb	f_mtx_answer
		setb	f_minvalid_command	;invalid command timeout処理へ
		clr	pcflag
		ret
;***
mta_ng_id				;NG answer+ID and jump to コマンド待ち処理(#受信）
		movr#	rbyte,'N'
		call	txdata_from_route
		movr#	rbyte,'G'
		call	txdata_from_route

		call	mta_id_common		; ':ID'を送信する

		movrr	rbyte,crlf_code_save	;CR　LF codeを取り出す
		call	txdata_from_route
		jmp	mta_no			;コマンド待ち処理(#受信）へ
;***
mta_ok_id				;OK answer+ID and jump to コマンド待ち処理(#受信）
		movr#	rbyte,'O'
		call	txdata_from_route
		movr#	rbyte,'K'
		call	txdata_from_route

		call	mta_id_common		; ':ID'を送信する

		movrr	rbyte,crlf_code_save	;CR　LF codeを取り出す
		call	txdata_from_route

		call	setup_f_routing		;*確立したルートに対応する　フラグ　をセットる
		setb	f_routing		;ルートを確立、routing処理実行

		jmp	mta_no			;コマンド待ち処理(#受信）へ

;***
mta_busy_id				;BUSY answer+ID and jump to コマンド待ち処理(#受信）
		movr#	rbyte,'B'
		call	txdata_from_route
		movr#	rbyte,'U'
		call	txdata_from_route
		movr#	rbyte,'S'
		call	txdata_from_route
		movr#	rbyte,'Y'
		call	txdata_from_route

		call	mta_id_common

		movrr	rbyte,crlf_code_save	;CR　LF codeを取り出す
		call	txdata_from_route
		jmp	mta_no			;コマンド待ち処理(#受信）へ

;
mta_id_common					; ':ID'を送信する
		movr#	rbyte,':'
		call	txdata_from_route
		
		movrr	wk1_mta,id_cnt		;ID送信
		movr#	pnt,id_save
mta_ng_id_1
		call	getdt
		call	txdata_from_route	;*元ルート from_route へ１文字送信する
		djnz	wk1_mta,mta_ng_id_1
		ret


;*
;*	確立したルートに対応する　フラグ　をセットる
setup_f_routing
		cjer#	from_route,1,from_route_1
		cjer#	from_route,2,from_route_2
		cjer#	from_route,3,from_route_3
		jmp	from_route_4
from_route_1
		setb	f_routing_1
		jmp	to_r1
from_route_2
		setb	f_routing_2
		jmp	to_r1
from_route_3
		setb	f_routing_3
		jmp	to_r1
from_route_4
		setb	f_routing_4
to_r1
		cjer#	to_route,1,to_route_1
		cjer#	to_route,2,to_route_2
		cjer#	to_route,3,to_route_3
		setb	f_routing_4
to_route_1
		setb	f_routing_1
		ret
to_route_2
		setb	f_routing_2
		ret
to_route_3
		setb	f_routing_3
		ret



;**********************************************************************
;*	invalid command timeout処理
;* #がつかないコマンド、未登録、不正なコマンドは全て無効な文字列として無視する。アンサーしない。
minvalid_command
		sb	f_minvalid_command
		ret
		test	pcflag
		jnz	mivc1
		movrr	invalid_command_timeout,invalid_command_time	;timeout初期化
		inc	pcflag
		ret
mivc1
		test	invalid_command_timeout
		jz	mivc2
		movrr	acc,from_route		
		dec	acc
		jz	mivc_1
		dec	acc
		jz	mivc_2
		dec	acc
		jz	mivc_3
		jmp	mivc_4
mivc_1
		snb	b_Rx1
		ret
		movrr	invalid_command_timeout,invalid_command_time
		ret
mivc_2
		snb	b_Rx2
		ret
		movrr	invalid_command_timeout,invalid_command_time
		ret
mivc_3
		snb	b_Rx3
		ret
		movrr	invalid_command_timeout,invalid_command_time
		ret
mivc_4
		snb	b_Rx4
		ret
		movrr	invalid_command_timeout,invalid_command_time
		ret	
mivc2
		clrb	f_minvalid_command
		setb	f_mcheck_command	;コマンド待ち処理(#受信）へ
		clr	pcflag
		ret

;****************************************
;*      subroutines                     *                
;****************************************
;
;*	先ルート to_route へ１文字送信する
;       entry   (rbyte)   :1 chara. data 
;
txdata_to_route
		movrr	acc,to_route		
		dec	acc
		jz	txdata_1
		dec	acc
		jz	txdata_2
		dec	acc
		jz	txdata_3
		jmp	txdata_4


;
;*	元ルート from_route から１文字受信する
;       exit:   f_ok=	    :0   ng
;                           :1   ok
;               (rbyte)     :1 chara.
rxdata_from_route
		movrr	acc,from_route		
		dec	acc
		jz	rxdata_1
		dec	acc
		jz	rxdata_2
		dec	acc
		jz	rxdata_3
		jmp	rxdata_4

;
;*      receive 1 chara. from  route
;       exit:   f_ok	    :0   ng
;                           :1   ok
;               (rbyte)     :1 chara.

rxdata_1	jnb     b_Rx1,rxdata12  
rxdata11        clrb    f_ok            ;ng
		ret
rxdata12        call    sdly           ;start bit delay (wait one-half bit time)
                jb      b_Rx1,rxdata11
		movr#   bitcnt,8
		clr     rbyte
rxdata13        call    bdly
                movb_b  CY,b_Rx1
		rr      rbyte
                djnz    bitcnt,rxdata13
                call    bdly            ;wait for stop bit
                setb    f_ok            ;ok
		ret
;*
rxdata_2	jnb     b_Rx2,rxdata22  
rxdata21        clrb    f_ok            ;ng
		ret
rxdata22        call    sdly           ;start bit delay (wait one-half bit time)
                jb      b_Rx2,rxdata21
		movr#   bitcnt,8
		clr     rbyte
rxdata23        call    bdly
                movb_b  CY,b_Rx2
		rr      rbyte
                djnz    bitcnt,rxdata23
                call    bdly            ;wait for stop bit
                setb    f_ok            ;ok
		ret

;*
rxdata_3	jnb     b_Rx3,rxdata32  
rxdata31        clrb    f_ok            ;ng
		ret
rxdata32        call    sdly           ;start bit delay (wait one-half bit time)
                jb      b_Rx3,rxdata31
		movr#   bitcnt,8
		clr     rbyte
rxdata33        call    bdly
                movb_b  CY,b_Rx3
		rr      rbyte
                djnz    bitcnt,rxdata33
                call    bdly            ;wait for stop bit
                setb    f_ok            ;ok
		ret

;*
rxdata_4	jnb     b_Rx4,rxdata42  
rxdata41        clrb    f_ok            ;ng
		ret
rxdata42        call    sdly           ;start bit delay (wait one-half bit time)
                jb      b_Rx4,rxdata41
		movr#   bitcnt,8
		clr     rbyte
rxdata43        call    bdly
                movb_b  CY,b_Rx4
		rr      rbyte
                djnz    bitcnt,rxdata43
                call    bdly            ;wait for stop bit
                setb    f_ok            ;ok
		ret



;*	元ルート へ　文字列(string)を	送信する (binaryでもasciiでも良い)
;	entry	from_pnt:	data addr  data=length + string...
;
txstring_from_route
		movrr	pnt,from_pnt
		call	getdt
		movrr	wk_txstring,rbyte	;string length
tx_s1
		call	getdt
		call	txdata_from_route
		djnz	wk_txstring,tx_s1
		ret


;
;*	元ルート from_route へ１文字送信する
;       entry   (rbyte)   :1 chara. data 
;
txdata_from_route
		movrr	acc,from_route		
		dec	acc
		jz	txdata_1
		dec	acc
		jz	txdata_2
		dec	acc
		jz	txdata_3
		jmp	txdata_4

;
;*      transmit 1 chara. to route
;       entry   (rbyte)   :1 chara. data 
;
                                         
txdata_1	movr#	bitcnt,8
                clrb    b_Tx1
                call    bdly            ;start bit!
txdata11        rr      rbyte
                movb_b	b_Tx1,CY
                call    bdly
                djnz    bitcnt,txdata11
                setb    b_Tx1
                call    bdly            ;stop bit!
		ret

;*
txdata_2	movr#	bitcnt,8
                clrb    b_Tx2
                call    bdly            ;start bit!
txdata21        rr      rbyte
                movb_b	b_Tx2,CY
                call    bdly
                djnz    bitcnt,txdata21
                setb    b_Tx2
                call    bdly            ;stop bit!
		ret

;*
txdata_3	movr#	bitcnt,8
                clrb    b_Tx3
                call    bdly            ;start bit!
txdata31        rr      rbyte
                movb_b	b_Tx3,CY
                call    bdly
                djnz    bitcnt,txdata31
                setb    b_Tx3
                call    bdly            ;stop bit!
		ret

;*
txdata_4	movr#	bitcnt,8
                clrb    b_Tx4
                call    bdly            ;start bit!
txdata41        rr      rbyte
                movb_b	b_Tx4,CY
                call    bdly
                djnz    bitcnt,txdata41
                setb    b_Tx4
                call    bdly            ;stop bit!
		ret

;       start bit delay
sdly						;104us delay
		movr#   dlycnt,10
bdly11           
		nop
		nop
		call	execute_routing	
		djnz    dlycnt,bdly11
		ret

;       bit delay
bdly		nop				;208us delay
		movr#   dlycnt,20
bdly1           
		nop
		nop
		call	execute_routing	
		djnz    dlycnt,bdly1
		nop
		ret

;*	
;dly4u						;4us dlay
;		movr#	dlycnt,4
;dly4u1		nop
;		djnz	dlycnt,dly4u1
;		ret



;*	hex > from_route
;	元ルート from_route へ　hex　の内容(ascii)を送信する（主にモニタ用）
;       entry   acc:    hex
txhex_from_route
	call	hex_to_ascii
	movrr	rbyte,wk_h
	call	txdata_from_route
	movrr	rbyte,wk_l
	call	txdata_from_route
	ret


;       hex > ascii
;       entry   acc:    hex
;       exit    wk_h:   ascii
;               wk_l:   ascii   
hex_to_ascii
		movrr   wk_h,acc
                andr#   acc,0x0F
                cjber#  acc,9,hta1      ;0-9?
                addr#   acc,0x37
                jmp     hta2
hta1            addr#   acc,0x30
hta2            movrr   wk_l,acc

                andr#   wk_h,0xF0
                clc
                rr      wk_h
                rr      wk_h
                rr      wk_h
                rr      wk_h
                cjber#  wk_h,9,hta3
                addr#   wk_h,0x37
                ret
hta3            addr#   wk_h,0x30
                ret

;	ascii (2bytes) > hex
;       entry   pnt:     ascii data addr
;       exit    rbyte:   hex
;               pnt:     pnt+2
;               f_hex_ok 0:ng
;                        1:ok
;
getdt_hex
		call    getdt
                csaer#  rbyte,'0'
                jmp     hex_ng
                cjber#  rbyte,'9',hex_h0_9
                csaer#  rbyte,'A'
                jmp     hex_ng
                cjber#  rbyte,'F',hex_ha_f
                jmp     hex_ng

hex_ha_f        subr#   rbyte,0x37
                jmp     hex_m0
                            
hex_h0_9        andr#   rbyte,0x0F
hex_m0          clc
                rl      rbyte
                rl      rbyte
                rl      rbyte
                rl      rbyte
                movrr   wk_getdt_hex,rbyte

                call    getdt
                csaer#  rbyte,'0'
                jmp     hex_ng
                cjber#  rbyte,'9',hex_l0_9
                csaer#  rbyte,'A'
                jmp     hex_ng
                cjber#  rbyte,'F',hex_la_f
                jmp     hex_ng

hex_la_f        subr#   rbyte,0x37
                jmp     hex_m1

hex_l0_9        andr#   rbyte,0x0F
hex_m1          orrr    rbyte,wk_getdt_hex              
                setb    f_hex_ok
                ret

hex_ng          clrb    f_hex_ok
                ret



;*	move string in the registers
;	entry	movstring_length:	データ数
;		from_pnt:		from_data addr
;		to_pnt:			to_data addr
movstring
		movrr	pnt,from_pnt
		call	getdt
		movrr	from_pnt,pnt
		movrr	pnt,to_pnt
		call	putdt
		movrr	to_pnt,pnt
		djnz	movstring_length,movstring
		ret


;*      indirect data save 
;       entry   pnt:    FSR addr
;               rbyte:  data
;       exit    pnt:    pnt+1
putdt
		movrr	FSR,pnt
		movrr	INDF,rbyte
		inc	pnt
		ret

;*      indirect data read 
;       entry   pnt:    FSR addr
;       exit    rbyte:  data
;               pnt:    pnt+1
getdt
		movrr	FSR,pnt
		movrr	rbyte,INDF
		inc	pnt
		ret


;*	data EEPROM wtite
;	entry	rom_pnt: 	eeprom addr
;		rbyte:		data
;	exit	rom_pnt+1
rom_putdt
		movwr	w,rom_pnt
		bank1
		movrw	EEADR,w
		bank0
		movwr	w,rbyte
		bank1
		movrw	EEDATA,w
		BSF	EECON1,WREN
		MOVLW	55h
		MOVWF	EECON2
		MOVLW	0AAh
		MOVWF	EECON2
		BSF	EECON1,WR
		btfsc	EECON1,WR
		goto	$-1
		bcf	EECON1,WREN
		bank0
		inc	rom_pnt
		ret


;*	data EEPROM read
;	entry	rom_pnt: 	eeprom addr
;	exit	rbyte:		data
;		rom_pnt+1
rom_getdt
		movwr	w,rom_pnt
		bank1
		movrw	EEADR,w
		BSF	EECON1,RD
		movwr	w,EEDATA
		bank0
		movrw	rbyte,w
		inc	rom_pnt
		ret



; initialize eeprom locations

		ORG	0x2100

t_routing_time_eeprom_minus
		de	t_routing_time_minus	;- ルート 通常初期値*****************************************

t_routing_time_eeprom_plus
		de	t_routing_time_plus	;+ ルート

id_string_eeprom
		de	4,"tree"

		ORG	0x2100+0x10
		de	9,"NS KIKAKU"

		END                       ; directive 'end of program'

