;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		Ｉ２Ｃコントロールテスト　Ver０．２	ＪＡ０ＱＯＮ
;
;		マスター送信ルーチンを作ってみる
;		PIC16F1705 32MHZ（内部オシレータ）
;
;       目的
;       Ｉ２Ｃインターフェイスの手動制御実験
;       ４桁７セグＬＥＤの制御と時計動作
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

		LIST	P=PIC16F1705
		INCLUDE	P16F1705.INC

;
;CONFIGURATION WORD 1(ADDRESS:8007H)
;					設定
;bit13		FCMEN	0	Fail-Safe Clock Monitor
;						1=有効,0=無効
;bit12		IESO	0	内部･外部切替スイッチモード
;						1=有効,0=無効
;bit11		CLKOUTEN 1	クロックアウトイネーブルビット
;						1=無効　RA4I/O使用可
;						0=有効　FoscがCLKPUTピンに出力される
;bit10-9	BOREN	00	ブラウンアウト設定
;						11=有効
;						10=スリープ時以外有効
;			___			00=無効
;bit8		CPD		1	データメモリプロテクション
;			__			1=無効,0=有効
;bit7		CP		1	プログラムメモリプロテクション　
;						1=無効,0=有効
;bit6		MCLRE	0	RA3/MCLRピン選択ビット
;			_____		1=MCLR有効,0=RA3有効(Digital input)
;bit5		PWRTE	0	power_up timer　使います。
;						1=無効,0=有効
;bit4-3		WDTE	00	Watchdog Timer
;						11=有効
;						10=ランニング中に有効、スリープ中は無効
;						01=レジスタによるコントロール
;						00=無効
;bit2-0		FOSC	100	発振器選択ビット
;						111=ECH:外部クロック入力（4-32MHZ)、RA4I/O可
;						110=ECM:外部クロック入力（0.5-4MHZ)、RA4I/O可
;						101=ECL:外部クロック入力（0-0.5MHZ)、RA4I/O可
;						100=INTOSC:内部発振、RA4-RA5I/O可
;						011=EXTRC:外部RC発振、RA4I/O可、RA5不可
;						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  1  0  0  1  1  0  0  0  0  1  0  0
;
;
	__CONFIG _CONFIG1,	B'0000100110000100'
;
;CONFIGURATION WORD 2(ADDRESS:8008H)マニュアル52ページ
;					設定
;bit13		LVP		0	低電圧プログラミング設定
;						1=有効
;			_____		0=無効、高電圧必要
;bit12		DEBUG	1	インサーキット･デバッガ モード設定
;						1=無効
;						0=有効、RA0-1をデバッガに使用
;bit11				0	Unimplemented
;bit10		BORV	0	ブラウンアウト･リセット電圧選択ビット（Vbor参照)
;						1=低電圧で動作
;						0=高電圧で動作
;bit9		STVREN	0	スタック･オーバーフロー･リセット設定
;						1=有効
;						0=無効
;bit8		PLLEN	0	PLL設定
;						1=4xPLL有効
;						0=4xPLL無効
;bit7       ZCDDIS  1   ZCDディセーブルビット
;                       1=ZCDを無効にする、ZCDCONで有効可
;                       0=ZCDを常に有効にする
;bit6-3					Unimplemented(read as '1'）
;bit2		PPS1WAY 0   PPSLOCKビット単方向セット･イネーブルビット
;                       1=ロック解除シーケンスを実行後に1度だけ解除できる
;                       0=ロック解除シーケンスを実行すると何度でも解除できる
;bit1-0		WRT		11	フラッシュメモリ プロテクション設定
;						11=無効
;						10=0h-1FFh有効、200H?1FFFHはPMCONで制御可
;						01=0h-FFFh有効、1000H?1FFFHはPMCONで制御可
;						00=0h-1FFFh有効、PMCON制御不可
;
;bit	15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
;data    0  0  0  1  0  0  0  0  1  1  1  1  1  0  1  1
;
;
	__CONFIG _CONFIG2,	B'0001000011111011'



;		ワークエリア定義
;
;		BANK0	20h-7Fh
;
;		使用していないのもあります
;

hex0		equ		020h		;32ビット取得HEXデータ
hex1		equ		021h		;
hex2		equ		022h
hex3		equ		023h
hexw0		equ		024h		;32ビットバイナリ演算用
hexw1		equ		025h
hexw2		equ		026h
hexw3		equ		027h
cnt0		equ		028h		;時間待ちルーチン用
cnt1		equ		029h
cnt2		equ		02ah
cnt3		equ		02bh
tmp0		equ		02ch		;汎用ワーク
tmp1		equ		02dh
flg			equ		02eh		;エラー＆設定フラグ
MODE		equ		02fh		;実行モード設定
TMC			equ		030h		;タイマオーバーフローカウンタ
CYC0		equ		031h		;呼び出し周期カウンタ
CYC1		equ		032h		;呼び出し周期カウンタ
;DCX		equ		033h		;DAC X軸進行カウンタ
;DCM		equ		034h		;DAC X軸分解能設定
;DCR        equ     035h        ;TMR0リスタート情報
FRQ0		equ		036h		;周波数表示データ
FRQ1		equ		037h
TBAL        equ     038h        ;参照テーブル先頭アドレス下位8ビット
TBAH        equ     039h        ;同上位8ビット
;
digit12     equ     03ah        ;BCD変換出力1，2桁
digit34     equ     03bh		;BCD変換出力3，4桁
digit56     equ     03ch		;BCD変換出力5，6桁
digit78     equ     03dh        ;BCD変換出力7，8桁
digit9A     equ     03eh        ;BCD変換出力9，10桁
bcdw0		equ		03fh		;BCD補正処理ワーク
bcdw1		equ		040h
wrk0		equ		041h        ;演算用汎用ワーク
wrk1		equ		042h
shift       equ     043h        ;ビットシフト用ワーク
blk			equ		044h		;ゼロブランキング制御フラグ
colum		equ		045h		;現在の桁位置
colw0		equ		046h		;桁位置処理ワーク
colw1		equ		047h		;
;
CMD0		equ		048h		;コマンドパケット下位8ビット
CMD1		equ		049h		;コマンドパケット上位8ビット
DBUF0		equ		04ah		;SPI送信データ編集用バッファ
DBUF1		equ		04bh
DBUF2		equ		04ch
DBUF3		equ		04dh
DBUF4		equ		04eh
DBUF5		equ		04fh
DBUF6		equ		050h
DBUF7		equ		051h
;
REDAT       equ     052h        ;ロータリーエンコーダ・データ
RESTP       equ     053h        ;変化ステップ量
rew0        equ     054h        ;専用ワーク
rew1        equ     055h        ;専用ワーク
;
tcnt0		equ     056h        ;周波数データアドレス下位8ビット
tcnt1		equ     057h        ;周波数データアドレス上位8ビット
tcnt2		equ     058h        ;DACデータテーブルNO過去データ
TBNO1       equ     059h        ;DACデータテーブルNO現在データ
PSDT0       equ     05ah        ;プリスケーラ過去データ
PSDT1       equ     05bh        ;プリスケーラ現在データ
FLNO        equ     05ch        ;LPF選択
fdw0        equ     05dh        ;専用ワーク
fdw1        equ     05eh        ;専用ワーク
;
DSP_ADR     equ     05fh
icw0        equ     060h
icw1        equ     061h
icw2		equ		062h
;
SCL_H		MACRO
			movlb	02h
			bsf		LATC,0
			clrf	BSR
			ENDM
SCL_L		MACRO
			movlb	02h
			bcf		LATC,0
			clrf	BSR
			ENDM
SDA_H		MACRO
			movlb	02h
			bsf		LATC,1
			clrf	BSR
			ENDM
SDA_L		MACRO
			movlb	02h
			bcf		LATC,1
			clrf	BSR
			ENDM
DELAY_C		MACRO
			call	w10u
			ENDM
;
			ORG		0h          ;リセットベクタ
			goto	init
			ORG		04h         ;割り込みベクタ
INT
			clrf	BSR
			btfss	blk,0
			bra		DOTOFF
DOTON		call	secup		;秒カウントアップ
			call	EXCHG
			call	SETBUF
			call	PUTL
			bcf		blk,0
;			TMR1リスタート処理
INTOUT		movlw	0c0h		;TMR1リスタート値
			movwf	TMR1H
			clrf	TMR1L		;TMR1は0.5秒
			bcf		PIR1,TMR1IF	;フラグクリア
			retfie				;
DOTOFF		bcf		DBUF2,4
			movf	DBUF2,W
			call	PUTW
			bsf		blk,0
			bra		INTOUT
			
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			PIC16F1705　イニシャライズ
;
;		OSCCON(BANK1　099H) 
;			bit7	SPLLEN	ソフトウエアPLL設定ビット
;							1 = 4xPLL有効
;							0 = 4xPLL無効(リセット後)
;			＊コンフィグレーションワードPLLEN=1の時、この設定は無視される。
;			bit6-3	IRCF	内部発振器クロック選択ビット
;							000x = 31KHZ LF
;							0010 = 31.25KHZ MF
;							0011 = 31.25KHZ HF
;							0100 = 62.5KHZ MF
;							0101 = 125KHZ MF
;							0110 = 250KHZ MF
;							0111 = 500KHZ MF（デフォルト）
;							1000 = 125kHZ HF
;							1001 = 250kHZ HF
;							1010 = 500kHZ HF
;							1011 = 1MHZ HF
;							1100 = 2MHZ HF
;							1101 = 4MHZ HF
;							1110 = 8MHZ or 32MHZ HF
;							1111 = 16MHZ HF
;			bit2			Unimplemented
;			bit1-0	SCS		システムクロック選択ビット
;							1x = 内部発振器
;							01 = タイマ1発振器
;							00 = FOSCで指定された発振器(リセット後)
;			(注)詳細はマニュアルあるいは当局HP内解説を参照
;							HF=HFINTOSC（16MHZ)
;							MF=MFINTOSC(500KHZ)
;							LF=LFINTOSC(32KHZ)
;
;
;			32MHZ内部発振設定
;		コンフィグレーションワード1		FOSC=100
;		OSCCON				SCS=00
;		OSCCON				IRCF=1110
;		OSCCON				SPLLEN=1(#1)
;		コンフィグレーションワード2		PLLEN=1(#1)
;						(#1)設定はどちらかでOKだが、PLLEN=1とすると、
;							OSCCONのSPLLEN=0の設定は無効となる。
;							また、8MHZのHFINTOSCは選択の余地が無い。
;
;		PORTA(BANK0　00CH）
;			bit7-6	Unimplemented(read=0)
;			bit5-4	RA5-4	デジタルI/O、アナログ入力
;			bit3	RA3		デジタルInputのみ
;			bit2	RA2-1	デジタルI/O、アナログ入力
;			bit0	RA0		デジタル･アナログI/O,DAコンバータ出力
;
;		PORTC(BANK0　00EH）
;			bit7-6	Unimplemented(read=0)
;			bit5-0	RC5-0	デジタルI/O、アナログ入力
;
;		TRISA(BANK1　08CH)
;			bit7-6	Unimplemented(read=0)
;			bit5-4	RA5-4	1=入力、0=出力
;			bit3	RA3		常に1
;			bit2	RA2-0	1=入力、0=出力
;
;		TRISC(BANK1　08EH)
;			bit7-6	Unimplemented(read=0)
;			bit5-4	RA5-0	1=入力、0=出力
;
;		LATA(BANK2　10CH)　データラッチレジスタ
;			bit7-6	Unimplemented(read=0)
;			bit5-4	RA5-4	出力データ保持
;			bit3	Unimplemented(read=0)
;			bit2	RA2-0	出力データ保持
;		（このラッチデータはTRISAレジスタ設定で各ピンに反映される）
;
;		LATC(BANK2　10EH)　データラッチレジスタ
;			bit7-6	Unimplemented(read=0)
;			bit5-4	RC5-0	出力データ保持
;		（このラッチデータはTRISCレジスタ設定で各ピンに反映される）
;
;
;		ANSELA(BANK3　18CH)
;			bit7-5	Unimplemented(read=0)
;			bit4	ANSA3/RA4	アナログ/デジタル選択ビット
;								1=アナログ入力
;								0=デジタルI/O
;			bit3	Unimplemented(read=0)
;			bit2-0	ANSA2-0/RA2-0アナログ/デジタル選択ビット
;								1=アナログ入力
;								0=デジタルI/O
;			＊デフォルトでは、すべて1(アナログ入力)となっている
;
;		ANSELC(BANK3　18EH)
;			bit7-6	Unimplemented(read=0)
;			bit5-0	ANSC5-0/RC5-0アナログ/デジタル選択ビット
;								1=アナログ入力
;								0=デジタルI/O
;			＊デフォルトでは、すべて1(アナログ入力)となっている
;
;		ODCONA（BANK5　28CH)
;			bit7-6	Unimplemented(read=0)
;			bit5-4			1=オープンドレイン駆動
;							0=標準のプッシュプル駆動
;			bit3	Unimplemented(read=0)
;			bit2-0			1=オープンドレイン駆動
;							0=標準のプッシュプル駆動
;			＊デフォルトでは、すべて０となっている
;
;		ODCONC（BANK5　28EH)
;			bit7-6	Unimplemented(read=0)
;			bit5-0			1=オープンドレイン駆動
;							0=標準のプッシュプル駆動
;			＊デフォルトでは、すべて０となっている
;
;		WPUA(BANK4　20CH)　ポートAプルアップ設定ビット
;			bit7-6	Unimplemented(read=0)
;			bit5-0			1=PORTA各ビットプルアップ有効
;					 _____	0=PORTA各ビットプルアップ無効
;					*WPUENビットが有効の時のみ、設定有効となる。
;
;		WPUC(BANK4　20EH)　ポートCプルアップ設定ビット
;			bit7-6	Unimplemented(read=0)
;			bit5-0			1=PORTA各ビットプルアップ有効
;					 _____	0=PORTA各ビットプルアップ無効
;					*WPUENビットが有効の時のみ、設定有効となる。
;
;
;		OPTION_REG(BANK1　095H)
;					_____
;			bit7=1	WPUEN	プルアップ グローバル設定ビット
;							0=有効,1=無効
;			bit6=0	INTEDG	INTピン割り込み信号エッジ
;							1=↑
;							0=↓
;			bit5=0	TMR0CS	TMR0クロックソース選択ビット
;							1=外部入力RA2/T0CKI
;							0=内部システムクロック(Fosc/4)
;			bit4=1	TMR0SE	TMR0ソースエッジ選択ビット
;							1=RA4/T0CKIピンが↑の時インクリメント
;							0=RA4/T0CKIピンが↓の時インクリメント
;			bit3=0	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レジスタ(#2)　コア　00BH
;			bit7	GIE		全割込制御
;							1許可、0禁止
;			bit6	PEIE	周辺装置割込制御
;							1許可、0禁止
;			bit5	TMR0IE	タイマ0割込許可制御
;							1許可、0禁止
;			bit4	INTE	RA2外部割込許可制御
;							1許可、0禁止
;			bit3	IOCIE	I/Oポート状態変化割込許可制御
;							1許可、0禁止
;			bit2	TMR0IF	タイマ0割込みフラグ(#1)
;							1オーバーフロー
;							0オーバーフローなし
;			bit1	INTF	RA2外部割込みフラグ(#1)
;							1割込み発生
;							0割込み発生なし
;			bit0	IOCIF	I/Oポート状態変化割込フラグ(#1)
;							1割込発生
;							0割込無
;
;							#1)ソフトウエアでリセット必要
;							#2)初期値=0なので、初期設定で0設定する必要は無い
;
;
;		T1CONレジスタ
;			bit7-6	TMR1CS	タイマ1クロック源選択ビット
;							11=LFINTOSC
;							10=タイマ1クロック源にピンまたはオシレータを選択する
;								T1OSCEN=1の場合
;								T1CKIピンからの外部クロック（立ち上がりエッジ）
;								T1OSCEN=0の場合
;								SOSCI、SOSCOに接続された水晶振動子
;							01=システムクロック(FOSC）を選択
;							00=命令クロック(FOSC/4)を選択
;			bit5-4	T1CKPS	タイマ1入力プリスケーラ選択ビット
;							11=8:1
;							10=4:1プリスケーラ値
;							01=2:1
;							00=1:1
;			bit3	T1OSCEN	LPオシレータ イネーブル制御ビット
;							1=専用のセカンダリ オシレータを有効にする
;							0=専用のセカンダリ オシレータを無効にする
;			bit2	T1CYNC	タイマ1同期制御ビット
;							1=非同期クロック入力を同期しない
;							0=非同期クロック入力とシステムクロック(FOSC)を同期させる
;			bit1	未実装	「0」として読み出し
;			bit0	TMR1ON	タイマ1ONビット
;							1=タイマ1を有効にする
;							0=タイマ1を停止、タイマ1ゲートフィリップフロップをクリア
;
;		T1GCONレジスタ
;			bit7	TMR1GE	タイマ1 ゲートイネーブルビット
;							TMR1ON=0の場合はこのビットを無視する
;							TMR1ON=1の場合
;								1=タイマ1のカウントをタイマ1ゲート機能で制御する
;								0=タイマ1はタイマ1のゲート機能とは無関係にカウントする
;			bit6	TIGPOL	タイマ1ゲート極性ビット
;							1=タイマ1ゲートはアクティブH（ゲートがHの時にカウント)
;							0=タイマ1ゲートはアクティブL（ゲートがLの時にカウント)
;			bit5	T1GTM	タイマ1 ゲートトグルビット
;							1=タイマ1 ゲートトグルモードを有効にする
;							タイマ1ゲートフリップフロップは立ち上がりエッジごとに
;							トグルします
;							0=タイマ1 ゲートトグルモードを無効とする
;							トグル フリップフロップをクリアする
;			bit4	T1GSPM	タイマ1 ゲートシングルパルスモードビット
;							1=シングルパルスモードを有効にし、ゲートを制御
;							0=無効にする
;			bit3	T1GGO/DONE
;							タイマ1ゲート シングルパルスアクイジョン ステータスビット
;							1=シングルパルスアクイジョンがレディ状態、エッジを待機
;							0=シングルパルスアクイジョンは完了済み、または開始していない
;			bit2	T1GVAL	タイマ1 ゲート値ステータスビット
;							TMR1H:TMR1Lへ提供されるタイマ1ゲートの現在のステートを
;							示します。
;							タイマ1ゲートイネーブル(TMR1GE)の影響は受けない
;			bit0-1	T1GSS	タイマ1ゲートソース選択ビット
;							11=オプションで同期できるコンパレータ2出力(sync_C2OUT)
;							10=オプションで同期できるコンパレータ1出力(sync_C1OUT)
;							01=タイマ0オーバーフロー出力
;							00=タイマ1ゲートピン
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

init
;			各レジスタ初期設定(PIC16F1705)
            movlb	0h			;BANK0
			clrf	INTCON		;全割込みOFF
			clrf	PIR1
			movlb	01h
			clrf	PIE1		;タイマ1他割込みフラグクリア
			clrf	BSR
			clrf	PORTA		;Init PORT
            clrf	PORTC
            movlb   02h			;BANK2
            clrf    LATA
            clrf    LATC
			;クロック
			movlb	01h			;BANK１
			movlw	0f0h		;1111000B
			movwf	OSCCON		;内部発振器は8MHZに設定
                                ;4xPLL=ON

			;I/Oポート(TRIS→BANK1、ANSEL→BANK3)
			movlb	01h
			movlw	0fh			;00001111B
			movwf	TRISA		;RA0-3入力、RA4-5出力
            movlw	034h		;00110100B
            movwf	TRISC       ;RC0-1,3出力、RC2,4-5入力
			movlb	03h			;BANK3
			movlw	00h			;00000000B
			movwf	ANSELA		;RA0-5=デジタル
            movlw	00h         ;00000000B
            movwf	ANSELC      ;RC0-5デジタル
			movlb	05h			;ODCONx BANK5
			movlw	03h			;00000011B
			movwf	ODCONC		;RC0-1オープンドレイン

;			レジスタ設定終了
			clrf	BSR
			goto	coldst
			goto	DEBUG01


;
;	ＯＤ出力ラインの実験用
;
;	TRIS出力モードのままでPORTCを読めるのかの実験
;	PORTC設定はオープンドレイン出力となっている（必須）
;	LATC出力のままで、PORTCを読んでLEDに反映
;	該当PORTCラインはプルアップされており、PUSH_SWにてGNDに落とす事ができる
;
TEST1
			movlb	02h			;BANK2(LATC)
			bcf		LATC,0		;SCL=1
			bsf		LATC,1		;SDA=1
			clrf	BSR
			call	w10u
			call	CKSDA
			bra		$-3
			
;
;	ＳＤＡラインのチェック
;	RC1=1ならば、RED_LED=ON、Wreg=1
;	RC1=0ならば、GRN_LED=ON、Wreg=0
;

CKSDA
			btfss	PORTC,1		;SDAチェック
			bra		BUSL
BUSH		bcf		PORTA,5		;GRN_LED_OFF
			nop
			bsf		PORTA,4		;RED_LED_ON
			retlw	01h
BUSL		bcf		PORTA,4		;RED_LED_OFF
			nop
			bsf		PORTA,5		;GRN_LED_ON
			retlw	0h
			
			
TEST2
			call	wait1s
TEST21		call	I2C_START
			movlw	40h			;自動アクセス桁インクリメント
			call	I2C_SBYTE
			call	I2C_STOP

			call	I2C_START
			movlw	0c0h		;最下桁アドレス指定
			call	I2C_SBYTE

			movlw	06h
			call	I2C_SBYTE

			movlw	05bh
			call	I2C_SBYTE

			movlw	04fh
			call	I2C_SBYTE

			movlw	03fh
			call	I2C_SBYTE
			call	I2C_STOP

			call	I2C_START
			movlw	08fh		;表示開始、最大輝度
			call	I2C_SBYTE
			call	I2C_STOP
			call	wait1s

			nop
			bra		$-1
			

			
			
;
;		デバッグ０１
;
DEBUG01
			movlw	01h
			movwf	blk
			clrf	tcnt0
			clrf	tcnt1

DBLOOP		clrf	BSR
			btfss	blk,0
			bra		MINOFF
MINON		call	secup		;秒カウントアップ
			call	EXCHG
			call	SETBUF

			movf	DBUF0,W
			call	GET_7SEG
			movf	DBUF1,W
			call	GET_7SEG
			movf	DBUF2,W
			call	GET_7SEG
			movf	DBUF3,W
			call	GET_7SEG

			bcf		blk,0
			goto	DBLOOP

MINOFF		bsf		DBUF2,5
			bcf		DBUF2,4
			movf	DBUF2,W
			call	GET_7SEG
			bsf		blk,0
			goto	DBLOOP

;
;		メインループ
;

coldst
			call	wait1s
			movlw	01h			;00=分：秒　01=時：分
			movwf	MODE		;表示モード設定
			movlw	01h
			movwf	blk
			movlw	0c1h
			movwf	DSP_ADR		;秒ドットアドレス
			movlw	0ffh		;アップカウンタ初期値
			movwf	tcnt0
			clrf	tcnt1
			clrf	tcnt2
			movlw	08ch		;クロックソース→専用OSC
			movwf	T1CON		;専用発振回路使用、プリスケ1/1、タイマ1オフ
			call	wait100m	;専用OSC安定化待ち
			movlw	0c0h		;0.5s
			movwf	TMR1H		;カウンタ=C000H
			movlw	0h
			movwf	TMR1L
			bsf		T1CON,TMR1ON;タイマ１オン
			movlb	01h
			bsf		PIE1,TMR1IE	;タイマ1割込み許可
			clrf	BSR
			movlw	0c0h
			movwf	INTCON		;全体および周辺割り込み許可

mloop		;メインループ
			btfss	PORTA,3		;MODEスイッチ
			bra		mlp02
mlp01		bsf		MODE,0		;時：分表示モード
			goto	mloop
mlp02		bcf		MODE,0
			goto	mloop		;分：秒表示モード

;
;		カウントアップ
;
;	出力		tcont0：秒　0-59まで
;			tcont1：分　0-59まで
;			tcont2：時　0-23まで
;
secup
			incf	tcnt0,F
			movlw	03ch		;3CH=60
			subwf	tcnt0,W
			btfss	STATUS,C	;tcont0=60以上でボロー発生
			return	
			clrf	tcnt0
			incf	tcnt1,F
			movlw	03ch
			subwf	tcnt1,W
			btfss	STATUS,C
			return
			clrf	tcnt1
			incf	tcnt2,F
			movlw	018h
			subwf	tcnt2,W
			btfss	STATUS,C
			return
			clrf	tcnt2
			return
;
;		
;	入力		tcnt0：下2桁(秒）
;			tcnt1：上2桁(分)
;	出力		digit12（0-59秒）
;			digit34（0-59分）
；

EXCHG
			btfsc	MODE,0
			goto	EXCHG_H
EXCHG_L		movf	tcnt1,W
			movwf	hex0
			clrf	hex1
			clrf	hex2
			clrf	hex3
			call	BCD
			movf	digit12,W
			movwf	rew1
			movf	tcnt0,W
			movwf	hex0
			clrf	hex1
			clrf	hex2
			clrf	hex3
			call	BCD
			movf	rew1,W
			movwf	digit34
			clrf	digit56
			clrf	digit78
			clrf	digit9A
			return

;
;		
;	入力		tcnt1：下2桁(分）
;			tcnt2：上2桁(時)
;	出力		digit12（0-59秒）
;			digit34（0-59分）
;

EXCHG_H
			movf	tcnt2,W
			movwf	hex0
			clrf	hex1
			clrf	hex2
			clrf	hex3
			call	BCD
			movf	digit12,W
			movwf	rew1
			movf	tcnt1,W
			movwf	hex0
			clrf	hex1
			clrf	hex2
			clrf	hex3
			call	BCD
			movf	rew1,W
			movwf	digit34
			clrf	digit56
			clrf	digit78
			clrf	digit9A
			return

;
;       ＧＬＯＶＥ　ＬＥＤ ＤＩＳＰＬＡＹ
;			ＴＭ１６３７
;
;       書込みサブルーチン群
;
;       Ｉ２Ｃアドレス　無と思われる
;
;       コマンド
;		データセットアップ命令
;		bit7-6		bit7=0、bit6=1 でこの命令となる
;		bit5-4		00固定
;		bit3		bit=0でノーマル、bit=1でテスト
;		bit2		bit=0で桁アドレス自動インクリメント、bit=1で桁アドレス固定
;		bit1-0		00でデータはそのままレジスタ、10でキーを読んでデータ生成
;
;		アドレス設定命令
;		bit7-6		bit7=1、bit6=1 でこの命令となる
;		bit5-4		00固定
;		bit3-0		0000で桁アドレス00h
;		bit3-0		0001で桁アドレス01h
;		bit3-0		0010で桁アドレス02h
;		bit3-0		0011で桁アドレス03h
;		bit3-0		0100で桁アドレス04h（未実装）
;		bit3-0		0101で桁アドレス05h（未実装）
;
;		ＬＥＤ表示命令
;		bit7-6		bit7=1、bit6=0でこの命令
;		bit5-4		00固定
;		bit3		0でLED表示OFF、1でLED表示ON
;		bit2-0		000で輝度1/16
;		bit2-0		001で輝度2/16
;		bit2-0		010で輝度4/16
;		bit2-0		011で輝度10/16
;		bit2-0		100で輝度11/16
;		bit2-0		101で輝度12/16
;		bit2-0		110で輝度13/16
;		bit2-0		111で輝度14/16
;
;		データ
;
;	出力		FDA0：下2桁(秒）
;			FDA1：上2桁(分)
;
SETBUF
;			表示する数値データをバッファに書込み
			swapf	digit34,W
			andlw	0fh
			movwf	DBUF3		;4桁目に数値データ書込み

			movf	digit34,W
			andlw	0fh
			movwf	DBUF2		;3桁目に数値データ書込み
			
			swapf	digit12,W
			andlw	0fh
			movwf	DBUF1		;2桁目に数値データ書込み

			movf	digit12,W
			andlw	0fh
			movwf	DBUF0		;1桁目に数値データ書込み

;			その他指定処理を全バッファに行う
;			呼び出し順番によっては上手く機能しなくなるので注意
			call	zbk			;ゼロブランキング処理
			call	addot		;ドット表示処理
			return

;
;			ゼロブランキング処理
;
;		入力		DBUFx　（数値データ設定済であること)
;
zbk
			movf	DBUF3,W		;
			andlw	0fh			;数値データゼロチェック
			btfss	STATUS,Z
			return				;データはゼロで無いので終了
			bsf		DBUF3,5		;ブランキングセット

			movf	DBUF2,W		;
			andlw	0fh			;数値データゼロチェック
			btfss	STATUS,Z
			return				;データはゼロで無いので終了
			bsf		DBUF2,5		;ブランキングセット

			movf	DBUF1,W		;
			andlw	0fh			;数値データゼロチェック
			btfss	STATUS,Z
			return				;データはゼロで無いので終了
			bsf		DBUF1,5		;ブランキングセット

			return				;DBUF0はゼロブランキングしない



;
;			ドットを表示するか否か
;
addot
			bcf		DBUF2,4		;ドット点灯ビットリセット
			btfss	blk,0		;ドット点燈指令チェック
			return				;ドット消灯
			bsf		DBUF2,4		;ドット点灯
			return


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		GROVE７セグモジュール用セグメントデータへの変換
;
;	入力			Wレジスタに桁データ(DBUFx)を入れてコール
;				ドット消灯の場合、00H~0FH
;				ドット点灯の場合、10H~1FH
;
;	使用ワーク		segw0
;				
;	出力			Wレジスタに8ビット分ポート出力データを入れてリターン
;				
;	モジュール内セグメント
;		bit=1の時SEG_ON、BIT=0の時SEG_OFF
;
;		a				bit0=a	bit4=e
;	f		b			bit1=b	bit5=f
;		g		Dp		bit2=c	bit6=g
;	e		c			bit3=d	bit7=Dp
;		d		Dp		
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

GET_7SEG
			
			movwf	tmp0		;Wreg保存
			btfss	tmp0,5		;ブランク制御フラグチェック
			bra		seg01		;ブランク制御しない
			btfss	tmp0,4
			retlw	0h			;ドット無ブランク返し
			retlw	080h		;ドット有ブランク返し
			
seg01		andlw	01fh		;下位5ビット取り出し
			brw

;			ドット無
			retlw	B'00111111'	;Code 0 abcdef
			retlw	B'00000110'	;Code 1 bc
			retlw	B'01011011'	;Code 2 abdeg
			retlw	B'01001111'	;Code 3 abcdg
			retlw	B'01100110'	;Code 4 bcfg
			retlw	B'01101101'	;Code 5 acdfg
			retlw	B'01111101'	;Code 6 acdefg
			retlw	B'00000111'	;Code 7 abc
			retlw	B'01111111'	;Code 8 abcdefg
			retlw	B'01100111'	;Code 9 abcfg

			retlw	B'01110111'	;Code A abcefg
			retlw	B'01111100'	;Code B cdefg
			retlw	B'00111001'	;Code C adef
			retlw	B'01011110'	;Code D bcdeg
			retlw	B'01110011'	;Code E adefg
			retlw	B'01110001'	;Code F aefg

;			ドット有
			retlw	B'10111111'	;Code 0 abcdef
			retlw	B'10000110'	;Code 1 bc
			retlw	B'11011011'	;Code 2 abdeg
			retlw	B'11001111'	;Code 3 abcdg
			retlw	B'11100110'	;Code 4 bcfg
			retlw	B'11101101'	;Code 5 acdfg
			retlw	B'11111101'	;Code 6 acdefg
			retlw	B'10000111'	;Code 7 abc
			retlw	B'11111111'	;Code 8 abcdefg
			retlw	B'11100111'	;Code 9 abcfg

			retlw	B'11110111'	;Code A abcefg
			retlw	B'11111100'	;Code B cdefg
			retlw	B'10111001'	;Code C adef
			retlw	B'11011110'	;Code D bcdeg
			retlw	B'11110011'	;Code E adefg
			retlw	B'11110001'	;Code F aefg


;
;       ＧＬＯＶＥ　４桁７セグＬＥＤ ＤＩＳＰＬＡＹ
;			ＴＭ１６３７
;
;       書込みサブルーチン群
;
;       Ｉ２Ｃアドレス　無と思われる
;
;       コマンド
;		データセットアップ命令
;		bit7-6		bit7=0、bit6=1 でこの命令となる
;		bit5-4		00固定
;		bit3		bit=0でノーマル、bit=1でテスト
;		bit2		bit=0で桁アドレス自動インクリメント、bit=1で桁アドレス固定
;		bit1-0		00でデータはそのままレジスタ、10でキーを読んでデータ生成
;
;		アドレス設定命令
;		bit7-6		bit7=1、bit6=1 でこの命令となる
;		bit5-4		00固定
;		bit3-0		0000で桁アドレス00h
;		bit3-0		0001で桁アドレス01h
;		bit3-0		0010で桁アドレス02h
;		bit3-0		0011で桁アドレス03h
;		bit3-0		0100で桁アドレス04h（未実装）
;		bit3-0		0101で桁アドレス05h（未実装）
;
;		ＬＥＤ表示命令
;		bit7-6		bit7=1、bit6=0でこの命令
;		bit5-4		00固定
;		bit3		0でLED表示OFF、1でLED表示ON
;		bit2-0		000で輝度1/16
;		bit2-0		001で輝度2/16
;		bit2-0		010で輝度4/16
;		bit2-0		011で輝度10/16
;		bit2-0		100で輝度11/16
;		bit2-0		101で輝度12/16
;		bit2-0		110で輝度13/16
;		bit2-0		111で輝度14/16
;

;
;   Ｗレジスタの数値を単発で書き込む
;
;		表示位置指定	DSP_ADR
;
PUTW
			movwf	icw2		;PUSH Wreg
			call	I2C_START	;スタートコンディション送信
			movlw	044h        ;桁アドレス固定モード
			call	I2C_SBYTE   ;Command1送信
			call	I2C_STOP

			call	I2C_START
			movf	DSP_ADR,W
			call	I2C_SBYTE	;Command2：桁アドレス送信
			movf	icw2,W		;POP Wreg
			call	GET_7SEG
			call	I2C_SBYTE	;表示セグメントデータ
			call	I2C_STOP
			call	I2C_START
			movlw	08fh		;Command3：最大光度
			call	I2C_STOP
			return

;
;	バッファの数値データを桁アドレスに連続送信・ラッチ
;
;		DBUF3	C0H
;		DBUF2	C1H
;		DBUF1	C2H
;		DBUF0	C3H
;
PUTL
			call	I2C_START	;スタートコンディション送信
			movlw	040h        ;桁アドレス自動インクリメントモード
			call	I2C_SBYTE   ;Command1送信
			call	I2C_STOP

			call	I2C_START
			movlw	0c0h		;開始桁アドレス
			call	I2C_SBYTE	;Command2：桁アドレス送信

			movf	DBUF3,W
			call	GET_7SEG
			call	I2C_SBYTE	;SEGデータをレジスタに転送

			movf	DBUF2,W
			call	GET_7SEG
			call	I2C_SBYTE

			movf	DBUF1,W
			call	GET_7SEG
			call	I2C_SBYTE

			movf	DBUF0,W
			call	GET_7SEG
			call	I2C_SBYTE
			call	I2C_STOP

			call	I2C_START
			movlw	08fh		;ラッチ、最大光度
			call	I2C_SBYTE	;Command3
			call	I2C_STOP
			return



;
;	手動Ｉ２Ｃ制御　低レベルサブルーチン群
;

;
;	I2Cバス アイドル
;		SCL=1
;		SDA=1
;
I2C_IDL
			SCL_H				;SCL=1
			SDA_H				;SDA=1
			DELAY_C
			return
			
;
;	スタートコンディション生成
;
;	START CONDITION
;		SCL=1の状態の時に、SDAが↓となるとSTARTと判断
;		これはマスタが行う
;
I2C_START
			SCL_H				;SCL=1
			SDA_H				;SDA=1 バス アイドル
			DELAY_C
			SDA_L				;SDA=0 スタートコンディション
			DELAY_C
			SCL_L				;SCL=0
			return
			
;
;	ACK確認
;
I2C_ACK
			SCL_L				;SCLがH→LになるとACK応答始まる
			DELAY_C
			SDA_H				;SDA=1としても0のまま
;			DELAY_C
;			SCL_H				;SCL=1とするとACK応答終了してしまう
;			DELAY_C
			btfsc	PORTC,1		;SDA_PORT=0？
			bra		$-1
			SCL_H				;SCL１クロックでスレーブはACK解除する
			DELAY_C
			SCL_L				;ACK確認・処理終了
			return				;SDA=0（ACK受信）なので終了
			
;
;	STOP送信
;
I2C_STOP
			SCL_L				;SCL=0
			DELAY_C
			SDA_L				;SDA=0
			DELAY_C
			SCL_H				;SCL=1
			DELAY_C
			SDA_H				;SDA=1　バス アイドル
			DELAY_C
			return

;
;	1バイト送信（TM1637専用）
;
;	SCL=0の状態の間に、SDAビットをセッティング
;	SCL=1の状態の時に、スレーブはそのSDAビットをデータとして読み込む
;	SCL=1の状態の間に、SDAビットを変更すると、STARTあるいはSTOP他とみなされる
;
;	使用方法
;		Wregに送信データバイトを設定して呼び出す事
;		下位ビットより送信される（標準と違うので注意）
;		事前にI2C_STARTをコールしている事
;		SCL=0、SDA=0となっている
I2C_SBYTE
			movwf	icw0
			movlw	08h
			movwf	icw1
			
SNDLP		SCL_L				;SCL=0→SDAビット設定・変更可
			DELAY_C
			lsrf	icw0,F		;右シフト
			btfss	STATUS,C
			bra		SBITL
SBITH		SDA_H				;SDA=1→送信ビット
			bra		SNDEN
SBITL		SDA_L				;SDA=0→送信ビット
SNDEN		DELAY_C
			SCL_H				;SCL=1→スレーブがSDAビットを受信
			DELAY_C
			decf	icw1,F
			btfss	STATUS,Z
			bra		SNDLP
			;ACK待ち
RCVACK		SCL_L				;SCLがH→LになるとACK応答始まる
			DELAY_C
			SDA_H				;SDA=1としても0のまま
			btfsc	PORTC,1		;SDA_PORT=0？
			bra		$-1
			SCL_H				;SCL１クロックでスレーブはACK解除する
			DELAY_C
			SCL_L				;ACK確認・処理終了
			return


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		４バイトバイナリの10桁BCDへの変換
;		MicroChip社のアプリケーションノートより
;
;		入力		4バイト(32ビット)16進バイナリ
;				hex0
;				hex1
;				hex2
;				hex3
;
;		出力		5バイト(10桁)ＢＣＤ
;				digit12
;				digit34
;				digit56
;				gidit78
;				gidit9A
;
;		使用ワーク
;				hexw0	入力データ保存用
;				hexw1
;				hexw2
;				hexw3
;				shift	シフトカウンタ
;				bcdw0	補正処理ワーク
;				bcdw1
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BCD
			BCF		STATUS,C	;キャリーリセット
			MOVLW	020H		;シフトカウンタ初期化
			MOVWF	shift		;4バイト分32回の指定 
			CLRF	digit12		;BCDデータエリア初期化
			CLRF	digit34
			CLRF	digit56
			CLRF	digit78
			CLRF	digit9A
			MOVF	hex0,W
			MOVWF	hexw0
			MOVF	hex1,W
			MOVWF	hexw1
			MOVF	hex2,W
			MOVWF	hexw2
			MOVF	hex3,W
			MOVWF	hexw3
			
			;変換ループ処理
loop
			RLF		hexw0,F		;16進データ左シフト
			RLF		hexw1,F
			RLF		hexw2,F
			RLF		hexw3,F
			RLF		digit12,F	;BCDデータ左シフト
			RLF		digit34,F
			RLF		digit56,F
			RLF		digit78,F
			RLF		digit9A,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
			MOVF	digit9A,W	;digit9A
			CALL	adjbcd
			MOVWF	digit9A
			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

			

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			遅延時間サブルーチン	32MHZ用
;
;		1cycle	= 0.125us
;		使用レジスタ	= cnt2,cnt3
;		BSR		=0(BANK0)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

wait100u						;呼び出しも含めて、100us
								;call is 2cycles
			movlw	09h			;1
			movwf	cnt2		;1
			movlb	0h
			nop
			nop					;3
w100u		nop					;
			call	w10u		;10*9=90us(ここだけ命令ステップを数えない）
			decfsz	cnt2,F		;4*8+3=31cycles
			goto	w100u
			return				;2+5+31+2=40cycles=20us

wait50u							;呼び出しも含めて、50us
			call	wait25u
wait25u							;呼び出しも含めて、25us
			call	w10u
			call	w10u
			movlw	0bh			;5us=0.125us*40cycles
			movwf	cnt2		;
w25u		decfsz	cnt2,F		;ループ 2+10*3+2=34cycles
			goto	w25u
			nop
			nop
			return				;2+34+2+2=40cycles=5us

wait5m							; 5ms
			movlb	0h
			movlw	05h
			movwf	cnt2
w5m			call	w1m
			decfsz	cnt2,F
			goto	w5m
			return

wait10m							; 10ms
			movlb	0h
			movlw	d'10'
			movwf	cnt2
w10m		call	w1m
			decfsz	cnt2,F
			goto	w10m
			return

wait20m							; 20ms
			movlb	0h
			movlw	d'20'
			movwf	cnt2
w20m		call	w1m
			decfsz	cnt2,F
			goto	w20m
			return
wait50m							; 50ms
			movlb	0h
			movlw	d'50'
			movwf	cnt2
w50m		call	w1m
			decfsz	cnt2,F
			goto	w50m
			return

wait100m						; 100ms
			movlb	0h
			movlw	d'100'
			movwf	cnt2
w100m		call	w1m
			decfsz	cnt2,F
			goto	w100m
			return

wait500m						; 500ms
			movlb	0h
			movlw	05h
			movwf	cnt3
w500m		call	wait100m
			decfsz	cnt3,F
			goto	w500m
			return

wait1s							; 1s
			movlb	0h
			movlw	d'10'
			movwf	cnt3
w1s			call	wait100m
			decfsz	cnt3,F
			goto	w1s
			return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			1ms 基本ウェイト
;			呼び出しを含めて1msとなる。
;
;		clock	= 32MHz(0.03125usec)
;		1cycle	= 0.125usec
;		1ms		= 0.125usec * 8000cycles
;
;			使用変数　cnt0,cnt1
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
w1m
			movlb	0h
			movlw	08h
			movwf	cnt0		;
;			外周ループ
w1m0		movlw	0c7h		;199d
			movwf	cnt1		;
;			内周ループ
w1m1		nop					;
			nop					;5cycles*cnt1
			decfsz	cnt1,F		;2+5*198+4=996c/s
			goto	w1m1		;
;
			decfsz	cnt0,F		;
			goto	w1m0		;2+7*999+998=7993cycles
			nop
			return					;other=(3+4)cycles
									;Total 8000*0.125us=1ms


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			10us 基本ウェイト
;			呼び出し（call　w10u)も含めて、10usとなる。
;
;		clock	= 32MHZ(0.03125us)
;		1cycle	= 0.125us
;		10us	= 0.125us * 80cycles
;		使用変数　cnt0,cnt1
;		'goto','call','return'は2サイクル消費する
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

w10u
			movlb	0h
			movlw	018h		;18H=24
			movwf	cnt0		;
w10u0		decfsz	cnt0,F		;3*23+2=71
			goto	w10u0		;
			nop
			nop
			return				;2+3+71+2+2=80cycles

w05u
			movlw	0bh			;5us=0.125us*40cycles
			movwf	cnt0		;
w05u0		decfsz	cnt0,F		;ループ 2+3*10+2=34cycles
			goto	w05u0
			nop
			nop
			return				;2+34+2+2=40cycles=5us

w02u
			movlw	04h			;2us=0.125us*16cycles
			movwf	cnt0		;
w02u0		decfsz	cnt0,F		;2+3*3+2+1+2=16cycles
			goto	w02u0
			nop
			return				;
w01u
			nop					;1us=0.125us*8cycles
			nop					;2+4+2=8cycles
			nop
			nop
			return

;
            END
