; 内部クロック 8MHz
; MCLR必要


	LIST		P=PIC16F88
	INCLUDE		"P16F88.INC"
	__CONFIG _CONFIG1,_CP_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_IO & _BODEN_ON & _LVP_OFF & _CPD_OFF & _DEBUG_OFF

	radix	dec
;	NOLIST
	ERRORLEVEL	2
;
;***** CONST *****
;

W100US		EQU	65		; 165 :CPUCLK = 20MHz
						;  81 :CPUCLK = 10MHz
						;  65 :CPUCLK =  8MHz
						;  31 :CPUCLK =  4MHz
LCDPORT		EQU	PORTB	; Select LCD Port
LCD_RS		EQU	3		; Select Port Bit for LCD RS
LCD_E		EQU	0		; Select Port Bit for LCD_E
;
;
;***** User RAM Area *****
;
	CBLOCK 0x20



lcdTim0	
lcdTim1	
lcdTmp0	
lcdTmp1	
CNT1
CNT2
CNT3
CNT4
CNT5
RA6SW
RA6SWT
swn1	
swnow	;	EQU 0x28
swnow2	;	EQU 0x29
RA1valH	;	EQU 0x34	; A/D変換の一時退避 上位16bit
RA1valL	;	EQU 0x35	; 下位 16bit
RA0valH
RA0valL
RA2valH
RA2valL
RA4valH
RA4valL

RA0addH		; 16回平均化 一時保管用
RA0addL		; 
RA1addH		; 
RA1addL		; 
RA2addH		; 
RA2addL		; 
RA4addH		; 
RA4addL		; 

RA0inpH		; サンプリング終了して
RA0inpL		; LCD表示するための保存用
RA1inpH
RA1inpL
RA2inpH
RA2inpL
RA3inpH
RA3inpL
RA4inpH
RA4inpL


RA0count	; 平均化用カウンター
RA1count	; 
RA2count	; 
RA4count	; 

inpH		; 10bitの上位
inpL		; 10bitの下位

tmpH
tmpL

tmp2count	; テンポラリー

BatRelay
AccRelay

EngStartT
EngStartCT
EngStCountH
EngStCountL
EngStTimer2
EngStTimer1

AccLowHi

AccTimer1
AccTimer2

BatTimer1
BatTimer2

RA6Timer1
RA6Timer2


octtmp		; 共通一時使用変数
octtmp2		; 共通一時使用変数

s83
s84
s85
s86

s8B
s8C
s8D
s8E

sC3
sC4
sC5
sC6

sC9
sCC

a89
a8A
a8B
a8C
a8D

aC7
aC8
aCA
aCC

srlc1				; カウンタ(サブルーチンで使用)
srwk1				; 一時余り格納場所(サブルーチンで使用)
out5				;10進格納場所(5バイト)
out4		
out3		
out2		
out1				;〜下位
dec_top:			;間接アクセス用ラベル
	endc

;**********************************************************************
;
; ここからプログラム開始
;
;**********************************************************************

; EEPROM初期データー

	ORG		0x2100 
	DE		0x00,0x00,0x00,0x00,0x00

	ORG	0x000		; processor reset vector


; 初期設定

	call	initA
	call	initB
	call	initC
	call	initD


	call	initEEPROMRead
	call	initLCDA
	call	LCDN1CLR

	call	SW_INPUT

	call	RA2_KIJYUN
	call	RA4_SUB

; メインのプログラム

loop_top

	call	RA1_ACC
	call	ACC_HIKAKU
;	call	RA6_SW_ONOFF	; どっちか好きなほうを使う
	call	RA6_SW_XOR	; 

	call	RA1_ACC
	call	ACC_HIKAKU
	call	RA2_KIJYUN

	call	RA1_ACC
	call	ACC_HIKAKU
	call	RA4_SUB

	call	RA1_ACC
	call	ACC_HIKAKU
	call	EEPROMRead

	call	RA1_ACC
	call	ACC_HIKAKU
	call	ENGSTART

	call	RA1_ACC
	call	ACC_HIKAKU
	call	SA_LCD	

	call	RA1_ACC
	call	ACC_HIKAKU
	call	RA0_BATT
;	call	BAT_HIKAKU

	call	RA1_ACC
	call	ACC_HIKAKU
	call	ENGSTART_LCD

	call	RA1_ACC
	call	ACC_HIKAKU
	call	RA1_LCD
	call	LoopCount

	goto	loop_top


;************************************************************************
;
; ここから下はサブルーチン
;
;************************************************************************





;**************************************************************
;
; STBY BATT RELAY / ACC RELAY LCD表示ルーチン
;
;**************************************************************
SA_LCD

	movf	RA6SW,W			; SWが 1画面目か?
	btfsc	STATUS,Z
	goto	SA_LCD_FIN		; RA6SW=1だったとき、何もしないで終了


nextCC

	movf	AccRelay,W
	addlw	0x30
	movwf	tmpH
	xorwf	sCC,W
	btfsc	STATUS,Z
	goto	nextC9

	movlw	0xCC
	call	lcd_Cmd
	movf	tmpH,W
	movwf	sCC
	call	lcd_Dat

	
nextC9

	movf	BatRelay,W
	addlw	0x30
	movwf	tmpH
	xorwf	sC9,W
	btfsc	STATUS,Z
	goto	SA_LCD_FIN

	movlw	0xC9
	call	lcd_Cmd
	movf	tmpH,W
	movwf	sC9
	call	lcd_Dat


SA_LCD_FIN
	
	return
















;**************************************************************
;
; ACC電圧比較ルーチン
;
; RA1 ACC電圧
; RA2 切り替え電圧
; の比較
;
; RA1 >= RA2  だったら ACC RELAY ON
; RA1 <  RA2  だったら 数秒後 ACC RELAY OFF
;
; RA1 < RA2 の立下りで BAT RELAY ON
; 数秒後 BAT RELAY OFF
;
;**************************************************************
ACC_HIKAKU

	movf	RA1valH,W
	movwf	tmpH
	movf	RA1valL,W
	movwf	tmpL

	movf	RA2valL,W
	subwf	tmpL,W		; ACC - 比較 -> W
						; >=0 で C=1
	btfsc	STATUS,C
	goto	aHIKAKUH	; 下位は繰り下がり無し

	movf	tmpH,W
	btfsc	STATUS,Z
	goto	aHIKUI		; 元から上位が 0なので低い
	decf	tmpH,F		; 下位が繰り下がりありなので上位を -1

aHIKAKUH
	movf	RA2valH,W
	subwf	tmpH,W		; ACC - 比較 -> W
						; >=0 で C=1
	btfsc	STATUS,C
	goto	aTAKAI		; 上位も繰り下がり無し ACC > 比較

aHIKUI

	movf	AccLowHi,W	; 前回の値をロード
	btfsc	STATUS,Z
	goto	aHIKUI1		; 前回も 0のとき

; ACC LOWになって 1回だけ流れる AccLowHi=1のとき

	movlw	D'0'
	movwf	AccLowHi

; ACC LOWでも ACC RELAYは 1のときのみ

	movf	AccRelay,W
	btfsc	STATUS,Z
	goto	aHIKUI05

; AccLowHi=1で AccRelay=1のとき

	movlw	D'1'
	movwf	BatRelay	; BAT RELAY FLAG
	bsf		PORTB,2		; BAT RELAY ON

aHIKUI05

	movlw	D'50'		; Batタイマー初期値セット
	movwf	BatTimer2
	movlw	D'18'
	movwf	BatTimer1

	goto	ACC_HIKAKU_FIN

aHIKUI1
; ACC LOWのカウントダウン中

	movf	AccTimer1,W
	btfss	STATUS,Z
	goto ACC_HIKAKU_FIN	; カウントダウン中 何もせず終了

	movf	AccRelay,W	; 前回の値をロード
	btfsc	STATUS,Z
	goto	aHIKUI3		; 前回も 0のとき

; ACC LOWの 5秒後に 1回だけ流れる

	movlw	D'0'
	movwf	AccRelay

	bcf		PORTB,1		; ACC RELAY OFF
	bcf		PORTA,7		; 液晶バックライト OFF

;内部クロック設定 100 1MHz
;	bsf		STATUS,RP0
;	bsf		OSCCON,IRCF2
;	bcf		OSCCON,IRCF1
;	bcf		OSCCON,IRCF0
;	bcf		STATUS,RP0

aHIKUI3
; ACC LOWになって 5秒後に毎回流れる部分

	goto	ACC_HIKAKU_FIN

; ACC HIGHの時
aTAKAI
	movf	AccLowHi,W
	btfss	STATUS,Z
	goto	aTAKAI2		; 前回も高かったとき

; ACC HIGHになって 1回だけ流れる

;	movlw	D'0'
;	movwf	BatRelay

	movlw	D'1'
	movwf	AccRelay	; トリガーを 1
	movwf	AccLowHi


;	bcf		PORTB,2		; BAT RELAY OFF
	bsf		PORTB,1		; ACC RELAY ON
	bsf		PORTA,7		; 液晶バックライト ON

;内部クロック設定 111 = 8MHz
;	bsf		STATUS,RP0
;	bsf		OSCCON,IRCF2
;	bsf		OSCCON,IRCF1
;	bsf		OSCCON,IRCF0
;	bcf		STATUS,RP0

aTAKAI2
; ACC HIGHになって毎回流れる

	movlw	D'100'
	movwf	AccTimer2
	movlw	D'18'
	movwf	AccTimer1
	goto	ACC_HIKAKU_FIN

ACC_HIKAKU_FIN

; BAT RELAYの処理
	movf	BatRelay,W
	btfsc	STATUS,Z
	goto	aBat_FINISH	; BatRelay=0だったら終わり

; Bat Relay ON時の処理
	movf	BatTimer1,W
	btfss	STATUS,Z
	goto	aBat_FINISH	

aBat1
; Bat RELAY ONになって数秒後
	movlw	D'0'
	movwf	BatRelay	; トリガーを 1
	bcf		PORTB,2		; Bat RELAY OFF


aBat_FINISH


; BAT電圧のモニター
; EngStart回数のカウントに使う
;
; RA0 > RA2の立ち上がりからカウントし、
; 1秒後も同じ条件だったら EngStartTを 1

BAT_HIKAKU

	movf	RA0valH,W
	movwf	tmpH
	movf	RA0valL,W
	movwf	tmpL

	movf	RA2valL,W
	subwf	tmpL,W		; BAT - 比較 -> W
						; >=0 で C=1
	btfsc	STATUS,C
	goto	bHIKAKUH	; 下位は繰り下がり無し

	movf	tmpH,W
	btfsc	STATUS,Z
	goto	bHIKUI		; 元から上位が 0なので低い
	decf	tmpH,F		; 下位が繰り下がりありなので上位を -1

bHIKAKUH
	movf	RA2valH,W
	subwf	tmpH,W		; ACC - 比較 -> W
						; >=0 で C=1
	btfsc	STATUS,C
	goto	bTAKAI		; 上位も繰り下がり無し ACC > 比較

bHIKUI
; カウントダウン中
	movf	EngStTimer1,W
	btfss	STATUS,Z
	goto 	BAT_HIKAKU_FIN	; カウントダウン中 何もせず終了

; カウントダウン終了
; その時 BatRelay=1かどうかを確認
; =0 だったらカウント無効にする

	movf	BatRelay,W
	btfsc	STATUS,Z
	goto	BAT_HIKAKU_FIN	; BatRelay=0だったら終わり

	movlw	D'1'
	movwf	EngStartCT	; カウントダウン終了Tセット
	goto	BAT_HIKAKU_FIN

bTAKAI
	movlw	D'10'		; EngStタイマー初期値セット
	movwf	EngStTimer2
	movlw	D'18'
	movwf	EngStTimer1

	movf	EngStartCT,W
	btfsc	STATUS,Z
	goto	BAT_HIKAKU_FIN




; BAT電圧 LOW -> カウントダウン終了 -> HIGHになって 1回目
; EngStartTを 1にする

	movlw	D'1'
	movwf	EngStartT
	movlw	D'0'
	movwf	EngStartCT	

BAT_HIKAKU_FIN


	return




;**************************************************
;
; ループ全体で作る長時間カウンター
;
;**************************************************
LoopCount

; 全体のループから

Bat2
	movf	BatTimer2,W
	btfsc	STATUS,Z
	goto	Bat1
	decf	BatTimer2,F	; ゼロになって無かったら -1
	goto	Acc2

Bat1
	movlw	D'50'
	movwf	BatTimer2		; 初期値に戻す

	movf	BatTimer1,W
	btfss	STATUS,Z
	decf	BatTimer1,F		; ゼロでない時 -1

Acc2
	movf	AccTimer2,W
	btfsc	STATUS,Z
	goto	Acc1
	decf	AccTimer2,F
	goto	Eng2

Acc1

	movlw	D'100'
	movwf	AccTimer2		; 初期値に戻す

	movf	AccTimer1,W
	btfss	STATUS,Z
	decf	AccTimer1,F		; ゼロでない時

Eng2
	movf	EngStTimer2,W
	btfsc	STATUS,Z
	goto	Eng1
	decf	EngStTimer2,F
	goto	RA6SWTimer2

Eng1

	movlw	D'10'
	movwf	EngStTimer2		; 初期値に戻す

	movf	EngStTimer1,W
	btfss	STATUS,Z
	decf	EngStTimer1,F		; ゼロでない時

RA6SWTimer2

	movf	RA6Timer2,W
	btfsc	STATUS,Z
	goto	RA6SWTimer1
	decf	RA6Timer2,F
	goto	LoopCount_FIN

RA6SWTimer1

	movlw	D'2'
	movwf	RA6Timer2		; 初期値に戻す

	movf	RA6Timer1,W
	btfss	STATUS,Z
	decf	RA6Timer1,F		; ゼロでない時

LoopCount_FIN
	return


RA6_SW_ONOFF
;**************************************************************
;
; RA6 SWの取り込み
; こっちは押したら ON、はなしたら OFF
;
;**************************************************************
SW_INPUT


	btfss	PORTA,6
	goto	SW_ON		; bit6 SETされてたら ON

SW_OFF
	call	wt10us		; 10us wait
	btfss	PORTA,6
	goto	SW_FINISH	; 反転してたらチャタリング、終了

	movf	RA6SW,W
	btfss	STATUS,Z	; Z=0 RA6SW=1 N-1は SWON?
	goto	SW_FINISH	; SWそのまま、戻る
	goto	on2off

SW_ON
	call	wt10us		; 10us wait
	btfsc	PORTA,6
	goto	SW_FINISH	; 反転、チャタリング、終了

	movf	RA6SW,W
	btfsc	STATUS,Z	; Z=1 RA6SW=0 N-1 は SWOFF?
	goto	SW_FINISH	; SWそのまま、戻る
	goto	off2on

on2off
	movlw	D'1'
	movwf	RA6SW		; 1セット
	movlw	D'1'
	movwf	RA6SWT		; SW変更トリガーセット
	call	initLCDA	; 2画面目を表示
	call	LCDN1CLR
	goto	SW_FINISH

off2on
	movlw	D'0'
	movwf	RA6SW		; 0セット
	movlw	D'1'
;	movwf	RA6SWT		; SW変更トリガーセット
	call	initLCDB	; 1画面目表示
	call	LCDN1CLR

SW_FINISH
	return


RA6_SW_XOR
;**************************************************************
;
; RA6 SWの取り込み
; こっちのサブルーチンは、RA6 ONになっていたら SWの状態を
; 反転する
;
;**************************************************************
xSW_INPUT

; RA6Timer1が 0でない時は、チャタリング表示防止のため
; ルーチン通さない

	movf	RA6Timer1,W
	btfss	STATUS,Z
	goto	xSW_FINISH

; SW押されてるか

	btfsc	PORTA,6
	goto	xSW_FINISH


; タイマーの値を初期値に

	movlw	D'2'
	movwf	RA6Timer2
	movlw	D'100'
	movwf	RA6Timer1


xSW_ON

	movlw	D'1'
	movwf	RA6SWT		; SW変更トリガーセット

	movf	RA6SW,W
	btfsc	STATUS,Z
	goto	xSWN1_0
	movlw	D'0'		; N-1が 1だった場合
	movwf	RA6SW
	call	initLCDB	; 1画面目表示
	call	LCDN1CLR
	goto	xSW_FINISH

xSWN1_0
	movlw	D'1'
	movwf	RA6SW
	call	initLCDA	; 2画面目を表示
	call	LCDN1CLR

xSW_FINISH
	return






;**************************************************************
;
; ENG START回数カウントルーチン
; BAT電圧の上がったところのトリガー
; EngStartT が 1になっていたら
; EngStCountH,Lを +1して EEPROMルーチン呼び出す
;
;**************************************************************

ENGSTART

	movf	EngStartT,W	; BAT電圧の立ち上がったときセットされている
	btfsc	STATUS,Z
	goto	ENGSTART_FIN	; EngStartT=0だったとき、何もしないで終了

	movlw	D'0'
	movwf	EngStartT		; トリガーフラグはクリアー

	movlw	D'1'
	addwf	EngStCountL,F	; +1する
	btfsc	STATUS,C
	incf	EngStCountH,F	; 繰り上がり

	movf	EngStCountL,W
	movwf	inpL
	movf	EngStCountH,W
	movwf	inpH

	call	EEPROMWrite

ENGSTART_FIN

	return



;**************************************************************
;
; EEPROM読み出しルーチン
; RA6SWTが 1になっていたら、毎回読み込む必要も無いけど
; EEPROMから値を読み出して EngStCountXへ書き込む
;
;**************************************************************

EEPROMRead

	movf	RA6SWT,W		; SWを 2画面目にしたか?
	btfsc	STATUS,Z
	goto	EEPROMRead_FIN	; RA6SWT=0だったとき、何もしないで終了

	movlw	D'0'
	movwf	RA6SWT
	bcf		STATUS,RP0
	bcf		STATUS,RP1

	movlw	0x01
	bsf		STATUS,RP1
	movwf	EEADR
	bsf		STATUS,RP0
	bsf		EECON1,RD
	bcf		STATUS,RP0
	movf	EEDATA,W
	bcf		STATUS,RP1
	movwf	EngStCountH

	movlw	0x02
	bsf		STATUS,RP1
	movwf	EEADR
	bsf		STATUS,RP0
	bsf		EECON1,RD
	bcf		STATUS,RP0
	movf	EEDATA,W
	bcf		STATUS,RP1
	movwf	EngStCountL


EEPROMRead_FIN

	bcf		STATUS,RP0
	bcf		STATUS,RP1

	return








;**************************************************************
;
; EEPROM書き込みルーチン
;
; inpHと inpLに値を入れこのルーチンを流すと
; EEADR 1,2に書き込みを行う
;
;**************************************************************
EEPROMWrite

	bcf		STATUS,RP0
	bcf		STATUS,RP1

	movlw	0x01
	bsf		STATUS,RP1
	movwf	EEADR
	bcf		STATUS,RP1
	movf	inpH,W
	bsf		STATUS,RP1
	movwf	EEDATA
	bsf		STATUS,RP0
	bsf		EECON1,WREN
	movlw	055H
	movwf	EECON2
	movlw	0AAH
	movwf	EECON2
	bsf		EECON1,WR
ELoop1
	btfsc	EECON1,WR
	goto	ELoop1
	bcf		STATUS,RP1
	bcf		STATUS,RP0


	movlw	0x02
	bsf		STATUS,RP1
	movwf	EEADR
	bcf		STATUS,RP1
	movf	inpL,W
	bsf		STATUS,RP1
	movwf	EEDATA
	bsf		STATUS,RP0
	bsf		EECON1,WREN
	movlw	055H
	movwf	EECON2
	movlw	0AAH
	movwf	EECON2
	bsf		EECON1,WR
ELoop2
	btfsc	EECON2,WR
	goto	ELoop2


	bcf		STATUS,RP1
	bcf		STATUS,RP0

	return



;**************************************************************
;
; ENG START回数 LCD表示ルーチン
;
;**************************************************************
ENGSTART_LCD

	movf	RA6SW,W				; SWが 2画面目か?
	btfss	STATUS,Z
	goto	ENGSTART_LCD_FIN	; RA6SW=0だったとき、何もしないで終了


	movf	EngStCountH,W
	movwf	inpH
	movf	EngStCountL,W
	movwf	inpL

	call	hexdec16

nexta89
	movf	out5,W
	addlw	0x30
	movwf	out5
	xorwf	a89,W
	btfsc	STATUS,Z
	goto	nexta8A

	movlw	0x89
	call	lcd_Cmd
	movf	out5,W
	movwf	a89
	call	lcd_Dat

nexta8A
	movf	out4,W
	addlw	0x30
	movwf	out4
	xorwf	a8A,W
	btfsc	STATUS,Z
	goto	nexta8B

	movlw	0x8A
	call	lcd_Cmd
	movf	out4,W
	movwf	a8A
	call	lcd_Dat

nexta8B
	movf	out3,W
	addlw	0x30
	movwf	out3
	xorwf	a8B,W
	btfsc	STATUS,Z
	goto	nexta8C

	movlw	0x8B
	call	lcd_Cmd
	movf	out3,W
	movwf	a8B
	call	lcd_Dat

nexta8C
	movf	out2,W
	addlw	0x30
	movwf	out2
	xorwf	a8C,W
	btfsc	STATUS,Z
	goto	nexta8D

	movlw	0x8C
	call	lcd_Cmd
	movf	out2,W
	movwf	a8C
	call	lcd_Dat

nexta8D
	movf	out1,W
	addlw	0x30
	movwf	out1
	xorwf	a8D,W
	btfsc	STATUS,Z
	goto	ENGSTART_LCD_FIN

	movlw	0x8D
	call	lcd_Cmd
	movf	out1,W
	movwf	a8D
	call	lcd_Dat

ENGSTART_LCD_FIN
	
	return







RA0_BATT
;*****************************************************
; RA0 バッテリー電圧
;*****************************************************

; ADCON0 	10000
; ADCS1,0	10		Fosc/32
; CHS2,1,0	000		CH0 RA0
;
; ADCON1	10100000
; ADFM		1		右詰
; ADCS2		0
; VCFG1,0	10		VREF+ AVss


	movlw	B'10000001'
	movwf	ADCON0
	movlw	B'10100000'
	bsf		STATUS,RP0
	movwf	ADCON1
	bcf		STATUS,RP0

	call	wt10us
	call	wt10us
	call	wt10us
	call	wt10us
	call	wt10us

	bsf		ADCON0,GO	; A/D変換スタート
RA0adloop
	btfsc	ADCON0,GO
	goto	RA0adloop		; 変換終了してなかったら loop

	bcf		STATUS,RP1
	bcf		STATUS,RP0	; bank0
	movf	ADRESH,W	; 上位
	movwf	RA0valH
	bsf		STATUS,RP0
	movf	ADRESL,W	; 下位は BANK1
	bcf		STATUS,RP0
	movwf	RA0valL

;
; --------------- A/D 変換ここまで


; サンプリング 64回
; 16bit加算
; RA0addX = RA0addX+RA0VALx
;
	movf	RA0valL,W	; 下位
	addwf	RA0addL,F
	btfsc	STATUS,C
	incf	RA0addH,F	; 下位がケタ上がり 上位を 1加算
	movf	RA0valH,W
	addwf	RA0addH,F

; カウンターが 0になったかの判断

	decfsz	RA0count,F
	goto	RA0_FINISH	; カウンターが 0で無いので、処理せず次へ

; サンプリング終了

	movlw	D'64'
	movwf	RA0count	; カウンター初期値へ戻す

; 下位の bit2で四捨五入 bit2 = 00000100
; 下位の bit5で四捨五入 bit2 = 00100000

	btfss	RA0addL,4	; bit5が setだったら次を jump
	goto	RA0_0		; bit2=0の場合 繰り上げない


; 1足す処理 最初繰上げのケタだけ設定した後
; 16bit加算
; RA0addX = RA0addX+RA0VALx
;
	movlw	B'00000000'
	movwf	tmpH
	movlw	B'00100000'
	movwf	tmpL		; 繰り上げるケタだけをセット

	addwf	RA0addL,F
	btfsc	STATUS,C
	incf	RA0addH,F	; 下位がケタ上がり 上位を 1加算
	movf	tmpH,W
	addwf	RA0addH,F


RA0_0
;
; 64回加算したので 6回右シフトして液晶処理
; Max 1023で 20.48V表示のため

	bcf		STATUS,C	; 1回目
	rrf		RA0addH,F	; 右シフトは上位から
	rrf		RA0addL,F
	bcf		STATUS,C
	rrf		RA0addH,F
	rrf		RA0addL,F
	bcf		STATUS,C
	rrf		RA0addH,F
	rrf		RA0addL,F
	bcf		STATUS,C
	rrf		RA0addH,F
	rrf		RA0addL,F
	bcf		STATUS,C
	rrf		RA0addH,F
	rrf		RA0addL,F

	movf	RA0addH,W
	movwf	inpH		; 変換用シンボルへ入れる
	movf	RA0addL,W
	movwf	inpL		;

	movlw	D'0'
	movwf	RA0addH		; 0に戻す
	movwf	RA0addL

RA0_1
; RA6SWが 0 1画面目だったら電圧の表示をする

	movf	RA6SW		; 0だと 1画面目
	btfsc	STATUS,Z
	goto	RA0_FINISH	; 1だったので電圧表示無し

; バッテリー電圧部分の液晶表示

	call	hexdec16

next83
; 10のけた
	movf	out4,W
	btfss	STATUS,Z	; Z=1 out4が 0だったら次を NOP
	goto	next831

next83_0
; 0で消していい時
	movlw	0x20		; スペースを入れる
	movwf	out4
	goto	next832

next831
; 1-9のとき
	movf	out4,W
	addlw	0x30		; W + 0x30 -> W
	movwf	out4

next832
	xorwf	s83,W		; 1回前表示した数値と比較
	btfsc	STATUS,Z	; Zフラグはゼロ = 変化なし
	goto	next84		; 液晶表示変更なし次へ

; 10のケタ更新
	movlw	0x83
	call	lcd_Cmd
	movf	out4,W		; bcd変換 10のケタ
	movwf	s83			; N-1保存
	call	lcd_Dat

next84
	movf	out3,W		; 1のケタ
	addlw	0x30		; W + 0x30 -> W
	movwf	out3
	xorwf	s84,W		; 1回前表示した数値と比較
	btfsc	STATUS,Z	; Zフラグはゼロ = 変化なし
	goto	next85		; 液晶表示変更なし次へ

; 1のケタ更新
	movlw	0x84
	call	lcd_Cmd
	movf	out3,W		; bcd変換 1のケタ
	movwf	s84			; N-1保存
	call	lcd_Dat


next85
	movf	out2,W		; .1のケタ
	addlw	0x30		; W + 0x30 -> W
	movwf	out2
	xorwf	s85,W		; 1回前表示した数値と比較
	btfsc	STATUS,Z	; Zフラグはゼロ = 変化なし
	goto	next86		; 液晶表示変更なし次へ

; .1のケタ更新
	movlw	0x85
	call	lcd_Cmd
	movf	out2,W		; bcd変換 0.1のケタ
	movwf	s85			; N-1保存
	call	lcd_Dat

next86
	movf	out1,W		; .01のケタ
	addlw	0x30		; W + 0x30 -> W
	movwf	out1
	xorwf	s86,W		; 1回前表示した数値と比較
	btfsc	STATUS,Z	; Zフラグはゼロ = 変化なし
	goto	RA0_FINISH	; 液晶表示変更なし次へ

; .01のケタ更新
	movlw	0x86
	call	lcd_Cmd
	movf	out1,W
	movwf	s86			; N-1保存
	call	lcd_Dat

RA0_FINISH

	return












RA1_ACC
;*****************************************************
; RA1 ACC電圧
;*****************************************************

; ADCON0 	10001
; ADCS1,0	10		Fosc/32
; CHS2,1,0	001		CH1 RA1
;
; ADCON1	10100000
; ADFM		1		右詰
; ADCS2		0
; VCFG1,0	10		VREF+ AVss


	movlw	B'10001001'
	movwf	ADCON0
	movlw	B'10100000'
	bsf		STATUS,RP0
	movwf	ADCON1
	bcf		STATUS,RP0

	call	wt10us
	call	wt10us
	call	wt10us
	call	wt10us
	call	wt10us

	bsf		ADCON0,GO	; A/D変換スタート
RA1adloop
	btfsc	ADCON0,GO
	goto	RA1adloop		; 変換終了してなかったら loop

	bcf		STATUS,RP1
	bcf		STATUS,RP0	; bank0
	movf	ADRESH,W	; 上位
	movwf	RA1valH
	bsf		STATUS,RP0
	movf	ADRESL,W	; 下位は BANK1
	bcf		STATUS,RP0
	movwf	RA1valL

;
; --------------- A/D 変換ここまで


; サンプリング 8回
; 16bit加算
; RA1addX = RA1addX+RA1VALx
;
	movf	RA1valL,W	; 下位
	addwf	RA1addL,F
	btfsc	STATUS,C
	incf	RA1addH,F	; 下位がケタ上がり 上位を 1加算
	movf	RA1valH,W
	addwf	RA1addH,F

; カウンターが 0になったかの判断

	decfsz	RA1count,F
	goto	RA1_FINISH	; カウンターが 0で無いので、処理せず次へ

; 64回サンプリング終了

	movlw	D'64'
	movwf	RA1count	; カウンター初期値へ戻す

; 下位の bit2で四捨五入 bit2 = 00010000

	btfss	RA1addL,4	; bit2が setだったら次を jump
	goto	RA1_0		; bit2=0の場合 繰り上げない


; 1足す処理 最初繰上げのケタだけ設定した後
; 16bit加算
; RA1addX = RA1addX+RA1VALx
;
	movlw	B'00000000'
	movwf	tmpH
	movlw	B'00100000'
	movwf	tmpL		; 繰り上げるケタだけをセット

	addwf	RA1addL,F
	btfsc	STATUS,C
	incf	RA1addH,F	; 下位がケタ上がり 上位を 1加算
	movf	tmpH,W
	addwf	RA1addH,F


RA1_0
;
; 64回加算したので 1/32 5回右シフトして液晶処理
; Max 1023で 20.48V表示のため

	bcf		STATUS,C	; 1回目
	rrf		RA1addH,F	; 右シフトは上位から
	rrf		RA1addL,F
	bcf		STATUS,C
	rrf		RA1addH,F
	rrf		RA1addL,F
	bcf		STATUS,C
	rrf		RA1addH,F
	rrf		RA1addL,F
	bcf		STATUS,C
	rrf		RA1addH,F
	rrf		RA1addL,F
	bcf		STATUS,C
	rrf		RA1addH,F
	rrf		RA1addL,F

	movf	RA1addH,W
	movwf	RA1inpH		; 保存用シンボルへ入れる
	movf	RA1addL,W
	movwf	RA1inpL		;

	movlw	D'0'
	movwf	RA1addH		; 0に戻す
	movwf	RA1addL

RA1_FINISH

	return





RA1_LCD
;*****************************************************
; RA1 LCD表示ルーチン
;*****************************************************
RA1_1
; RA6SWが 0 1画面目だったら電圧の表示をする

	movf	RA6SW		; 0だと 1画面目
	btfsc	STATUS,Z
	goto	RA1_LCDFIN	; 1だったので電圧表示無し

; ACC電圧部分の液晶表示

	movf	RA1inpH,W
	movwf	inpH
	movf	RA1inpL,W
	movwf	inpL

	call	hexdec16

next8B
; 10のけた
	movf	out4,W
	btfss	STATUS,Z	; Z=1 out4が 0だったら次を NOP
	goto	next8B1

next8B_0
; 0で消していい時
	movlw	0x20		; スペースを入れる
	movwf	out4
	goto	next8B2

next8B1
; 1-9のとき
	movf	out4,W
	addlw	0x30		; W + 0x30 -> W
	movwf	out4

next8B2
	xorwf	s8B,W		; 1回前表示した数値と比較
	btfsc	STATUS,Z	; Zフラグはゼロ = 変化なし
	goto	next8C		; 液晶表示変更なし次へ

; 10のケタ更新
	movlw	0x8B
	call	lcd_Cmd
	movf	out4,W		; bcd変換 10のケタ
	movwf	s8B			; N-1保存
	call	lcd_Dat

next8C
	movf	out3,W		; 1のケタ
	addlw	0x30		; W + 0x30 -> W
	movwf	out3
	xorwf	s8C,W		; 1回前表示した数値と比較
	btfsc	STATUS,Z	; Zフラグはゼロ = 変化なし
	goto	next8D		; 液晶表示変更なし次へ

; 1のケタ更新
	movlw	0x8C
	call	lcd_Cmd
	movf	out3,W		; bcd変換 1のケタ
	movwf	s8C			; N-1保存
	call	lcd_Dat


next8D
	movf	out2,W		; .1のケタ
	addlw	0x30		; W + 0x30 -> W
	movwf	out2
	xorwf	s8D,W		; 1回前表示した数値と比較
	btfsc	STATUS,Z	; Zフラグはゼロ = 変化なし
	goto	next8E		; 液晶表示変更なし次へ

; .1のケタ更新
	movlw	0x8D
	call	lcd_Cmd
	movf	out2,W		; bcd変換 0.1のケタ
	movwf	s8D			; N-1保存
	call	lcd_Dat

next8E
	movf	out1,W		; .01のケタ
	addlw	0x30		; W + 0x30 -> W
	movwf	out1
	xorwf	s8E,W		; 1回前表示した数値と比較
	btfsc	STATUS,Z	; Zフラグはゼロ = 変化なし
	goto	RA1_FINISH	; 液晶表示変更なし次へ

; .01のケタ更新
	movlw	0x8E
	call	lcd_Cmd
	movf	out1,W
	movwf	s8E			; N-1保存
	call	lcd_Dat

RA1_LCDFIN

	return




























RA4_SUB
;*****************************************************
; RA4 SUBバッテリー電圧
;*****************************************************

; ADCON0 	10100
; ADCS1,0	10		Fosc/32
; CHS2,1,0	100		CH4 RA4
;
; ADCON1	10100000
; ADFM		1		右詰
; ADCS2		0
; VCFG1,0	10		VREF+ AVss


	movlw	B'10100001'
	movwf	ADCON0
	movlw	B'10100000'
	bsf		STATUS,RP0
	movwf	ADCON1
	bcf		STATUS,RP0

	call	wt10us
	call	wt10us
	call	wt10us
	call	wt10us
	call	wt10us

	bsf		ADCON0,GO	; A/D変換スタート
RA4adloop
	btfsc	ADCON0,GO
	goto	RA4adloop		; 変換終了してなかったら loop

	bcf		STATUS,RP1
	bcf		STATUS,RP0	; bank0
	movf	ADRESH,W	; 上位
	movwf	RA4valH
	bsf		STATUS,RP0
	movf	ADRESL,W	; 下位は BANK1
	bcf		STATUS,RP0
	movwf	RA4valL

;
; --------------- A/D 変換ここまで


; サンプリング 8回
; 16bit加算
; RA4addX = RA4addX+RA4VALx
;
	movf	RA4valL,W	; 下位
	addwf	RA4addL,F
	btfsc	STATUS,C
	incf	RA4addH,F	; 下位がケタ上がり 上位を 1加算
	movf	RA4valH,W
	addwf	RA4addH,F

; カウンターが 0になったかの判断

	decfsz	RA4count,F
	goto	RA4_FINISH	; カウンターが 0で無いので、処理せず次へ

; 64回サンプリング終了

	movlw	D'64'
	movwf	RA4count	; カウンター初期値へ戻す

; 下位の bit2で四捨五入 bit2 = 00000100

	btfss	RA4addL,4	; bit2が setだったら次を jump
	goto	RA4_0		; bit2=0の場合 繰り上げない


; 1足す処理 最初繰上げのケタだけ設定した後
; 16bit加算
; RA4addX = RA4addX+RA4VALx
;
	movlw	B'00000000'
	movwf	tmpH
	movlw	B'00100000'
	movwf	tmpL		; 繰り上げるケタだけをセット

	addwf	RA4addL,F
	btfsc	STATUS,C
	incf	RA4addH,F	; 下位がケタ上がり 上位を 1加算
	movf	tmpH,W
	addwf	RA4addH,F


RA4_0
;
; 64回加算したので 1/32 5回右シフトして液晶処理
; Max 1023で 20.48V表示のため

	bcf		STATUS,C	; 1回目
	rrf		RA4addH,F	; 右シフトは上位から
	rrf		RA4addL,F
	bcf		STATUS,C
	rrf		RA4addH,F
	rrf		RA4addL,F
	bcf		STATUS,C
	rrf		RA4addH,F
	rrf		RA4addL,F
	bcf		STATUS,C
	rrf		RA4addH,F
	rrf		RA4addL,F
	bcf		STATUS,C
	rrf		RA4addH,F
	rrf		RA4addL,F

	movf	RA4addH,W
	movwf	inpH		; 変換用シンボルへ入れる
	movf	RA4addL,W
	movwf	inpL		;

	movlw	D'0'
	movwf	RA4addH		; 0に戻す
	movwf	RA4addL

RA4_1
; RA6SWが 0 1画面目だったら電圧の表示をする

	movf	RA6SW		; 0だと 1画面目
	btfsc	STATUS,Z
	goto	RA4_FINISH	; 1だったので電圧表示無し

; バッテリー電圧部分の液晶表示

	call	hexdec16

nextC3
; 10のけた
	movf	out4,W
	btfss	STATUS,Z	; Z=1 out4が 0だったら次を NOP
	goto	nextC31

nextC3_0
; 0で消していい時
	movlw	0x20		; スペースを入れる
	movwf	out4
	goto	nextC32

nextC31
; 1-9のとき
	movf	out4,W
	addlw	0x30		; W + 0x30 -> W
	movwf	out4

nextC32
	xorwf	sC3,W		; 1回前表示した数値と比較
	btfsc	STATUS,Z	; Zフラグはゼロ = 変化なし
	goto	nextC4		; 液晶表示変更なし次へ

; 10のケタ更新
	movlw	0xC3
	call	lcd_Cmd
	movf	out4,W		; bcd変換 10のケタ
	movwf	sC3			; N-1保存
	call	lcd_Dat

nextC4
	movf	out3,W		; 1のケタ
	addlw	0x30		; W + 0x30 -> W
	movwf	out3
	xorwf	sC4,W		; 1回前表示した数値と比較
	btfsc	STATUS,Z	; Zフラグはゼロ = 変化なし
	goto	nextC5		; 液晶表示変更なし次へ

; 1のケタ更新
	movlw	0xC4
	call	lcd_Cmd
	movf	out3,W		; bcd変換 1のケタ
	movwf	sC4			; N-1保存
	call	lcd_Dat


nextC5
	movf	out2,W		; .1のケタ
	addlw	0x30		; W + 0x30 -> W
	movwf	out2
	xorwf	sC5,W		; 1回前表示した数値と比較
	btfsc	STATUS,Z	; Zフラグはゼロ = 変化なし
	goto	nextC6		; 液晶表示変更なし次へ

; .1のケタ更新
	movlw	0xC5
	call	lcd_Cmd
	movf	out2,W		; bcd変換 0.1のケタ
	movwf	sC5			; N-1保存
	call	lcd_Dat

nextC6
	movf	out1,W		; .01のケタ
	addlw	0x30		; W + 0x30 -> W
	movwf	out1
	xorwf	sC6,W		; 1回前表示した数値と比較
	btfsc	STATUS,Z	; Zフラグはゼロ = 変化なし
	goto	RA4_FINISH	; 液晶表示変更なし次へ

; .01のケタ更新
	movlw	0xC6
	call	lcd_Cmd
	movf	out1,W
	movwf	sC6			; N-1保存
	call	lcd_Dat

RA4_FINISH

	return












RA2_KIJYUN
;*****************************************************
; RA2 切り替え比較電圧
;*****************************************************

; ADCON0 	10010
; ADCS1,0	10		Fosc/32
; CHS2,1,0	010		CH2 RA2
;
; ADCON1	10100000
; ADFM		1		右詰
; ADCS2		0
; VCFG1,0	10		VREF+ AVss


	movlw	B'10010001'
	movwf	ADCON0
	movlw	B'10100000'
	bsf		STATUS,RP0
	movwf	ADCON1
	bcf		STATUS,RP0

	call	wt10us
	call	wt10us
	call	wt10us
	call	wt10us
	call	wt10us

	bsf		ADCON0,GO	; A/D変換スタート
RA2adloop
	btfsc	ADCON0,GO
	goto	RA2adloop		; 変換終了してなかったら loop

	bcf		STATUS,RP1
	bcf		STATUS,RP0	; bank0
	movf	ADRESH,W	; 上位
	movwf	RA2valH
	bsf		STATUS,RP0
	movf	ADRESL,W	; 下位は BANK1
	bcf		STATUS,RP0
	movwf	RA2valL

;
; --------------- A/D 変換ここまで


; サンプリング 64
; 16bit加算
; RA2addX = RA2addX+RA2VALx
;
	movf	RA2valL,W	; 下位
	addwf	RA2addL,F
	btfsc	STATUS,C
	incf	RA2addH,F	; 下位がケタ上がり 上位を 1加算
	movf	RA2valH,W
	addwf	RA2addH,F

; カウンターが 0になったかの判断

	decfsz	RA2count,F
	goto	RA2_FINISH	; カウンターが 0で無いので、処理せず次へ

; 8回サンプリング終了

	movlw	D'64
	movwf	RA2count	; カウンター初期値へ戻す

; 下位の bit2で四捨五入 bit2 = 00010000

	btfss	RA2addL,4	; bit2が setだったら次を jump
	goto	RA2_0		; bit2=0の場合 繰り上げない


; 1足す処理 最初繰上げのケタだけ設定した後
; 16bit加算
; RA2addX = RA2addX+RA2VALx
;
	movlw	B'00000000'
	movwf	tmpH
	movlw	B'00100000'
	movwf	tmpL		; 繰り上げるケタだけをセット

	addwf	RA2addL,F
	btfsc	STATUS,C
	incf	RA2addH,F	; 下位がケタ上がり 上位を 1加算
	movf	tmpH,W
	addwf	RA2addH,F


RA2_0
;
; 64回加算したので 1/32  5回右シフトして液晶処理
; Max 1023で 20.48V表示のため

	bcf		STATUS,C	; 1回目
	rrf		RA2addH,F	; 右シフトは上位から
	rrf		RA2addL,F
	bcf		STATUS,C
	rrf		RA2addH,F
	rrf		RA2addL,F
	bcf		STATUS,C
	rrf		RA2addH,F
	rrf		RA2addL,F
	bcf		STATUS,C
	rrf		RA2addH,F
	rrf		RA2addL,F
	bcf		STATUS,C
	rrf		RA2addH,F
	rrf		RA2addL,F

	movf	RA2addH,W
	movwf	inpH		; 変換用シンボルへ入れる
	movf	RA2addL,W
	movwf	inpL		;

	movlw	D'0'
	movwf	RA2addH		; 0に戻す
	movwf	RA2addL

RA2_1
; RA6SWが 0 1画面目だったら電圧の表示をする

	movf	RA6SW		; 0だと 1画面目
	btfss	STATUS,Z
	goto	RA2_FINISH	; 0だったので電圧表示無し

; バッテリー電圧部分の液晶表示

	call	hexdec16

nextaC7
; 10のけた
	movf	out4,W
	btfss	STATUS,Z	; Z=1 out4が 0だったら次を NOP
	goto	nextaC71

nextaC7_0
; 0で消していい時
	movlw	0x20		; スペースを入れる
	movwf	out4
	goto	nextaC72

nextaC71
; 1-9のとき
	movf	out4,W
	addlw	0x30		; W + 0x30 -> W
	movwf	out4

nextaC72
	xorwf	aC7,W		; 1回前表示した数値と比較
	btfsc	STATUS,Z	; Zフラグはゼロ = 変化なし
	goto	nextaC8		; 液晶表示変更なし次へ

; 10のケタ更新
	movlw	0xC7
	call	lcd_Cmd
	movf	out4,W		; bcd変換 10のケタ
	movwf	aC7			; N-1保存
	call	lcd_Dat

nextaC8
	movf	out3,W		; 1のケタ
	addlw	0x30		; W + 0x30 -> W
	movwf	out3
	xorwf	aC8,W		; 1回前表示した数値と比較
	btfsc	STATUS,Z	; Zフラグはゼロ = 変化なし
	goto	nextaCA		; 液晶表示変更なし次へ

; 1のケタ更新
	movlw	0xC8
	call	lcd_Cmd
	movf	out3,W		; bcd変換 1のケタ
	movwf	aC8			; N-1保存
	call	lcd_Dat


nextaCA
	movf	out2,W		; .1のケタ
	addlw	0x30		; W + 0x30 -> W
	movwf	out2
	xorwf	aCA,W		; 1回前表示した数値と比較
	btfsc	STATUS,Z	; Zフラグはゼロ = 変化なし
	goto	nextaCC		; 液晶表示変更なし次へ

; .1のケタ更新
	movlw	0xCA
	call	lcd_Cmd
	movf	out2,W		; bcd変換 0.1のケタ
	movwf	aCA			; N-1保存
	call	lcd_Dat

nextaCC
	movf	out1,W		; .01のケタ
	addlw	0x30		; W + 0x30 -> W
	movwf	out1
	xorwf	aCC,W		; 1回前表示した数値と比較
	btfsc	STATUS,Z	; Zフラグはゼロ = 変化なし
	goto	RA2_FINISH	; 液晶表示変更なし次へ

; .01のケタ更新
	movlw	0xCB
	call	lcd_Cmd
	movf	out1,W
	movwf	aCC			; N-1保存
	call	lcd_Dat

RA2_FINISH

	return




initEEPROMRead


	bcf		STATUS,RP0
	bcf		STATUS,RP1

	movlw	0x01
	bsf		STATUS,RP1
	movwf	EEADR
	bsf		STATUS,RP0
	bsf		EECON1,RD
	bcf		STATUS,RP0
	movf	EEDATA,W
	bcf		STATUS,RP1
	movwf	EngStCountH

	movlw	0x02
	bsf		STATUS,RP1
	movwf	EEADR
	bsf		STATUS,RP0
	bsf		EECON1,RD
	bcf		STATUS,RP0
	movf	EEDATA,W
	bcf		STATUS,RP1
	movwf	EngStCountL

	bcf		STATUS,RP0
	bcf		STATUS,RP1

	return





LCDN1CLR
;***************************************************************
;
; SW切り替えて画面が変わったときだけ N-1の値を全てクリアーする
;
;***************************************************************

	movlw	H'FF'

	movwf	s83
	movwf	s84
	movwf	s85
	movwf	s86
	movwf	s8B
	movwf	s8C
	movwf	s8D
	movwf	s8E
	movwf	sC3
	movwf	sC4
	movwf	sC5
	movwf	sC6
	movwf	sC3
	movwf	sC9
	movwf	sCC

	movwf	a89
	movwf	a8A
	movwf	a8B
	movwf	a8C
	movwf	a8D

	movwf	aC7
	movwf	aC8
	movwf	aCA
	movwf	aCC

LCDN1FIN

	return




























initA
	bcf		STATUS,RP1
	bcf		STATUS,RP0	; bank0
	clrf	PORTA
	clrf	PORTB
	clrwdt
	bsf		STATUS,RP0	; bank1
	bsf		OPTION_REG,7
	movlw	B'00000000'	; 0 = Output
	movwf	TRISB
	movlw	B'01111111'	; 1 = input
	movwf	TRISA
	bcf		STATUS,RP0	; bank0
	clrf	PORTB

;内部クロック設定 111 = 8MHz
	bsf		STATUS,RP0
	bsf		OSCCON,IRCF2
	bsf		OSCCON,IRCF1
	bsf		OSCCON,IRCF0

;	movlw	B'01110000'
;	movwf	OSCCON
	bcf		STATUS,RP0	; bank0

	return



initB

	bsf		STATUS,RP0
	movlw	B'00011111'	; AN0-AN4間で Analog入力
	movwf	ANSEL
	bcf		STATUS,RP0



	return



initC
;
; 定数領域のクリアー

	movlw	D'64'
	movwf	RA0count	; BAT
	movwf	RA1count	; ACC
	movwf	RA2count	; 切り替え
	movwf	RA4count	; SUB


	movlw	D'100'
	movwf	AccTimer2

	movlw	D'50'
	movwf	BatTimer2

	movlw	D'18'
	movwf	BatTimer1
	movwf	AccTimer1

	movlw	D'0'
	movwf	RA6Timer1

	movlw	D'0'
	movwf	RA6Timer2


	movlw	D'0'
	movwf	RA0addH
	movwf	RA0addL
	movwf	RA1addH
	movwf	RA1addL
	movwf	RA2addH
	movwf	RA2addL
	movwf	RA4addH
	movwf	RA4addL
	movwf	inpL
	movwf	inpH

	movlw	D'0'
	movwf	BatRelay
	movwf	AccLowHi
	movwf	AccRelay

	movwf	RA6SWT

	movlw	D'1'

	return

initD
	call	lcd_Init

;
;【Control Commandの一覧表】
; Commnad     DB7 6 5 4 3 2 1 0    説    明   
;Clear Display     0 0 0 0 0 0 0 1  全消去、CursorはHomeへ
;Cursor At Home    0 0 0 0 0 0 1 *  表示内容は変化なし
;Entry Mode Set    0 0 0 0 0 1 I/D S  I/D=Increment/Decrement
;                        S=With Display Shift
;Display On/Off    0 0 0 0 1 D C B  D=Display C=Cursor B=Blink
;Cursor/Dislay Shift 0 0 0 1 S/CR/L * *  S/C=Display/Cursor R/L=Right/Left
;Function Set     0 0 1 DL N F * *  DL=8/4Bit N=2/1Line F=Large/Small
;CGRAM Address Set  0 1  CCRAM Address   Character Generator RAM
;DDRAM Address Set  1 L  DDRAM Address   Display RAM L=Line
;Busy Flag/Adrs Read BF  Address       BF=Busy Flag
;Data Write        8 Bits Data      CGRAM/DDRAM Common
;Data Read         8 Bits Data      CGRAM/DDRAM Common 
;
	movlw	B'00000110'
	call	lcd_Cmd
	movlw	B'00001100'
	call	lcd_Cmd
	return


initLCDA
;
; 液晶表示
; 通常時の表示
;
;   0123456789ABCDEF
;  +----------------
; 8|BAT     ACC        
; C|SUB     S A          

	movlw	0x80
	call	lcd_Cmd
	movlw	"B"
	call	lcd_Dat
	movlw	"A"
	call	lcd_Dat
	movlw	"T"
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	"A"
	call	lcd_Dat
	movlw	"C"
	call	lcd_Dat
	movlw	"C"
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat

	movlw	0xC0
	call	lcd_Cmd
	movlw	"S"
	call	lcd_Dat
	movlw	"U"
	call	lcd_Dat
	movlw	"B"
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	"B"
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	"A"
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat


	return


initLCDB
;
; 液晶表示
; SW ON時の表示
;
;   0123456789ABCDEF
;  +----------------
; 8|EngStart         
; C|Thresh   .      


	movlw	0x80
	call	lcd_Cmd
	movlw	"E"
	call	lcd_Dat
	movlw	"n"
	call	lcd_Dat
	movlw	"g"
	call	lcd_Dat
	movlw	"S"
	call	lcd_Dat
	movlw	"t"
	call	lcd_Dat
	movlw	"a"
	call	lcd_Dat
	movlw	"r"
	call	lcd_Dat
	movlw	"t"
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat

	movlw	0xC0
	call	lcd_Cmd
	movlw	"T"
	call	lcd_Dat
	movlw	"h"
	call	lcd_Dat
	movlw	"r"
	call	lcd_Dat
	movlw	"e"
	call	lcd_Dat
	movlw	"s"
	call	lcd_Dat
	movlw	"h"
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	"."
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	"V"
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat
	movlw	" "
	call	lcd_Dat

	return












;
;
;----------------------------------------
;- LCD Initial operation                -
;- Use          call    lcd_Init        -
;----------------------------------------
;
lcd_Init
	bcf	LCDPORT,LCD_RS
	bcf	LCDPORT,LCD_E
	movlw	150		; 15mS wait
	call	waitOpe
	movlw	B'00110000'
	call	lcd_Out
	movlw	50		; 5mS wait
	call	waitOpe
	movlw	B'00110000'
	call	lcd_Out
	call	wt100us
	movlw	B'00110000'
	call	lcd_Out
	call	wt100us
	movlw	B'00100000'
	call	lcd_Out
	call	wt100us
	movlw	B'00101000'
	call	lcd_Cmd
	movlw	B'00001000'
	call	lcd_Cmd
	movlw	B'00000001'
	call	lcd_Cmd
	movlw	17		; 1.7mS wait
	call	waitOpe
	return
;
;
;
;----------------------------------------
;- COMMAND to LCD operation             -
;- Use          movlw   COMMAND         -
;-              call    lcd_Cmd         -
;- DATA    to LCD operation             -
;- Use          movlw   DATA            -
;-              call    lcd_Dat         -
;----------------------------------------
;
lcd_Cmd				; Command to LCD
	bcf	LCDPORT,LCD_RS
	goto	lcd_Out4
lcd_Dat				; Data to LCD
	bsf	LCDPORT,LCD_RS
lcd_Out4
	movwf	lcdTmp1		; Entry :w = Command or Data
	movlw	B'11110000'
	andwf	lcdTmp1,w
	call	lcd_Out
	swapf	lcdTmp1,f
	movlw	B'11110000'
	andwf	lcdTmp1,w
	call	lcd_Out
	call	wt100us
	return
;
;
;
;----------------------------------------
;- 4bit DATA to LCD operation           -
;- Use          movlw   B'????0000'     -
;-              call    lcd_Out         -
;----------------------------------------
;
lcd_Out
	movwf	lcdTmp0
	movlw	B'00001111'
	andwf	LCDPORT,f
	movf	lcdTmp0,w
	iorwf	LCDPORT,f
	bsf	LCDPORT,LCD_E
	nop
	bcf	LCDPORT,LCD_E
	return
;
;
;
waitOpe				; Wait operation
	movwf	lcdTim1		; Wait time = W * 100uS
waitOp1
	call	wt100us
	decfsz	lcdTim1,f
	goto	waitOp1
	return
;
;
;
wt100us				; 100uS wait operation
	movlw	W100US
	movwf	lcdTim0
wt100u1
	decfsz	lcdTim0,f
	goto	wt100u1
	return
;

wt10us				; 10us wait operation
	nop				; 10MHzだと 1サイクル 0.4μsなので
	nop				; 25サイクル実行すると 10μsとなる
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	return


;
; 長時間用のタイマー
;

;100μsec
DLYS
	movlw	W100US
	MOVWF 	CNT1
TM_1
	DECFSZ	CNT1,F
	GOTO	TM_1
	NOP
	RETURN

;2msec
DLY2m
DLYM
	MOVLW	d'21'
	MOVWF	CNT2
TM_2
	CALL	DLYS
	DECFSZ	CNT2,F
	GOTO	TM_2
	RETURN

;5msec
DLY5m
DLYL
	MOVLW	d'51'
	MOVWF	CNT3
TM_3
	CALL	DLYS
	DECFSZ	CNT3,F
	GOTO	TM_3
	RETURN

DLY20m
	MOVLW	d'200'
	MOVWF	CNT3
DLY20m_1
	CALL	DLYS
	DECFSZ	CNT3,F
	GOTO	DLY20m_1
	RETURN


DLY100m
	MOVLW	d'20'
	MOVWF	CNT4
DLY100m_1
	CALL	DLYL
	DECFSZ	CNT4,F
	GOTO	DLY100m_1
	RETURN

;1sec
WAIT1SEC
	MOVLW	d'201'
	MOVWF	CNT4
TM_4
	CALL	DLYL
	DECFSZ	CNT4,F
	GOTO	TM_4
	RETURN


hexdec16:	;16ビット(2バイト)数値を10進数5桁のBCD値に変換する
		;引き数は inpH(上位),inpL(下位) の2バイト
		;結果は out5,out4,out3,out2,out1 に得られる。
		;右の out1 が下位の数になる
		;使用変数宣言の際に out1 の下で、ラベル名 dec_top: を記述しておくこと。

;------------------------------  hexdec16 での使用変数

;inpH		ds	1		; 変換したい値(16ビット。変換後は壊れる)
;inpL		ds	1		;〜下位
;out5		ds	1		;10進格納場所(5バイト)
;out4		ds	1
;out3		ds	1
;out2		ds	1
;out1		ds	1		;〜下位
;dec_top:				;間接アクセス用ラベル
;srlc1		ds	1		; カウンタ(サブルーチンで使用)
;srwk1		ds	1		; 一時余り格納場所(サブルーチンで使用)

;------------------------------
;					;使用例
;		movlw	0ffh		;ffffh=65535
;		movwf	inpH
;		movlw	0ffh
;		movwf	inpL
;		call	hexdec16
;
;------------------------------

		movlw	dec_top		;格納場所初期値
		movwf	4h		;4h=fsr
		call	devide		;最下位変換
		call	devide
		call	devide
		call	devide
		call	devide		;最上位変換

		return

devide:					;÷10サブルーチン (10で除算)
		movlw	16		;16ビットくり返し
		movwf	srlc1
		clrf	srwk1
devide0:
		bcf	3h,0		;キャリフラグのクリア
		rlf	inpL,1
		rlf	inpH,1
		rlf	srwk1,1
		movlw	11110110b
		addwf	srwk1,0
		btfsc	3h,0
		movwf	srwk1
		btfsc	3h,0
		incf	inpL,1
		decfsz	srlc1,1
		goto	devide0
		decf	4h,1		;4h=fsr
		movf	srwk1,0
		movwf	0h		;余り (0h=indirect)

		return




hex2oct:
;
; 自作 10bit A/Dから OCTAL 4ケタ変換
; out5は常に 0
; BCD 4〜1に 0〜7の数字が入る
; 元の数字は inpHと inp Lに入れておく
;

	movlw	B'00000111' ; 1のケタ
	andwf	inpL,W
	movwf	out1		; 1のケタ保存

	movlw	B'00111000' ; 10のケタ
	andwf	inpL,W
	movwf	octtmp		; 一時保存
	rrf		octtmp,1	; 1bit右 octtmpへ上書き
	rrf		octtmp,1	; 1bit右 octtmpへ上書き
	rrf		octtmp,1	; 1bit右 octtmpへ上書き
	movlw	B'00000111' ; 1のケタのみ
	andwf	octtmp,W	; 必要なところだけ mask
	movwf	out2		; 10のケタ保存
	
	movlw	B'11000000' ; 100のケタ
	andwf	inpL,W
	movwf	octtmp		; 一時保存
	rrf		octtmp,1	; 1bit右 octtmpへ上書き
	rrf		octtmp,1	; 1bit右 octtmpへ上書き
	rrf		octtmp,1	; 1bit右 octtmpへ上書き
	rrf		octtmp,1	; 1bit右 octtmpへ上書き
	rrf		octtmp,1	; 1bit右 octtmpへ上書き
	rrf		octtmp,1	; 1bit右 octtmpへ上書き
	movlw	B'00000001' ; 100のケタ
	andwf	inpH,W
	movwf	octtmp2		; 一時保存
	rlf		octtmp2,1	; 1bit左 octtmp2へ上書き
	rlf		octtmp2,1	; 1bit左 octtmp2へ上書き
	movlw	B'00000100'	; 必要なところだけ mask
	andwf	octtmp2,W
	iorwf	octtmp,W	; さっき計算した下 2bitと orする
	movwf	out3		; 100のケタ保存

	movlw	B'00001110' ; 1000のケタ
	andwf	inpH,W
	movwf	octtmp		; 一時保存
	rrf		octtmp,1	; 1bit右 octtmpへ上書き
	movlw	B'00000111'	; 必要なところだけ mask
	andwf	octtmp,W
	movwf	out4		; 1000のケタ保存

	movlw	B'01110000' ; 10000のケタ
	andwf	inpH,W
	movwf	octtmp		; 一時保存
	rrf		octtmp,1	; 1bit右 octtmpへ上書き
	rrf		octtmp,1	; 1bit右 octtmpへ上書き
	rrf		octtmp,1	; 1bit右 octtmpへ上書き
	rrf		octtmp,1	; 1bit右 octtmpへ上書き
	movlw	B'00000111'	; 必要なところだけ mask
	andwf	octtmp,W
	movwf	out5		; 10000ケタ目は常にゼロ
	
	return








	END