;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		実験用周波数カウントユニット
;
;		PIC12F683
;
;
;
;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



		LIST	P=PIC12F683
		INCLUDE	P12F683.INC
		
;CONFIGURATION WORD(ADDRESS:2007H)
;bit13-12		Unimplemented
;bit11			FCMEN	0セット、使いません。
;						1=enabled,0=disabled
;bit10			IESO	0セット
;						1=enabled,0=disabled
;bit9-8			BODEN	00セット
;						00=disabled
;bit7			CPD		データメモリプロテクション　0セット
;						1=enabled,0=disabled
;bit6			CP		プログラムメモリプロテクション　0セット　
;						1=enabled,0=disabled
;bit5			MCLRE	0セット
;						1=enabled,0=disabled(Digital input)
;bit4			PWRTE	power_up timer　1セット、使います。
;						1=enabled,0=disabled
;bit3			WDTE	Watchdog Timer　0セット、使いません。
;						1=enabled,0=disabled
;bit2-0			FOSC	今回は、011Bを使用
;						111=RC:2pinでRC発振、3pinCLKOUT、I/O不可
;						110=RCIO:　〃　GP4I/O可
;						101=INTOSC:内部発振　3pinCLKOUT、GP5I/O可
;						100=INTOSCIO:内部発振、GP4-5I/O可
;						011=EC:2pin外部クロック入力、GP4I/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  0  0  0  0  0  0  0  0  0  1  0  0  1  1
;

		__CONFIG	B'0000000000010011'
	

;		ワークエリア定義
;
;		使用していないのもあります
;

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
tcnt0		equ			039h
tcnt1		equ			03ah
tcnt2		equ			03bh
ovflw		equ			03ch
band		equ			03dh
gtime		equ			03eh

;

			ORG			0h
			goto		init
			ORG			04h
			goto		init

			org			05h
			


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			PIC12F683　イニシャライズ			
;
;		CMCON0_REG
;			bit7=0	Unimplemented
;			bit6=x	COUT	コンパレータ出力ﾋﾞｯﾄ
;			bit5=0	Unimplemented
;			bit4=x	CINV
;			bit3=1	CIS
;			bit2-0	CM		コンパレータモード	111	Off
;										入力はデジタル
;										他モードは使用しない
;
;		ANSEL_REG
;			bit7=1	Unimplemented
;			bit6-4	ADCS	A/Dコンバータクロック選択
;			bit3-0	ANS		アナログ選択ビット
;							1=アナログ入力
;							0=デジタルI/O
;
;		TRISIO_REG	1=input mode,0=output mode
;			bit7=0	Unimplemented
;			bit6=0	Unimplemented
;			bit5=0	GP5	I/O	設定条件あり、コンフィグレーションワード参照
;			bit4=1	GP4	I/O　設定条件あり、　〃
;			bit3=1	GP3	Inputのみ
;			bit2=1	GP2	I/O
;			bit1=0	GP1	I/O
;			bit0=0	GP0	I/O
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	
init
			bcf			STATUS,RP0	;Bank0
			clrf		GPIO		;Init GPIO
			movlw		07h
			movwf		CMCON0		;コンパレータoff、アナログポート→デジタル
			bsf			STATUS,RP0	;バンク１に切替
			clrf		ANSEL		;デジタルI/O
			bcf			ADCON0,ADON	;ADコンバータOFF
			movlw		0f8H		;11111000b
			movwf		OPTION_REG	;プリスケーラ無しにセット
			movlw		01ch		;00011100b
			movwf		TRISIO		;GP2,3,4入力　GP0,1出力モード
			bcf			STATUS,RP0	;バンク０に切替
;			goto		main_dbg

main
			call		get_mode
			call		fcount
			call		correct
			call		tx_data
			goto		main


;
;データ転送デバッグ用仮メイン
;

main_dbg
			clrf		hex0
			clrf		hex1
			clrf		hex2
m0
			call		tx_data
			movlw		0c7h
			movwf		hex0
			movlw		08ah
			movwf		hex1
			movlw		0a9h
			movwf		hex2		;11111111
			call		wait1s

			call		tx_data
			movlw		08eh
			movwf		hex0
			movlw		0e8h
			movwf		hex1
			movlw		021h
			movwf		hex2		;02222222
			call		wait1s

			call		tx_data
			movlw		0d5h
			movwf		hex0
			movlw		0dch
			movwf		hex1
			movlw		032h
			movwf		hex2		;03333333
			call		wait1s

			call		tx_data
			movlw		01ch
			movwf		hex0
			movlw		0d1h
			movwf		hex1
			movlw		043h
			movwf		hex2		;04444444
			call		wait1s

			call		tx_data
			movlw		063h
			movwf		hex0
			movlw		0c5h
			movwf		hex1
			movlw		054h
			movwf		hex2		;05555555
			call		wait1s

			call		tx_data
			movlw		0aah
			movwf		hex0
			movlw		0b9h
			movwf		hex1
			movlw		065h
			movwf		hex2		;06666666
			call		wait1s

			call		tx_data
			movlw		0f1h
			movwf		hex0
			movlw		0adh
			movwf		hex1
			movlw		076h
			movwf		hex2		;07777777
			call		wait1s

			call		tx_data
			movlw		038h
			movwf		hex0
			movlw		0a2h
			movwf		hex1
			movlw		087h
			movwf		hex2		;08888888
			call		wait1s

			call		tx_data
			movlw		07fh
			movwf		hex0
			movlw		096h
			movwf		hex1
			movlw		098h
			movwf		hex2		;09999999
			call		wait1s

			call		tx_data
			movlw		04eh
			movwf		hex0
			movlw		061h
			movwf		hex1
			movlw		0bch
			movwf		hex2		;123456789
			call		wait1s

			call		tx_data
			call		wait1s
			goto		m0



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			動作モードセット(今回はゲートタイムの設定は不可、1s固定）
;
;		プリスケーラSW	ON(GP4=0)、OFF(GP4=1)
;		ゲートタイムSW	1秒(GP3=0)、0.1秒(GP3=1)使用不可、他用途使用
;
;		使用ワーク
;				狭帯域(1/1)モード	band=0
;				広帯域(1/8)モード	band=1
;				0.1秒ゲートタイム		gtime=0
;				１秒ゲートタイム		gtime=1
;
;		OPTION_REG
;			bit7=1	GPPU	GPIOプルアップOFF
;							0=enabled,1=disabled
;			bit6=1	INTEGE	INT割り込み信号エッジ↑
;							1=↑,0=↓
;			bit5=1	T0CS	TMR0クロックは外部
;							1=外部入力GP2,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
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

get_mode
			btfsc		GPIO,4		;プリスケーラ設定SWチェック
			goto		ps_off		;GP4=H then PS=OFF
ps_on		;プリスケーラ　ON
			bsf			band,0		;8倍モード(BAND=1)
			bsf			STATUS,RP0	;バンク１に切替え
			movlw		0f2H		;11110010b
			movwf		OPTION_REG	;プリスケーラ1/8分周にセット
			bcf			STATUS,RP0	;バンク0に戻る
			goto		ckgtm
ps_off		;プリスケーラ　OFF
			bcf			band,0		;1倍モード(BAND=0)
			bsf			STATUS,RP0	;バンク１に切替え
			movlw		0f8H		;11111000b
			movwf		OPTION_REG	;プリスケーラ無しにセット
        	bcf         STATUS,RP0	;バンク０に戻る
ckgtm		;ｹﾞｰﾄタイム　設定　今回は1秒固定です。
			clrf		gtime		;set 0.1s
;			btfss		GPIO,3		;SWチェック
			bsf			gtime,0		;set 1sec
			return


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
;			入力パルス　カウントサブルーチン
;
;		入力ポート		GP2
;		ゲート解放時間	1s、100ms
;		出力データ		hex0
;					hex1
;					hex2
;
;		ゲートSW		H=100ms、L=1s
;
;		使用ワーク		;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

fcount
;			GP2　gate_off
			bsf			STATUS,RP0	;バンク１に切替
			bcf			TRISIO,2	;GP2出力モード
			bcf			STATUS,RP0	;バンク０に切替
			bcf			GPIO,2		;GP2=0
;			reset
			clrf		hex0		;データエリアリセット
			clrf		hex1
			clrf		hex2
			clrf		TMR0		;タイマー０カウンタリセット
			btfss		gtime,0		;ゲートタイム確認
			goto		gate100m	;100msec
			goto		gate1s		;1sec
;
;			ゲートタイム100ms=250000cycles
;
gate100m
			clrf		ovflw		;OverFlowフラグをクリア

;			gate_open オープン後2サイクル経過
			bsf			STATUS,RP0	;バンク１に切替
			bsf			TRISIO,2	;GP2入力モード
			bcf			STATUS,RP0	;バンク０に切替
			call		count100m	;249995cycles
			
;			gate_closed　クローズまで2サイクル経過
			nop						;時間微調整
			bsf			STATUS,RP0	;バンク１に切替
			bcf			TRISIO,2	;GP2出力モード(ゲートクローズ)
			bcf			STATUS,RP0	;バンク０に切替
			bcf			GPIO,2		;GP2=0
			nop
			nop
			return

;
;			ゲートタイム1sec=2500000cycles
;
gate1s
			clrf		ovflw		;OverFlowフラグをクリア
			movlw		0aH			;10回
			movwf		tmp0

;			gate_open
			bsf			STATUS,RP0	;バンク１に切替
			bsf			TRISIO,2	;GP2入力モード
			bcf			STATUS,RP0	;バンク０に切替


g1s0		nop						;時間調整
			call		count100m	;249995cycle
			decfsz		tmp0,F		;
			goto		g1s0		;(249995+4)*10-1=2499989(-11)
			nop						;時間微調整
			nop
			nop
			nop
			nop
			nop
			nop
			
;			gate_closed　クローズまで2サイクル経過
			bsf			STATUS,RP0	;バンク１に切替
			bcf			TRISIO,2	;GP2出力モード(ゲートクローズ)
			bcf			STATUS,RP0	;バンク０に切替
			bcf			GPIO,2		;GP2=0
			nop
			nop
			return



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		タイマー０への入力パルス　カウントループ
;
;		ゲートオン、オフの時間も考慮し、100ms間の入力パルスカウントとなる様に設定する事
;		f=10MHZ only	249995cycles(call&return命令含む)
;
;		入力		無し
;
;		出力		hex1	中位8ビット
;				hex2	上位8ビット
;						下位8ビットはゲートクローズ後、TMR0から読み出すこと
;
;	INTCONレジスタ
;		bit7	GIE		全割込制御		1許可、0禁止
;		bit6	PEIE	周辺割込制御	1許可、0禁止
;		bit5	T0IE	タイマ0割込許可制御
;		bit4	INTE	GP2外部割込許可制御
;		bit3	GPIE	GPIOポート状態変化割込許可制御	1許可、0禁止	
;		bit2	T0IF	タイマ0割込みフラグ	1オーバーフロー、0オーバーフローなし(#1)
;		bit1	INTF	GP2外部割込みフラグ(#1)
;		bit0	GPIF	GPポート状態変化割込フラグ 1割込発生、0割込無(#1)
;
;		#1)ソフトウエアでリセット必要
;
;		使用ワーク		tcnt1	外周カウンタ　
;					tcnt2	内周カウンタ　
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



count100m							;100ms=100000us=250000cycles
									;呼び出しで4c/s、ｹﾞｰﾄで4c/s
			movlw		055h		;外周カウンタ85
			movwf		tcnt1

cnt101m		movlw		0adH		;内周カウンタ=173
			movwf		tcnt2		;
;
;	タイマ0のオーバーフローした時の桁上げカウント処理
;	下桁8ビットはゲートクローズ後、TMR0から読み込みすること
;

cnt102m		nop						;時間調整
			nop
			nop
			nop
			btfss		INTCON,T0IF	;タイマ０オーバーフラグチェック
			goto		if_off		;T0IF=0 then 
			bcf			INTCON,T0IF	;T0IFフラグをリセット
			movlw		01h			;add,sub命令でなければキャリー使えない
			goto		if_on
if_off		nop						;時間差調整
			nop						;　〃
			movlw		0h			;
if_on		addwf		hex1,F		;hex1=hex1+W_REG
			rlf			hex1,W		;キャリービットがWの0ビット目に入る
			andlw		01h			;キャリー以外をマスク
			addwf		hex2,F		;hex2=hex2+Carry(Wreg)

;			内周カウンタ　17cycles/loop = 6.8us
			decfsz		tcnt2,F		;内周ループ終了か？
			goto		cnt102m		;13*210=2730c/s=1092us
			nop						;時間差調整

;			外周カウンタ　13*xxcycles/loop
cnt103m		decfsz		tcnt1,F		;(17*tcnt2)*tcnt1+6
			goto		cnt101m		;(17*173)*85+6=249991cycles
									;CALLとRETURNで4cycles
			return					;合計249995cycles
									;



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		計測値の桁補正　1/1　1/8
;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

correct
;			プリスケーラモード確認
			btfsc		band,0		;1=1/8プリスケーラ使用,0=プリスケーラ無し
			goto		x8			;８倍モード処理へ

;			プリスケーラ　OFF
x1
			movf		TMR0,W		;
			movwf		hex0
			return

;			1/8プリスケーラ　ON
x8
			movf		TMR0,W		;下桁8ビット
			movwf		hex0		;プリスケーラ８倍
			bcf			STATUS,C	;
			rlf			hex0,F		;２倍を３回実行する
			rlf			hex1,F
			rlf			hex2,F
			bcf			STATUS,C	;
			rlf			hex0,F
			rlf			hex1,F
			rlf			hex2,F
			bcf			STATUS,C
			rlf			hex0,F
			rlf			hex1,F
			rlf			hex2,F

			btfsc		STATUS,C	;オーバーフローか？
			bsf			ovflw,0		;オーバーフローフラグをON
			return


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			シリアルデータ転送サブルーチン
;
;		入力		hex0	16進バイナリ24ビット
;				hex1
;				hex2
;		出力		W=0	送信成功
;				W=1	送信失敗
;
;
;		データ線	GP0		1bit width = 100us
;		制御線	TX（送信）	GP1	=0	送信不可
;						GP1	=1	送信可
;				RX（受信）	GP3 =0	受信不可
;						GP3 =1	受信可
;
;		使用ワーク	bsyc0
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

tx_data
;
;		送信準備OK
;

		bsf			GPIO,1		;TX ON

;
;		応答待ち(約720ms)
;

;stby	clrf		bsyc0		;外周カウンタ
;stb0	clrf		bsyc1		;内周カウンタ
stb1
		call		d10u
		btfsc		GPIO,3		;RX line check
		goto		tx_start
;		decfsz		bsyc1,F
		goto		stb1
;		decfsz		bsyc0,F
;		goto		stb0
;		retlw		01h

;
;		送信開始
;

tx_start
		bcf			GPIO,0		;DATA スタートビット　セット
		call		wait100u
		movf		hex2,W
		call		tx_byte
		movf		hex1,W
		call		tx_byte
		movf		hex0,W
		call		tx_byte
;
;		送信終了
;

		bsf			GPIO,0		;ストップビット　セット
		call		wait100u
		bcf			GPIO,1		;TX OFF
		retlw		0h			;送信終了

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;		１バイト転送サブルーチン
;
;		上位ビットから送信します
;
;		1ビット幅は概ね100usで送出
;
;		使用ワーク	shift
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


								;コール以前に3cyles
tx_byte
		movwf		tmp0		;送信バイトをワークへ保存
		movlw		08H			;
		movwf		shift		;左シフトカウンタ

txb0							;tx loop
		rlf			tmp0,F		;左シフトで最上位ビットはキャリーへ
		btfss		STATUS,C	;キャリービット　チェック
		GOTO		send0
		GOTO		send1		;4

send0	bcf			GPIO,0		;DATA 0 send
		goto		txb1
send1	bsf			GPIO,0		;DATA 1 send

txb1	call		wait50u		;90us delay
		call		d10u
		call		d10u
		call		d10u
		call		d10u
		
		movlw		05h			;時間調整
		movwf		bsyc0		;2+3*4+2=16cycles
txb2	decfsz		bsyc0,F
		goto		txb2
		
		decfsz		shift,F		;(shift-1)=0 then return 
		goto		txb0		;(8or10）+16=25cycles=10us
		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								;呼び出しも含めて、50us
			movlw		04h
			movwf		cnt2
w05u		nop
			call		d10u
			decfsz		cnt2,F		;4*4+3=19cycles
			goto		w05u
			return					;2+19+4=25cycles=10us


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
			
			


