;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			ＰＩＣ１６Ｆ６４８Ａ　　実験用８桁７セグＬＥＤ基板
;
;			シリアルデータ入力表示プログラム
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


		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

;		ワークエリア定義
;
;		使用していないのもあります
;

hex0		equ			020h		;表示するデータ32ビット16進バイナリ
hex1		equ			021h		;実際は24ビットしか使用しない
hex2		equ			022h
hex3		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
bsyc0		equ			037h
bsyc1		equ			038h
hexw0		equ			039h
hexw1		equ			03ah
hexw2		equ			03bh
hexw3		equ			03ch

;

			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


;
;		初期設定
;
;		RA ポート
;		RA0		入出力
;		RA1		入出力
;		RA2		入出力
;		RA3		入出力
;		RA4		入出力
;		RA5		入力のみ
;		RA6		入出力(条件あり)
;		RA7		入出力(条件あり)
;
init
			movlw		07h
			movwf		CMCON		;アナログポート→デジタル
			bsf			STATUS,RP0	;バンク１に切替
			bcf			STATUS,RP1
			movlw		030h		;00110000b
			movwf		TRISA		;RA0-RA3出力、RA4-RA5入力モード
			clrf    	TRISB		;RBポート全出力モード
			bcf			STATUS,RP0	;バンク０に切替
			call		wait100u
			bcf			PORTA,3		;RB5(RX)=0




			

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		メインプログラム
;
;		6桁16進数をシリアル受信、それを１０進８桁に変換表示
;
;
;		
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


main
			call		rx_data
			call		bcd
			call		disp_all
mlp0
			goto		main




;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			シリアルデータ受信サブルーチン
;
;		出力			hex0	16進バイナリ24ビット
;					hex1
;					hex2
;		ステータス		W=0	受信成功
;					W=1	受信失敗
;					W=2　送信未準備
;
;
;		データ線	DATA	RA4		1bit width = 100us
;		制御線	RX（送信）	RA3	=0	受信不可
;						RA3	=1	受信可
;				TX（受信）	RA5 =0	送信不可
;						RA5 =1	送信可
;
;		使用ワーク	bsyc0
;
;	TX format
;
;	RX_検出	→	スタートビットL	→	データビット		→	ストップビットH(この後そのまま放置)
;
;			0us	100us		0us	100us		0us	100us
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rx_data
;
;		送信ステータスチェック
;
		call		wait50u
		btfss		PORTA,5			;TX 受信チェック
		goto		rxer0			;not ready
		call		wait50u
		btfsc		PORTA,5			;TX check
		goto		rstat			;送信可
rxer0	call		wait50u			;送信未準備
		retlw		02h
		
;
;		受信可能ステータス送出
;
;
rstat	movlw		018h			;24ビット分
		movwf		shift			;シフトカウンタ
		bsf			PORTA,3			;RX_ON送出、受信準備OK
		call		wait50u
		btfss		PORTA,4			;スタートビット(0)確認
		goto		rloop			;データ受信開始
		call		wait50u
		bcf			PORTA,3			;RX_OFF　送信
		retlw		01h				;受信失敗
		

;
;		受信開始
;
;		１ループに付き、100us間隔でデータ取込
;

rloop
		call		wait50u			;90us delay
		call		d10u
		call		d10u
		call		d10u
		call		d10u
rlp0	rlf			hex0,F			;全ビット左シフト
		rlf			hex1,F			;
		rlf			hex2,F			;
		bcf			hex0,0			;最下位に0をセット
		btfsc		PORTA,4			;入力データを取得
		bsf			hex0,0			;最下位に1にセット

		movlw		05h				;時間調整
		movwf		bsyc0			;2+3*4+2=16cycles
rlp1	decfsz		bsyc0,F
		goto		rlp1

		decfsz		shift,F			;２４ビット受信完了か
		GOTO		rloop			;90+(9+16)*0.4=100usec

		call		wait100u		;
		btfss		PORTA,4			;ストップビット確認
		goto		rlp2
		goto		rlp3
rlp2	call		wait50u
		bcf			PORTA,3			;RX OFF
		retlw		01h				;受信失敗
rlp3	call		wait50u
		bcf			PORTA,3			;RX OFF
		retlw		0h				;受信完了



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			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		hex2,w	;5,6桁目16進表示データ
			call		disp2c
			movf		hex1,w	;3,4
			call		disp2c
			movf		hex0,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		hex2,w	;5,6桁目16進表示データ
			call		disp2c
			movf		hex1,w	;3,4
			call		disp2c
			movf		hex0,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
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

wait100u							;呼び出しも含めて、100usec
									;call is 2cycles
			movlw		08h			;1
			movwf		cnt2		;1
w1u			nop						;
			nop						;
			call		d10u		;10*8=80usec(ここだけ命令ステップを数えない）
			decfsz		cnt2,F		;5*8+4=44cycles
			goto		w1u
			return					;2+44+4=50cycles=20usec

wait50u								;呼び出しも含めて、50usec
									;call is 2cycles
			movlw		04h			;1
			movwf		cnt2		;1
w05u		nop						;
			call		d10u		;10*4=40usec(ここだけ命令ステップを数えない）
			decfsz		cnt2,F		;4*4+3=19cycles
			goto		w05u
			return					;2+19+4=25cycles=10usec

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
;
;		# goto and call and return - 2cycles
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
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)*cnt0
			goto		d1m0		;(1245-1+5)*2=2498cycles
			return					;other=3cycles
									;Total 2501*0.4usec=1msec

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			10usec Base delay
;			呼び出しも含めて、10usecとなる。
;
;		clock = 10MHZ(0.1usec)
;		1cycle = 0.4usec
;		10usec = 0.4usec * 25cycles
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

									;"call" inst = 2cycles
d10u
			movlw		05h			;1
			movwf		cnt0		;1
d10u0		nop						;4*4+3=19
			decfsz		cnt0,F		;
			goto		d10u0		;
			return					;2+1+1+19+2=25cycles
			






		

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;		３バイトバイナリの８桁BCDへの変換
;		MicroChip社のアプリケーションノートより
;
;		入力		3バイト(24ビット)16進バイナリ
;				hex0
;				hex1
;				hex2
;
;		出力		4バイト(32ビット)ＢＣＤ
;				digit12
;				digit34
;				digit56
;				gidit78
;
;		使用ワーク
;				hexw0	入力データ保存用
;				hexw1
;				hexw2
;				shift	シフトカウンタ
;				bcdw0
;				bcdw1
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
bcd
			BCF			STATUS,C	;キャリーリセット
			MOVLW		018H		;シフトカウンタ初期化
			MOVWF		shift		;3バイト分24回の指定 
			CLRF		digit12		;BCDデータエリア初期化
			CLRF		digit34
			CLRF		digit56
			CLRF		digit78
			movf		hex0,W
			movwf		hexw0
			movf		hex1,W
			movwf		hexw1
			movf		hex2,W
			movwf		hexw2
			
			;変換ループ処理
loop
			RLF			hexw0,F		;16進データ左シフト
			RLF			hexw1,F
			RLF			hexw2,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
			
