;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			ＰＩＣ１６Ｆ６４８Ａ　ＢＣＤ変換サブルーチン　実験用
;
;			８桁７セグメントＬＥＤ表示コントロール
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


		LIST	P=PIC16F648A
		INCLUDE	P16F648A.inc
		
;
;bit4,1,0=010		_HS_OSC		ex x'tal osc
;bit2=0				_WDT_OFF	watch dog timer off
;bit3=1				_PWRTE_ON	power on reset on
;bit5=0				_MCLRE_OFF	5pin int off = RA5 on
;bit6=0				_BODEN_OFF	brown out off
;bit7=0				_LVP_OFF	low power off
;bit8=0				_CPD_OFF	data memory protection off
;bit9-12=0						Uninplemented
;bit13=1			_CP_OFF		FLASH memory protection off
;
		
		__CONFIG	B'0010000000001010'
	
; _HS_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _BODEN_OFF & _LVP_OFF

;		ワークエリア定義
;
;		使用していないのもあります
;

dspdt0		equ			020h		;表示するデータ32ビット16進バイナリ
dspdt1		equ			021h		;実際は24ビットしか使用しない
dspdt2		equ			022h
dspdt3		equ			023h
digit12		equ			024h		;表示する桁BCDデータ
digit34		equ			025h
digit56		equ			026h
digit78		equ			027h
colum		equ			028h		;現在の桁位置
cnt0		equ			029h
cnt1		equ			02ah
cnt2		equ			02bh
cnt3		equ			02ch
tmp0		equ			02dh
tmp1		equ			02eh
bcdw0		equ			02fh
bcdw1		equ			030h
cary1		equ			031h
cary2		equ			032h
cary3		equ			033h
shift		equ			034h
work1		equ			035h
work2		equ			036h
binw0		equ			037h
binw1		equ			038h
ccnt0		equ			039h
ccnt1		equ			03ah

;

			ORG			0h
			goto		init
			ORG			04h
			goto		init

			org			05h
			
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			ＢＣＤからLEDセグメントへの変換　Ver2
;
;	注意			このルーチンのアドレス範囲の設定が必要
;				PCLATHにその上位アドレスを入れること
;	入力			Wレジスタに表示バイナリデータを入れてコール
;				ドットも表示させる時は、ビット4=1
;	出力			Wレジスタに8ビットポート出力データを入れてリターン
;	使用ワーク		tmp1
;	ELD512 anodo common	PORT=0　then　seg=on
;
;		a				RB0=a	RB4=e
;	f		b			RB1=b	RB5=f
;		g				RB2=c	RB6=g
;	e		c			RB3=d	RB7=Dp
;		d		dp		
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

get_7seg
			andlw		01fh		;下位5ビット取り出し
			addwf		PCL,F
			retlw		B'11000000'	;Code 0 abcdef
			retlw		B'11111001'	;Code 1 bc
			retlw		B'10100100'	;Code 2 abdeg
			retlw		B'10110000'	;Code 3 abcdg
			retlw		B'10011001'	;Code 4 bcfg
			retlw		B'10010010'	;Code 5 acdfg
			retlw		B'10000010'	;Code 6 cdefg
			retlw		B'11111000'	;Code 7 abc
			retlw		B'10000000'	;Code 8 abcdefg
			retlw		B'10011000'	;Code 9 abcfg

			retlw		B'10001000'	;Code A abcefg
			retlw		B'10000011'	;Code B cdefg
			retlw		B'11000110'	;Code C adef
			retlw		B'10100001'	;Code D bcdeg
			retlw		B'10000110'	;Code E adefg
			retlw		B'10001110'	;Code F aefg

			retlw		B'01000000'	;Code 0. abcdef
			retlw		B'01111001'	;Code 1. bc
			retlw		B'00100100'	;Code 2. abdeg
			retlw		B'00110000'	;Code 3. abcdg
			retlw		B'00011001'	;Code 4. bcfg
			retlw		B'00010010'	;Code 5. acdfg
			retlw		B'00000010'	;Code 6. cdefg
			retlw		B'01111000'	;Code 7. abc
			retlw		B'00000000'	;Code 8. abcdefg
			retlw		B'00011000'	;Code 9. abcfg

			retlw		B'00001000'	;Code A. abcefg
			retlw		B'00000011'	;Code B. cdefg
			retlw		B'01000110'	;Code C. adef
			retlw		B'00100001'	;Code D. bcdeg
			retlw		B'00000110'	;Code E. adefg
			retlw		B'00001110'	;Code F. aefg


;
;		初期設定
;

init
			movlw		07h
			movwf		CMCON		;アナログポート→デジタル
			bsf			STATUS,RP0	;バンク１に切替
			BCF			STATUS,RP1
			movlw		038h		;00111000b
			movwf		TRISA		;RA0-RA2 出力、RA3-RA5入力モード
			clrf    	TRISB		;RBポート全出力モード
			BCF			STATUS,RP0	;バンク０に切替




			

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		メインプログラム(実験用)
;
;		6桁16進数を入力、それを１０進８桁に変換表示
;
;		入力モード		1桁目でドットを点滅し、16進数を入力待ち、6桁まで
;					デフォルトはゼロ、SW3を押す度に、入力数字は大きくなるが、fの次は0
;		入力16進数	ＳＷ３		0-Fと変化する、カーソルつき
;		桁確定		ＳＷ４		現在桁を桁上げし、その下位桁入力となる
;		変換ボタン		ＳＷ５		出力モードへ
;
;		出力モード		入力モードで入力された６桁１６進数を８桁１０進数に変換表示
;					ＳＷ４		入力モードへ
;
;		
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


main
			call		linputb
			call		bcd
mlp0
			call		disp_all
			call		sw4chk
			iorlw		0h
			btfsc		STATUS,Z	;
			goto		mlp0
			goto		main




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		１６進データ　ライン入力サブルーチン
;
;		6桁16進数の数を１行入力受付、
;		16進数入力	ＳＷ３		0-Fと順に変化する、カーソルつきでLEDに反映
;		１字確定		ＳＷ４		現在桁を桁上げし、その下位桁入力となる
;		１行確定		ＳＷ５		終了
;
;		入力モード		1桁目でドットを点滅し、16進数を入力待ち、６桁まで
;					デフォルトはゼロ、SW3を押す度に、入力数字は大きくなるが、fの次は0
;					
;		出力			１６進バイナリワーク、dspdt0~2の３バイトに出力
;
;		使用ワーク		scnt0		カーソル点滅の間隔時間設定
;					scnt1
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



linputb
			clrf		dspdt0
			clrf		dspdt1
			clrf		dspdt2
linpb0		;loop start
			movlw		010h
			movwf		ccnt0		;ループ回数
			;sw3 check
linpb2		call		disp_6hd	;カーソル表示オン
			call		sw3chk
			iorlw		0h
			btfss		STATUS,Z	;z=0(sw3_on) then goto inpbs3
			call		pudt		;1桁目の表示数を1アップ
			
			;sw4 check
			call		sw4chk
			iorlw		0h
			btfss		STATUS,Z	;z=0(sw4_on) then goto inpbs4
			call		clmup		;各桁を桁上げ
			
			;sw5 check
			call		sw5chk
			iorlw		0h
			btfss		STATUS,Z	;z=0(sw5_on) then goto inpbs5
			return

			decf		ccnt0,F		;z=1(sw_all_off)
			btfss		STATUS,Z	;if ccnt0=0 then goto inpb3
			goto		linpb2		;if ccnt0=x then goto inpb2
			
linpb3
			movlw		010h
			movwf		ccnt0		;ループ回数
			;sw3 check
linpb5		call		disp_6hn	;カーソル表示オフ
			call		sw3chk
			iorlw		0h
			btfss		STATUS,Z	;z=0(sw3_on) then goto inpbs3
			call		pudt		;1桁目の表示数を1アップ
			
			;sw4 check
			call		sw4chk
			iorlw		0h
			btfss		STATUS,Z	;z=0(sw4_on) then goto inpbs4
			call		clmup		;各桁を桁上げ
			
			;sw5 check
			call		sw5chk
			iorlw		0h
			btfss		STATUS,Z	;z=0(sw5_on) then goto inpbs5
			return

			decf		ccnt0,F		;z=0(sw_all_off)
			btfss		STATUS,Z	;if tmp1=0 then goto main loop
			goto		linpb5		;if tmp1=x then goto linpb5
			goto		linpb0		;main loop



;
;			sw3_on return01
;			sw3_off return00
;

sw3chk		btfsc   	PORTA,RA3	;RA3=0(sw3 on) then next skip
			goto		sw3ch0		;RA3=1(sw3 off) then return00
			call		wait20m		;チャタリング防止
			btfsc		PORTA,RA3	;ra3=0(sw3 on) then return01
sw3ch0		retlw		0h
			call		wait100m
			retlw		01h


;
;			sw4_on return01
;			sw4_off return00
;

sw4chk		btfsc   	PORTA,RA4	;RA4=0(sw3 on) then next skip
			goto		sw4ch0		;RA4=1(sw3 off) hen return00
			call		wait20m		;チャタリング防止
			btfsc		PORTA,RA4	;ra4=0(sw3 on) hen return01
sw4ch0		retlw		0h
			call		wait100m
			retlw		01h

;
;			sw5_on return01
;			sw5_off return00
;

sw5chk		btfsc		PORTA,RA5	;RA5=0(sw3 on) then next skip
			goto		sw5ch0		;RA5=1(sw3 off) hen return00
			call		wait20m		;チャタリング防止
			btfsc		PORTA,RA5	;ra5=0(sw3 on) hen return01
sw5ch0		retlw		0h
			call		wait100m
			retlw		01h

;
;			1桁目のドットの点灯あるいは消灯
;			データはそのまま
;

corsor_on
			movf		PORTA,W		;xxxxx000b 11111000b=F8H
			andlw		B'11111000'
			movwf		PORTA
			movlw		07fh
			movwf		PORTB		;cursor on
			return

corsor_off	movf		PORTA,W		;xxxxx000b 11111000b=F8H
			andlw		B'11111000'
			movwf		PORTA
			movlw		0ffh
			movwf		PORTB		;cursor on
			return



;
;
;		16進バイナリデータ1桁目（最下位4ビット）のデータを1増やす（Fの次は0)
;		その桁以上のビットには影響しない
;
;		入力		dspdt0下位4ビット
;		出力		dspdt0下位4ビットおよびw_reg
;
;		使用ワーク	binw0
;				binw1
;

pudt
			movf		dspdt0,W	;バイナリデータ1バイト目
			andlw		0fh			;
			movwf		binw0		;下位4ビットをbinw0に保存
			incf		binw0,F		;binw0=binw0+1
			addlw		01h
			btfss		STATUS,DC
			goto		pudt1		;桁上り無ならpudt1へ
			clrf		binw0		;桁上り発生ならゼロにする
pudt1		movf		dspdt0,W
			andlw		0f0h		;下位4ビットを消去
			movwf		binw1		;
			movf		binw0,W
			iorwf		binw1,W		;上位下位合成
			movwf		dspdt0
			return


;
;		桁上げ処理サブルーチン
;
;		6桁目に存在していたデータは破棄される
;
;		入力		dspdt0～dspdt2の3バイト
;		出力		dspdt0～dspdt2の3バイト
;
;		使用ワーク	binw0
;				binw1	上位4ビット用一時ワーク
;


clmup
			;3バイト目の下位データを上位に移動
			movf		dspdt2,W
			movwf		binw1
			swapf		binw1,W		;下位4ビットを上位4ビットへ移動
			andlw		0f0h		;下位4ビット（元の上位4ビット)破棄
			movwf		binw1		;元の下位4ビットを上位4ビットとしてワークに保存

			;2バイト目の上位データを3バイト目の下位データへ移動
			movf		dspdt1,W
			movwf		binw0
			swapf		binw0,W
			andlw		0fh			;W(下位4ビット)=2バイト目の上位ビット
			iorwf		binw1,F		;binw1=3バイト目合成データ
			movf		binw1,W
			movwf		dspdt2		;3バイト目確定、保存

			;2バイト目の下位データを上位に移動
			movf		dspdt1,W
			movwf		binw1
			swapf		binw1,W
			andlw		0f0h		;元の上位データ破棄
			movwf		binw1		;下位4ビットを上位4ビットとしてワークに保存
			
			;1バイト目の上位データを2バイト目の下位データへ移動
			movf		dspdt0,W
			movwf		binw0
			swapf		binw0,W
			andlw		0fh
			iorwf		binw1,F
			movf		binw1,W
			movwf		dspdt1		;2バイト目確定、保存

			;1バイト目の下位データを上位に移動
			movf		dspdt0,W
			movwf		binw1
			swapf		binw1,W
			andlw		0f0h		;元の上位データ破棄
			movwf		binw1		;下位4ビットを上位4ビットとしてワークに保存

			;1バイト目の下位データをそのまま保存
			movf		dspdt0,W
			andlw		0fh
			iorwf		binw1,F
			movf		binw1,W
			movwf		dspdt0		;1バイト目確定、保存
			return


			

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			10進8桁LED表示出力サブルーチン　
;　
;		入力		BCD4バイト8桁分　digit0-3
;				PORTA0-2：桁制御
;				PORTB0-7：セグメント制御
;		使用ワーク	colum,tmp0,tmp1
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

disp_all		
			movlw		07h
			movwf		colum		;8桁目から開始
			movf		digit78,w	;7,8桁目BCD表示データ
			call		disp2c
			movf		digit56,w	;5,6
			call		disp2c
			movf		digit34,w	;3,4
			call		disp2c
			movf		digit12,w	;1,2
			call		disp2c			
			return

;
;			LED2桁表示サブルーチン
;
;		入力　wレジスタに表示データ１バイト２桁分
;		columに表示桁位置
;		出力　columに次の表示桁位置セット（上位桁から下位桁に移行する）
;

disp2c
			movwf		tmp0
			swapf		tmp0,W		;上位下位入れ替え
			andlw		0fh			;上位取り出し
			call		get_7seg	;セグメントデータに変換
			movwf		PORTB		;ポートBへ出力
			movf		colum,w		;桁位置取り出し
			movwf		PORTA		;桁位置出力
			decf		colum,f		;次の桁へシフト
			call		wait5m		;Wait 5msec
			movlw		0ffh
			movwf		PORTB		;桁表示クリア

			movf		tmp0,w		;下位取り出し
			andlw		0fh			;
			call		get_7seg	;セグメントへ変換
			movwf		PORTB		;ポートBへ出力
			movf		colum,w		;
			movwf		PORTA		;桁位置出力
			decf		colum,f		;次の桁へシフト
			call		wait5m
			movlw		0ffh
			movwf		PORTB		;桁表示クリア
			return


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			１６進6桁LED表示出力サブルーチン　(ドット無)
;　
;		入力		16進バイナリ3バイト6桁分　dspdt0-2
;				PORTA0-2：桁制御
;				PORTB0-7：セグメント制御
;		使用ワーク	colum,tmp0,tmp1
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

disp_6hn		
			movlw		05h
			movwf		colum		;6桁目から開始
			movf		dspdt2,w	;5,6桁目16進表示データ
			call		disp2c
			movf		dspdt1,w	;3,4
			call		disp2c
			movf		dspdt0,w	;1,2
			call		disp2c			
			return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			１６進6桁LED表示出力サブルーチン　(ドット有)
;			1桁目だけドットも点燈
;　
;		入力		16進バイナリ3バイト6桁分　dspdt0-2
;				PORTA0-2：桁制御
;				PORTB0-7：セグメント制御
;		使用ワーク	colum,tmp0,tmp1
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

disp_6hd
			movlw		05h
			movwf		colum		;6桁目から開始
			movf		dspdt2,w	;5,6桁目16進表示データ
			call		disp2c
			movf		dspdt1,w	;3,4
			call		disp2c
			movf		dspdt0,w	;1,2

			movwf		tmp0
			swapf		tmp0,W		;上位下位入れ替え
			andlw		0fh			;上位取り出し
			call		get_7seg	;セグメントデータに変換
			movwf		PORTB		;ポートBへ出力
			movf		colum,w		;桁位置取り出し
			movwf		PORTA		;桁位置出力
			decf		colum,f		;次の桁へシフト
			call		wait5m		;Wait 5msec
			movlw		0ffh
			movwf		PORTB		;桁表示クリア

			movf		tmp0,w		;下位取り出し
			andlw		0fh			;
			iorlw		010h		;ドット点燈分加算
			call		get_7seg	;セグメントへ変換
			movwf		PORTB		;ポートBへ出力
			movf		colum,w		;
			movwf		PORTA		;桁位置出力
			decf		colum,f		;次の桁へシフト
			call		wait5m
			movlw		0ffh
			movwf		PORTB		;桁表示クリア
			return

	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			遅延時間サブルーチン
;
;		clock = 10MHz(0.1usec)
;		use work reg = cnt0,cnt1,cnt2,cnt3
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

wait5m								; 5msec delay
			movlw		05h
			movwf		cnt2
w5m			call		d1m
			decfsz		cnt2,f
			goto		w5m
			return

wait10m								; 10msec delay
			movlw		d'10'
			movwf		cnt2
w10m		call		d1m
			decfsz		cnt2,f
			goto		w10m
			return

wait20m								; 20msec delay
			movlw		d'20'
			movwf		cnt2
w20m		call		d1m
			decfsz		cnt2,f
			goto		w20m
			return

wait50m								; 50msec delay
			movlw		d'50'
			movwf		cnt2
w50m		call		d1m
			decfsz		cnt2,f
			goto		w50m
			return

wait100m							; 100msec delay
			movlw		d'100'
			movwf		cnt2
w100m		call		d1m
			decfsz		cnt2,f
			goto		w100m
			return

wait500m							; 500msec delay
			movlw		05h
			movwf		cnt3
w500m		call		wait100m
			decfsz		cnt3,f
			goto		w500m
			return

wait1s								; 1sec delay
			movlw		d'10'
			movwf		cnt3
w1s			call		wait100m
			decfsz		cnt3,f
			goto		w1s
			return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			1msec Base delay 
;
;		clock = 10MHz(0.1usec)
;		1cycle = 0.4usec
;		1msec = 0.4usec * 2500cycles
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
d1m
			movlw		02h
			movwf		cnt0		;loop0 2times
d1m0		movlw		d'249'		;
			movwf		cnt1		;loop1 249times

d1m1		nop						;5cycles*cnt1
			nop						;5*249=1245
			decfsz		cnt1,f		;
			goto		d1m1		;

			decfsz		cnt0,f		;(d1m1-1+3)*cnt1
			goto		d1m0		;(1245-1+5)*2=2498cycles
			return					;other=3cycles
									;Total 2501*0.4usec=1msec


		

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;		３バイトバイナリの８桁BCDへの変換
;		マイクロチップ社のアプリケーションノートより
;
;		入力		3バイト(24ビット)16進バイナリ
;				dspdt0
;				dspdt1
;				dspdt2
;
;		出力		4バイト(32ビット)ＢＣＤ
;				digit12
;				digit34
;				digit56
;				gidit78
;
;		使用ワーク
;				shift	シフトカウンタ
;				bcdw0
;				bcdw1
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
bcd
			BCF			STATUS,C	;キャリーリセット
			MOVLW		018H		;シフトカウンタ初期化
			MOVWF		shift		;3バイト分24回の指定 
			CLRF		digit12		;BCDデータエリア初期化
			CLRF		digit34
			CLRF		digit56
			CLRF		digit78
			
			;変換ループ処理
loop
			RLF			dspdt0,F	;16進データ左シフト
			RLF			dspdt1,F
			RLF			dspdt2,F
			RLF			digit12,F	;BCDデータ左シフト
			RLF			digit34,F
			RLF			digit56,F
			RLF			digit78,F
			DECFSZ		shift,F		;
			GOTO		adjst		;BCD調整処理へ
			RETURN
			
			;BCDデータ全桁補正処理
adjst
			MOVF		digit12,W	;digit12
			CALL		adjbcd
			MOVWF		digit12
			MOVF		digit34,W	;digit34
			CALL		adjbcd
			MOVWF		digit34
			MOVF		digit56,W	;digit56
			CALL		adjbcd
			MOVWF		digit56
			MOVF		digit78,W	;digit78
			CALL		adjbcd
			MOVWF		digit78
			GOTO		loop

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			1バイト2桁分必要に応じて+3補正処理
;
;			入力		W_reg
;			出力		W_reg
;
;			使用ワーク	bcdw0
;					bcdw1
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
adjbcd
			MOVWF		bcdw0		;元データをbcdw0に保存
			MOVLW		3			;W=3
			ADDWF		bcdw0,W		;W=3+bcdw0
			MOVWF		bcdw1		;下桁を+3した上下桁をbcdw1に保存
			BTFSC		bcdw1,3		;if 下桁<7 then next_skip
			MOVWF		bcdw0		;下桁を+3した上下桁をbcdw0に保存 
		
			MOVLW		030H		;W+30
			ADDWF		bcdw0,W		;W=上桁+3
			MOVWF		bcdw1		;それをいったんbcdw1に保存
			BTFSC		bcdw1,7		;if 上桁<7 then next_skip
			MOVWF		bcdw0		;上桁を+3した上下桁をbcdw0に保存
			MOVF		bcdw0,W		;W_regに入れてリターン
			RETURN

;
			end
			
