;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		ＰＩＣ１６Ｆ６４８Ａ　練習用プログラム　その０
;
;		８桁７セグメントＬＥＤ表示
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	list	P=PIC16F648A
	include	p16f648a.inc

;
;		ＰＩＣ１６Ｆ６４８Ａ
;		コンフィグレーションビット　セッティング
;
;		_HS_OSC		ex x'tal osc
;		_WDT_OFF	watch dog timer off
;		_PWRTE_ON	power on reset on
;		_MCLRE_OFF	5pin int off
;		_BODEN_OFF	brown out off
;		_LVP_OFF	low power off
;		_CPD_OFF	data memory protection off
;		_CP_OFF		FLASH memory protection off
;


	__config _HS_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _BODEN_OFF & _LVP_OFF


;
;	ワークエリア定義
;

dspdt0		equ		020h			;表示するデータ32ビットバイナリ
dspdt1		equ		021h			;
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			;BCD用ワーク
bcdw1		equ		030h

;

			org	0h
			goto	init
			org	04h
			goto	init

;
;		初期設定
;

        	org     05h
init
			movlw	07h
			movwf	CMCON			;アナログポート→デジタル
			bsf		STATUS,RP0		;バンク１に切替
			bcf		STATUS,RP1		;RP1:RP0=01b BANK 1
			movf	TRISA,w	        ;xx111000b 00111000b=38H
			andlw	B'11000000'
			iorlw	B'00111000'
			movwf	TRISA			;RA0-RA2 出力、RA3-RA5入力モード
			clrf    TRISB			;RBポート全出力モード

;
;		LED点燈チェック
;		全セグメントを下桁から順に点燈
;		使用ワークエリア		tmp0

			bcf		STATUS,RP0		;バンク０に切替
			movlw	0h
			movwf	colum			;桁位置ワークへリセットデータ
			movlw	08h
			movwf	tmp0			;繰り返しカウンタ値
			movlw	0ffh
			movwf	PORTB			;LED消灯
			call	wait500m
			clrf	digit12
			clrf	digit34
			clrf	digit56
			clrf	digit78
init0		
			movf	PORTA,W	        ;xxxxx000b 11111000b=F8H
			andlw	B'11111000'
			addwf	colum,W			;一桁ずつ点燈
			movwf	PORTA			;桁位置出力
			movlw	0				;
			movwf	PORTB			;全セグ点燈500ms
			call	wait500m
			movlw	0ffh			;
			movwf	PORTB			;全セグ消灯
			incf	colum,f
			decfsz	tmp0,f
			goto	init0
			

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		メインプログラム(練習用)
;		８桁７セグLED　アップカウンタ
;
;		スイッチをスキャンして何をするか分岐
;		アップカウントボタン	ＳＷ３
;		ストップボタン		ＳＷ４（現在サーチしていない）
;		ダウンカウントボタン	ＳＷ５（現在サーチしていない）
;		
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

main
			call	corsor_on
			movlw	0f0h
			movwf	tmp0
			movlw	0ffh
			movwf	tmp1
main0		call	sw3chk
			iorlw	0h
			btfss	STATUS,Z		;z=0(sw3_on) then goto main1
			goto	main1
			decf	tmp1,F			;z=1(sw3_off)
			btfss	STATUS,Z		;if tmp1=0 then goto main2
			goto	main0			;if tmp1=x then goto main0
			decf	tmp0
			btfss	STATUS,Z
			goto	main0
			goto	main2
main1		call	upcnt			;表示数を連続アップカウント
			goto	main

main2		call	corsor_off
			movlw	0f0h
			movwf	tmp0
			movlw	0ffh
			movwf	tmp1
main3		call	sw3chk
			iorlw	0h
			btfss	STATUS,Z		;z=1(sw3_on) then goto main1
			goto	main1
			decf	tmp1,F			;z=0(sw3_off)
			btfss	STATUS,Z		;if tmp1=0 then goto main
			goto	main3			;if tmp1=x then goto main3
			decf	tmp0
			btfss	STATUS,Z
			goto	main3
			goto	main			;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) hen return00
			call	wait20m			;チャタリング防止
			btfss	PORTA,RA3		;ra3=0(sw3 on) hen return01
			retlw	01h
sw3ch0		retlw	0h


;
;			sw4_on return01
;			sw4_off return00
;

sw4chk		btfsc   PORTA,RA4		;RA3=0(sw3 on) then next skip
			goto	sw4ch0			;RA3=1(sw3 off) hen return00
			call	wait20m			;チャタリング防止
			btfss	PORTA,RA4		;ra3=0(sw3 on) hen return01
			retlw	01h
sw4ch0		retlw	0h

;
;			sw5_on return01
;			sw5_off return00
;

sw5chk		btfsc   PORTA,RA5		;RA3=0(sw3 on) then next skip
			goto	sw5ch0			;RA3=1(sw3 off) hen return00
			call	wait20m			;チャタリング防止
			btfss	PORTA,RA5		;ra3=0(sw3 on) hen return01
			retlw	01h
sw5ch0		retlw	0h

;
;			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


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		ＢＣＤ８桁アップカウントループ
;		ストップボタン（ＳＷ４）で一時停止、さらに押すと終了
;		一時停止中にアップボタン（ＳＷ３）で再開
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

upcnt	
			call	dcnt01			;w=0 thn normal
			iorlw	0h				;W=1 then error
			btfss	STATUS,Z		;w=0 then nextskip
			goto	upcer			;w=1 then upcounter error
			call	disp_all

			call	sw4chk			;w=0 or w=1
			iorlw	0h
			btfsc	STATUS,Z		;W=1(sw4_on) then pouse
			goto	upcnt			;W=0(sw4_off) then goto upcnt
			call	pouse_up		;表示数を一時停止
			iorlw	0h				;
			btfsc	STATUS,Z		;w=0 then goto upcnt
			goto	upcnt			;w=1 then reset_return
upc0		clrf	digit12
			clrf	digit34
			clrf	digit56
			clrf	digit78
			return

upcer		call	pouse_up		;upcounter error
			iorlw	0h
			btfss	STATUS,Z		;w=0 then next skip
			return					;w=1 then return
									;count retry
			clrf	digit12
			clrf	digit34
			clrf	digit56
			clrf	digit78
			call	disp_all
			goto	upcnt


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;		
;
;		ポーズ
;		sw3 on　あるいは　sw5　on　で、w reg = 0 リターン
;		sw4 on w reg　に01hを入れてリターン
;
;		現在SW5はサーチしていません
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

pouse_up							;SW3(RA3)チェック
			call	disp_all
			call	sw3chk
			iorlw	0h
			btfsc	STATUS,Z		;Z=0(sw3 on) then return00
			goto	pose0			;Z=1(sw3 off) then SW4
			retlw	0h				;

pose0								;SW4(RA4)チェック
			call	disp_all
			call	sw4chk
			iorlw	0h
			btfsc	STATUS,Z		;Z=0(sw4 on) then return01
			goto	pouse_up		;Z=1(sw4 off) then loop
			retlw	01h				;

pouse_dwn							;チェック無し（ここには来ません)
			call	disp_all
			call	sw5chk
			iorlw	0h
			btfsc	STATUS,Z		;Z=0(sw5 on) then return00
			goto	pouse_up		;Z=1(sw5 off) then loop
			retlw	0h				;




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		８桁ＢＣＤアップカウンター
;
;		コールされると下記ワークの８桁BCDデータを１だけカウントアップする
;
;		出力		diget12　1･2桁目(下位4ビット）と2桁目(上位4ビット)
;				diget34　
;				diget56
;				diget78
;				Wreg	00h　カウント成功
;						01h　オーバーフロー発生
;
;		使用ワーク	bcdw0　下位4ビットワークエリア
;				bcdw1　上位4ビットワークエリア
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

dcnt01
;			BCD1桁目のカウントアップ処理
			movf		digit12,W
			movwf		bcdw1
			swapf		bcdw1,F
			movlw		0fh
			andwf		bcdw1,F		;上位4ビット分現在値をワークへ転送
			
			movf		digit12,W	;下位4ビットの処理
			andlw		0fh			;上位4ビットをマスク
			movwf		bcdw0		;下位4ビット分をワークへ転送
			incf		bcdw0,F
									;0-9hかどうかをチェック
			movf		bcdw0,W		;
			sublw		0ah			;w = 0ah - w
			btfss		STATUS,Z	;if z=1 then nextword skip
			goto		bcd12s		;桁上がり無で1,2桁終了処理へ

;			BCD2桁目下位4ビットからの桁上がりあり
			movlw		0ah			;data - 0ah = dec (ex bh-ah=1)
			subwf		bcdw0,F		;1桁目変換処理し、BCDデータをワークに保存
			incf		bcdw1,F		;2桁目＋１
			
;			3桁目に桁上がり必要かどうかをチェック
			movf		bcdw1,W		;
			sublw		0ah			;w = 10 - w
			btfss		STATUS,Z	;if z=0 then nextword skip
			goto		bcd12s		;桁上がり無で1,2桁終了処理へ
			
;			BCD3桁目、2桁目からの桁上がりあり
			movlw		0ah			;data - 0ah = dec (ex bh-ah=1)
			subwf		bcdw1,F		;2桁目変換処理し、BCDデータをワークに保存
			call		bcd12s		;1,2桁を終了処理

			movf		digit34,W
			movwf		bcdw1
			swapf		bcdw1,F
			movlw		0fh
			andwf		bcdw1,F		;上位4ビット分現在値をワークへ転送

			movf		digit34,W	;下位4ビットの処理
			andlw		0fh
			movwf		bcdw0		;下位4ビット分をワークへ
			incf		bcdw0,F		;3桁目＋１
			movf		bcdw0,W
			sublw		0ah			;0-9hかどうかをチェック
			btfss		STATUS,Z
			goto		bcd34s		;桁上がり無で、3,4桁終了処理へ
			
;			BCD4桁目下位4ビットからの桁上がりあり
			movlw		0ah			;data - 10 = dec (ex bh-ah=1)
			subwf		bcdw0,F		;3桁目変換処理し、BCDデータをワークに保存
			incf		bcdw1,F		;4桁目＋１
			
;			5桁目に桁上がり必要かどうかをチェック
			movf		bcdw1,W		;
			sublw		0ah			;w = 10 - w
			btfss		STATUS,Z	;if z=0 then nextword skip
			goto		bcd34s		;桁上がり無で3,4桁終了処理へ

;			BCD5桁目、4桁目からの桁上がりあり
			movlw		0ah			;data - 0ah = dec (ex bh-ah=1)
			subwf		bcdw1,F		;4桁目変換処理し、BCDデータをワークに保存
			call		bcd34s		;3,4桁を終了処理

			movf		digit56,W
			movwf		bcdw1
			swapf		bcdw1,F
			movlw		0fh
			andwf		bcdw1,F		;上位4ビット分現在値をワークへ転送

			movf		digit56,w	;下位4ビットの処理
			andlw		0fh
			movwf		bcdw0		;下位4ビット分をワークへ
			incf		bcdw0,F		;5桁目＋１
			movf		bcdw0,W
			sublw		0ah			;0-9hかどうかをチェック
			btfss		STATUS,Z
			goto		bcd56s		;桁上がり無で、5,6桁終了処理へ
			
;			BCD6桁目下位4ビットからの桁上がりあり
			movlw		0ah			;data - 10 = dec (ex bh-ah=1)
			subwf		bcdw0,F		;5桁目変換処理し、BCDデータをワークに保存
			incf		bcdw1,F		;6桁目＋１
			
;			6桁目に桁上がり必要かどうかをチェック
			movf		bcdw1,W		;
			sublw		0ah		;w = 10 - w
			btfss		STATUS,Z	;if z=0 then nextword skip
			goto		bcd56s		;桁上がり無で5,6桁終了処理へ

;			BCD7桁目、6桁目からの桁上がりあり
			movlw		0ah			;data - 0ah = dec (ex bh-ah=1)
			subwf		bcdw1,F		;6桁目変換処理し、BCDデータをワークに保存
			call		bcd56s		;5,6桁を終了処理

			movf		digit78,W
			movwf		bcdw1
			swapf		bcdw1,F
			movlw		0fh
			andwf		bcdw1,F		;上位4ビット分現在値をワークへ転送

			movf		digit78,w	;下位4ビットの処理
			andlw		0fh
			movwf		bcdw0		;下位4ビット分をワークへ
			incf		bcdw0,F		;7桁目＋１
			movf		bcdw0,W
			sublw		0ah		;0-9hかどうかをチェック
			btfss		STATUS,Z
			goto		bcd78s		;桁上がり無で、7,8桁終了処理へ
			
;			BCD6桁目下位4ビットからの桁上がりあり
			movlw		0ah			;data - 10 = dec (ex bh-ah=1)
			subwf		bcdw0,F		;7桁目変換処理し、BCDデータをワークに保存
			incf		bcdw1,F		;8桁目＋１
			
;			8桁目に桁上がり必要かどうかをチェック
			movf		bcdw1,W		;
			sublw		0ah			;w = 10 - w
			btfss		STATUS,Z	;if z=0 then nextword skip
			goto		bcd78s		;桁上がり無で7,8桁終了処理へ

;			オーバーフロー処理
			call		bcd78s
			retlw		01h

			
;			bcd1,2桁目終了処理
;
;			入力		bcdw0	下位4ビット分BCDデータ
;					bcdw1	上位4ビット分BCDデータ
;			出力		digit12
;

bcd12s		swapf		bcdw1,F		;
			movf		bcdw0,W
			iorwf		bcdw1,F
			movf		bcdw1,W
			movwf		digit12
			retlw		0h
			

;			bcd3,4桁目終了処理
;
;			入力		bcdw0	下位4ビット分BCDデータ
;					bcdw1	上位4ビット分BCDデータ
;			出力		digit34
;

bcd34s		swapf		bcdw1,F		;
			movf		bcdw0,W
			iorwf		bcdw1,F
			movf		bcdw1,W
			movwf		digit34
			retlw		0h
			

;			bcd5,6桁目終了処理
;
;			入力		bcdw0	下位4ビット分BCDデータ
;					bcdw1	上位4ビット分BCDデータ
;			出力		digit56
;

bcd56s		swapf		bcdw1,F		;
			movf		bcdw0,W
			iorwf		bcdw1,F
			movf		bcdw1,W
			movwf		digit56
			retlw		0h
			
;			bcd7,8桁目終了処理
;
;			入力		bcdw0	下位4ビット分BCDデータ
;					bcdw1	上位4ビット分BCDデータ
;			出力		digit78
;

bcd78s		swapf		bcdw1,F		;
			movf		bcdw0,W
			iorwf		bcdw1,F
			movf		bcdw1,W
			movwf		digit78
			retlw		0h
			

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			8桁表示出力サブルーチン　
;　
;		入力		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

;
;			BCD2桁表示
;
;		入力　wレジスタにBCD表示データ１バイト２桁分
;		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


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			ＢＣＤからLEDセグメントへの変換
;
;	注意			このルーチンのアドレス範囲の設定が必要
;				PCLATHにその上位アドレスを入れること
;	入力			WレジスタにBCDデータを入れてコール
;	出力			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
			movwf		tmp1
			movlw		01h
			movwf		PCLATH
			movf		tmp1,W
			andlw		0fh			;下位のみ取り出し
			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'10000011'	;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'00000011'	;Code 6. cdefg
			retlw		B'01111000'	;Code 7. abc
			retlw		B'00000000'	;Code 8. abcdefg
			retlw		B'00011000'	;Code 9. abcfg

		
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			遅延時間サブルーチン
;
;		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


			end
			
