
;****************************************************************************
;　　リモート操作装置のPIC_16F84ソフト　　　特製Linux本体装置専用　 2005/10/01
;  							
;  RS232C経由　双方向シリアル通信　9600bps, non_parity, 8bits_data, 1stop_bit 
;  Timer0 interrupt採用、RTS&CTS不使用　http://www.picfun.com/equipj30.htmlより引用
; 
;  受信データの20文字4行ＬＣＤ表示、ボタンのほかロータリエンコーダ状態の送信　　
;  
;  If you use this modules, you must check RECV flag for waiting
;  received data in main routine.
;  
;  The status register "RESULT"'s bits are explained below.
;     BIT0 : TXBUSY  (1 is tarnsimission in progress)
;     BIT1 : unused
;     BIT2 : RXBUSY  (1 indicates in receive process)
;     BIT3 : RECV    (1 indicates there are received data)
;     BIT4 : ERROR   (1 indicates any error)
;  The flag of "BUSY" is send/receive busy flag,check before use.
;
;
;    PORTA RA0,2   LCD 制御出力   0:E  2:RS（R/Wはロー固定、書き込み専用に)
;	   RA1	   LED点灯表示出力
;          RA3 :  シリアル送信出力
;          RA4 :  シリアル受信入力
;    PORTB RB0-3  LCD_DATA出力（常時）／ボタン入力（必要時だけ切り替える）
;	   RB4-7  ロータリエンコーダ入力（ビット7,6使用　5,4－将来拡張用）
;
;　　REリードではチャタリング対処　　ステイタス送信は　20h～7FhのASCII文字コード範囲内に
;	チャタ除去処理付でミリ秒サイクルで常時監視し積算データを保持　
;	その時点での積算値を　20h～7FhというASCII文字コード範囲内の
;	96のコードの循環データ値での応答としました
;	(RE使用のLinux側応用テストプログラムでの実績の結果　この形にした
;	１．16進データでは循環量不足だった　
;	２．生のバイトデータでは　制御コードで問題発生　　ということでした)
;
;
; 　　　　　　　　　　　　　　　　　　　　MPASMにてアセンブルのこと
;*****************************************************************
;
  
		LIST		P=PIC16F84
		INCLUDE		"P16F84.INC"

	__CONFIG _HS_OSC & _PWRTE_ON & _WDT_OFF 
;========================================================
;*************************************
;  Define constant module
;*************************************
#DEFINE		TXBUSY		RESULT,0	;sending
#DEFINE		RXBUSY		RESULT,2	;receiving
#DEFINE		RECV		RESULT,3	;receive end
#DEFINE		ERROR		RESULT,4	;error bit

;****  Define Variables  ***** 
RESULT		EQU		0CH		;current status
WREG		EQU		0DH		;wreg save area
SREG		EQU		0EH		;status reg save area
BITCNT		EQU		0FH		;send bit counter
EXTRA		EQU		10H		;stop bit flag
TXREG		EQU		11H		;send data buffer
RXREG		EQU		12H		;receive data buffer
RXREG_1		EQU		13H		;追加バッファ
CNT2_I		EQU		14H		;Timer counter for 10us for INTRPTprocess
CNT2		EQU		15H		;Timer counter for 10us

;***** for LCD variables ****
DPDT		EQU		16H		;buffer for display data
CNT1		EQU		17H		;Timer counter for 100us
CNT3            EQU             18H		;Timer counter for 1ms
CNT4		EQU		19H		;Timer counter for 5ms		

POS		EQU		0x20
POS_SAVE	EQU		0x21		


;**** ROTARY ENCODER ***********
ROTARY		EQU 		0x22	;読み取り値(前後）バッファ
ROTARY_DATA	EQU 		0x23	;累算結果
TEMP		EQU		0x24	;チャタ対策用temp
CNT_re		EQU		0x25	;チャタ対策用ms_Delay_Counter

;**** EEPROM DATA				;取りあえずです　<-PENDING
E_ADRS		EQU		0x26
E_DATA		EQU		0x27

		ORG		02100H
		DE		02AH, 01H, 03FH, 0
		DE		"Hello!", 0


;*************************************
;  Jump vector
;*************************************
		ORG		0		;reset
		GOTO		START
		ORG		4 		;Interrupt
		GOTO		INTERRUPT

		ORG		08H		;code
;********************************************************
; rotary encoder data read	
;　　　　　REリードではチャタリング対処　　ステイタス送信は　20h～7FhのASCII文字コード範囲内に
;********************************************************
ROTARY_READ_P0
		MOVF	PORTB,W			;
		ANDLW	B'11000000'		;　Bit 7,6
		XORWF	TEMP,F			;ここでのZフラグ
		MOVWF	TEMP			;movwfはｚフラグに影響与えない
		BTFSS	STATUS,Z		;ここで使用　TEMPと同じ?
		RETURN			;初回の変化　チャタ対策で戻す　TEMPにはホールド
						;（ミリ秒近くのwaitを期待）
			MOVF	TEMP,W		;ここで　2度読み変化無し持続のBit 7,6を採用
			IORWF	ROTARY,F		;
			SWAPF	ROTARY,W		;Bit 7-4に保持されている
			ANDLW	B'00001111'		;　Bit 7,6
			ADDWF	PCL,F			;
L_ROTARY		GOTO	NORMAL			; 0000
			GOTO	NORMAL			; 0001 UP
			GOTO	NORMAL			; 0010 DOWN
			GOTO	NORMAL			; 0011
			GOTO	NORMAL			; 0100 DOWN
			GOTO	NORMAL			; 0101
			GOTO	NORMAL			; 0110
			GOTO	NORMAL			; 0111 UP
			GOTO	NORMAL			; 1000 UP
			GOTO	NORMAL			; 1001
			GOTO	NORMAL			; 1010
			GOTO	NORMAL			; 1011 DOWN
			GOTO	NORMAL			; 1100
			GOTO	DOWN			; 1101
			GOTO	UP			; 1110
L_ROTARY_END		GOTO	NORMAL			; 1111
L_ROTARY_B						;
	IF (HIGH(L_ROTARY)!=HIGH(L_ROTARY_B-1))		;
		ERROR "L_ROTARYテーブルエラー" 		;
	ENDIF						;
							;
							;
			;--------------------------------
			; rotary encoder up mode   - 7FH
			;--------------------------------
UP			MOVLW	1			;
			ADDWF	ROTARY_DATA,F		;
		MOVF	ROTARY_DATA,W	; <- データを　持って来て　80H以上か吟味
		SUBLW	7FH		;kk-wreg -> wreg  結果 0,posのとき Cが1です　注意！！
		BTFSC	STATUS,C	;80h以上だと(C立たず)スキップですね　
		GOTO	ROTARY_READ_P0_OK	;
		MOVLW 20H
		MOVWF	ROTARY_DATA	;ROTARY_DATAを20Hに更新
			GOTO	ROTARY_READ_P0_OK	;
							;
			;--------------------------------
			; rotary encoder down mode  20H -
			;--------------------------------
DOWN			MOVLW	-1			;
			ADDWF	ROTARY_DATA,F		;
		MOVF	ROTARY_DATA,W	; <- データを　持って来て　1FH以下か吟味
		SUBLW	1FH		;kk-wreg -> wreg  結果 0,posのとき Cが1です　注意！！
		BTFSS	STATUS,C	;1FH以下だと(C立ち)スキップですね　
		GOTO	ROTARY_READ_P0_OK	;
		MOVLW 7FH
		MOVWF	ROTARY_DATA	;ROTARY_DATAを7FHに更新
			
			
			GOTO	ROTARY_READ_P0_OK	;
							;
			;--------------------------------
			; rotary encoder not moveing
			;--------------------------------
NORMAL			NOP				;
							;
ROTARY_READ_P0_OK
			RRF	ROTARY,F		; ->
			RRF	ROTARY,F		; ->
			MOVLW	B'00110000'		;
			ANDWF	ROTARY,F		;
			RETURN				;

;********************************************************
; binary to ascii routine			下位４ＢＩＴのHex変換
;********************************************************
BIN_2_ASC		ANDLW	0x0F			;
			ADDWF	PCL,F			;
BIN_2_ASC_TBL		RETLW	'0'			;
			RETLW	'1'			;
			RETLW	'2'			;
			RETLW	'3'			;
			RETLW	'4'			;
			RETLW	'5'			;
			RETLW	'6'			;
			RETLW	'7'			;
			RETLW	'8'			;
			RETLW	'9'			;
			RETLW	'A'			;
			RETLW	'B'			;
			RETLW	'C'			;
			RETLW	'D'			;
			RETLW	'E'			;
BIN_2_ASC_END		RETLW	'F'			;
BIN_2_ASC_T_B						;
	IF (HIGH(BIN_2_ASC_TBL)!=HIGH(BIN_2_ASC_T_B-1))	;
		ERROR "BIN_2_ASC_TBLテーブルエラー" 	;
	ENDIF						;							;
							;
;********************************************************
CONTROL_CODE	MOVF		RXREG_1,W		;get received data		
			;このあと制御文字分岐処理   <-

			ADDWF	PCL,F			;
JUMP_TABLE		GOTO	DISP_clr	;0x0	^@  ヌル　画面クリア、カーソルホーム	
			GOTO	POS_1		;0x1	^a　LCD1行目頭へ　POS保存 
	;引き続きの\オクタルデータ指定あればその位置へ  
	;無ければ行頭(ただし次は必ず文字であること) 位置データは文字とは重ならない
			GOTO	POS_2		;0x2	^b　LCD2行目頭へ　POS保存　
			GOTO	POS_3		;0x3	^c　LCD3行目頭へ　POS保存
			GOTO	POS_4		;0x4	^d　LCD4行目頭へ　POS保存
			GOTO	POS_RSTR	;0x5	^e  POSコール以前の位置に戻す
			GOTO	DISP_TEST		;6	^f
			GOTO	DISP_TEST		;7	^g  ベル
			GOTO	DISP_BS		;8 BS,\b ^h　バックスペース（行頭判断し行替え処理もします）
			GOTO	DISP_ht		;9 HT,\t ^i　タブ
			GOTO	DISP_CR		;A LF,\n ^j　\rと同じ処理に(行頭では改行せず)
			GOTO	DISP_TEST		;B VT,\v ^k
			GOTO	POS_1	;とりあえず	;C FF,\f ^l　カーソル位置設定
			GOTO	DISP_CR		;0x0D CR,\r ^m　改行・行末まで空白埋め
						;行頭では（4行と限られたエリアなので）改行せず SP+改行で一行空白になる
			GOTO	DISP_TEST		;E SO 	^n
			GOTO	DISP_TEST		;F SI 	^o　eepromから64バイト読み取り
			GOTO	LED_ON		;10	^p　LED　on
			GOTO	LED_OFF		;11	^q　LED　off
			GOTO	DISP_TESTr	;12	^r　ロータリエンコーダの操作状況データの応答をします
				;	チャタ除去処理付でミリ秒サイクルで常時監視し積算データを保持　
				;	その時点での積算値を　20h～7FhというASCII文字コード範囲内の
				;	96のコードの循環データ値での応答としました
				;	(RE使用のLinux側応用テストプログラムでの実績の結果　この形にした
				;	１．16進データでは循環量不足だった　
				;	２．生のバイトデータでは　制御コードで問題発生　　ということでした)
				;
			GOTO	DISP_TESTs	;13	^s　ボタンSW読み取り用　4つのボタンが下位4ビットに対応していて
				;	40hを加算し文字化した応答です　4つのボタン全てopenで "O"(4Fh)
				;	押された位置がlowの文字G,K,M,Nなどです
				;	連続押しで困る場合は　一度開放されるのを待つ処理などで、　
				;	同時押し判定は時間差を配慮し数回のコールなどして対処のこと　
				;　　
			GOTO	DISP_TEST		;14	^t
			GOTO	DISP_TEST		;15	^u
			GOTO	DISP_TEST		;16	^v
			GOTO	DISP_TEST		;17	^w
			GOTO	DISP_TEST		;18	^x
			GOTO	DISP_TEST		;19	^y
			GOTO	DISP_TEST		;1A	^z
			GOTO	DISP_TEST		;1B	^[
			GOTO	CMD2LCD		;0x1C ^\   LCDへの直接制御　（使用には注意が必要です）
				;	引き続きの受信データまでも必要とする特別なコードです
				;	Linux本体側のプログラムで　LCDモジュールの機能を制御、
				;	例えば　^\^aで表示クリア、^\^b or ^cでカーソルホーム
				;	^\^lでブリンクオフ、^\^mでブリンクオン　など行えます
				;	CGRAMアドレス設定のあとフォントパターンデータのセット
				;	し　自作のキャラクタも出せます　しかし　0x20～3fなどは
				;	LCDの動作モードの設定といった機能設定ですので　問題を
				;	起こします　また　使用後は初期設定に戻すことが肝要です
				;	LCDモジュールの仕様書を詳しく調べながら使用するように	
			GOTO	DISP_TEST		;1D	^]
			GOTO	DISP_TEST		;1E	^^
			GOTO	DISP_TEST		;1F	^_
;********************************************************
; Fill Blank_CHR routine			CR時の行末までの空白埋め
;********************************************************
FILL_BLANK		SUBLW	0x00		;行頭でzero、一文字目が-1、n文字目が-nで
						;callされますので　kk -W -> W を利用し符号反転
			ADDWF	PCL,F		;
			CALL	CHR_FILL	;20個sp埋め　0では跳んでこないが　一般化
			CALL	CHR_FILL		;19　
			CALL	CHR_FILL		;18
			CALL	CHR_FILL		;17
			CALL	CHR_FILL		;16
			CALL	CHR_FILL		;15
			CALL	CHR_FILL		;14
			CALL	CHR_FILL		;13
			CALL	CHR_FILL		;12
			CALL	CHR_FILL		;11
			CALL	CHR_FILL		;10
			CALL	CHR_FILL		;9
			CALL	CHR_FILL		;8
			CALL	CHR_FILL		;7
			CALL	CHR_FILL		;6
			CALL	CHR_FILL		;5
			CALL	CHR_FILL		;4
			CALL	CHR_FILL		;3
			CALL	CHR_FILL		;2
			CALL	CHR_FILL		;1
			RETURN				;0
CHR_FILL		MOVLW	" "			;SPACE
			CALL	LCD_DATA
			INCF	POS,F
			RETURN
;*************************************
;  Initialise process
;*************************************

START		BCF		INTCON,T0IE	;TMR0 interrupt disable
		BCF		INTCON,GIE	;Interrupt disable
		CLRF		RESULT		;Reset status
		CALL		PORT_INI	;Initialise
		CALL 		LCD_INI		;Reset LCD
		MOVLW 20H
		MOVWF	ROTARY_DATA	;ROTARY_DATAを20Hに
;*************************************
;  Main loop for waiting any event
;*************************************
MAIN
		CALL		LCD_CLR		;clear display

	;初期化チェック済み表示
		MOVLW		"O"
		CALL		LCD_DATA	;display O
		MOVLW		"K"
		CALL		LCD_DATA	;display K
		MOVLW		" "
		CALL		LCD_DATA	;display SPACE
	;初期化チェック済み表示<-ここまで

		MOVLW		0x80		;POSの初期化
		MOVWF		POS
		CALL		LCD_CMD		;

		BSF		INTCON,GIE	;permit interrupt
;****  ボタンチェックと　受信データ有無 の　チェックループ
EVENT		CALL		GETCHAR		;受信許可　(受信完でRECVflag->0、RXREG_1にデータ)

RCVWAIT		CALL		ROTARY_READ_P0	;RE　チャタ対策で2度読み式
						;ms近くの間隔で　コールする
		MOVLW		0xFF		; チャタ対策用ms_細かくし回数増し	
		MOVWF		CNT_re		; Delay_Counterカウンタ廻し	
T_LP_re		BTFSS		RECV		;受信データ の　有無チェックしながら
		GOTO		RECVed		;(受信したときはwait時間変わる　いいね？)
		NOP
		NOP		
		NOP
		NOP		
		DECFSZ		CNT_re,F	;2+8*255-1=2000 (*0.4=0.8ms)		
		GOTO		T_LP_re		;のRE読み出しのループ		
		GOTO		RCVWAIT	
;****	LOOP抜けた　				　
RECVed		BTFSC	ERROR		;error check
		GOTO	ERR
		MOVF	RXREG_1,W	; <- 追加バッファからにしました
		SUBLW	01FH		;kk-wreg -> wreg  結果 0,posのとき Cが1です　注意！！
		BTFSC	STATUS,C	;ＳＰや文字だと(C立たず)スキップですね　
		GOTO	CONTROL_CODE	;0x00～0x1f　を制御コード扱いで
					;　分析(計算ジャンプ)テーブルへ
		MOVF	RXREG_1,W	;文字ですね <- 追加バッファからにしました
		CALL	SR_W2LCD	;文字なら　すぐLCD表示しましょう　
					;20文字超えると自動改行してくれます
		GOTO	EVENT		;そして　次の受信待ちループへ戻る

;******* 0x1C ^\  LCDへの直接制御　（使用には注意が必要です）
;			引き続きの受信データまでも必要とする特別なコードです
CMD2LCD		CALL		GETCHAR		;受信許可　(受信完でRECVflag->0、RXREG_1にデータ)
RCVWAIT_CMD					;待ちの間　どうする？　特別なので何もしない
		BTFSC		RECV		;
		GOTO		RCVWAIT_CMD	; 
		BTFSC	ERROR		;error check
		GOTO	ERR
		MOVF	RXREG_1,W	; 
		CALL	LCD_CMD		;引き続きの受信データをLCDへCMDとして渡します
		GOTO	EVENT
 
;******* 文字表示・位置データ更新　　自動改行　のSRです　　Wに文字コードをsetしてあること
SR_W2LCD	CALL		LCD_DATA	;文字は　LCD表示へ 
		INCF		POS,F		;文字位置データ　カウントアップ 
		MOVF		POS,W		;文字位置データの分析、処理
		SUBLW		0x94		;　　
		BTFSC		STATUS,Z
		GOTO		SR_POS_2		;1行目超えた 改行必要
		MOVF		POS,W		;文字位置データ
		SUBLW		0xD4	;　　
		BTFSC		STATUS,Z
		GOTO		SR_POS_3		;2行目超えた
		MOVF		POS,W		;文字位置データ
		SUBLW		0xA8		;改行必要？　の条件処理　　
		BTFSC		STATUS,Z
		GOTO		SR_POS_4		;3行目超えた
		MOVF		POS,W		;文字位置データ
		SUBLW		0xE8		;改行必要？　の条件処理　　
		BTFSC		STATUS,Z
		GOTO		SR_POS_1		;4行目超えた
		RETURN				;超えなかった
	
;******* 文字位置データ更新SR　＆　行末まで空白文字埋め・改行SR
;				SR_FILL_BLANKへは　Wに行末までの文字数をsetしてあること
;				行頭でzero、一文字目が-1、n文字目が-nでcallします
SR_FILL_POS_2	CALL		FILL_BLANK
SR_POS_2		MOVLW		0C0H	        ;2行目頭へ 40h
		GOTO		SR_POS_CHG
SR_FILL_POS_3	CALL		FILL_BLANK
SR_POS_3		MOVLW		094H	        ;3行目頭へ 14h
		GOTO		SR_POS_CHG
SR_FILL_POS_4	CALL		FILL_BLANK
SR_POS_4		MOVLW		0D4H	        ;4行目頭へ 54h
		GOTO		SR_POS_CHG
SR_FILL_POS_1	CALL		FILL_BLANK
SR_POS_1		MOVLW		080H	        ;1行目頭へ 00h
SR_POS_CHG		MOVWF		POS	;POSを更新
		CALL		LCD_CMD		;LCDへもCMD渡し
		RETURN

;******* 位置データ変更　　コントロールコードでの利用
POS_1		MOVF		POS,W		;cont+a
		MOVWF		POS_SAVE		;
		MOVLW		080H	        ;1行目頭へ 00h
		GOTO		POS_move

POS_2		MOVF		POS,W		;cont+b
		MOVWF		POS_SAVE		;
		MOVLW		0C0H	        ;2行目頭へ 40h
		GOTO		POS_move

POS_3		MOVF		POS,W		;cont+c
		MOVWF		POS_SAVE		;
		MOVLW		094H	        ;3行目頭へ 14h
		GOTO		POS_move

POS_4		MOVF		POS,W		;cont+d
		MOVWF		POS_SAVE		;
		MOVLW		0D4H	        ;4行目頭へ 54h
POS_move	MOVWF		POS
		CALL		GETCHAR		;引き続きのデータ受信許可
RCVWAIT_POS					;待ちの間　どうする？　特別なので何もしない
		BTFSC		RECV		;
		GOTO		RCVWAIT_POS	; 
		BTFSC	ERROR		;error check
		GOTO	ERR
		MOVF	RXREG_1,W	;
		SUBLW	01FH		;kk-wreg -> wreg  結果 0,posのとき Cが1です　注意！！
		BTFSC	STATUS,C	;ＳＰや文字だと(C立たず)スキップですね　
		GOTO	POS_move2	;0x00～0x1f　を位置データ扱いで　POSに加算
		MOVF	POS,W		;文字ですね <- 文字位置　行頭のままで　セットし　
		CALL	LCD_CMD		;	
		MOVF	RXREG_1,W	;文字として　表示へ
		CALL	SR_W2LCD	;
		GOTO	EVENT		;そして　次の受信待ちへ

POS_move2	MOVF	RXREG_1,W	;0x00～0x13(\23)　位置データ　0x14以上はどうする？
		SUBLW	013H		;kk-wreg -> wreg  結果 0,posのとき Cが1です　注意！！
		BTFSS	STATUS,C	;0x00～0x13(\23)だと(C立ち)スキップですね　
		GOTO	POS_move3	;0x14～　では　POSに加算せず
		MOVF	RXREG_1,W
		ADDWF	POS,F 		;位置データ扱いで　POSに加算
POS_move3	MOVF	POS,W		;文字位置セット　
		CALL	LCD_CMD		
		GOTO	EVENT		;そして　次の受信待ちへ

POS_RSTR	MOVF		POS_SAVE,W	;cont+e
		MOVWF		POS		;文字位置戻し　
		CALL		LCD_CMD		
		GOTO		EVENT		;

;******* 改行コードの処理です　　行末まで空白埋め・改行です　　cont+m or "Enter"
;　　　　　　　処理時間掛かるので　GETCHARコールしてます　戻しは　RCVWAITになります		
DISP_CR						;
		CALL		GETCHAR		;時間の掛かるCR処理の前に　次の受信準備
		MOVF		POS,W		;文字位置データ
		SUBLW		0xD4	;　kk-wreg -> wreg  結果 0,posのとき Cが1です　注意！！　
		BTFSC		STATUS,Z
		GOTO		RCVWAIT		;そのまま　戻り　行頭でのCR無効にしました
		BTFSS		STATUS,C
		GOTO		FILL_POS_1	;1行目へ　D4を超えていた　4行目だったので

		MOVF		POS,W		;文字位置データ
		SUBLW		0xC0		;　　
		BTFSC		STATUS,Z
		GOTO		RCVWAIT		;そのまま　戻り　行頭でのCR無効にしました
		BTFSS		STATUS,C
		GOTO		FILL_POS_3		;3行目

		MOVF		POS,W		;文字位置データ
		SUBLW		0x94		;　　
		BTFSC		STATUS,Z
		GOTO		RCVWAIT		;そのまま　戻り　行頭でのCR無効にしました
		BTFSS		STATUS,C	;kk-wreg -> wreg  結果 0,posのとき Cが1です　注意！！
		GOTO		FILL_POS_4		;4行目 改行

		MOVF		POS,W		;文字位置データ
		SUBLW		0x80		;　　
		BTFSC		STATUS,Z
		GOTO		RCVWAIT		;そのまま　戻り　行頭でのCR無効にしました
		BTFSS		STATUS,C	;kk-wreg -> wreg  結果 0,posのとき Cが1です　注意！！
		GOTO		FILL_POS_2		;2行目 改行
		GOTO		RCVWAIT		;ここへは来ること無いはずだが
FILL_POS_1	CALL		SR_FILL_POS_1
		GOTO		RCVWAIT		;そして　戻りは　RCVWAITです
FILL_POS_2	CALL		SR_FILL_POS_2
		GOTO		RCVWAIT		;そして　戻りは　RCVWAITです
FILL_POS_3	CALL		SR_FILL_POS_3
		GOTO		RCVWAIT		;そして　戻りは　RCVWAITです
FILL_POS_4	CALL		SR_FILL_POS_4
		GOTO		RCVWAIT		;そして　戻りは　RCVWAITです
;*******
DISP_BS		DECF		POS,F		;文字位置データ　カウントdown 
		MOVF		POS,W		;文字位置データの分析、処理
		SUBLW		0x7F		;　　
		BTFSC		STATUS,Z
		GOTO		POS_4end	;1行目頭を外れた　POS再計算必要
		MOVF		POS,W		;文字位置データ
		SUBLW		0xBF	;　　
		BTFSC		STATUS,Z
		GOTO		POS_1end	;2行目頭を外れた　POS再計算必要
		MOVF		POS,W		;文字位置データ
		SUBLW		0x93		;条件処理　　
		BTFSC		STATUS,Z
		GOTO		POS_2end	;3行目頭を外れた　POS再計算必要
		MOVF		POS,W		;文字位置データ
		SUBLW		0xD3		;条件処理　　
		BTFSC		STATUS,Z
		GOTO		POS_3end	;4行目頭を外れた　POS再計算必要
BS_WR		MOVF		POS,W		;
		CALL		LCD_CMD	
		MOVLW		" "
		CALL		LCD_DATA	;SPACEを記入
		MOVF		POS,W		;も一度POS設定し直し
		CALL		LCD_CMD	
		GOTO		EVENT

POS_1end	MOVLW		093H	        ;1行目末へ 
		GOTO		POS_CHGend
POS_2end	MOVLW		0D3H	        ;2行目末へ 
		GOTO		POS_CHGend
POS_3end	MOVLW		0A7H	        ;3行目末へ 
		GOTO		POS_CHGend
POS_4end	MOVLW		0E7H	        ;4行目末へ 
POS_CHGend	MOVWF		POS		;
		GOTO		BS_WR
;*******

DISP_ht		MOVLW		0A5H	;ht文字"*"　表示へ
		CALL	SR_W2LCD	;POSもカウントアップ
		GOTO	EVENT		;そして　次の受信待ちへ

;******* LED
LED_ON		BSF		PORTA,1		;LED on   cont+p
		GOTO		EVENT

LED_OFF		BCF		PORTA,1		;LED off  cont+q
		GOTO		EVENT

;*******
DISP_clr	
		CALL		LCD_CLR							;
		GOTO		EVENT

;*******　cont+s　REデータ送出
DISP_TESTr
		MOVF		ROTARY_DATA,W
;		CALL		BIN_2_ASC	;下位4bitのHex変換  9-29　生データ送出に
		MOVWF		TXREG
		CALL		PUTCHAR
		GOTO		WAITLP_tx

;*******　　ノーアクションです
DISP_TEST					;no action
		GOTO		EVENT

;*******　cont+s　ボタンチェックとデータ送出
DISP_TESTs	BSF             STATUS,RP0      ;Set page 1
		MOVLW		0FFH		;<--RB3-0も入力に for　ボタンチェック
                MOVWF           TRISB           ;PortB set all output
                BCF             STATUS,RP0      ;Set Page 0 この設定　読み取ったあと　もどせよ
		CALL		TIME10
		MOVF		PORTB,W		;RB読み取り　keyINバッファに
		ANDLW		B'00001111'
		ADDLW		040H		;文字化
		MOVWF		TXREG
		BSF             STATUS,RP0      ;Set page 1
		MOVLW		0F0H		;ボタンチェック終了で　RB3-0を出力に戻す　
                MOVWF           TRISB           ;
                BCF             STATUS,RP0      ;Set Page 0 
		
		CALL		PUTCHAR
WAITLP_tx	
		BTFSC		TXBUSY		;wait end of sending
		GOTO		WAITLP_tx
		CALL		TIME10		
		GOTO		EVENT

;***  receive error display ****
ERR		MOVLW		"?"
		CALL		SR_W2LCD		;表示そして EVENT戻り
		GOTO		EVENT

;******************************************************************
;**************  RS232C PROCESS  **********************************
;****  Preset Baud Rate  ****
;************  Define constant for TIMER0  ****
;  BaudRate   PulseWidth     Counter  prescale TMR0(BITTMR)  width
;   300	      3333.33usec    8333      64(5)    130(7E)     3328usec
;  1200	      833.33	     2083      16(3)    130(7E)      832
;  2400       416.67	     1041       8(2)    128(80)      409
;  4800       208.33          521       4(1)    124(84)      198
;  9600       104.17          260       2(0)    122(86)       99
; This TMR0 RATE is used for BAUDRATE parameter as prescaler.
;
;BAUDRATE:boud rate  300 to 9600 at 10MHz clock.
; 5=300bps  3=1200bps  2=2400bps  1=4800bps  0=9600bps
;
BAUDRATE	SET		0		;preset to 9600bps
BITTMR		SET		086H  		;TMR0 DATA -122
BITTMR1		SET		06AH		;TMR0 DATA -150
;
;****************************************
; Interrupt process module
;****************************************
INTERRUPT
		BTFSS		INTCON,T0IF	;TMR0's interrupt?
		RETFIE				;not, quick return
		BCF		INTCON,T0IF	;reset T0IF bit
;****  save W register & status register
		MOVWF		WREG		;save w reg
		SWAPF		STATUS,W	;status to wreg
		MOVWF		SREG		;save status
		BTFSC		TXBUSY		;In send mode
		GOTO		TXNEXT		;send next bit
		BTFSC		RXBUSY		;In receive mode
		GOTO		RXNEXT		;receive next bit
		GOTO		STARTBIT	;must be start bit
;****  register restore and return
RESTORE		
 		SWAPF		SREG,W		;get saved status
		MOVWF		STATUS
		SWAPF		WREG,F		;get saved wreg				
		SWAPF		WREG,W
		RETFIE
		
;************************************
; Transmission process module
;************************************
PUTCHAR
		BSF		TXBUSY		;set busy bit
		MOVLW		8		;bit count
		MOVWF		BITCNT		;reset bit counter
		MOVLW		1
		MOVWF		EXTRA		;set stopbit flag
		CALL		TXSTART		;start send dumy bit
		BCF		INTCON,T0IF	;reset flag
		BSF		INTCON,T0IE	;permit TMR0 interrupt
		RETFIE
;**** Send start bit ****
TXSTART
		CLRF		TMR0		;reset timer
		BSF		STATUS,RP0	;page 1
		CLRWDT
		MOVLW		BAUDRATE	;set prescaler
		MOVWF		OPTION_REG
		BCF		STATUS,RP0	;page 0	
		BCF		PORTA,3		;send start bit
		MOVLW		BITTMR
		MOVWF		TMR0		;start timer
		RETURN
;******  Interrupt process for Send next bit  *****
TXNEXT
		MOVLW		BITTMR		;timer restart
		MOVWF		TMR0
		MOVF		BITCNT,1	;end test
		BTFSC		STATUS,Z	
		GOTO		STOPBIT		;send stop bit
NEXTTXBIT
		DECF		BITCNT,F	;BITCNT-1
		BSF		STATUS,C	;C on
		RRF		TXREG,1		;shift send data
		BTFSS		STATUS,C	;bit test
		BCF		PORTA,3		;0 out
		BTFSC		STATUS,C
		BSF		PORTA,3		;1 out
		GOTO		RESTORE		;return			
;****  Send Stop bit  ****
STOPBIT
		MOVF		EXTRA,W
		BTFSC		STATUS,Z	;end test
		GOTO		DONE		;goto end
		DECF		EXTRA,F		;end of stop
		BSF		PORTA,3		;send 1 for stop bit
		GOTO		RESTORE		;return
;***  all end of send ****
DONE
		BCF		INTCON,T0IE	;Disable interrupt
		BCF		TXBUSY		;reset busy flag
		GOTO		RESTORE		;return


;**************************************************************
;*************************************
;  Receiving process module
;*************************************
GETCHAR
		BSF		RECV		;wait bit on
		MOVLW		9	
		MOVWF		BITCNT		;set bit counter
		CLRF		RXREG		;clear buffer
		BCF		ERROR		;clear error bit
;****  Start bit wait  ****
		CLRF		TMR0		;timer reset
		BSF		STATUS,RP0	;page 1
		CLRWDT				;clear WDT
		MOVLW		038H		;set to external WDT
		MOVWF		OPTION_REG
		BCF		STATUS,RP0	;page 0
		MOVLW		0FFH
		MOVWF		TMR0		;set timer for start bit
		BCF		INTCON,T0IF
		BSF		INTCON,T0IE	;enable TMR0 interrupt
		RETFIE				;wait interrupt

;****  Start bit process  ****
STARTBIT
		CLRWDT				;timer reset
		CALL		TIME10_I	;Delay 10usec
		BTFSC		PORTA,4		;retry
		GOTO		NOISE		;not start bit
		BSF		RXBUSY		;set busy
;
		CLRF		TMR0		;reset timer for next bit
		BSF		STATUS,RP0	;page 1
		MOVLW		BAUDRATE	;
		MOVWF		OPTION_REG
		BCF		STATUS,RP0	;page 0
		MOVLW		BITTMR1		;set bit width over 1.1bit 
		MOVWF		TMR0
		GOTO		RESTORE		;return
;*** missing start bit ****
NOISE		
		MOVLW		0FFH		;retry
		MOVWF		TMR0
		GOTO		RESTORE		;return

;****  receive next bit  ****
RXNEXT
		BSF		STATUS,RP0	;page 1
		CLRWDT				;reset timer
		MOVLW		BAUDRATE
		MOVWF		OPTION_REG
		BCF		STATUS,RP0	;page 0
		MOVLW		BITTMR
		MOVWF		TMR0		;restart timer
		DECFSZ		BITCNT,F	;counter-1
		GOTO		NEXTRXBIT
;*** stop bit process  ***
		BTFSS		PORTA,4		;stop bit check
		BSF		ERROR		;not stop
		BCF		INTCON,T0IE	;inhibit interrupt
		BCF		RXBUSY		;reset busy flag
		BCF		RECV		;set receive complete
;
;**** If pararell process, insert call at this position ****
;		CALL		RECEIVEPROCESS
		MOVF		RXREG,W		;追加バッファにコピーを置いて
		MOVWF		RXREG_1		;REREGを早く開放、LCD処理待たずに　次の受信を許可

		GOTO		RESTORE
;**** next bit process  ***
NEXTRXBIT
		BCF		STATUS,C	;prepare bit for shift
		BTFSC		PORTA,4		;data=0 or 1?
		BSF		STATUS,C	;1 case
		RRF		RXREG,F		;set data to RXREG
		GOTO		RESTORE
;*****  10usec delay routine for INTRPTprocess
TIME10_I						;10usec for INTRPTprocess
		MOVLW		7H 		
		MOVWF		CNT2_I		
T_LP2_I		DECFSZ		CNT2_I,F		;2+3*7-1=22		
		GOTO		T_LP2_I		
		RETURN				;22+1=23

;******************  This is the end of RS232C modules *********************


;******************************************************
;  PORT A & B Initialize Routine
;  This routine includes RS232C and LCD initilization.
;******************************************************

PORT_INI
                BSF             STATUS,RP0      ;Set page 1
		MOVLW	0F0H		;RB4,5,6,7 RE入力　RB0-3はLCDへ出力
					;RB0-3については　ボタン読み取りでは入力(0FFH)
                MOVWF           TRISB           ;PortB 
		BCF		OPTION_REG,7	;zeroで RB in PullUp使用するです
                MOVLW           010H            ;only RA4 input
                MOVWF           TRISA           ;PortA set
                BCF             STATUS,RP0      ;Set Page 0
                BSF		PORTA,3		;RS232 TX SET TO H
		BSF		PORTA,1		;LED TO H  on  初期　点灯　どっちがいい？
               RETURN          

;***************************************************************************

;***************************************************
;       LCD control routines
;***************************************************

;****  LCD Data Write  ****
LCD_DATA
		MOVWF		DPDT		;save dat
		SWAPF		DPDT,W		;<- RB3-0がDB7-4に接続されてるので
		ANDLW		0FH		;mask lower　<-　0F0ではなく0Fで
		MOVWF		PORTB
		BSF		PORTA,2		;RS high
		BSF		PORTA,0		;E high
		BCF		PORTA,0		;E low
		MOVF		DPDT,W		;get data lower
		ANDLW		0FH		;mask lower　<-　0F0ではなく0Fで
		MOVWF		PORTB
		BSF		PORTA,0
		BCF		PORTA,0
		CALL		TIME10
		CALL		TIME10
		CALL		TIME10
		CALL		TIME10		;40us以上の固定　フラグ監視を止めました
		RETURN

;****  LCD command out  *****
LCD_CMD
		MOVWF		DPDT		;save dat
		SWAPF		DPDT,W		;<- RB3-0がDB7-4に接続されてるので
		ANDLW		0FH		;mask lower　<-　0F0ではなく0Fで
		MOVWF		PORTB
		BCF		PORTA,2		;RS low
		BSF		PORTA,0		;E high
		BCF		PORTA,0		;E low
		MOVF		DPDT,W		;get data lower
		ANDLW		0FH		;mask lower　<-　0F0ではなく0Fで
		MOVWF		PORTB
		BSF		PORTA,0
		BCF		PORTA,0
		CALL		TIME10	
		CALL		TIME10
		CALL		TIME10
		CALL		TIME10	;40us以上の固定　フラグ監視を止めました
			;表示クリアとカーソルホームでは　1.6ms以上ということで　
			;そちらで　2ms位の待ちを入れて下さい
		RETURN

;****  LCD Display Clear ****
LCD_CLR
		MOVLW		01H		;clear command
		CALL		LCD_CMD
		MOVLW		0x80		;Position 0,0 <-80H このままLCD_CMDに渡せます
		MOVWF		POS
		CALL		TIME1M		;<- 固定ディレイに :1.6ms以上
		CALL		TIME1M
		RETURN

;****  Initialize  *****
LCD_INI
		CALL		TIME5M		;wait
		CALL		TIME5M		;wait
		CALL		TIME5M		;wait
		CALL		TIME5M		;wait
		MOVLW		03H		;Function set 8bits <-030
		MOVWF		PORTB
		BCF		PORTA,2		;RS
		BSF		PORTA,0		;E high
		BCF		PORTA,0		;E low
		CALL		TIME5M		;wait
		MOVLW		03H		;Function reset 8bits <-030 
		MOVWF		PORTB
		BCF		PORTA,2		;RS
		BSF		PORTA,0		;E high
		BCF		PORTA,0		;E low
		CALL		TIME100
		MOVLW		03H		;Function reset 8bits <-030
		MOVWF		PORTB
		BCF		PORTA,2
		BSF		PORTA,0
		BCF		PORTA,0
		CALL		TIME100
		MOVLW		02H		;Function set 4bits mode <-020
		MOVWF		PORTB		;under the 8bits mode
		BCF		PORTA,2
		BSF		PORTA,0
		BCF		PORTA,0
		CALL		TIME100		;From here 4bits mode

		MOVLW		028H		;function DL=0 4bit mode,5x7:40us
		CALL		LCD_CMD
		MOVLW		08H		;Display off D=C=B=0 :40us
		CALL		LCD_CMD
		MOVLW		0CH		;Display on D=1 C=B=0 :40us
		CALL		LCD_CMD
		MOVLW		06H		;Entry I/D=1 S=0 :40us
		CALL		LCD_CMD
		RETURN



;*********************************
;  Timer Routine
;	TIME10  :10usec
;	TIME100 :100usec
;	TIME1M  :1msec
;	TIME5M  :5msec
;*********************************
;*****  10usec delay routine
TIME10						;10usec　
		MOVLW		7H 		
		MOVWF		CNT2		
T_LP2		DECFSZ		CNT2,F		;2+3*7-1=22		
		GOTO		T_LP2		
		RETURN				;22+1=23

TIME100						;100usec
		MOVLW		9H		
		MOVWF		CNT1		
T_LP1		CALL		TIME10		;2+(25+3)*9-1=253		
		DECFSZ		CNT1,F
		GOTO		T_LP1
		RETURN				;254*0.4=100usec(about)

TIME1M						;1msec(about)
		MOVLW		0AH
		MOVWF		CNT3
T_LP3		CALL		TIME100		;2+(254+3)*10-1=2541
		DECFSZ		CNT3,F
		GOTO		T_LP3
		RETURN				;2542

TIME5M						;5msec(about)
		MOVLW		3BH
		MOVWF		CNT4
T_LP4		CALL		TIME100		;2+(254+3)*59-1=15164
		DECFSZ		CNT4,F
		GOTO		T_LP4
		RETURN				;15165

;***************************************************************************
;***************************************************
;       EEPROM routines					10:27 2005/08/24現在　動作未確認ですよ！！
;		E_ADRS : データエリアのアドレス	　　E_DATA : データ　　E_ADRSとE_DATAは変数
;***************************************************

RD_EEPROM 
		MOVF		E_ADRS,W	;データエリアのアドレス指定
		MOVWF		EEADR		;Set address register 
		BSF		STATUS,RP0		;Set to page 1 
		BSF		EECON1,RD		;Start read 
		BCF		STATUS,RP0		;Return to page 0 
		MOVF		EEDATA,W		;Ｗレジスタにデータ取り出し
		RETURN 
WR_EEPROM 
		BCF		STATUS,RP0			;Set to page 0 
		MOVF		E_ADRS,W		;データエリアのアドレス指定
		MOVWF		EEADR			;Address set 
		MOVF		E_DATA,W		;書き込むデータ
		MOVWF		EEDATA			;Data set 
		BSF		STATUS,RP0			;Set to Page 1 
		BSF		EECON1,WREN			;Set WR Enable 
		MOVLW		55H				;Write Sequence 
		MOVWF		EECON2			;Start write 
		MOVLW		0AAH 
		MOVWF		EECON2 
		BSF		EECON1,WR			;Go write 
WR_LP								;書き込み確認待ちループ
		BTFSC		EECON1,WR		;Check Write end 
		GOTO		WR_LP 
		BCF			STATUS,RP0		;Return to page 0 
		RETURN 



		END
