;***** Counter7LED.asm ****************************************************
;
;	７セグメントＬＥＤ表示の４桁カウンタ
;
;	origin:  http://www.try-net.or.jp/~el_dream/counter/count4/count4.txt
;
;     ( coding:  Ver. 0.00   2005/04/03  by M.Yamamoto )
;	coding:  Ver. 1.00   2005/04/04  初期バージョン, PIC16F648A に変更
;	update:  Ver. x.xx
;	bugfix:  Ver. x.xx
;
;******************************************************* PicAsm 0189 ******

;==========　PIC16F648A のピン接続　=======================================
;				  +--v--+
;		  RA2/AN2/VREF  1 |     | 18  RA1/AN1
;		  RA3/AN3/CMP1  2 |	| 17  RA0/AN0
;		RA4/TOCKI/CMP2  3 |	| 16  RA7/OSC1/CLKIN
;		  RA5/MCLR/Vpp  4 |	| 15  RA6/OSC2/CLKOUT
;		           Vss  5 |	| 14  Vdd
;		       RB0/INT  6 |	| 13  RB7/T1OSI/PGD
;		     RB1/RX/DT  7 |	| 12  RB6/T1OSO/T1CKI/PGC
;		     RB2/TX/CK  8 |	| 11  RB5
;		      RB3/CCP1  9 |	| 10  RB4/PGM
;				  +-----+
;==========　Ｉ／Ｏポートの用途　==========================================
;
;	RA0	out	１桁目ＬＥＤ表示
;	RA1	out	２桁目ＬＥＤ表示
;	RA2	out	３桁目ＬＥＤ表示
;	RA3	out	４桁目ＬＥＤ表示
;	RA4	in	リセットスイッチ
;	RB0	in	カウント入力
;	RB1	out	ＬＥＤセグメントａ
;	RB2	out	ＬＥＤセグメントｂ
;	RB3	out	ＬＥＤセグメントｃ
;	RB4	out	ＬＥＤセグメントｄ
;	RB5	out	ＬＥＤセグメントｅ
;	RB6	out	ＬＥＤセグメントｆ
;	RB7	out	ＬＥＤセグメントｇ

;==========================================================================

        list            P=PIC16F648A	;デバイス情報
        include        "P16F648A.INC"	;インクルードファイル
        errorlevel      -302		;Eliminate bank warning

        __config _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _HS_OSC

;==========================================================================
;	ラベル定義
;==========================================================================

#define		CountIn	PORTB,0		;カウント入力ポート
#define		ResetSW	PORTA,4		;リセットスイッチ

		cblock  h'20'
count1					;カウントデータ１桁目
count2					;カウントデータ２桁目
count3					;カウントデータ３桁目
count4					;カウントデータ４桁目
wlc					;wait でのループ用
dwlc					;wait_disp でのループ用
wkdt					;ワークデータ
		endc

seg7_0		equ     b'10000000'     ;gfedcba- Pattern 0
seg7_1		equ     b'11110010'     ;         Pattern 1
seg7_2		equ     b'01001000'     ;         Pattern 2
seg7_3		equ     b'01100000'     ;         Pattern 3
seg7_4		equ     b'00110010'     ;         Pattern 4
seg7_5		equ     b'00100100'     ;         Pattern 5
seg7_6		equ     b'00000100'     ;         Pattern 6
seg7_7		equ     b'11110000'     ;         Pattern 7
seg7_8		equ     b'00000000'     ;         Pattern 8
seg7_9		equ     b'00100000'     ;         Pattern 9
seg7_off	equ     b'11111110'     ;         LED off

;==========================================================================
;	プログラム開始
;==========================================================================

		org	0		;リセットベクタ
		goto	start
		org	4		;割り込みベクタ
		goto	start

;==========================================================================
;	初期化処理
;==========================================================================

start
		bcf	STATUS,RP1
		bcf	STATUS,RP0	;バンク 0
		clrf	PORTA		;
		movlw	b'00000111'	;RA3-0 を Digital I/O
		movwf	CMCON		;CMCON の設定
		bsf	STATUS,RP0	;バンク 1
		movlw	b'10000'
		movwf	TRISA		;ポートA の I/0 設定
		movlw	b'00000001'
		movwf	TRISB		;ポートB の I/0 設定
		bcf	STATUS,RP0	;バンク 0

m00		clrf	count1		;カウントデータの初期化
		clrf	count2
		clrf	count3
		clrf	count4

;==========================================================================
;	メイン・ルーチン
;==========================================================================

main
		call	digit_disp
		btfss	ResetSW		;リセットスイッチ = ON か？
		goto	m00		;Yes

		btfsc	CountIn		;入力が 0 か？
		goto	main		;No
		call	wait_disp
		btfsc	CountIn		;入力が 0 か？
		goto	main		;No 確かでないなら戻る

		incf	count1,F	;１桁目の更新
		movlw	d'10'
		subwf	count1,W
		btfss	STATUS,Z
		goto	m01

		clrf	count1
		incf	count2,F	;２桁目の更新
		movlw	d'10'
		subwf	count2,W
		btfss	STATUS,Z
		goto	m01

		clrf	count2
		incf	count3,F	;３桁目の更新
		movlw	d'10'
		subwf	count3,W
		btfss	STATUS,Z
		goto	m01

		clrf	count3
		incf	count4,F	;４桁目の更新
		movlw	d'10'
		subwf	count4,W
		btfss	STATUS,Z
		goto	m01

		clrf	count4

m01		call	wait_disp
		btfss	CountIn		;入力が 1 か？
		goto	m01		;No 入力が 1 になるのを待つ
		call	wait_disp
		btfss	CountIn		;入力が 1 か？
		goto	m01		;確かに入力が 1 に戻ったかを確認
		goto	main

;==========================================================================
;	カウント入力時のウェイトルーチン
;==========================================================================

wait_disp
		movlw	6		;６回ループ
		movwf	dwlc
dwt01		call	digit_disp
		decfsz	dwlc,F
		goto	dwt01

		return

;==========================================================================
;	カウンタ値の４桁ＬＥＤ表示
;==========================================================================

digit_disp
		movlw	seg7_off
		movwf	PORTB
		movlw	b'00111'
		movwf	PORTA		;４桁目を指定
		movf	count4,W
		call	ptn_set
		call	wait

		movlw	seg7_off
		movwf	PORTB
		movlw	b'01011'
		movwf	PORTA		;３桁目を指定
		movf	count3,W
		call	ptn_set
		call	wait

		movlw	seg7_off
		movwf	PORTB
		movlw	b'01101'
		movwf	PORTA		;２桁目を指定
		movf	count2,W
		call	ptn_set
		call	wait

		movlw	seg7_off
		movwf	PORTB
		movlw	b'01110'
		movwf	PORTA		;１桁目を指定
		movf	count1,W
		call	ptn_set
		call	wait

		return

;==========================================================================
;	W に指定された 0～9 の数字を ポートB にセットする
;     （PCL を操作する場合はプログラムを配置する位置に配慮すること）
;==========================================================================

ptn_set
		movwf	wkdt
		bcf	STATUS,C	;キャリフラグのクリア
		rlf	wkdt,W		;２倍
		addwf	PCL,F		;プログラム・カウンタに加算（相対ジャンプ）

		movlw	seg7_0		;0
		goto	pt01
		movlw	seg7_1		;1
		goto	pt01
		movlw	seg7_2		;2
		goto	pt01
		movlw	seg7_3		;3
		goto	pt01
		movlw	seg7_4		;4
		goto	pt01
		movlw	seg7_5		;5
		goto	pt01
		movlw	seg7_6		;6
		goto	pt01
		movlw	seg7_7		;7
		goto	pt01
		movlw	seg7_8		;8
		goto	pt01
		movlw	seg7_9		;9

pt01		movwf	PORTB

		return

;==========================================================================
;	ウェイトルーチン（１桁の表示時間）
;==========================================================================

wait
		movlw	d'100'		;1
		movwf	wlc		;1
wt01		decfsz	wlc,F		;1,2
		goto	wt01		;2,0	1+1+(1+2)*100-1=301
		return			;2	2+301=303
					;	303/4000000*4 S = 303μS

		end
