;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			ＰＩＣ１６Ｆ６４８Ａ　10MHZ　８桁７セグＬＥＤ表示基板
;
;			シリアルデータ入力HEX表示プログラム(割込み版)
;			「PICEYE」実験基板出力専用32ビットデータ受信
;
;
;			データ入力はRB0割込み入力			
;			受信データは4バイト(32ビット)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


		LIST	P=PIC16F648A
		INCLUDE	P16F648A.inc
		
;	
;		
;CONFIGURATION WORD(ADDRESS:2007H)
;					設定
;bit13		CP		1	プログラムメモリプロテクション　0セット　
;						1=無効,0=有効
;bit12-9	Unimplemented
;bit8		CPD		1	データメモリプロテクション　0セット
;						1=無効,0=有効
;bit7		LPV		0	低電圧プログラミング設定
;						1=有効,0=無効
;bit6		BODEN	0	ブラウンアウト設定
;						1=有効,0=無効
;bit5		MCLRE	0	RA5/MCLRピン選択ビット
;						1=MCLR有効,0=RA5有効(Digital input)
;bit3		PWRTE	0	power_up timer　
;						1=無効,0=有効
;bit2		WDTE	0	Watchdog Timer
;						1=有効,0=無効
;bit4,1-0	FOSC	010	発振器選択ビット
;						111=RC:RA7でRC発振、RA6はCLKOUT、I/O不可
;						110=RCIO:　〃　RA6I/O可
;						101=INTOSC:内部発振、RA6はCLKOUT、RA7I/O可
;						100=INTOSC:内部発振、RA6-7I/O可
;						011=EC:RA7外部クロック入力、RA6I/O可
;						010=HS：外部発振子、I/O不可
;						001=XT：　〃
;						000=LP：　〃
;
;bit	15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
;data    0  0  1  0  0  0  0  1  0  0  0  0  0  0  1  0
;
;

		__CONFIG	B'0010000100000010'

	

;		ワークエリア定義
;
;		使用していないのもあります
;

hex0		equ			020h		;カウンタからの32ビット16進バイナリデータ
hex1		equ			021h
hex2		equ			022h
hex3		equ			023h
colum		equ			029h		;現在の桁位置
cnt0		equ			02ah		;時間待ち用ワーク
cnt1		equ			02bh
cnt2		equ			02ch
cnt3		equ			02dh
tmp0		equ			02eh		;雑用ワーク
tmp1		equ			02fh
bcdw0		equ			030h		;BCD補正処理ワーク
bcdw1		equ			031h
cary1		equ			032h
cary2		equ			033h
cary3		equ			034h
shift		equ			035h		;シリアルデータ受信カウンタ
work1		equ			036h
work2		equ			037h
bsyc0		equ			038h
bsyc1		equ			039h
hexw0		equ			03ah		;16進バイナリ保存用
hexw1		equ			03bh
hexw2		equ			03ch
hexw3		equ			03dh
flg			equ			03eh		;カウンタよりの制御フラグ
adtw0		equ			03fh		;ドット点燈処理ワーク
wtmp		equ			040h		;ワークレジスタ退避用
stmp		equ			041h		;ステータスレジスタ退避用
hexb0		equ			042h		;カウントデータ受信バッファ
hexb1		equ			043h
hexb2		equ			044h
hexb3		equ			045h
flgb		equ			046h		;制御フラグ受信バッファ
bitc		equ			047h		;受信ビットカウンタ
icnt0		equ			048h		;割込み内ウエイト用
icnt1		equ			049h		;割込み内ウエイト用
blk			equ			04ah		;ゼロブランキング制御ワーク
;

			ORG			0h
			goto		init
			ORG			04h
			goto		INT

			org			05h
			
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			４ビットHEXをLEDセグメントデータへ変換
;
;	ELD432 アノードコモン　７セグLED
;
;		a				RB1=a	RB5=e
;	f		b			RB2=b	RB6=f
;		g				RB3=c	RB7=g
;	e		c			RB4=d	RA4=Dp
;		d		dp		
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

get_7seg
			andlw		0fh			;下位4ビット取り出し
			addwf		PCL,F
			retlw		B'10000000'	;Code 0 abcdef
			retlw		B'11110010'	;Code 1 bc
			retlw		B'01001000'	;Code 2 abdeg
			retlw		B'01100000'	;Code 3 abcdg
			retlw		B'00110010'	;Code 4 bcfg
			retlw		B'00100100'	;Code 5 acdfg
			retlw		B'00000100'	;Code 6 acdefg
			retlw		B'11110000'	;Code 7 abc
			retlw		B'00000000'	;Code 8 abcdefg
			retlw		B'00110000'	;Code 9 abcfg

			retlw		B'00010000'	;Code A abcefg
			retlw		B'00000110'	;Code B cdefg
			retlw		B'10001100'	;Code C adef
			retlw		B'01000010'	;Code D bcdeg
			retlw		B'00001100'	;Code E adefg
			retlw		B'00011100'	;Code F aefg


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		初期設定
;
;			PIC16F648A　イニシャライズ			
;
;		CMCON_REG
;			bit7	C2OUT	コンパレータ2出力ビット
;			bit6	C1OUT	コンパレータ１出力ビット
;			bit5	C2INV	コンパレータ2出力反転ビット
;			bit4	C1INV	コンパレータ１出力反転ビット
;			bit3	CIS		コンパレータ入力スイッチビット
;			bit2-0	CM		コンパレータモード	111	Off
;										入力はデジタル
;										他モードは使用しない
;
;		TRISA_REG	1=input mode,0=output mode
;			bit7=0	RA7	I/O	設定条件あり、コンフィグレーションワード参照
;			bit6=0	RA6　I/O	設定条件あり、　〃
;			bit5=1	RA5	Inputのみ
;			bit4=0	RA4	I/O
;			bit3=0	RA3	I/O
;			bit2=0	RA2	I/O
;			bit1=0	RA1	I/O
;			bit0=0	RA0	I/O
;
;		TRISB_REG	1=input mode,0=output mode
;			bit7=0	RB7	I/O
;			bit6=0	RB6	I/O
;			bit5=0	RB5	I/O
;			bit4=0	RB4	I/O
;			bit3=0	RB3	I/O
;			bit2=0	RB2	I/O
;			bit1=0	RB1	I/O
;			bit0=0	RB0	I/O	外部割込み入力ピン
;
;		OPTION_REG
;			bit7=0	RBPU	POTRBプルアップON
;							1=diabled,0=inabled
;			bit6=0	INTEGE	RB0_INT割り込み信号エッジ
;							1=↑,0=↓
;			bit5=0	T0CS	TMR0クロックは外部
;							1=外部入力RA4,0=内部
;			bit4=0	T0SE	TMR0カウントエッジ↑
;							1=↓,0=↑,
;			bit3=1	PSA		プリスケーラ割当ビット
;							1=WDT,0=TMR0
;			bit2-0	PS		プリスケーラ分周比	000 1/2
;										001	1/4
;										010	1/8
;										011	1/16
;										100	1/32
;										101	1/64
;										110	1/128
;										111	1/256
;		INTCONレジスタ
;			bit7=1	GIE		全割込制御
;							1許可、0禁止
;			bit6=0	PEIE	周辺割込制御
;							1許可、0禁止
;			bit5=0	T0IE	タイマ0割込許可制御
;							1許可、0禁止
;			bit4=1	INTE	RB0外部割込許可制御
;							1許可、0禁止
;			bit3=0	RBIE	RBポート状態変化割込許可制御
;							1許可、0禁止	
;			bit2=0	T0IF	タイマ0オーバーフロー割込みフラグ
;							1オーバーフロー、0オーバーフローなし(#1)
;			bit1=0	INTF	RB0外部割込みフラグ(#1)(#2)
;							1割込み発生、0割込み発生なし
;			bit0=0	RBIF	RB4-7ポート状態変化割込フラグ(#1)
;							1割込発生、0割込無
;
;							#1)ソフトウエアでリセット必要
;							#2)割り込み中及び割込み禁止中でもフラグONとなる
;							　　　その場合、GIE=1に設定と同時に割込みが発生する
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;




init
			clrf		INTCON		;割り込み禁止
			movlw		07h
			movwf		CMCON		;アナログポート→デジタル
			bsf			STATUS,RP0	;バンク１に切替
			bcf			STATUS,RP1
			movlw		08h			;プルアップ及び割り込みエッジを↓に設定
			movwf		OPTION_REG	;
			movlw		020h		;00100000b
			movwf		TRISA		;RA0-RA4出力、RA5入力モード
			movlw		01h			;00000001b
			movwf    	TRISB		;RB0入力、RB1-7出力モード
			bcf			STATUS,RP0	;バンク０に切替
			movlw		090h		;10010000b
			movwf		INTCON		;割込設定


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		メインプログラム
;
;		4バイト16進数をシリアル受信、それを８桁表示
;
;
;		
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


main
			call		disp_8hn
			goto		main



;
;		割込み処理
;
;		割り込み発生により、INTCON_GIE=0となる(自動)
;		retfie実行でINTCON_GIE=1となる(自動)
;		INTCON_INTFは手動でクリアする事
;		レジスタ退避方法は、これが定石だそうです。
;			movwf,swapf命令はSTATUS変化しない
;

INT
			movwf		wtmp		;Wレジスタ退避
			swapf		STATUS,W
			movwf		stmp		;STATUSレジスタ退避
			btfss		INTCON,INTF	;割込みチェック
			goto		INTERR

INTRBE		call		int_rx
INTEND
			swapf		stmp,W
			movwf		STATUS		;STATUSレジスタ回復
			swapf		wtmp,F
			swapf		wtmp,W		;Wレジスタ回復
			bcf			INTCON,INTF	;RB0割込みフラグクリア
			retfie

;			割込みエラー　リセット待ち
INTERR		bcf			PORTA,4		;LED ON
			movlw		064h
			movwf		tmp0
INTER0		decfsz		tmp0,F
			goto		INTER1
			call		intw100u
			goto		INTER0

INTER1		bsf			PORTA,4		;LED OFF
			goto		INTERR
		
		



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			シリアルデータ割込み受信サブルーチン（ビット幅10us版)
;
;		受信バッファ		hexb0	4バイト32ビット
;					hexb1
;					hexb2
;					hexb3
;		ステータス		W=0		受信成功
;					W=1		受信失敗
;					W=2　	送信未準備
;
;
;		データ線	DATA	RB0		1bit width = 10us
;
;		使用ワーク	bsyc0,bitc,icnt0,icnt1
;
;	TX format
;
;	スタートビットH→L	→		データビット	→		ストップビットH(この後そのまま放置)
;
;		10us			10us*40			10us
;
;	INTCONレジスタ
;		bit7	GIE		全割込制御
;						1許可、0禁止
;		bit6	PEIE	周辺割込制御
;						1許可、0禁止
;		bit5	T0IE	タイマ0割込許可制御
;						1許可、0禁止
;		bit4	INTE	RB0外部割込許可制御
;						1許可、0禁止
;		bit3	RBIE	RBポート状態変化割込許可制御
;						1許可、0禁止	
;		bit2	T0IF	タイマ0オーバーフロー割込みフラグ
;						1オーバーフロー、0オーバーフローなし(#1)
;		bit1	INTF	RB0外部割込みフラグ(#1)
;						1割込み発生、0割込み発生なし
;		bit0	RBIF	RB4-7ポート状態変化割込フラグ(#1)
;						1割込発生、0割込無
;
;						#1)ソフトウエアでリセット必要
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



									;ここまで9c/s(3.6us)
int_rx
			movlw		03h			;時間調整
			movwf		bsyc0
irlp0		decfsz		bsyc0,F
			goto		irlp0		;2+3*2+2=10c/s(4us)
			nop
			nop
			nop						;13c/s
			
			movlw		020h		;32ビット分
			movwf		bitc		;シフトカウンタ
			clrf		hexb0
			clrf		hexb1
			clrf		hexb2
			clrf		hexb3		;19c/s、PORTB入力まであと6c/s
			
			
;
;		32bitシリアルデータ受信開始
;
;		１ループに付き、10us間隔でデータ取込
;

irloop
			rlf			hexb0,F		;全ビット左シフト
			rlf			hexb1,F		;
			rlf			hexb2,F
			rlf			hexb3,F		;
			bcf			hexb0,0		;最下位に0をセット
			btfsc		PORTB,0		;入力データを取得
			bsf			hexb0,0		;最下位に1にセット
			nop						;8
			movlw		04h			;時間調整
			movwf		bsyc0		;2+3*3+2=13cycles
irlp1		decfsz		bsyc0,F
			goto		irlp1
			nop
			decfsz		bitc,F		;32ビット受信完了か
			GOTO		irloop		;(9+13+3)*0.4=10usec
									;最終ビット受信から18c/s
			nop						;
			nop
			nop
			nop
			nop
			nop
			btfss		PORTB,0		;ストップビット確認
			goto		irlp2
			retlw		0h			;受信完了
irlp2		call		intw10u
			bcf			PORTA,4		;error
			call		intw100u
			bsf			PORTA,4
			retlw		03h			;受信失敗





;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			割込み専用　時間待ち
;			呼び出しも含めての待ち時間となる。
;
;		clock = 10MHZ(0.1usec)
;		1cycle = 0.4usec
;		10usec = 0.4usec * 25cycles
;
;		使用ワーク	icnt0,icnt1
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

intw100u							;呼び出しも含めて、100usec
									;call is 2cycles
			movlw		08h			;1
			movwf		icnt1		;1
iw1u		nop						;
			nop						;
			call		intw10u		;10*8=80usec(ここだけ命令ステップを数えない）
			decfsz		icnt1,F		;5*8+4=44cycles
			goto		iw1u
			return					;2+44+4=50cycles=20usec

intw50u								;呼び出しも含めて、50usec
									;call is 2cycles
			movlw		04h			;1
			movwf		icnt1		;1
iw05u		nop						;
			call		intw10u		;10*4=40usec(ここだけ命令ステップを数えない）
			decfsz		icnt1,F		;4*4+3=19cycles
			goto		iw05u
			return					;2+19+4=25cycles=10usec
intw25u
			call		intw10u
			call		intw10u
			
			movlw		02h			;1
			movwf		icnt1		;1
iw02u		decfsz		icnt1,F		;2+3+2+1=8cycles
			goto		w02u
			return					;2+8+2=12cycles=4.8usec




									;"call" inst = 2cycles
intw10u
			movlw		05h			;1
			movwf		icnt0		;1
iw01u		nop						;4*4+3=19
			decfsz		icnt0,F		;
			goto		iw01u		;
			return					;2+1+1+19+2=25cycles


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			データセット及び動作モードセット設定
;
;		受信バッファよりデータを取得
;				hexb0→hex0
;				hexb1→hex1
;				hexb2→hex2
;				hexb3→hex3
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

get_data
			bcf			INTCON,GIE	;割り込み禁止
			movf		hexb0,W
			movwf		hex0
			movf		hexb1,W
			movwf		hex1
			movf		hexb2,W
			movwf		hex2
			movf		hexb3,W
			movwf		hex3
			bsf			INTCON,GIE	;割り込み許可
			return




;
;			LED2桁表示サブルーチン
;
;		入力　wレジスタに表示データ１バイト２桁分
;		columに表示桁位置
;		出力　columに次の表示桁位置セット（上位桁から下位桁に移行する）
;

disp2c		
			movwf		tmp0		;表示データ保存
			swapf		tmp0,W		;上位下位入れ替え
			andlw		0fh			;上位取り出し
			call		get_7seg	;セグメントデータに変換
			movwf		PORTB		;ポートBへ出力
			
			movf		PORTA,W		;ポート現在情報
			andlw		0f8h		;bit3-7保存
			iorwf		colum,W		;桁位置合成
			movwf		PORTA		;桁位置出力

			decf		colum,F		;次の桁へシフト
			call		wait2m		;Wait 2msec
			movlw		0feh
			movwf		PORTB		;桁表示クリア
			bsf			PORTA,3		;ドットクリア

			movf		tmp0,W		;下位取り出し
			andlw		0fh			;
			call		get_7seg	;セグメントへ変換
			movwf		PORTB		;ポートBへ出力

			movf		PORTA,W		;ポート現在情報
			andlw		0f8h		;bit3-7保存
			iorwf		colum,W		;桁位置合成
			movwf		PORTA		;桁位置出力
			
			movf		colum,W
			iorlw		0h
			btfsc		STATUS,Z
			goto		disp21
			
			decf		colum,F		;次の桁へシフト
			call		wait2m
			movlw		0feh
			movwf		PORTB		;桁表示クリア
			bsf			PORTA,3		;ドットクリア
			retlw		0h			;続き有り

disp21		;表示終了
			call		wait2m
			movlw		0feh
			movwf		PORTB		;桁表示クリア
			bsf			PORTA,3		;ドットクリア
			retlw		01h

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			１６進8桁LED表示出力サブルーチン　(ドット無)
;　
;		入力		16進バイナリ4バイト8桁分　hex0-hex3
;				PORTA0-2：桁制御
;				PORTB1-7：セグメント制御
;		使用ワーク	colum,tmp0,tmp1
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

disp_8hn
			call		get_data			
			movlw		07h
			movwf		colum		;
			movf		hex3,W		;7,8桁目16進表示データ
			call		disp2c
			movf		hex2,W		;5,6桁目16進表示データ
			call		disp2c
			movf		hex1,W		;3,4
			call		disp2c
			movf		hex0,W		;1,2
			call		disp2c		
			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

wait25u
			call		d10u
			call		d10u
			
			movlw		02h			;1
			movwf		cnt2		;1
w02u		decfsz		cnt2,F		;2+3+2+1=8cycles
			goto		w02u
			return					;2+8+2=12cycles=4.8usec

wait2m
			movlw		02h
			movwf		cnt2
w2m			call		d1m
			decfsz		cnt2,F
			goto		w2m
			return

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
;
			END
			
