;******************************************************************************
;Decoder address display　unit Via BDL168 Transponding
;PIC16F873A 
;copyright (c) 2015 名古屋電鉄　　http://www007.upp.so-net.ne.jp/nagoden/
;ADDRDISP01.asm  2015/03/17 Ver1.11 
;
;参考　BDL168　InstructionSheet　http://www.digitrax.com/products/detection-signaling/bdl168/
;      BCD変換ルーチン　趣味の電子工作　http://orange.zero.jp/electronics/pic/pic.html
;
;******************************************************************************
;【概要】
;PIC16F873AのUSART機能を使いLOCONETに接続し、BDL168のRX4を使用したTransponding機能によって
;検出されたデコーダのアドレスをLoconetからのコマンドで読み取り７セグＬＥＤに表示させます。
;
;表示の解除はBDL168からくるSection　On/Off のコマンドを使用しており、検出したセクションがOFFとなった
;時のコマンドで解除します。
;
;このため、EEPROMに以下の情報を持ちます。
;   1.BDL168ボードアドレス
;		どのBDL168からのコマンドを受け取るかの指定ができます。アドレスは1～255の範囲で指定します。
;		0を指定した場合はボードアドレスは無視してコマンドを受信します。
;	2.Zone番号
;		BDL168のどのゾーンからのコマンドを受け取るかの指定ができます。
;		Zone番号は A=01 B=03 C=05 D=07 E=09 F=11 G=13 H=15と指定します。
;		(BDL168からのコマンドは上記値を-1した値であるが、0を設定値として使いたいため＋１していします）
;		00を指定した場合はZoneを無視してコマンドを受信します。
;	3.Section番号
;		BDL168のどのセクションがON/OFFしたかのコマンドでどのセクションoffで表示解除をするかを指定します。
;		基本、Transpondingでアドレスを検知しているセクションを指定します。
;		BDL168で車輌が離線してOFFのコマンドを遅延して送信することができ、BDL168のOpSwの37をC
;		(Slow Detection Section OFF timing(DS release))に設定すると約5秒遅延してコマンド
;		を受け取ることができます。
;		Section番号は１～１６を指定します。
;	4.番線番号
;		7セグＬＥＤ5桁ある内の左1桁を、番線番号やユニット識別のための識別文字を表示できます。
;		表示できるのは、プログラム内にあるテーブル定義した４８文字となり、０～４７で指定します。
;
;	これらのEEPROMの設定を容易にするためにセットアップモードを実装しています。
;	PIC16F873A　の２番ピン（RA0）がLowの時にセットアップモードとなり、上記４つの項目を設定して
;	EEPROMに書き込むようにしています。
;	また、操作には、スロットルから操作できるように、ポイント等を切り替えるスイッチ設定のコマンドを使用し	
;	て特殊な操作なく設定できるようにします。
;
;	直接EEPROMに値を書き込む場合は、EEPROMアドレス03hの番線番号の値は、10進数で47を絶対に超え
;	いでください。プログラムが暴走して正しく動作しません。
;
;   ※　ＤＢ１５０、ＤＢ２００をコンロトーラとして使用している場合は、正しく検出できません。　　
;
;------------------------------------------------------------------------------
;●USARTモードは以下の指定をしています 
;------------------------------------------------------------------------------
;   Mode : Asyncronous transfer mode only
;   Speed: 16K bps(12h 20Mhz) 
;   Bit  : startx1 datax8 stopx1
;　	※Loconetはボーレート16600bpsと特殊です。ここでは設定値から16447bpsにしています。
;------------------------------------------------------------------------------
;●PIC16F873A　ピンアサイン 
;------------------------------------------------------------------------------
;	RA1			セットアップモード（ショートピンでLowにて有効）
;	RA2			未使用
; 	RB0～RB6　　	7セグLED　a～g		
; 	RC0 		7セグLED　1ブロック目　コモン制御
; 	RC1 		7セグLED　4連左1ブロック目　コモン制御　
; 	RC2 		7セグLED　4連左2ブロック目　コモン制御
; 	RC3			7セグLED　4連左3ブロック目　コモン制御		
; 	RC4 		7セグLED　4連左4ブロック目　コモン制御
; 	RC5　		状態表示用　ＬＥＤ
; 	RC6 		TX（送信）　ユニット間通信用でＬｏｃｏｎｅｔには返しません。
; 	RC7 		RX（受信）　Loconetより受信
;-------------------------------------------------------------------------------
;●LoconetのBDL168からくるTransPondingのコマンド
;-------------------------------------------------------------------------------
;　D0 aa bb cc dd ee の6バイト
;		aa  0 0 n A7 A6 A5 A4 A3
;  		bb  0 A2 A1 A0 Z3 Z2 Z1 Z0
;　			n=1 Absent（検出） n=0 Present（未検出）
;			A7～A0　BDL168のアドレス   
;			Z3～Z0　ゾーン番号
;
;		cc	下位7ビットが車輌アドレスの上位アドレス（2桁アドレスの場合は0x7D）
;		dd 	下位7ビットが車輌アドレスの下位アドレス
;			上位アドレス+下位アドレスの並びでビットから１０進数に変換すると車輌アドレスになる
;           2桁アドレスの場合は　下位アドレスのみ１０進数に変換
;  		ee  check SUM
;--------------------------------------------------------------------------------
;●LoconetのBDL168からくるSection　On/Off のコマンド
;--------------------------------------------------------------------------------
; B2 aa bb cc の4バイト
;		aa  0 A7 A6 A5　 A4 S3 S2 S1
;  		bb  0  N S0  L  A3 A2 A1 A0 
;　			n=1 常時１
;　			L=1 検出 　L=0 未検出
;			A7～A0　BDL168のアドレス   
;			S3～S0　セクション番号（０~
;  		ｃｃ  check SUM;
;
;---------------------------------------------------------------------------------
;●LoconetのBDL168からくるSwitch のコマンド
;---------------------------------------------------------------------------------
;　SETUPモードでは、Loconet上に他のオプション機器（ポイントデコーダなど）が接続されていない上でスロットルのSwitchで操作する 
;  tでカウントアップ　ｃでカウントダウン
;	Switch 01			;BDL168のボードアドレス　	（0-255）	０はアドレスチェックしない　実際のボードアドレスは1~254
;	Switch 02			;ゾーン番号	　　		（Zone A=01 B=03 C=05 D=07 E=09 F=11 G=13 H=15）
;	Switch 03			;セクション番号　			（1-16）　
;	Switch 04			;番線番号　　　			（1-48）	番号と表示文字は7セグ文字マッピングに依存
;	Switch 05			;EEPROM書き込み		tで書き込み
;	Switch 06			;セットアップモード終了		tで終了
;
;---------------------------------------------------------------------------------
;SWITCHを選択時のコマンド（セットアップモードのみ）
;---------------------------------------------------------------------------------
;　BC　aa bb cc　　
;		aa  0 A6 A5 A4　 A3  A2 A1 A0
;		bb  0  0 S1 S2  A10 A9 A8 A7 
;			A7～A0　Switchのアドレス
;			s1=0 Thrown 　s1=1 Close
;			s2=0　output off   S2=1 output 0n   
;		ｃｃ  check SUM;
;
;---------------------------------------------------------------------------------
; Switch　の　ｔ　Or　C　を選択時のコマンド　（セットアップモードのみ）
;---------------------------------------------------------------------------------
; B0　aa bb cc
;		aa  0 A6 A5 A4　 A3  A2 A1 A0
; 		bb  0  0 S1 S2  A10 A9 A8 A7 
;　			A7～A0　Switchのアドレス
;　			s1=0 Thrown 　s1=1 Close
;			s2=0　output on   S2=1 output 0ff   
;  			ｃｃ  check SUM;
;   DCS50KとDT300で出力が違い　dt300では　ONと0FFを続けて出力するが、DCS50KではONのみを出力
;   DCS50K   B0 00 30 7F → c      B0 00 10 5F → t
;
;---------------------------------------------------------------------------------
	list      p=16f873a
	#include <p16f873a.inc>

	__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC & _WRT_OFF & _LVP_OFF & _CPD_OFF

;*****************************************************************************
;　EEPROMへのデータ定義（デフォルト値）
;*****************************************************************************
	org	0x2100		;
;-----　初期データ ---------説明----------------------
	de	0x00		;BDL168のボードアドレス　	(0-255)	  ０はアドレスチェックしない　実際のボードアドレスは1~254
	de	0x00		;ゾーン番号	　　		(Zone A=01 B=03 C=05 D=07 E=09 F=11 G=13 H=15)														
	de	0x00		;セクション番号　			(0，1-16)　　０は、セクションを無視
	de	0x00		;番線番号　　　			(0-47)	  番号と表示文字はプログラム中７セグ文字マッピングに依存
;*****************************************************************************
;変数定義
;*****************************************************************************
;割り込みルーチンで使用
w_temp		EQU	0x20 
status_temp	EQU	0x21
;hexdec16ルーチンで使用
up_byte		EQU	0x22		; 変換したい値（１６ビット　　上位8ビット）
ud_byte		EQU	0x23		; 変換したい値（１６ビット　　下位8ビット）
colm5		EQU	0x24		;～下位５　10進格納場所（５バイト）
colm4		EQU	0x25		;～下位４
colm3		EQU	0x26		;～下位３
colm2		EQU	0x27		;～下位２
colm1		EQU	0x28		;～下位１
srlc1		EQU	0x29		; カウンタ（サブルーチンで使用）
srwk1		EQU	0x2A		; 一時余り格納場所（サブルーチンで使用）
;表示変数(間接アドレッシングで使用のためアドレス２Ｂ~２Ｆまでは変更禁止)
dp5			EQU 0x2B		;番線用　7SegＬＥＤ	
dp4			EQU 0x2C		;アドレス表示用	7SegＬＥＤ　4桁目
dp3			EQU 0x2D		;アドレス表示用	7SegＬＥＤ　3桁目			
dp2			EQU 0x2E		;アドレス表示用	7SegＬＥＤ　2桁目			
dp1			EQU 0x2F		;アドレス表示用	7SegＬＥＤ　1桁目			
BADRS		EQU 0x30		;ターゲットBDL168ボードアドレス(EEPROM値)
ZONE		EQU 0x31		;ターゲットBDL168Zone番号(EEPROM値)
SECT		EQU 0x32		;ターゲットBDL168セクション番号(EEPROM値)
TRCNO		EQU 0x33		;番線（トラック）番号(EEPROM値)
;内部処理変数
ADDR		EQU	0x34		;EEPROM アドレス
EE_DAT		EQU	0x35		;EEPROM データ
point_f		EQU	0x36		;表示ループﾎﾟｲﾝﾀ退避用
netcmd		EQU 0x37		;USART受信用
cmd_chk		EQU 0x38		;未使用
flg_d0		EQU 0x39		;コマンド受信フラグ
cmd_cnt		EQU 0x3A		;データ受信時のバイト数
;内部処理変数
C_CNT		EQU	0x3B		;文字番号
R_CNT		EQU	0x3C		;ループカウンタ
B_CNT		EQU	0x3D		;ループカウンタ
cnt1		EQU	0x3E		;タイマーカウント
cnt2		EQU	0x3F		;タイマーカウント
cnt3		EQU	0x40		;タイマーカウント
;コマンド受信変数（受信して分解した結果）
R_BADRS		EQU 0x41		;受信ボードアドレス
R_ZONE		EQU 0x42		;受信Zone番号)
R_SECT		EQU 0x43		;受信セクション番号
R_ADR1		EQU 0x44		;受信アドレス下位８ビット
R_ADR2		EQU 0x45		;受信アドレス上位８ビット
R_WK1		EQU 0x46		;コマンド編集用ワーク１
R_WK2		EQU 0x47		;コマンド編集用ワーク２
wk_data		EQU 0x48		;コマンド送信用ワーク
;SECOFF		EQU	0x49		;表示解除遅延時間
;コマンド受信　内部処理変数(間接アドレッシングで使用のためアドレス４Ａ~４Ｆまでは変更禁止)
cmd1		EQU 0x4A		;受信コマンド１バイト目
cmd2		EQU 0x4B		;受信コマンド２バイト目
cmd3		EQU 0x4C		;受信コマンド３バイト目
cmd4		EQU 0x4D		;受信コマンド４バイト目
cmd5		EQU 0x4E		;受信コマンド５バイト目
cmd6		EQU 0x4F		;受信コマンド６バイト目
;セットアップモード時の変数
S_MODE		EQU	0x50		;セットアップモード＝１
R_SWNO		EQU	0x51		;コマンド受信したスイッチ番号
DEFNO		EQU	0x52		;不在線時の表示文字
bcmd1		EQU 0x53		;受信コマンドバックアップ１バイト目
bcmd2		EQU 0x54		;受信コマンドバックアップ２バイト目
bcmd3		EQU 0x55		;受信コマンドバックアップ３バイト目
bcmd4		EQU 0x56		;受信コマンドバックアップ４バイト目
bcmd5		EQU 0x57		;受信コマンドバックアップ５バイト目
bcmd6		EQU 0x58		;受信コマンドバックアップ６バイト目
wcmd1		EQU 0x59		;受信コマンドワーク１バイト目
wcmd2		EQU 0x5A		;受信コマンドワーク２バイト目
wcmd3		EQU 0x5B		;受信コマンドワーク３バイト目
wcmd4		EQU 0x5C		;受信コマンドワーク４バイト目
wcmd5		EQU 0x5D		;受信コマンドワーク５バイト目
wcmd6		EQU 0x5E		;受信コマンドワーク６バイト目
;CPMODE		EQU 0x5F		;連結（転送）モード

;*****************************************************************************
;マクロ定義
;*****************************************************************************
;バンクの指定
BANK0	MACRO
	BCF	STATUS,RP0	;BANK 0に切替
	BCF	STATUS,RP1	;
	ENDM
BANK1	MACRO
	BSF	STATUS,RP0	;BANK 1に切替
	BCF	STATUS,RP1	;
	ENDM
BANK2	MACRO
	BCF	STATUS,RP0	;BANK 2に切替
	BSF	STATUS,RP1	;
	ENDM
BANK3	MACRO
	BSF	STATUS,RP0	;BANK 3に切替
	BSF	STATUS,RP1	;
	ENDM
;*****************************************************************************
;プログラムスタート
;*****************************************************************************
		ORG	0x000             
 	 	goto	init  				
		ORG	0x004					; 割り込みベクタ
		movwf	w_temp        	  	; ワークレジスタ退避
		movf	STATUS,w          	; ステータスレジスタをワークレジスタに
		movwf	status_temp       	; ワークレジスタ（ステータス）退避
								  	; ←ここに割り込みルーチン設定
		BANK0						; バンク０に切り替え	
		movf	status_temp,w     	;　退避ステータスのワークレジスタへ戻し
		movwf	STATUS            	; ワークレジスタからステータスへ戻し
		swapf	w_temp,f			;　ワークレジスタの戻し	
		swapf	w_temp,w          	; ワークレジスタの戻し
		retfie                    	; 割り込み終了
init
;*****************************************************************************
;ＰＩＣの入力ポートと割り込みの設定
;*****************************************************************************
		BANK1
		;ポートの設定
		movlw	0x06			;コレをしないとportＡのデジタル入力ができません
		movwf	ADCON1			;ADCON1に06Hを設定しポートＡをすべてデジタルに
		movlw	B'00000011'
		movwf	TRISA			; ポートAは RA0,RA1のみ入力　
		movlw	B'00000000'
		movwf	TRISB			; ポートBは全て出力端子
		movlw	0x80
		movwf	OPTION_REG		; ポートＢプルアップなし
		movlw	B'10000000'
		movwf	TRISC			; ポートCはrc7が入力端子　後は出力
		BANK0
		clrf	PORTA			; PORTクリア
		clrf	PORTB			; PORTクリア
		bcf		PORTC,6

		;USARTの設定 PIC12F873 20Mhｚ
		BANK1
		movlw	0x20			;↓でAsync mode　に設定 
		movwf	TXSTA			;TXSTAにセット
		movlw	d'18'			;18→ボーレート 16Kbps   16447.37=20Mhz/((18+1)*64)
		movwf	SPBRG			;SPBRGにボーレート設定		
		BANK0					;Bank 0に切り替え
		movlw	0x90			;↓でシリアルピン設定、継続受信許可　に設定 
		movwf	RCSTA			;RCSTAにセット
	
main_init
;*****************************************************************************
;ＥＥＰＲＯＭを読んで　ボードのアドレスとゾーンの番号を取得
;ここで取得されるアドレスとゾーン番号から来るデコーダアドレスのみを
;表示する
;*****************************************************************************
		;BDL168ボードアドレス
		movlw	0x00
		movwf	ADDR		
		call	eeprom_r	
		movwf	BADRS	
		;BDL168ゾーン番号
		movlw	0x01
		movwf	ADDR		
		call	eeprom_r	
		movwf	ZONE	
		;BDL168セクション番号
		movlw	0x02
		movwf	ADDR		
		call	eeprom_r	
		movwf	SECT	
		;表示番線番号
		movlw	0x03
		movwf	ADDR
		call	eeprom_r	
		movwf	TRCNO

main
;*****************************************************************************
;メインルーチン
;*****************************************************************************
		;セットアップモードチェック
		clrf	S_MODE
		btfsc	PORTA,0		;RA0が０　ショートピンでショートしていた場合
		goto	stat_n		;０でない場合は通常モード
		movlw	d'1'
		movwf	S_MODE		;セットアップモード時は１
		goto	stat_s
stat_s
		;起動時のセットアップモードデフォルト文字
		movlw	d'5'	;S
		movwf	dp5	
		movlw	d'14'	;E
		movwf	dp4
		movlw	d'31'	;T
		movwf	dp3
		movlw	d'28'	;U
		movwf	dp2
		movlw	d'27'	;P
		movwf	dp1
		goto	stat_e

stat_n
		movlw	d'18'	;_
		movwf	DEFNO
		;起動時のデフォルト表示値を設定　
		movf	TRCNO,w
		movwf	dp5	
		movf	DEFNO,w
		movwf	dp4
		movf	DEFNO,w
		movwf	dp3
		movf	DEFNO,w
		movwf	dp2
		movf	DEFNO,w
		movwf	dp1
stat_e
		clrf	R_CNT
		clrf	B_CNT
main_loop
		;カウンタ初期化
		movlw	d'5'
		movwf	R_CNT		;7Segの数5個分ダイナミック点灯のためのループ数
		movlw	b'00001'	;ポートｃのビット　5バイト分
		movwf	B_CNT
		movlw 	0x2B		;dp5～dp1まで間接アドレッシングでアクセスするための初期アドレス
		movwf	FSR			;ﾎﾟｲﾝﾀセット
led_disp
		;桁分ループして数値を表示　　　
		movf	INDF,w		;間接アドレスでdp5～dp1までの値をワークにセット
		movwf	C_CNT		;データをセットして
		movlw	d'0'		;7セグテーブルで変換
        movwf	PORTB		;ＰＯＲＴＢクリア（７セグメントクリア）
        movf	B_CNT,w		;表示するセグメント桁
		btfss	B_CNT,0
		bcf		PORTC,0
		btfsc	B_CNT,0
		bsf		PORTC,0
		btfss	B_CNT,1
		bcf		PORTC,1
		btfsc	B_CNT,1
		bsf		PORTC,1
		btfss	B_CNT,2
		bcf		PORTC,2
		btfsc	B_CNT,2
		bsf		PORTC,2
		btfss	B_CNT,3
		bcf		PORTC,3
		btfsc	B_CNT,3
		bsf		PORTC,3
		btfss	B_CNT,4
		bcf		PORTC,4
		btfsc	B_CNT,4
		bsf		PORTC,4
		call	setchr		;7セグテーブルで変換
        movwf	PORTB		;ＰＯＲＴＢに出力

	;----------------------------------------------------------
	;コマンド受信
	;----------------------------------------------------------
		;FSRポインタ退避
		movf	FSR,w
		movwf	point_f
		;受信処理
		call	rcv_usart
		;FSRポインタ復帰
        movf	point_f,w
        movwf	FSR

		incf	FSR,F		;FSR+1
		rlf		B_CNT,f		;出力桁のビットシフト（セグメント制御用で順番にシフト）
		decfsz	R_CNT,f		;-1して０か判断して	
    	goto	led_disp	;０でなければ
		goto	main_loop	;０なら　　　

;*****************************************************************************
;USART コマンド受信処理
;*****************************************************************************
rcv_usart
	;----------------------------------------------------------
	;受信したコマンドが該当（D0,BC,B2,B0)だったら受信フラグを立てて残りバイト受信
	;----------------------------------------------------------
		movlw	0x4A			;set buffer top address
		movwf	FSR				;間接アドレスポインタ初期化
		clrf	cmd_cnt
		clrf	flg_d0
lprcv
		;受信ステータスチェック
		btfss	PIR1,RCIF		;受信完了フラグのチェック
		goto	re_recv
		;エラーチェック
		btfsc	RCSTA,FERR		;FRAME エラー
		goto	frame_err
		btfsc	RCSTA,OERR		;オーバーラン　エラー
		goto	ovrun_err
		;データ受信
		bsf		PORTC,5			;LED on
	 	movf	RCREG,W			;受信データ取得しワークエリアに
		movwf	netcmd			;ワークにある受信したデータをnetcmdにセット
		;D0受信フラグ（flg_d0）が０以外の場合コマンドチェックせず以降のコマンド受信
		movf	flg_d0,f
		btfss	STATUS,Z		;０かどうか判定
		goto	other_cmd		;0<>なら　D0受信フラグ＝1なのでother_cmdへ
		goto	tsp_cmd			;0= なら　１バイト目のコマンドチェック
frame_err
		movf	RCREG,W			;ダミーで読み取りフレームエラー解除
        btfss	RCSTA,OERR
		goto	rcv_end
ovrun_err
		BCF		RCSTA,CREN		;crenのビットをリセットすることでｏｖｅｒRunエラー解除　　		
		BSF		RCSTA,CREN
		goto	rcv_end	
re_recv
		movf	flg_d0,f
		btfss	STATUS,Z		;０かどうか判定
		goto	lprcv			;0<>なら　D0受信フラグ＝1なので受信待ち
		goto	rcv_end			;０ならそのまま受信ループ終了
tsp_cmd
		;RA1がLowのときDOのチェックはしない
		btfss	PORTA,1			;RA1が０　ショートピンでショートしていた場合
		goto	ctrl_cmd		;０の場合はＤ０のチェックをしない
		;コマンドがＤ０かチェック
		movf	netcmd,w
		sublw	0xD0			;D0と受信したコマンドを引いて０かチェック
		btfss	STATUS,Z		;０かどうか判定
		goto	ctrl_cmd		;0<>なら次のコマンドチェック
		;D0だったら受信フラグに１を立てる
		movlw	d'1'			;受信フラグ＝１にセット
		movwf	flg_d0			;受信フラグ（flg_d0）に1セット
 		movlw	d'6'
		movwf	cmd_cnt			;D0を受信時 6バイト受信
		goto	other_cmd		;
ctrl_cmd
		;コマンドがＢ２かチェック
		movf	netcmd,w
		sublw	0xB2	
		btfss	STATUS,Z		;０かどうか判定
		goto	ctrl_cmd2		;0<>なら次のコマンドチェック
		;B2だったら受信フラグに２を立てる
		movlw	d'2'			;受信フラグ＝２にセット
		movwf	flg_d0			;受信フラグ（flg_d0）に2をセット
		movlw	d'4'
		movwf	cmd_cnt			;B2を受信時 4バイト受信
		goto	other_cmd		;
ctrl_cmd2
		;セットアップモードの確認　セットアップモード時のみBC　B0コマンドチェック
		movf	S_MODE,w
		sublw	d'1'	
		btfss	STATUS,Z		;1かどうか判定
		goto	rcv_end			;S_MODE=0ならrcv_endへ飛ぶ
		;コマンドがＢＣ（スイッチコマンド選択）かチェック
		movf	netcmd,w
		sublw	0xBC	
		btfss	STATUS,Z		;０かどうか判定
		goto	ctrl_cmd3		;0<>なら次のコマンドチェック
		;BCだったら受信フラグに３を立てる
		movlw	d'3'			;受信フラグ＝3にセット
		movwf	flg_d0			;受信フラグ（flg_d0）に３をセット
		movlw	d'4'
		movwf	cmd_cnt			;BCを受信時 4バイト受信
		goto	other_cmd		;
ctrl_cmd3
		;コマンドがＢ０（スイッチコマンドのtｃ選択）かチェック
		movf	netcmd,w
		sublw	0xB0	
		btfss	STATUS,Z		;０かどうか判定
		goto	rcv_end			;0<>ならrcv_endへ飛ぶ
		;B0だったら受信フラグに４を立てる
		movlw	d'4'			;受信フラグ＝4にセット
		movwf	flg_d0			;受信フラグ（flg_d0）に３をセット
		movlw	d'4'
		movwf	cmd_cnt			;B0を受信時 4バイト受信
		goto	other_cmd		;
other_cmd
		;受信フラグが１なら指定バイト数になるまで順次受信
		movf	netcmd,w		;ワークにある受信したデータをnetcmdにセット
		movwf	INDF			;save in buffer
		incf	FSR,F			;FSR+1
		decf	cmd_cnt,f		;cmd_cnt-1
		btfss	STATUS,Z		;０かどうか判定
		goto	lprcv

		;受信コマンド判別
		movf	flg_d0,w
		sublw	D'1'			;1->D0 2->B2 3->BC 4->B0
		btfsc	STATUS,Z		;０かどうか判定
		goto	cmd_D0
			
		movf	flg_d0,w
		sublw	D'2'			;1->D0 2->B2 3->BC 4->B0
		btfsc	STATUS,Z		;０かどうか判定
		goto	cmd_B2

		movf	flg_d0,w
		sublw	D'3'			;1->D0 2->B2 3->BC 4->B0
		btfsc	STATUS,Z		;０かどうか判定
		goto	cmd_BC

		movf	flg_d0,w
		sublw	D'4'			;1->D0 2->B2 3->BC 4->B0
		btfsc	STATUS,Z		;０かどうか判定
		goto	cmd_B0
		goto	rcv_end

;*****************************************************************************
;　コマンドＤ０（Ｔｒａｎｓｐｏｎｄｉｎｇ）の処理
;*****************************************************************************
cmd_D0
	;----------------------------------------------------------
	;   受信データのらcheckSumの確認(cmd1~cmd6 をｘｏｒして　FFｈになるか確認)
	;----------------------------------------------------------   	
		movf	cmd1,w
		xorwf	cmd2,w
		xorwf	cmd3,w
		xorwf	cmd4,w
		xorwf	cmd5,w
		xorwf	cmd6,w		
		sublw	0xFF		
		btfss	STATUS,Z	;FFｈかどうか判定
		goto	rcv_end		;不一致の場合
	;コマンド退避  cmd -> wcmd
		movf	cmd1,w
        movwf	wcmd1
		movf	cmd2,w
        movwf	wcmd2
		movf	cmd3,w
        movwf	wcmd3
		movf	cmd4,w
        movwf	wcmd4
		movf	cmd5,w
        movwf	wcmd5
		movf	cmd6,w
        movwf	wcmd6
	;---------------------------------------------------------------
	;  CheckSumＯＫならコマンド分解
	;	２バイト目	0,0,S,B7,B6,B5,B4,B3
	;	３バイト目	0，B2,B1,B0,Z3,Z2,Z1,Z0		
	;	４バイト目	0，A13,A12,A11,A10,A9,A8,A7
	;	５バイト目	0,A6,A5,A4,A3,A2,A1,A0
	;		S=1 検出　S=0　未検出
	;		B7~B0  	ボードアドレス
	;		Z3~Z0	ゾーン番号
	;		A13~A0	車輌アドレス
	;   ※2桁アドレスの場合　A13,A12,A11,A10,A9,A8,A7　＝1111101 = 7Dh を受信
	;
	;	コマンド受信変数
	;		R_BADRS		EQU 0x40		;受信ボードアドレス
	;		R_ZONE		EQU 0x41		;受信Zone番号)
	;		R_SECT		EQU 0x42		;受信セクション番号
	;		R_ADR1		EQU 0x43		;受信アドレス下位８ビット
	;		R_ADR2		EQU 0x44		;受信アドレス上位８ビット
	;---------------------------------------------------------------

	;1.受信ボードアドレス(上位バイトの上位４～８ビット目と下位バイトの上位２～４ビット目を結合して８ビットにする）
		;上位バイトを３ビット左にシフト							
		movlw	b'00011111'
		andwf	cmd2,f
		rlf		cmd2,f
		bcf		cmd2,0				;キャリーが最下位ビットに１で入るので最下位ビットのみ０にする
		rlf		cmd2,f
		rlf		cmd2,f
		;下位バイトを４ビット右にシフトして上位バイトと結合
		movlw	b'01110000'
		andwf	cmd3,w
		movwf	cmd1
		rrf		cmd1,f
		rrf		cmd1,f
		rrf		cmd1,f
		rrf		cmd1,f
		movf	cmd1,w 
		addwf	cmd2,f
		movf	cmd2,w
		movwf	R_BADRS
		incf	R_BADRS,f			;ボードのアドレスは設定時のアドレスより-1で登録されているので＋１する
	;2.受信ゾーン番号
		;BDL162では０が返る
		movlw	b'00001111'
		andwf	cmd3,w
		movwf	R_ZONE
		incf	R_ZONE,f			;00が ZONE A なので ００は　ZONEチェックしない設定にするため　＋１する
									;ZONE A = 01  ZONE B = 03  ZONE C = 05 というようにする
	;3.受信車両番号
		;2桁アドレスの処理
		movf	cmd4,w		
		sublw	0x7D				;受信したコマンドが7Dhか確認するため7Dhを引いて０かチェック
		btfsc	STATUS,Z			;０かどうか判定
		clrf	cmd4				;０なら（cmd4が7Dhなら）cmd4をクリア
		;cmd4の下1ビットを下位バイトの最上位ビットにコピーして8ビットのデータにする
		movlw	b'00000001'
		andwf	cmd4,w
		movwf	R_ADR1
		rlf		R_ADR1,f
		bcf		R_ADR1,0			;キャリーが最下位ビットに１で入るので最下位ビットのみ０にする
		rlf		R_ADR1,f
		rlf		R_ADR1,f
		rlf		R_ADR1,f
		rlf		R_ADR1,f
		rlf		R_ADR1,f
		rlf		R_ADR1,f
		movf	cmd5,w
		addwf	R_ADR1,f
		;cmd5のビットを右に1ビットローテーﾄする	
		movlw	b'01111110'
		andwf	cmd4,w
		movwf	R_ADR2
		rrf		R_ADR2,f

	;-----------------------------------------------------------------
	;	ボードアドレスのチェック
	;-----------------------------------------------------------------
		movlw	d'0'		
		subwf	BADRS,w				;EEPROMのボードアドレスが０か
		btfsc	STATUS,Z			;０かどうか判定
		goto	b_chkend			;０ならボードアドレスチェックしない
		;EEPROMのボードアドレスが０以外の時は受信したボードアドレスと比較
		movf	BADRS,w		
		subwf	R_BADRS,w			;受信したコマンドとEEPROMのボードアドレスが一致しているか
		btfss	STATUS,Z			;０かどうか判定
		goto	rcv_end				;０以外なら受信処理終了

b_chkend
	;-----------------------------------------------------------------
	;	ゾーンチェック
	;-----------------------------------------------------------------
		movlw	d'0'		
		subwf	ZONE,w				;EEPROMのゾーン番号が０か
		btfsc	STATUS,Z			;０かどうか判定
		goto	z_chkend			;０ならゾーン番号チェックしない
		;EEPROMのゾーン番号が0以外
		movf	ZONE,w		
		subwf	R_ZONE,w			;受信したコマンドとEEPROMのゾーン番号が一致しているか
		btfss	STATUS,Z			;０かどうか判定
		goto	rcv_end				;０以外なら受信処理終了
z_chkend
	;コマンド退避  wcmd -> bcmd
		movf	wcmd1,w
        movwf	bcmd1
		movf	wcmd2,w
        movwf	bcmd2
		movf	wcmd3,w
        movwf	bcmd3
		movf	wcmd4,w
        movwf	bcmd4
		movf	wcmd5,w
        movwf	bcmd5
		movf	wcmd6,w
        movwf	bcmd6
	;-----------------------------------------------------------------
	;　　　チェックＯＫなら　4桁の数値化
	;-----------------------------------------------------------------
		movf	R_ADR2,w		
		movwf	up_byte				;上位バイト
		movf	R_ADR1,w
		movwf	ud_byte				;下位バイト
		call	hextodec
		;hextodecの結果は colm5,colm4,colm3,colm2,colm1に入る

		;４桁目が０の場合はブランクにする（２桁アドレス対応）
		movf	colm4,f
		btfss	STATUS,Z		;０かどうか判定
		goto	set_adr			;
		movlw	d'16'			;16はブランク文字
		movwf	colm4			;4桁目にブランクをセット
set_adr
		;アドレスを　dp4～dp1にセット
		movf	colm4,w
		movwf	dp4
		movf	colm3,w
		movwf	dp3
		movf	colm2,w
		movwf	dp2
		movf	colm1,w
		movwf	dp1
		goto	rcv_end
;*****************************************************************************
;　コマンドＢ２（セクションＯＮ／ＯＦＦ）の処理
;*****************************************************************************
cmd_B2
;----------------------------------------------------------
;   受信データのらcheckSumの確認(cmd1~cmd4 をｘｏｒして　FFｈになるか確認)
;---------------------------------------------------------- 
		movf	cmd1,w
		xorwf	cmd2,w
		xorwf	cmd3,w
		xorwf	cmd4,w
		sublw	0xFF		
		btfss	STATUS,Z	;FFｈかどうか判定
		goto	rcv_end		;不一致の場合
	;--------------------------------------------------------------------
	;●LoconetのBDL168からくるSection　On/Off のコマンド
	; B2 aa bb cc の4バイト
	;		aa  0 A7 A6 A5　 A4 S3 S2 S1
	;  		bb  0  N S0  L  A3 A2 A1 A0 
	;　			n=1 常時１
	;　			L=1 検出 　L=0 未検出
	;			A7～A0　BDL168のアドレス   
	;			S3～S0　セクション番号（0~15）
	;  		ｃｃ  check SUM;	
	;	関連コマンド受信変数
	;		R_BADRS		EQU 0x40		;受信ボードアドレス
	;		R_SECT		EQU 0x42		;受信セクション番号
	;--------------------------------------------------------------------

	;1.受信ボードアドレス(上位バイトの上位５～８ビット目と下位バイトの上位２～５ビット目を結合して８ビットにする）
		;上位バイトを4ビット左にシフト
        movf	cmd3,w
        movwf	R_WK1							
		movlw	b'00001111'
		andwf	R_WK1,f
		rlf		R_WK1,f
		bcf		R_WK1,0				;キャリーが最下位ビットに１で入るので最下位ビットのみ０にする
		rlf		R_WK1,f
		rlf		R_WK1,f
		rlf		R_WK1,f
		;下位バイトを3ビット右にシフトして上位バイトと結合
		movlw	b'01111000'
		andwf	cmd2,w
		movwf	R_WK2
		rrf		R_WK2,f
		rrf		R_WK2,f
		rrf		R_WK2,f
		movf	R_WK2,w 
		addwf	R_WK1,f
		movf	R_WK1,w
		movwf	R_BADRS
		incf	R_BADRS,f			;ボードのアドレスは設定時のアドレスより-1で登録されているので＋１する
	;2.セクション番号（上位バイトの上位６～８ビット目と下位バイトの上位３ビット目を結合して4ビットにする）
		;上位バイトを1ビット左にシフト
        movf	cmd2,w
        movwf	R_WK1
		movlw	b'00000111'
		andwf	R_WK1,f
		rlf		R_WK1,f
		bcf		R_WK1,0				;キャリーが最下位ビットに１で入るので最下位ビットのみ０にする
		;下位バイトを５ビット右にシフトして上位バイトと結合
		movlw	b'00100000'
		andwf	cmd3,w
		movwf	R_WK2
		rrf		R_WK2,f
		rrf		R_WK2,f
		rrf		R_WK2,f
		rrf		R_WK2,f
		rrf		R_WK2,f
		movf	R_WK2,w 
		addwf	R_WK1,f
		movf	R_WK1,w
		movwf	R_SECT
		incf	R_SECT,f			;セクション番号は０から登録されているので＋１する
	;-----------------------------------------------------------------
	;ボードアドレスのチェック
	;-----------------------------------------------------------------
		movlw	d'0'		
		subwf	BADRS,w				;EEPROMのボードアドレスが０か
		btfsc	STATUS,Z			;０かどうか判定
		goto	b_chkend2			;０ならボードアドレスのチェックしない

		;EEPROMのボードアドレスが０以外の時は受信したボードアドレスと比較
		movf	BADRS,w		
		subwf	R_BADRS,w			;受信したコマンドとEEPROMのボードアドレスが一致しているか
		btfss	STATUS,Z			;０かどうか判定
		goto	rcv_end				;０以外なら受処理終了
b_chkend2
	;-----------------------------------------------------------------
	;セクションチェック
	;-----------------------------------------------------------------
		movlw	d'0'		
		subwf	SECT,w				;EEPROMのゾーン番号が０か
		btfsc	STATUS,Z			;０かどうか判定
		goto	s_chkend			;０ならセクション番号のチェックしない
		;EEPROMのセクション番号が0以外
		movf	SECT,w		
		subwf	R_SECT,w			;受信したコマンドとEEPROMのセクション番号が一致しているか
		btfss	STATUS,Z			;０かどうか判定
		goto	tx_seccmd			;０以外ならセクションＯＦＦのコマンド送信
s_chkend
	;-----------------------------------------------------------------
	;コマンドの中でセクションＯＦＦであれば表示値を　初期化
	;-----------------------------------------------------------------
		btfsc	cmd3,4			;０かどうか（セクションＯＮか）判定
		goto	rcv_end			;０なら受処理終了
		movf	DEFNO,w
		movwf	dp4
		movf	DEFNO,w
		movwf	dp3
		movf	DEFNO,w
		movwf	dp2
		movf	DEFNO,w
		movwf	dp1
	;-----------------------------------------------------------------
	;TransPondingコマンド送信（該当のセクションをＯＦＦする場合）
	;-----------------------------------------------------------------
	;	コマンド送信	
		movf	bcmd1,w
		call	loco_tx
		movf	bcmd2,w
		call	loco_tx
		movf	bcmd3,w
		call	loco_tx
		movf	bcmd4,w
		call	loco_tx
		movf	bcmd5,w
		call	loco_tx
		movf	bcmd6,w
		call	loco_tx
		goto	rcv_end
tx_seccmd
	;-----------------------------------------------------------------
	;セクションコマンド（ＯＦＦの場合のみ）送信（該当のセクションでない場合）
	;-----------------------------------------------------------------
		btfsc	cmd3,4			;０かどうか（セクションＯＮか）判定
		goto	rcv_end			;０なら受処理終了
	;	コマンド送信		
		movf	cmd1,w
		call	loco_tx
		movf	cmd2,w
		call	loco_tx
		movf	cmd3,w
		call	loco_tx
		movf	cmd4,w
		call	loco_tx
		goto	rcv_end

;*****************************************************************************
;　コマンドＢＣ(スイッチ選択)の処理
;*****************************************************************************
cmd_BC
	;-------------------------------------------------------------------------
	;	●LoconetからくるSwitch のコマンド
	;　		BC　aa bb cc　　(SWITCHを選択時)
	;			aa  0 A6 A5 A4　 A3  A2 A1 A0
	;  			bb  0  0 S1 S2  A10 A9 A8 A7 
	;　				A7～A0　Switchのアドレス
	;　				s1=0 Thrown 　s1=1 Close	
	;				s2=0　output off   S2=1 output on   
	;  			ｃｃ  check SUM
	;	ここではスイッチ番号を取得するのみ(a6~a0の7ビット０~１２７まで）
	;-------------------------------------------------------------------------
		movf	cmd2,w
		movwf	R_SWNO
		incf	R_SWNO,f			;スイッチ番号は-1で登録されているので＋１する
	;-------------------------------------------------------------------------
	;スイッチ番号判別
		;１：	BDL168のボードアドレス　	（0-255）	０はアドレスチェックしない　実際のボードアドレスは1~254
		;						B _xxx
		;２：	ゾーン番号		　		（Zone A=01 B=03 C=05 D=07 E=09 F=11 G=13 H=15）	
		;						2 __xx										
		;３：	セクション番号　			（1-16）　　　　　０はセクションを無視
		;						5 __xx
		;４：	番線番号　　　			（1-48）	番号と表示文字はプログラム中７セグ文字マッピングに依存
		;						n __xx	
		;５：	ＳＡＶＥ				_ EEpr
		;６：	ＥＮＤ					_ End
	;-------------------------------------------------------------------------

		movf	R_SWNO,w
		sublw	D'1'			;SW1はボードアドレス
		btfsc	STATUS,Z		;０かどうか判定
		goto	dsp_01
			
		movf	R_SWNO,w
		sublw	D'2'			;SW2はゾーン番号
		btfsc	STATUS,Z		;０かどうか判定
		goto	dsp_02

		movf	R_SWNO,w
		sublw	D'3'			;SW3はセクション番号0
		btfsc	STATUS,Z		;０かどうか判定
		goto	dsp_03

		movf	R_SWNO,w
		sublw	D'4'			;SW4は番線番号
		btfsc	STATUS,Z		;０かどうか判定
		goto	dsp_04

		movf	R_SWNO,w
		sublw	D'5'			;SW6はＥＥＰＲＯＭへ保存
		btfsc	STATUS,Z		;０かどうか判定
		goto	dsp_08

		movf	R_SWNO,w
		sublw	D'6'			;SW7は　END
		btfsc	STATUS,Z		;０かどうか判定
		goto	dsp_09
		goto	rcv_end			;ルーチンから抜ける

dsp_01
	;アドレスの表示
		;チェックＯＫなら　4桁の数値化
		movlw	d'0'		
		movwf	up_byte				;上位バイト
		movf	BADRS,w
		movwf	ud_byte				;下位バイト
		call	hextodec
		;アドレスを　dp4～dp1にセット
		movlw	d'10'				;Aを表示
		movwf	dp5
		movlw	d'16'
		movwf	dp4
		movf	colm3,w
		movwf	dp3
		movf	colm2,w
		movwf	dp2
		movf	colm1,w
		movwf	dp1
		goto	rcv_end 
dsp_02
	;ゾーンの表示
		;チェックＯＫなら　4桁の数値化
		movlw	d'0'		
		movwf	up_byte				;上位バイト
		movf	ZONE,w
		movwf	ud_byte				;下位バイト
		call	hextodec
		;ゾーン番号を　dp4～dp1にセット
		movlw	d'2'				;Z を 2　で代用
		movwf	dp5
		movlw	d'16'				;sp
		movwf	dp4
		movlw	d'16'				;sp
		movwf	dp3
		movf	colm2,w
		movwf	dp2
		movf	colm1,w
		movwf	dp1
		goto	rcv_end 
dsp_03
	;セクションの表示
		;チェックＯＫなら　4桁の数値化
		movlw	d'0'		
		movwf	up_byte				;上位バイト
		movf	SECT,w
		movwf	ud_byte				;下位バイト
		call	hextodec
		;セクション番号を　dp4～dp1にセット
		movlw	d'5'				; S を　5　で代用
		movwf	dp5
		movlw	d'16'				;sp
		movwf	dp4
		movlw	d'16'				;sp
		movwf	dp3
		movf	colm2,w
		movwf	dp2
		movf	colm1,w
		movwf	dp1
		goto	rcv_end 
dsp_04
	;番線番号
		;チェックＯＫなら　4桁の数値化
		movlw	d'0'		
		movwf	up_byte				;上位バイト
		movf	TRCNO,w
		movwf	ud_byte				;下位バイト
		call	hextodec
		;番線番号を　dp4～dp1にセット
		movlw	d'24'				;n    
		movwf	dp5
		movf	TRCNO,w				;
		movwf	dp4
		movlw	d'16'				;sp
		movwf	dp3
		movf	colm2,w
		movwf	dp2
		movf	colm1,w
		movwf	dp1
		goto	rcv_end 

dsp_08
	;EEPROMに保存
		;EEPr を　d5～dp1にセット
		movlw	d'16'				;sp    
		movwf	dp5
		movlw	d'14'				;E
		movwf	dp4
		movlw	d'14'				;E
		movwf	dp3
		movlw	d'27'				;P
		movwf	dp2
		movlw	d'32'				;r
		movwf	dp1
		goto	rcv_end 
dsp_09
	; END
		;End を　d5～dp1にセット
		movlw	d'16'				;    
		movwf	dp5
		movlw	d'16'
		movwf	dp4
		movlw	d'14'				;E
		movwf	dp3
		movlw	d'24'				;n
		movwf	dp2
		movlw	d'13'				;d
		movwf	dp1
		goto	rcv_end 

;*****************************************************************************
;　コマンドＢ０の処理(Switch切替コマンド)
;*****************************************************************************
cmd_B0
	;----------------------------------------------
	;	B0　aa bb cc　（ｔ　Or　C　を選択時）
	;		aa  0 A6 A5 A4　 A3  A2 A1 A0
	; 		bb  0  0 S1 S2  A10 A9 A8 A7 
	;　			A7～A0　Switchのアドレス
	;　			s1=0 Thrown 　s1=1 Close
	;			s2=0　output off   S2=1 output on   
	;  		ｃｃ  check SUM;
	;	t,cで設定値をプラスマイナスする  ｃでマイナス　ｔでプラス
	;----------------------------------------------
		btfss	cmd3,4
		goto	rcv_end
		movf	cmd2,w			
		movwf	R_SWNO
		incf	R_SWNO,f		;スイッチ番号は-1で登録されているので＋１する
	;----------------------------------------------------------------------------
	;スイッチ番号判別
		;１：	BDL168のボードアドレス　	（0-255）	０はアドレスチェックしない　実際のボードアドレスは1~254
		;						B _xxx
		;２：	ゾーン番号		　		（Zone A=01 B=03 C=05 D=07 E=09 F=11 G=13 H=15）	
		;						2 __xx										
		;３：	セクション番号　			（1-16）	０はセクションを無視
		;						5 __xx
		;４：	番線番号　　　			（1-48）	番号と表示文字はプログラム中７セグ文字マッピングに依存
		;						n __xx	
		;５：	ＳＡＶＥ				_ EEpr  --> o EEpr
		;６：	ＥＮＤ					_  End	--> P  oFF
	;----------------------------------------------------------------------------
		movf	R_SWNO,w
		sublw	D'1'			;ボードアドレス
		btfsc	STATUS,Z		;０かどうか判定
		goto	dspc_01
			
		movf	R_SWNO,w
		sublw	D'2'			;ゾーン番号
		btfsc	STATUS,Z		;０かどうか判定
		goto	dspc_02

		movf	R_SWNO,w
		sublw	D'3'			;セクション番号0
		btfsc	STATUS,Z		;０かどうか判定
		goto	dspc_03

		movf	R_SWNO,w
		sublw	D'4'			;番線番号
		btfsc	STATUS,Z		;０かどうか判定
		goto	dspc_04

		movf	R_SWNO,w
		sublw	D'5'			;ＥＥＰＲＯＭへ保存
		btfsc	STATUS,Z		;０かどうか判定
		goto	dspc_08

		movf	R_SWNO,w
		sublw	D'6'			;END
		btfsc	STATUS,Z		;０かどうか判定
		goto	dspc_09
		goto	rcv_end			;ルーチンから抜ける

	;--------------------------------------------
	;アドレスの表示
	;--------------------------------------------
dspc_01

		btfsc	cmd3,5			;５ビット目でtかｃが押されたか判別　　０がｔ　１がｃ
		goto	dspc_011		;c(-)が押された
		incf	BADRS,f			;t(+)が押された
		goto	dspc_012
dspc_011
		decf	BADRS,f
dspc_012
		;4桁の数値化
		movlw	d'0'		
		movwf	up_byte			;上位バイト
		movf	BADRS,w
		movwf	ud_byte			;下位バイト
		call	hextodec
		;アドレスを　dp4～dp1にセット
		movlw	d'10'			;Aを表示
		movwf	dp5
		movlw	d'16'
		movwf	dp4
		movf	colm3,w
		movwf	dp3
		movf	colm2,w
		movwf	dp2
		movf	colm1,w
		movwf	dp1
		goto	rcv_end 

	;--------------------------------------------
	;ゾーンの表示 0>1>3>5>7>9>11>13>15 の規則で表示
	;--------------------------------------------
dspc_02

		btfsc	cmd3,5			;５ビット目でtかｃが押されたか判別　　０がｔ　１がｃ
		goto	dspc_022		;c(-)が押された
		nop						;t(+)が押された
		movlw	d'0'		
		subwf	ZONE,w			;EEPROMのゾーン番号が０か
		btfsc	STATUS,Z		;０かどうか判定
		goto	dspc_021		;=0
		movlw	d'15'		
		subwf	ZONE,w			;EEPROMのゾーン番号が15か
		btfsc	STATUS,Z		;０かどうか判定
		goto	dspc_025		;=0
		incf	ZONE,f			;+1

dspc_021
		incf	ZONE,f			;+1
		goto	dspc_024
dspc_025
		movlw	d'0'			;１５の場合は次の値を０にする
  		movwf	ZONE
		goto	dspc_024
dspc_022
		movlw	d'0'		
		subwf	ZONE,w			;EEPROMのゾーン番号が０か
		btfsc	STATUS,Z		;０かどうか判定
		goto	dspc_026		;=0
		movlw	d'1'		
		subwf	ZONE,w			;EEPROMのゾーン番号が15か
		btfsc	STATUS,Z		;０かどうか判定
		goto	dspc_023		;=0
		decf	ZONE,f			;-1
dspc_023
		decf	ZONE,f			;-1
		goto	dspc_024
dspc_026
		movlw	d'15'			;0の場合は次の値を15にする
  		movwf	ZONE
		goto 	dspc_024
dspc_024
		;4桁の数値化
		movlw	d'0'		
		movwf	up_byte			;上位バイト
		movf	ZONE,w
		movwf	ud_byte			;下位バイト
		call	hextodec
		;ゾーン番号を　dp4～dp1にセット
		movlw	d'2'			;Z を 2　で代用
		movwf	dp5
		movlw	d'16'			;sp
		movwf	dp4
		movlw	d'16'			;sp
		movwf	dp3
		movf	colm2,w
		movwf	dp2
		movf	colm1,w
		movwf	dp1
		goto	rcv_end 

	;--------------------------------------------
	;セクションの表示
	;--------------------------------------------
dspc_03
		btfsc	cmd3,5			;５ビット目でtかｃが押されたか判別　　０がｔ　１がｃ
		goto	dspc_032		;c(-)が押された
		nop						;t(+)が押された
		movlw	d'16'		
		subwf	SECT,w			;EEPROMのゾーン番号が16か
		btfsc	STATUS,Z		;０かどうか判定
		goto	dspc_035		;=0
dspc_031
		incf	SECT,f			;+1
		goto	dspc_034
dspc_035
		movlw	d'0'			;１６の場合は次の値を０にする
  		movwf	SECT
		goto	dspc_034
dspc_032
		movlw	d'0'		
		subwf	SECT,w			;EEPROMのゾーン番号が０か
		btfsc	STATUS,Z		;０かどうか判定
		goto	dspc_036		;=0
		nop						;<>0
dspc_033
		decf	SECT,f			;-1
		goto	dspc_034
dspc_036
		movlw	d'16'			;0の場合は次の値を16にする
  		movwf	SECT
		goto 	dspc_034
dspc_034
		;4桁の数値化
		movlw	d'0'		
		movwf	up_byte			;上位バイト
		movf	SECT,w
		movwf	ud_byte			;下位バイト
		call	hextodec
		;ゾーン番号を　dp4～dp1にセット
		movlw	d'2'			;Z を 2　で代用
		movwf	dp5
		movlw	d'16'			;sp
		movwf	dp4
		movlw	d'16'			;sp
		movwf	dp3
		movf	colm2,w
		movwf	dp2
		movf	colm1,w
		movwf	dp1
		goto	rcv_end 
	;--------------------------------------------
	;番線番号
	;--------------------------------------------
dspc_04
		btfsc	cmd3,5			;５ビット目でtかｃが押されたか判別　　０がｔ　１がｃ
		goto	dspc_042		;c(-)が押された
		nop						;t(+)が押された
		movlw	d'47'		
		subwf	TRCNO,w			;EEPROMのゾーン番号が47か
		btfsc	STATUS,Z		;０かどうか判定
		goto	dspc_045		;=0
dspc_041
		incf	TRCNO,f			;+1
		goto	dspc_044
dspc_045
		movlw	d'0'			;１６の場合は次の値を０にする
  		movwf	TRCNO
		goto	dspc_044
dspc_042
		movlw	d'0'		
		subwf	TRCNO,w			;EEPROMのゾーン番号が０か
		btfsc	STATUS,Z		;０かどうか判定
		goto	dspc_046		;=0
		nop						;<>0
dspc_043
		decf	TRCNO,f			;-1
		goto	dspc_044
dspc_046
		movlw	d'47'			;0の場合は次の値を47にする
  		movwf	TRCNO
		goto 	dspc_044
dspc_044
		;4桁の数値化
		movlw	d'0'		
		movwf	up_byte			;上位バイト
		movf	TRCNO,w
		movwf	ud_byte			;下位バイト
		call	hextodec
		;ゾーン番号を　dp4～dp1にセット
		movlw	d'24'			;n
		movwf	dp5
		movf	TRCNO,w			;表示文字
		movwf	dp4
		movlw	d'16'			;sp
		movwf	dp3
		movf	colm2,w
		movwf	dp2
		movf	colm1,w
		movwf	dp1
		goto	rcv_end 
	;--------------------------------------------
	;EEPROMに保存  tが押されたらセーブ
	;--------------------------------------------
dspc_08
		btfsc	cmd3,5			;５ビット目でtかｃが押されたか判別　　０がｔ　１がｃ
		goto	rcv_end			;c(-)が押された
		nop						;t(+)が押された
		;BDL168ボードアドレス
		movlw	0x00
		movwf	ADDR
		movf	BADRS,w	
		movwf	EE_DAT	
		call	eeprom_w	
		;BDL168ゾーン番号
		movlw	0x01
		movwf	ADDR		
		movf	ZONE,w
		movwf	EE_DAT	
		call	eeprom_w	
		;BDL168セクション番号
		movlw	0x02
		movwf	ADDR		
		movf	SECT,w
		movwf	EE_DAT	
		call	eeprom_w	
		;表示番線番号
		movlw	0x03
		movwf	ADDR
		movf	TRCNO,w	
		movwf	EE_DAT	
		call	eeprom_w

		;EEPr を　d5～dp1にセット
		movlw	d'25'			;o  書き込み終了のまる
		movwf	dp5
		movlw	d'14'			;E
		movwf	dp4
		movlw	d'14'			;E
		movwf	dp3
		movlw	d'27'			;P
		movwf	dp2
		movlw	d'32'			;r
		movwf	dp1
		goto	rcv_end 

	;--------------------------------------------
	; END
	;--------------------------------------------
dspc_09
		btfsc	cmd3,5			;５ビット目でtかｃが押されたか判別　　０がｔ　１がｃ
		goto	rcv_end			;c(-)が押された
		nop						;t(+)が押された
		movlw	d'27'			;P 　PowerOFFの意味で　P oFF
		movwf	dp5
		movlw	d'16'			;sp
		movwf	dp4
		movlw	d'25'			;o
		movwf	dp3
		movlw	d'15'			;F
		movwf	dp2
		movlw	d'15'			;F
		movwf	dp1
dspc_091
; 		セットアップモードを解除
		movlw	d'0'
		movwf	S_MODE
		goto	rcv_end 


;*****************************************************************************
;　コマンド処理終了によるフラグのクリア
;*****************************************************************************
rcv_end
		movlw	d'0'		;D0受信フラグ＝0にセット
		movwf	flg_d0		;D0受信フラグ（flg_d0）に0セット
		bcf		PORTC,5		;LED off
		RETURN


;*****************************************************************************
;２バイト（１６ビット）の値を５桁の１０進数値に変換する(0～65535)
;*****************************************************************************
;引き数は up_byte(上位),ud_byte(下位) の２バイト
;結果は colm5,colm4,colm3,colm2,colm1 右の colm1 が下位の数になる。
;※結果の戻り値は変数2Bh~2Fhまでを間接アドレッシングで使用
;使用例
;		movlw	0ffh		;２バイトffffh=65535
;		movwf	up_byte
;		movlw	0ffh
;		movwf	ud_byte
;		call	hextodec
;-----------------------------------------------
hextodec
		movlw	srlc1		;格納場所初期値
		movwf	FSR			;4h=fsr
		call	convert		;最下位変換
		call	convert
		call	convert
		call	convert
		call	convert		;最上位変換
		return
convert						;÷１０サブルーチン　（１０で除算）
		movlw	d'16'		;１６ビットくり返し
		movwf	srlc1
		clrf	srwk1
convert1
		bcf		STATUS,0	;キャリフラグのクリア
		rlf		ud_byte,1
		rlf		up_byte,1
		rlf		srwk1,1
		movlw	b'11110110'
		addwf	srwk1,0
		btfsc	STATUS,0
		movwf	srwk1
		btfsc	STATUS,0
		incf	ud_byte,1
		decfsz	srlc1,1
		goto	convert1
		decf	FSR,1		;4h=fsr
		movf	srwk1,0
		movwf	0h			;余り (0h=indirect)
		return

;*****************************************************************************
;ＥＥＰＲＯＭ読み書きルーチン
;*****************************************************************************
eeprom_r
	;EEPROM 読み出し
		BANK2
		movf 	ADDR,w			;呼び出すアドレス1セット
		movwf 	EEADR 			;EEADR(10Dh) アドレス呼び出し
        BANK3
		bcf		EECON1,EEPGD	;Point to Data memory
		bsf 	EECON1,RD		;EE Read(18Ch) readに設定 
		BANK2
		movf 	EEDATA,w 		;EEDATA(10Ch) 呼び出しデータをワークレジスタにセット:;
		BANK0
		return
eeprom_w
 	;EEPROMへの書き込み
		BANK2  
		movf	ADDR,w 			;EEPROMのアドレス指定  
		movwf	EEADR			;アドレスをEEADRへセット  
		movf 	EE_DAT,w		;内容をワークレジスタにセット  
		movwf 	EEDATA			;EEDATAにセット  
		BANK3
		bcf		EECON1,EEPGD	;Point to Data memory
		bsf 	EECON1,WREN 	;EEPROM書き込み許可  
		bcf		INTCON,GIE		;割り込み禁止
 		movlw	0x55 		  
		movwf	EECON2 	  
 		movlw	0xAA  
 		movwf	EECON2  
 		bsf		EECON1,WR 		;EEPROM書き込み開始
		bcf		EECON1,WREN 	;EEPROM書き込み禁止  
		bsf		INTCON,GIE		;割り込み許可
wr_wait    
 		btfsc 	EECON1,WR 		;EEPROM書き込み完了確認
 		goto 	wr_wait  
		BANK0
        return

;*****************************************************************************
;時間遅延ルーチン クロック20MHz用
;*****************************************************************************
	;---------------------------------
	; 60マイクロ秒遅延
	; 1/16600bps　=　60.24μｓ　=60μｓ
	;---------------------------------
dly_60u	; 60uS
		movlw	d'60'
		movwf	cnt1
dly_60u1
		nop
		nop
		nop
		nop
		decfsz	cnt1,f
		goto	dly_60u1
		return
	;---------------------------------
	; 100マイクロ秒遅延
	;---------------------------------
dly_100u	; 100uS
		movlw	d'100'
		movwf	cnt2
dly_100u1
		nop
		nop
		nop
		nop
		decfsz	cnt2,f
		goto	dly_100u1
		return
	;---------------------------------
	; 600マイクロ秒遅延
	;---------------------------------
dly_600u	; 600uS
		movlw	d'6'
		movwf	cnt1
dly_600u1
		call 	dly_100u
		decfsz	cnt1,f
		goto	dly_600u1
		return
	;---------------------------------
	; nミリ秒遅延
	;call 前にワークにループ数をセット
	;例：movlw		d'10'
;---------------------------------
dly_Nm	; NmS
		movwf	cnt1
dly_Nm1
		call	dly_1m
		decfsz	cnt1,f
		goto	dly_Nm1
		return
	;---------------------------------
	; 1ミリ秒遅延
	;---------------------------------
dly_1m	; 1ms
		movlw		d'4'
		movwf		cnt2
dly_1m1	
		movlw		d'250'
		movwf		cnt3
dly_1m2	; 250us
		nop
		nop
		nop
		nop
		decfsz		cnt3,f
		goto		dly_1m2
		decfsz		cnt2,f
		goto		dly_1m1
		return
;**********************************
; 送信ルーチン
; 送信バッファにデータをセット
; ワークレジスタに値をセットしてｃａｌｌ
;**********************************
loco_tx
		movwf	wk_data			;
		BANK1
loop_tx
		btfss	TXSTA,TRMT		;ステータスチェック
		goto	loop_tx
;
		BANK0
		movf	wk_data,W		;送信データをワークレジスタにセット
		movwf	TXREG			;送信・・・ビット単位の出力は、この先PICにおまかせ・・・・
		return
;*****************************************************************************
;７セグデータの取り出し
;*****************************************************************************
;C_CNT	文字番号(00h～2fh）
;上位バイト１ビット（ＭＳＢ）は未使用
;テーブルは0x380の位置に記述してプログラムが不意な暴走しないようにする
		org 0x480
setchr
 	;数字の1列分のデータを取り出し
		movlw	H'04'
		movwf	PCLATH
		movf 	C_CNT,w
		addwf	PCL,F
	;7セグＢＣＤ値
		retlw	B'00111111'		;0
		retlw	B'00000110'		;1
		retlw	B'01011011'		;2
		retlw	B'01001111'		;3
		retlw	B'01100110'		;4
		retlw	B'01101101'		;5
		retlw	B'01111101'		;6
		retlw	B'00100111'		;7
		retlw	B'01111111'		;8
		retlw	B'01101111'		;9
		retlw	B'01110111'		;A
		retlw	B'01111100'		;b
		retlw	B'00111001'		;C
		retlw	B'01011110'		;d
		retlw	B'01111001'		;E
		retlw	B'01110001'		;F
	;1x
		retlw	B'00000000'		;(Blank)	16
		retlw	B'01000000'		;- (ハイフン)	17
		retlw	B'00001000'		;_ (アンダー)	18
		retlw	B'00000001'		;- (アッパー)	19
		retlw	B'01110110'		;H			20
		retlw	B'01110100'		;h			21
		retlw	B'00011110'		;J			22
		retlw	B'00111000'		;L			23
		retlw	B'01010100'		;n			24
		retlw	B'01011100'		;o(下)		25
		retlw	B'01100011'		;o(上)		26
		retlw	B'01110011'		;P			27
		retlw	B'00111110'		;U			28
		retlw	B'01101110'		;y			29
		retlw	B'00110110'		;||			30
		retlw	B'00110001'		;「			31
	;2x
		retlw	B'01010000'		;ｒ			32
		retlw	B'00000001'		; a セグ		33
		retlw	B'00000010'		; b	セグ		34
		retlw	B'00000100'		; c セグ		35
		retlw	B'00001000'     ; d セグ		36
		retlw	B'00010000'     ; e セグ		37
		retlw	B'00100000'     ;　f セグ		38
		retlw	B'01000000'		; g セグ		39
		retlw	B'01001001'		;a,d,g セグ	40
		retlw	B'00001001'		;a,d セグ		41
		retlw	B'00010010'		;b,e セグ		42
		retlw	B'00100100'		;c,f セグ		43
		retlw	B'01010010'		;b,e,g		44
		retlw	B'01100100'		;c,f,g		45
		retlw	B'01101011'		;abdfg		46
		retlw	B'01011101'		;acdeg		47


	END