 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		ＰＩＣ１６Ｆ１８２８　Ｉ２Ｃ-パラレル変換
;
;							2019年10月	Ver2.0	JA0QON
;
;		パラレル接続ＬＣＤをＩ２Ｃ接続で使う
;		ＭＳＳＰプログラムの更新実験
;
;
;	ターゲットディスプレイ
;		SC1602 パラレル接続16桁2行液晶モジュール
;		PIC16F1828 32MHZ 内部発振
;		データバスは8bit
;
;	ＭＳＳＰスレーブモード　Ｖｅｒ０．２
;		
;		マスタへの送信対応
;		クロックストレッチ対応
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

		LIST	P=PIC16F1828
		INCLUDE	P16F1828.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=有効　クロックが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					Unimplemented(read = 1)
;bit10		BORV	0	ブラウンアウト･リセット電圧選択ビット（Vbor参照)
;						1=低電圧で動作
;						0=高電圧で動作
;bit9		STVREN	0	スタック･オーバーフロー･リセット設定
;						1=有効
;						0=無効
;bit8		PLLEN	0	PLL設定
;						1=4xPLL有効
;						0=4xPLL無効
;bit7-5					Unimplemented(read = 1)
;bit4					Reserved (read = 1)
;bit3-2					Unimplemented(read = 1)
;bit1-0		WRT		11	フラッシュメモリ プロテクション設定（EECONレジスタ参照)
;						11=無効
;						10=0h-1FFh有効
;						01=0h-3FFh有効
;						00=0h-7FFh有効
;
;bit	15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
;data    0  0  0  1  1  0  0  0  1  1  1  1  1  1  1  1
;
;
	__CONFIG _CONFIG2,	B'0001100011111111'



;		ワークエリア定義
;
;		BANK0	20h-7Fh
;
;		使用していないのもあります
;

;ウエイト用専用ワーク
cnt0		equ		020H		;時間待ちルーチン用専用ワーク
cnt1		equ		021H
cnt2		equ		022H
cnt3		equ		023H
;汎用ローカルワーク
tmp0		equ		024H		;汎用ワーク、その場所限定
tmp1		equ		025H		;移動した場合、破壊されること有
;機能専用広域ワーク
FLG			equ		026H		;8桁7セグLED表示設定フラグ
MODE		equ		027H		;実行モード設定フラグ
DSPM		equ		028H		;ディスプレイモード スイッチフラグ
;汎用広域ワーク
wrk0		equ		029H        ;演算用汎用ワーク
wrk1		equ		02AH
shift       equ     02BH        ;ビットシフト用ワーク
blk			equ		02CH		;ゼロブランキング制御フラグ
colum		equ		02DH		;現在の桁位置
colw0		equ		02EH		;桁位置処理ワーク
colw1		equ		02FH		;
;
DSP_ADR     equ     030H
icw0        equ     031H
icw1        equ     032H
MSAD0		equ		033H
MSAD1		equ		034H
LDWR		equ		035H		;Wreg退避用
I2C_MODE	equ		036H
I2C_DATA	equ		038H
CMD_CTRL	equ		039H		;コントロールバイト
CMD_DATA	equ		03AH		;コマンドデータ
BSLW0		equ		03BH
BSLW1		equ		03CH
BSLSP		equ		03DH
;
			ORG		0H			;リセットベクタ
			goto	init
			ORG		04H			;割り込みベクタ

;
;		割込み処理ルーチン
;		ＭＳＳＰスレーブモードＶ０．２
;
;		クロックストレッチに対応
;		送受信に於いて準備ができるまでマスタを待たせ、
;		要求されたデータを送信する事が可能となった
;
;
;	割込み要件１	自分のＩ２Ｃアドレスの受信(SEN=1)
;		I2Cアドレスが一致すると、MSSPはマスタに/ACKを送信
;		/ACK送信後MSSPはSSP1CON1CKPビットをクリア
;		それによりMSSPはSCLをホールド（クロックストレッチ）
;		同時に割り込み発生、ISRはこの処理を開始
;		SSP1STAT:R/Wビットからマスタへの送信かマスタからの受信かの確認
;
;		１）マスタからの受信準備
;			ISRはSSP1IFビットをクリア(割り込みフラグをリセット)
;			ISRはSSP1BUFのアドレスデータを読み込む
;			MSSPはSSP1BFフラグをクリアする
;			ISRはSSP1CON1CKPビットをセットし、SCLラインを開放(ストレッチ開放)
;			ISRはフラグ処理等を行い、一旦ISRを終了
;			ストレッチ開放処理(CKP=1)はメインプログラムのアドレス受信処理に委ねる
;
;			メインプログラムの「アドレス受信処理」はフラグから送信か受信かの確認
;			受信の場合、
;
;		２）マスタへの送信準備
;			ISRはSSP1IFビットをクリア(割り込みフラグをリセット)
;			ISRはSSP1BUFのアドレスデータを読み込む
;			MSSPはSSP1BFフラグをクリアする
;			ISRはフラグ処理等を行い、一旦ISRを終了
;
;			メインプログラムのアドレス受信処理はフラグから送信データを準備
;			送信データの準備が出来たらSSP1BUFに書き込む
;			その後はストレッチ開放処理(CKP=1)を行う
;
;
;
;	割込み要件２	Ｉ２Ｃデータバイトの受信(SEN=1)
;		マスタはSCL開放(CKP=1)されるとデータビットを送信し始める
;		MSSPはデータバイトを受信するとマスタに/ACKを送信
;		/ACK送信後MSSPはSSP1CON1CKPビットをクリア
;		それによりMSSPはSCLをホールド（クロックストレッチ）
;		同時に割り込み発生、ISRはこの処理を開始
;
;		１）データバイトの受信
;			ISRはSSP1IFビットをクリア(割り込みフラグをリセット)
;			ISRはSSP1BUFのデータを読み込み、データを保存
;			MSSPはSSP1BFフラグをクリアする
;			ISRは必要なフラグ処理等を行い、ISRは一旦終了する
;
;			「受信データ処理」は、
;			「LCD_CTRL」ならば次の「LCD_DATA」受信の準備をする
;			「LCD_DATA」ならばデータをLCDに送信する
;			SSP1CON1CKPビットをセットし、SCLラインを開放(ストレッチ開放)
;
;			マスタは次のデータを送信し始める
;			ただし、マスタがNACKを送信の場合はSCL閉鎖はされずストップに移行する
;
;
;	割込み要件３	Ｉ２Ｃデータバイトの送信(SEN=1)
;		マスタはSCL開放(CKP=1)されるとデータビットを受信し始める
;		マスタは1バイト受信すると/ACKあるいはNACKを返信してくる
;		MSSPは/ACKをSSP1CON2ACKDTビットに反映する
;		/ACK受信後MSSPはSSP1CON1CKPビットをクリア
;		それによりMSSPはSCLをホールド（クロックストレッチ）
;		MSSPはNACK受信の場合ストレッチを行わない(CKP=1のまま)
;		どちらにせよ、同時に割り込み発生、ISRはこの後の処理を開始
;		１）データバイトの送信(ACKの場合)
;			ISRはSSP1IFビットをクリア(割り込みフラグをリセット)
;			ISRはフラグ処理等を行い、一旦ISRを終了
;
;			メインプログラムのデータ送信処理はフラグから送信データを準備
;			すなわちLCDからデータを読み込む
;			送信データの準備が出来たらSSP1BUFに書き込む
;			その後はストレッチ開放処理(CKP=1)を行う
;
;
;	割込み要件４	ＳＴＯＰの受信
;		SSP1IFがセットされ、割り込み発生
;		SSP1IFを確認
;		SSP1STATのPビットを確認
;		SSP1IFをリセットする
;		MSSPモジュールをアイドルにする
;
;	ＬＥＤ制御
;		I2Cアドレス受信すると、LED(RB7)を点灯
;		ストップビットを検出すると、LEDを消灯
;
;	使用ワーク
;		CMD_CTRL	受信コマンドワードのコントロールバイトを格納
;			bit7	CO
;						1=連続コマンドワード
;						0=最終コマンドワード
;			bit6	RS
;						1=データは文字コード或いはCGRAMデータ
;						0=データはインストラクションコード
;			bit5	STATUS
;						1=返信データはLCDステータス
;						0=返信データはLCDデータ(文字コードあるいはCGRAMデータ)
;			bit4	
;			bit3	
;			bit2	
;			bit1	
;			bit0	
;
;		CMD_DATA	受信コマンドワードのデータバイトを格納
;
;		I2C_DATA	送受信したI2Cデータ(1バイト)を格納
;
;		I2C_MODE	I2C通信の進行状況を示すフラグ
;					通常プログラムはこれを頼りに処理を行う
;
;			bit7	RCV_STOP
;						1=I2Cストップビットを検出
;						0=I2C通信継続中
;			bit6	予約
;			bit5	RCV_NACK
;						1=マスタはデータ受信を完了(NACKを受信)
;						0=
;			bit4	RCV_ACK
;						1=マスタはデータ送信を要求(ACKを受信)
;						0=
;			bit3	RCV_DATA
;						1=MSSPはデータバイトを受信
;						0=データは無効
;			bit2	RCV_RW
;						1=マスタからの受信要求ビットを検出(スレーブは送信)
;						0=マスタからの送信要求ビットを検出(スレーブは受信)
;			bit1	RCV_ADRESS
;						1=I2Cスレーブアドレスを受信
;						0=MSSP1はアイドル
;			bit0	RCV_START
;						1=I2Cスタートビットを検出
;						0=MSSP1はアイドルあるいはオフライン
;
INT
;	割込み要件の確認
;

			clrf	BSR
			clrf	I2C_MODE	;I2Cフラグをリセット
			movlb	04H			;BANK4
			;STARTビット検出(MSSPがリセットされるまでクリアされない、現在割込無効)
;			btfsc	SSP1STAT,S	;
;			goto	RCV_STA

			;STOPビット検出(MSSPがリセットされるまでクリアされない)
			btfsc	SSP1STAT,P
			goto	RCV_STP

			;R/Wビット情報
			btfss	SSP1STAT,R_NOT_W
			bra		RW_W			;R/W=0マスタ送信
			;R/W=1スレーブ送信モード、フラグセット
RW_R		clrf	BSR
			bsf		I2C_MODE,2		;R/Wフラグ=1(スレーブ送信)
			bra		WRT_DA			;マスタ受信要求
			;R/W=0スレーブ受信モード、フラグセット
RW_W		clrf	BSR
			bcf		I2C_MODE,2		;R/Wフラグ=0(スレーブ受信)
			bra		RCV_DA

;スレーブ送信モードでアドレス受信したかデータ送信したかのチェック
;			D/Aビット(DATA or /ADRS)
WRT_DA
			movlb	04H
			btfss	SSP1STAT,D_NOT_A;D/Aビットのチェック
			goto	RCV_ADRS		;D/A=0スレーブ送信モードでアドレス受信

;D/A=1スレーブ送信モードでデータ送信した後のマスタからのACK返信チェック
WRT_ST
			btfss	SSP1CON2,ACKSTAT;ACKSTAT=1 ACKを受信していない
			bra		WRT_STA			;ACKSTAT=0 ACKを受信した
			;NACK受信
WRT_STN		clrf	BSR
			bcf		I2C_MODE,5		;NACK受信(送信終了要求)
			goto	INTOUT
			;ACK受信
WRT_STA		clrf	BSR
			bcf		I2C_MODE,4		;ACK受信(連続送信要求)
			goto	INTOUT

;スレーブ送受信モードでアドレス受信したかデータ受信したかのチェック
;			D/Aビット(DATA or /ADRS)
RCV_DA
			movlb	04H
			btfsc	SSP1STAT,D_NOT_A
			goto	RCV_DATA

;			D/A=0 I2Cアドレスの受信
RCV_ADRS
			movlb	04H
			movf	SSP1BUF,W	;アドレスは破棄
			clrf	BSR
			bsf		I2C_MODE,1	;I2Cアドレス受信フラグ セット
			bcf		PORTB,7		;LED ON
			goto	INTOUT
;			D/A=1 I2Cデータの受信
RCV_DATA
			movlb	04H			;BANK4 SSP1関連
			movf	SSP1BUF,W	;受信データ取得
			clrf	BSR			;BANK0
			movwf	I2C_DATA
			bsf		I2C_MODE,3	;I2Cデータ受信フラグ セット
			goto	INTOUT
;	スタートビットの受信
RCV_STA
			clrf	BSR
			bsf		I2C_MODE,0	;START_BIT
			goto	INTOUT
;	ストップビットの受信
RCV_STP
			clrf	BSR
			bsf		I2C_MODE,7	;STOP_BIT
			bsf		PORTB,7		;LED OFF
;	割込み終了処理
INTOUT
			clrf	BSR
			bcf		PIR1,SSP1IF	;MSSP1割り込みフラグクリア
			retfie				;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			PIC16F1828　イニシャライズ
;
;		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は選択の余地が無い。
;
;		各ポートのデジタル入出力は、TTL入力、CMOS出力が基本
;		PORTA(BANK0　00CH）
;			bit7-6	Unimplemented(read=0)
;			bit5	RA5		デジタルI/O
;			bit4	RA4		デジタルI/O、アナログ入力
;			bit3	RA3		デジタルInputのみ(TTL)
;			bit2	RA2		デジタルI/O（CMOSシュミット）、アナログ入力
;			bit2	RA1		デジタルI/O、アナログ入力
;			bit0	RA0		デジタル･アナログI/O,DAコンバータ出力
;
;		PORTB(BANK0　00DH）
;			bit7-6	RB7-6	デジタルI/O
;			bit5-4	RB5-4	デジタルI/O、アナログ入力
;			bit3-0	Unimplemented(read=0)
;
;		PORTC(BANK0　00EH）
;			bit7-6	RC7-6	デジタルI/O、アナログ入力
;			bit5-4	RC5-4	デジタルI/O
;			bit3	RC3-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=出力
;
;		TRISB(BANK1　08DH)
;			bit7-6	Unimplemented(read=0)
;			bit5-4	RB7-4	1=入力、0=出力
;
;		TRISC(BANK1　08EH)　マニュアル130ページ
;			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レジスタ設定で各ピンに反映される）
;
;		LATB(BANK2　10DH)
;			bit7-4	RAB7-4	出力データ保持
;			bit3-0	Unimplemented(read=0)
;			（このラッチデータはTRISBレジスタ設定で各ピンに反映される）
;
;		LATC(BANK2　10EH)
;			bit7-6	Unimplemented(read=0)
;			bit5-0	RA5-4	出力データ保持
;			（このラッチデータはTRISCレジスタ設定で各ピンに反映される）
;
;
;		ANSELA(BANK3　18CH)
;			bit7-5	Unimplemented(read=0)
;			bit4	ANSA3/RA4	アナログ/デジタル選択ビット
;								1=アナログ入力
;								0=デジタルI/O
;			bit3	Unimplemented(read=0)
;			bit2-0	ANA2-0/RA2-0アナログ/デジタル選択ビット
;								1=アナログ入力
;								0=デジタルI/O
;			＊デフォルトでは、すべて1(アナログ入力)となっている
;
;		ANSELB(BANK3　18DH)
;			bit7-4	ANSC3-0/RC3-0　アナログ/デジタル選択ビット
;								1=アナログ入力
;								0=デジタルI/O
;			bit3-0	Unimplemented(read=0)
;			＊デフォルトではアナログ入力となっている
;
;		ANSELC(BANK3　18EH)　マニュアル131ページ
;			bit7-4	Unimplemented(read=0)
;			bit3-0	ANSC3-0/RC3-0　アナログ/デジタル選択ビット
;								1=アナログ入力
;								0=デジタルI/O
;			＊デフォルトではアナログ入力となっている
;
;		WPUA(BANK4　20CH)　ポートAプルアップ設定ビット
;			bit7-6	Unimplemented(read=0)
;			bit5-0			1=PORTA各ビットプルアップ有効
;					 _____	0=PORTA各ビットプルアップ無効
;					*WPUENビットが有効の時のみ、設定有効となる。
;
;		WPUB(BANK4　20DH)　ポートBプルアップ設定ビット
;			bit7-4			1=PORTB各ビットプルアップ有効
;					 _____	0=PORTB各ビットプルアップ無効
;			bit3-0	Unimplemented(read=0)
;					*WPUENビットが有効の時のみ、設定有効となる。
;
;		WPUC(BANK4　20EH)　ポートCプルアップ設定ビット
;			bit7-0			1=PORTC各ビットプルアップ有効
;					 _____	0=PORTC各ビットプルアップ無効
;					*WPUENビットが有効の時のみ、設定有効となる。
;
;		INLVLA(BANK7　38CH)　ポートA入力レベル設定レジスタ
;			bit7-6	Unimplemented(read=0)
;			bit5-0	RA5-0	ST/TTL選択ビット
;								1=シュミットトリガー(ST)入力
;								0=TTL入力
;
;		INLVLB(BANK7　38DH)　ポートB入力レベル設定レジスタ
;			bit7-4	RB7-4	ST/TTL選択ビット
;								1=シュミットトリガー(ST)入力
;								0=TTL入力
;			bit3-0	Unimplemented(read=0)
;
;		INLVLB(BANK7　38EH)　ポートC入力レベル設定レジスタ
;			bit7-0	RC7-0	ST/TTL選択ビット
;								1=シュミットトリガー(ST)入力
;								0=TTL入力
;
;	ADCON0レジスタ(BANK1　09DH)
;		bit7	Unimplemented(read=0)
;		bit6-2	CHS		アナログ入力チャンネル選択ビット
;						00000 = AN0/RA0
;						00001 = AN1/RA1
;						00010 = AN2/RA2
;						00011 = AN3/RA4
;						00100 = AN4/RC0
;						00101 = AN5/RC1
;						00110 = AN6/RC2
;						00111 = AN7/RC3
;						01000 = AN8/RC6
;						01001 = AN9/RC7
;						01010 = AN10/RB4
;						01011 = AN11/RB5
;						11101 = 温度インジケータ
;						11110 = DAC出力
;						11111 = FVRバッファ1出力
;		bit1	GO/DONE	A/D変換ステータスビット
;						1=変換開始指令（１にすると変換動作開始）
;						0=変換完了(変換完了すると０になる）
;		bit0	ADON	A/D変換ステータスビット
;						1=A/Dコンバータ動作
;						0=A/Dコンバータ停止
;
;	ADCON1レジスタ(BANK1　09EH)
;		bit7	ADFM	変換結果格納指定
;						1=右詰
;						0=左詰め
;		bit6-4	ADCS	A/D変換クロック選択ビット
;						000	= Fosc/2
;						001 = Fosc/8
;						010 = Fosc/32
;						011 = Frc
;						100 = Fosc/4
;						101 = Fosc/16
;						110 = Fosc/64
;						111 = Frc
;		bit3	Unimplemented(read=0)
;		bit2	ADNREF	参照負電圧指定
;						0 = VSS
;						1 = 外部VREF- (RA0)
;		bit1-0	ADPREF	参照正電圧指定
;						00 = VDD
;						01 = Reserved
;						10 = 外部VREF+ (RA1)
;						11 = 内部FVRモジュール
;
;		FVRCONレジスタ(BANK2　117H)
;			bit7	FVREN	FVRイネーブルビット
;							1有効、0無効
;			bit6	FVRRDY	FVR準備フラグビット(#1)書込み不可
;							1使用可能、0使用不可能あるいは禁止されている
;			bit5	TSEN	温度表示器イネーブルビット
;							1有効、0無効
;			bit4	TSRNG	温度表示器測定レンジ選択ビット
;							1=High Range:Vout=VDD-4VT
;							0=Low Range:Vout=VDD-2VT
;			bit3-2	CDAFVR	コンパレータとDACへのFVR電圧選択ビット
;							00 = FVR出力OFF
;							01 = FVR出力 1x(1.024V)
;							10 = FVR出力　2x(2.048V)#2
;							11 = FVR出力　4x(4.096V)#2
;			bit1-0	ADFVR	ADCへのFVR電圧選択ビット
;							00 = FVR出力OFF
;							01 = FVR出力 1x(1.024V)
;							10 = FVR出力　2x(2.048V)#2
;							11 = FVR出力　4x(4.096V)#2
;
;							#1)12F1824/16F1828では常に"1"
;							#2)FVR電圧出力はVDDを超える事は出来ない
;
;
;	OPTION_REG(BANK1　095H)
;				_____
;		bit7=1	WPUEN	プルアップ グローバル設定ビット
;						0=有効,1=無効
;		bit6=0	INTEDG	INTピン割り込み信号エッジ↑
;						1=↑
;						0=↓
;		bit5=1	TMR0CS	TMR0クロックソース選択ビット
;						1=外部入力RA2/T0CKI
;						0=内部システムクロック(Fosc/4)
;		bit4=0	TMR0SE	TMR0ソースエッジ選択ビット
;						1=RA2/T0CKIピンが↑の時インクリメント
;						0=RA2/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
;
;	CPSCON0(BANK0　01EH)
;		bit7=0	CPSON	CPSモジュール･イネーブルビット
;						1=有効
;						0=無効
;		bit6=0	CPSRM	静電容量式センシング参照電圧モードビット
;						1=CPSモジュールをHIレンジに設定
;						　　オシレータの参照電圧にDACとFVRを使用
;						0=CPSモジュールをLOWレンジに設定
;						　　オシレータ内蔵の参照電圧を使用
;		bit5-4	Unimplemented(read=0)
;		bit3-2	CPSRNG	静電容量式センシング電流レンジビット
;						CPSRM=0の場合
;						00=オシレータはOFF
;						01=オシレータをLOWレンジに設定、充放電電流は0.1uA
;						10=オシレータをMediumレンジに設定、充放電電流は1.2uA
;						11=オシレータをHighレンジに設定、充放電電流は18uA
;						CPSRM=1の場合
;						00=オシレータはON、ノイズ検出モード
;							充放電電流は供給されない
;						01=オシレータをLOWレンジに設定、充放電電流は9uA
;						10=オシレータをMediumレンジに設定、充放電電流は30uA
;						11=オシレータをHighレンジに設定、充放電電流は100uA
;		bit1=0	CPSOUT	静電容量式センシングオシレータ ステータスビット
;						1=オシレータが電流をソース（ピンから電流を出力）
;						0=オシレータが電流をシンク（ピンから電流を入力）
;		bit0=0	T0XCS	Timer0外部クロック源選択ビット
;						TMR0CS=1の場合
;						コア/Timer0モジュールのどの外部クロックからTimer0に
;						クロックを供給するかをTOXCSビットで制御する
;						1=Timer0のクロック源に静電容量式センシングオシレータ使用
;						0=Timer0のクロック源にT0CKIピンを使う
;						TMR0CS=0の場合
;						Timer0のクロック源にコア/Timer0モジュールで制御する
;						すなわち、Fosc/4
;
;
;		DACCON0レジスタ(BANK2　11AH)　
;		bit7	DACEN	DACイネーブルビット　P156 Fig17-1参照
;						1=許可
;						0=禁止
;		bit6	DACLPS	電圧指定
;						1=DAC出力電圧は+sourecと同等
;						0=DAC出力電圧は-sourceと同等
;		bit5	DACOE	DAC電圧出力イネーブルビット
;						1=DAC出力電圧をDACOUTピンに接続される
;						0=DAC出力電圧はDACOUTピンに接続されない
;		bit4	Un		Read as '0'
;		bit3-2	DACPSS	DAC Vsource+接続選択ビット
;						00 = VDD
;						01 = VREF+ピン(RA1)
;						10 = FVRバッファ2出力
;						11 = 使用不可
;		bit1-0	Un		Read as '0'
;
;
;
;	SSP1STATレジスタ
;		bit7	SMP:データ入力サンプリングビット
;				1= 標準速度モード(100KHZと1MHZ)を無効にする
;				0= 高速モード(400KHZ)を有効にする
;		bit6	CKE:
;				1= SMBus仕様に準拠したしきい値の入力ロジックにする
;				0= SMBus仕様入力を無効にする
;		bit5	D/A:
;				1= 最後に送受信したバイトはデータである
;				0= 最後に送受信したバイトはアドレスである
;		bit4	P:ストップビット
;				1= 最後にストップビットが検出された
;				0= ストップビットは検出されない
;		bit3	S:スタートビット
;				1= 最後にスタートビットが検出された
;				0= スタートビットは検出されない
;		bit2	R/W:読み書きビット（スレーブの場合）
;				1= マスタからは読み出し命令
;				0= マスタからは書き込み命令
;				* STARTビット、STOPビット、NACKビットのいずれかを受信するまで有効
;		bit1	UA:アドレス更新ビット（10ビットアドレスモードのみ）
;
;		bit0	BF:バッファフル ステータスビット
;				受信の場合
;				1= 受信は完了した
;				0= 受信は未完了でバッファはエンプティ
;				送信の場合
;				1= 送信中でSSP1BUFはフルである
;				0= 送信は完了(ACKおよびSTOPビットは含まない)でSSP1BUFはエンプティ
;
;	SSP1CON1	SSP制御レジスタ１	BSR=4
;		bit7	WCOL：書込みコリジョン検出ビット
;				マスタの場合
;				1=I2Cの送信開始条件が無効の時にSSP1BUFレジスタへ書込みが行われた
;				0=問題無
;				スレーブの場合
;				1=前のワードの送信中にSSP1BUFレジスタへの書き込みが行われた
;				0=問題無
;					*ソフトウエアでクリアする必要あり
;		bit6	SSP1OV：受信オーバーフロー インジケータービット(注1)
;				1=オーバーフロー発生
;				2=問題無
;					*ソフトウエアでクリアする必要あり
;		bit5	SSP1EN：同期シリアルポートイネーブルビット
;				1=シリアルポート有効(注2)
;				0=シリアルポート無効、I/Oポート使用可
;		bit4	CKP：クロック極性選択ビット
;				1=クロックを有効化
;				0=クロックをLOWに保持（クロックストレッチ）
;					*マスタモードでは使用しない
;		bit3-0  SSP1M：同期シリアルポート モード選択ビット
;				0110=スレーブモード、7ビットアドレス
;				0111=スレーブモード、10ビットアドレス
;				1000=マスターモード、クロック=FOSC/(4*SP1ADD+1))(注3)
;				1011=ファームウエア制御のマスターモード（スレーブアイドル）
;				1110=スレーブモード、7ビットアドレス、
;					スタートビットとストップビットの割込み有効
;				1111=スレーブモード、10ビットアドレス、
;					スタートビットとストップビットの割込み有効
;
;		注1)マスターモードの場合、新たな送受信はSSP1BUFへの書込みによって
;			開始するため、オーバーフロービットはセットされない
;		注2)SDAピンとSCLピンは入力としてTRIS=1設定
;		注3)SP1ADDの値、0,1,2はサポートされない
;
;	SSP1CON2	SSP制御レジスタ２
;		bit7	GCEN：ジェネラルコールイネーブルビット
;				1=SSP1SRでGCアドレス(00H)を受信した時の割込みを有効にする
;				0=GCアドレスを無効にする
;		bit6	ACKSTAT：肯定応答(ACK)ステータスビット
;				1=ACK受信した
;				0=ACK受信していない
;		bit5	ACKDT：ACKデータビット（受信モード）
;				1=ACKしない
;				0=ACKあり
;		bit4	ACKEN：ACKシーケンス イネーブルビット（マスタ受信モード）（注1）
;				1=ACKシーケンスを開始し、ACKDTビットを送信する
;				0=ACKシーケンスをアイドルにする
;		bit3	RCEN：受信イネーブルビット（マスターモードのみ）（注1）
;				1=受信モードを有効にする
;				0=受信をアイドルにする
;		bit2	PEN：ストップ条件イネーブルビット（注1）
;				SCK解放制御
;				1=ストップ条件を開始する、ハードウエアによって自動でクリアされる
;				0=ストップ条件をアイドルにする
;		bit1	RSEN：反復スタート条件イネーブルビット（注1）
;				1=反復スタート条件を開始する
;					ハードウエアによって自動でクリアされる
;				0=反復スタート条件をアイドルにする
;		bit0	SEN：スタート条件イネーブルビット（注1）
;				マスターモードの場合
;				1=スタート条件を開始する、ハードウエアによって自動でクリアされる
;				0=スタート条件をアイドルにする
;
;		注1）I2Cモジュールがアイドルで無い場合、これらのビットはセットされず、
;			 SSP1BUFに書き込まれない場合がある（SSP1BUFへの書込み無効）
;
;	SSP1CON3	SSP1制御レジスタ３
;		bit7	ACKTIM：肯定応答(ACK)タイムステータスビット（注1）
;				1=ACKシーケンスを実行中。
;				　SCLクロックの8番目の立下りエッジでセットされる
;				0=ACKシーケンスではない。
;				　SCLクロックの9番目の立上がりエッジでクリアされる
;		bit6	PCIE：ストップ条件割込みイネーブルビット
;				1=ストップ条件検出時の割込みを有効にする
;				0=ストップ条件検出時の割込みを無効にする
;		bit5	SCIE：スタート条件割込みイネーブルビット
;				1=スタート／リスタート条件検出時の割込みを有効にする
;				0=スタート条件検出時の割込みを無効にする
;		bit4	BOEN：バッファ上書きイネーブルビット
;				1=SSP1BUFは更新され、受信したアドレス／データバイトに対して
;				　ACK信号が生成される。
;				　BFビットが0の場合のみSSP1OVビットの状態を無視する。
;				0=SSP1OVがクリアされている時のみSSP1BUFが更新される
;				*マスタモードの場合、このビットは無視される
;		bit3	SDAHT：SDAホールド時間の選択ビット
;				1=SDAのホールド時間はSCLの立下りエッジから最小300ns
;				0=SDAのホールド時間はSCLの立下りエッジから最小100ns
;		bit2	SBCDE：スレーブモードのバスコリジョン検出イネーブルビット
;				1=スレーブバスコリジョン割込みを有効にする
;				0=スレーブバスコリジョン割込みを無効にする
;		bit1	AHEN：アドレスホールドイネーブルビット（スレーブモードのみ）
;				1=一致受信アドレスバイトのSCLの8番目の立下りエッジ後、SSP1CON1
;				　レジスタのCKPビットをクリアし、SCLがLOWに保持される
;				0=アドレスホールド機能を無効にする
;		bit0	DHEN：データホールドイネーブルビット（スレーブモードのみ）
;				1=受信データバイトのSCLの8番目の立下りエッジ後、スレーブハードウ
;				エアがSSP1CON1レジスタのCKPビットをクリアし、SCLがLOWに保持される
;				0=データホールド機能を無効にする
;		*注1）ACKTIMステータスビットがアクティブになるのは、AHENビットまたは、
;             DHENビットがセットされている場合のみ
;
;	SSP1MSK		SSP1マスクレジスタ
;		bit7-1	MSK：マスクビット
;				1=受信アドレスbitnをSSP1ADD(n)と比較して、I2Cアドレス一致を検出
;				0=受信アドレスbitnをI2Cアドレス一致の検出に使わない
;		bit0	I2Cスレーブモードのマスクビット、10ビットアドレス
;				I2Cスレーブモード、10ビットアドレス（SSP1M3-0=0111または1111)
;				1=受信アドレスbit0をSSP1ADD(0)と比較して、I2Cアドレス一致を検出
;				0=受信アドレスbit0をI2Cアドレス一致の検出に使わない
;				*スレーブモード、7ビットアドレスでは、このビットは無視される
;
;	SSP1ADD		MSSP1アドレス／ボーレートジェネレータ
;				マスターモードの場合
;		bit7-0	ADD：ボーレートクロック分周ビット（(ADD(7-0)+1)*4）/FOSC
;				スレーブモードの場合
;		bit7-1	ADD：7ビットのアドレス
;		bit0	未使用
;		*10ビットアドレスモードでの状態は割愛します
;
;	SSP1STAT	SSP1ステータスレジスタ
;		bit7	SMP：スルーレート制御
;				1=スルーレート制御の標準速度モード(100KHZ,1MHZ)を無効にする
;				0=スルーレート制御の高速モード(100KHZ)を有効にする
;		bit6	CKE：SMBus仕様互換入力
;				1=しきい値がSMBus仕様に準拠する入力
;				0=無効
;		bit5	D_NOT_A：データ/アドレスビット
;				1=最後に送受信したバイトがデータ
;				0=最後に送受信したバイトがアドレス
;		bit4	P：ストップビット
;				1=最後にストップビットが検出された事を示す
;				0=最後にストップビットが検出されなかった事を示す
;		bit3	S：スタートビット
;				1=最後にスタートビットが検出された事を示す
;				0=最後にスタートビットが検出されなかった事を示す
;		bit2	R_NOT_W：READ/WRITEビット情報
;				スレーブモード
;				1=読み出し
;				0=書込み
;				マスタモード
;				1=送信動作中
;				0=送信動作中で無い
;		*このビットとSEN,RSEN,PEN,RCEN,ACKENのどれかをORするとMSSP1がアイドル中
;		 かどうかが判る
;		bit1	UA：交信アドレスビット（10ビットアドレスモードのみ）
;				1=アドレスの更新が必要
;				0=アドレスの更新が不要
;		bit0	BF：バッファフル ステータスビット
;				受信
;				1=受信が完了、SSP1BUFがフルである
;				0=受信が完了していない、SSP1BUFがエンプティ
;				送信
;				1=データ送信中(ACK及びｽﾄｯﾌﾟﾋﾞｯﾄを含まない)SSP1BUFはフル
;				0=データ送信完了(ACK及びｽﾄｯﾌﾟﾋﾞｯﾄを含まない)SSP1BUFはエンプティ
;
;
;
;		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設定する必要は無い
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

init
;			各レジスタ初期設定(PIC16F1828)
			movlb	0h			;BANK0
			movlw	040h		;01000000B
			movwf	INTCON		;全割込みOFF、PEIE_ON
			movlb	01h			;BANK1
			bsf		PIE1,SSP1IE	;MSSP割込み有効
			;クロック設定
			movlb	01h			;BANK１に切替
			movlw	0f0h		;1111000B
			movwf	OSCCON		;内部発振器は8MHZに設定
								;4xPLL=ON
			;I/Oポート初期化
			movlb	0h			;BANK0
			clrf	PORTA		;Init PORT
			clrf	PORTB
			clrf	PORTC
			movlb	02h			;BANK2
			clrf	LATA		;出力ラッチレジスタ
			clrf	LATB
			clrf	LATC
			movlb	03h			;BANK3
			clrf	ANSELA		;RA0-7デジタルI/O
			clrf	ANSELB		;RB4-7デジタルI/O
			clrf	ANSELC		;RC0-7デジタルI/O
			movlb	01h			;BANK1
			movlw	0h			;TRISx=0は出力
			movwf	TRISA		;RA0-7出力
			movlw	050h		;50H=01010000B
			movwf	TRISB		;RB4,RB6入力(I2C)、RB5,RB7出力
			movlw	0h			;
			movwf	TRISC		;RC0-RC7出力

			;TMR0およびプルアップ設定
			movlb	01H			;BANK1
			movlw	0A7H		;10100111B
			movwf	OPTION_REG	;プルアップOFF
								;割込みエッジ↓
								;クロックソース外部
								;TMR0カウントエッジ↓
								;プリスケーラ割当→TMR0
								;プリスケーラ分周1/256にセット

			;ADC
;			movlb	01h			;BANK1
;			movlw	0E0h		;11100000B
;			movwf	ADCON1		;10bit変換、左詰め、基準電圧VDD
								;ADCクロック　Fosc/64=2us(32MHZ)

			;FVR
;			movlb	02h			;BANK2
;			movlw	082h		;10000010B
;			movwf	FVRCON		;FVRイネーブル
								;DACとCPSはOFF
								;ADCに4.096V
;			設定終了
			movlb	0H



;			初期値セット

;
;		メイン プログラム
;
;

coldst
			bsf		PORTB,7		;LED_OFF
			call	SC1602_INIT8;SC1602B/D初期設定
			call	MSSP_SLV	;MSSP1スレーブモード設定

			movlw	LOW MSG01	;MSG01間接アドレス値下位8ビット
			movwf	MSAD0
			movlw	HIGH MSG01	;MDG01間接アドレス値上位8ビット
			movwf	MSAD1
			call	CLRLCD		;LCD画面全クリア
			call	PUTL1		;LCD1行目にMSG01の内容を連続書込み
			movlw	LOW MSG02
			movwf	MSAD0
			movlw	HIGH MSG02
			movwf	MSAD1
			call	PUTL2		;LCD2行目に連続書込み
			call	wait500m

			movlw	LOW MSG03
			movwf	MSAD0
			movlw	HIGH MSG03
			movwf	MSAD1
			call	CLRLCD
			call	PUTL1
			movlw	LOW MSG04
			movwf	MSAD0
			movlw	HIGH MSG04
			movwf	MSAD1
			call	PUTL2
			call	wait500m
			call	CLRLCD

			bsf		INTCON,GIE	;全割込み許可


;
;	コマンドワード（スレーブアドレスの後に送信される２バイト）
;		コントロールバイト＋データバイトで構成される
;
;	コントロールバイトのビット構成
;		ＣＯ＋ＲＳ＋下位６ｂｉｔ
;		CO:連続送信、最終送信の指定
;			CO=1連続コマンドワード
;			CO=0 最終コマンドワード
;		RS:データの属性
;			RS=1 液晶の表示データ
;			RS=0 液晶のインストラクションコード
;


;	使用ワーク
;		CMD_CTRL	コマンドワードのコントロールバイト
;			bit7	CO
;						1=連続コマンドワード
;						0=最終コマンドワード
;			bit6	RS
;						1=データは文字コード或いはCGRAMデータ
;						0=データはインストラクションコード
;			bit5	STATUS	
;			bit4	
;			bit3	
;			bit2	
;			bit1	
;			bit0	
;
;		CMD_DATA	コマンドワードのデータバイト
;
;		I2C_DATA	受信したI2Cデータ(1バイト)を格納
;
;		I2C_MODE	I2C通信の進行状況を示すフラグ
;					通常プログラムはこれを頼りに処理を行う
;					消去はＩＳＰで行わないので注意
;			bit7	RCV_STOP
;						1=I2Cストップビットを検出
;						0=I2C通信継続中
;			bit6	予約
;			bit5	RCV_NACK
;						1=マスタはデータ受信を完了
;						0=
;			bit4	RCV_ACK
;						1=マスタはデータ送信を要求(ACKを受信)
;						0=
;			bit3	RCV_DATA
;						1=MSSPはデータバイトを受信
;						0=データは無効
;			bit2	RCV_RW
;						1=マスタからの受信要求ビットを検出(スレーブは送信)
;						0=マスタからの送信要求ビットを検出(スレーブは受信)
;			bit1	RCV_ADRESS
;						1=I2Cスレーブアドレスを受信
;						0=MSSP1はアイドル
;			bit0	RCV_START（現在未使用）
;						1=I2Cスタートビットを検出
;						0=MSSP1はアイドルあるいはオフライン
;
;	START-ADRS-(CTRL-CMD-CTRL-DATA)-STOP or NEXT WORD
;
hotst
			clrf	I2C_MODE
			call	MSSP_RESET
;		I2Cアドレス受信待ち(MSSPアイドル状態)
LV11		btfsc	I2C_MODE,7		;STOP_BIT
			bra		hotst			;MSSP1ディセーブル
			btfss	I2C_MODE,1		;I2Cアドレス受信フラグ
			bra		LV11			;LV1アイドル状態ループ
;		アドレス受信、R/Wチェック
LV12
			btfsc	I2C_MODE,2		;0=スレーブ受信モード,1=スレーブ送信モード
			goto	LV41			;R/W=1なので送信準備処理へ


;		スレーブ受信モード、コントロールバイト受信待ち
			call	MSSP_OPCLK		;アドレス受信後のSCL閉鎖解除
LV21		btfsc	I2C_MODE,7		;ストップビット検出フラグ
			goto	hotst			;P=1,MSSP1受信アイドルへ
			btfss	I2C_MODE,3		;I2C_DATA受信フラグ
			bra		LV21			;LV2x データバイト受信待ちループ

;		コントロールバイト処理　CMD_CTRL(CO+RS+000000)
;			C0H=連続コマンドワード、次の受信は液晶の表示データ
;			80H=連続コマンドワード、液晶のインストラクションコード
;			40H=最終コマンドワード、液晶の表示データ
;			00H=最終コマンドワード、液晶のインストラクションコード

			movf	I2C_DATA,W		;受信I2Cデータ
			movwf	CMD_CTRL		;CTRL_BYTEとして保存
			movlw	0C0H
			xorwf	CMD_CTRL,W
			btfsc	STATUS,Z
			goto	LV25			;C0H=連続コマンド表示データ
			movlw	080H
			xorwf	CMD_CTRL,W
			btfsc	STATUS,Z
			goto	LV24			;80H=連続コマンドインストラクション
			movlw	040H
			xorwf	CMD_CTRL,W
			btfsc	STATUS,Z
			goto	LV23			;40H=最終コマンド表示データ
;			goto	LV22			;00Hとみなす、最終インストラクション

;
;		CTRL=00H:最終コマンド インストラクションコード待ち
;
LV22
			bcf		I2C_MODE,3		;I2C_DATAフラグクリア
			call	MSSP_OPCLK		;ストレッチ開放、マスタ送信開始
			btfss	I2C_MODE,3		;I2C_DATA受信フラグ
			bra		$-1				;I2C_DATA受信待ちループ
;
			movf	I2C_DATA,W		;I2C_DATAはLCD_INSTとみなす
			movwf	CMD_DATA		;データ保存
			bcf		I2C_MODE,3		;I2C_DATAフラグクリア
;			call	CHK_CMD			;LCD_INSTチェック・変更
;			movf	CMD_DATA,W
			call	SEND8C			;Wreg=液晶命令
			call	MSSP_OPCLK
			goto	hotst			;MSSPアイドルへ

;
;		CTRL=40H:最終コマンド液晶データバイト待ち			
;
LV23
			bcf		I2C_MODE,3		;I2C_DATAフラグクリア
			call	MSSP_OPCLK		;ストレッチ開放、マスタ送信開始
			btfss	I2C_MODE,3		;I2C_DATA受信フラグ
			bra		$-1
;
			movf	I2C_DATA,W		;I2C_DATAはLCD_DATAとみなす
			movwf	CMD_DATA
			bcf		I2C_MODE,3		;I2C_DATAフラグクリア
			call	SEND8D
			call	MSSP_OPCLK
			goto	hotst			;MSSPアイドルへ

;
;		CTRL=80H:連続コマンド インストラクションコード待ち
;
LV24
			bcf		I2C_MODE,3		;I2C_DATAフラグクリア
			call	MSSP_OPCLK		;ストレッチ開放、マスタ送信開始
			btfss	I2C_MODE,3		;I2C_DATA受信フラグ
			bra		$-1				;I2C_DATA受信待ちループ
;
			movf	I2C_DATA,W		;I2C_DATAはLCD_INSTとみなす
			movwf	CMD_DATA
			bcf		I2C_MODE,3		;I2C_DATAフラグクリア
;			call	CHK_CMD
;			movf	CMD_DATA,W
			call	SEND8C			;Wreg=液晶命令
			call	MSSP_OPCLK
			goto	LV21			;次のI2C_DATA受信へ

;
;		CTRL=C0H:連続コマンド データコード待ち
;
LV25
			bcf		I2C_MODE,3		;I2C_DATAフラグクリア
			call	MSSP_OPCLK		;ストレッチ開放、マスタ送信開始
			btfss	I2C_MODE,3		;I2C_DATA受信フラグ
			bra		$-1				;I2C_DATA受信待ちループ
;
			movf	I2C_DATA,W		;I2C_DATAはLCD_DATAとみなす
			movwf	CMD_DATA
			bcf		I2C_MODE,3		;I2C_DATAフラグクリア
			call	SEND8D			;Wreg=液晶表示データ
			call	MSSP_OPCLK
			goto	LV21			;次のI2C_DATA受信へ

;
;			送信準備
;

;
;		CTRL解析
;
;		bit7=CO
;			1=複数コマンド
;			0=最終コマンド
;		bit6=RS
;			1=データレジスタ選択
;			0=LCDコマンドレジスタ選択
;		bit5=STATUS
;			1=LCDステータスレジスタ選択
;			0=データレジスタ選択
;		R/W	=1
;			ここに来た時点で、I2Cアドレス受信し、
;			R/W=1,CKP=0(クロック閉鎖)している
;
LV41		;RSによる処理分岐
			btfss	CMD_CTRL,5		;STATUSビット
			bra		LV42			;STATUS=0,データレジスタ読み込み処理

;			LCDステータス読み込み、マスタに送信
;			BF(bit7,ビジィフラグ）およびAC(bit6-0=アドレスカウンタ値)
			call	RECV8C			;Wreg=SC1602_STATUS
			movwf	I2C_DATA		;送信データ保存
			call	MSSP_WRTBF		;MSSPバッファに転送
									;このコマンドは1バイト送信で終了
			goto	hotst			;MSSPアイドルへ

;			LCDデータレジスタ読み込み、マスタに1バイト送信処理
LV42
			call	RECV8D			;Wreg=SC1602_DATA
			movwf	I2C_DATA		;送信データ保存
			call	MSSP_WRTBF		;MSSPバッファに転送
									;マスタが読み込みACKorNACKを返すとIF=1
			clrf	I2C_MODE
;			連続送信あるいは送信終了処理
LV43		;9bit目の割り込み発生待ち
			btfsc	I2C_MODE,7		;1=STOP受信
			goto	hotst			;STOP受信でMSSPリセット
			btfsc	I2C_MODE,5		;1=NACK受信
			goto	hotst			;MSSPアイドルへ
			btfss	I2C_MODE,4		;1=ACKを受信、MSSPはCLK閉鎖
			bra		LV43			;マスタACK返信待ちループ
;
			bra		LV42			;次の送信データ用意


MSG01		DT		"SC1602 I2C CTRL"
			DW		0			;エンドコード
MSG02		DT		"Ver2 by JA0QON"
			DW		0
MSG03		DT		"MSSP Slave Mode"
			DW		0h
MSG04		DT		"        Ver 0.2"
			DW		0h


			

;
;	ＭＳＳＰモジュール　Ｉ２Ｃスレーブモード制御サブルーチン
;
;								ＪＡ０ＱＯＮ	Ｖ０．２
;
;	注意
;	スレーブモード用ルーチン群は、ここと割り込み領域とに分かれている
;

MSSP_SLV
			movlb   04h			;BANK4
			;SSP1CON1設定
			movlw   036h		;36H=0011 0110 B
								;bit7=WCOL:書き込みコリジョン検出ビット
								;bit6=SSPOV:受信オーバーフロー
								;bit5=SSPEN:シリアルポートイネーブルビット
								;	1=I2Cポート有効
								;	0=I2Cポート無効
								;bit4=CKP:SCL開放制御
								;	1=クロックを有効にする
								;	0=クロック閉鎖(クロックストレッチ)
								;bit3-0=SSPM:シリアルポート モード選択ビット
								;	1111=スレーブモード10bitアドレスS/P割り込み有効
								;	1110=スレーブモード7bitアドレスS/P割り込み有効
								;	1000=マスターモード
								;	0111=スレーブモード10bitアドレス
								;	0110=スレーブモード7bitアドレス
			movwf   SSP1CON1	;
			;SSP1CON2設定
			movlw	01h			;0000 0001 B
								;bit7=0 GCEN	ジェネラルコール割り込み無効
								;bit6=0 ACKSTST	ACKステータス
								;bit5=0 ACKDT	送信ACKデータはACK(=1はNACK)
								;bit4=0 ACKEN	マスタ用受信ACKシーケンス
								;bit3=0 RCEN	受信イネーブルビット（マスタ用）
								;bit2=0 PEN		ストップ条件イネーブルビット(マスタ用)
								;bit1=0 RCEN	リスタート条件イネーブルビット(マスタ用)
								;bit0=1 SEN		ストレッチイネーブルビット(スレーブでは)
								;				=1で送受信で有効、=0で無効
			movwf	SSP1CON2	;
;			SSP1CON3設定
			movlw	050h		;0101 0000 B
								;bit7=0 ACKTIM	ACKシーケンス ステータス
								;bit6=1 PCIE	ストップ条件割り込み有効
								;bit5=0 SCIE	スタート条件割り込み無効
								;bit4=1 BOEN	ACK生成する
								;bit3=0 SDAHT	SDAホールド時間
								;bit2=0 SBCDE=0	スレーブバスコリジョン無効
								;bit1=0 AHEN	アドレスホールド機能無効
								;bit0=0 DHEN	データホールド機能無効
			movwf	SSP1CON3	;STOP検出割込み有効
			movlw	07ch		;I2Cアドレス 7CH(7bit 3EH+LSB(0))
			movwf	SSP1ADD		;
;			movlw	0FFH		;デフォルト値はFFH(マスクビット無し）
;			movwf	SSP1MSK
			clrf	BSR
			return


			;クロックストレッチを開放する
			;クロックストレッチ開始はハードウエアが行う
MSSP_OPCLK
			movlb	04H
			bsf		SSP1CON1,CKP	;SCL開放
			clrf	BSR
			return

			;MSSPスレーブモード・リセット
			;ストップビットとスタートビットをクリアしアイドル状態に移行
MSSP_RESET
			movlb	04h
			bsf		SSP1CON1,SSPEN	;MSSP有効
			clrf	BSR
			return

			;Wregのデータをスレーブからマスタに送信
MSSP_WRTBF
			movlb	04H
			movwf	SSP1BUF			;I2Cバッファに転送
			bsf		SSP1CON1,CKP	;CLKを有効(ストレッチ開放)マスタは受信開始
			clrf	BSR				;マスタが読み込みACKorNACKを返すとIF=1
			return					;返信がACKの場合MSSPによりクロック閉鎖される

;
;       ＬＣＤ　ＤＩＳＰＬＡＹ　ＳＣ１６０２Ｂ／Ｄ
;
;       制御サブルーチン群			2017年11月版
;		メッセージメモリが256ワード境目の表示不良のバグフィックスしてあります
;		VRAMアドレスとはDDRAMアドレス+コマンドビットで事実上の位置アドレスを言う
;		PORTC使用、パラレル接続 4bitデータバス、制御3bit
;
;		Set DDRAM address = RS=0 + R/W=0 + DB7=1,DB6-DB0=00H-4FH
;		Write data to RAM = RS=1 + R/W=0 + DB7-DB0=CGRAM or DDRAM data
;		RS=1の時、液晶の表示データあるいはCGRAMのデータ
;		RS=0の時、液晶のインストラクションコード
;		R/W=1の時、データ読込み
;		R/W=0の時、データ書込み
;		コマンド間には37us以上、あるいは1.52ms以上のウエイトが必要
;		使用専用変数
;			DSP_ADR		80H-8FH 1行目　表示位置アドレス(DDRAM)
;						C0H-CFH 2行目　同じ
;					※これは機能ビット(DB7=1)+DDRAMアドレスで表示されている

;
;   Ｗレジスタの「データ」を単発で読み書き
;		表示位置指定	DSP_ADR
;	使用ワーク	icw0,icw1

PUTW
			movwf	icw0		;PUSH Wreg
			movf	DSP_ADR,W	;表示アドレス
			call	SEND8C
            call    wait50u
			movf	icw0,W		;POP Wreg
			call	SEND8D		;表示文字コード
			call	wait50u
			return
GETW
			movf	DSP_ADR,W	;
			call	SEND8C
            call    wait50u
			call	RECV8D		;
			movwf	icw0		;
			call	wait50u
			movf	icw0,W
			return
;
;	指定の文字列をＬＣＤ1行目に先頭から連続書込み
;
;		MSAD0	指定データ格納アドレス下位8ビット
;		MSAD1	指定データ格納アドレス上位7ビット
;		LCD最左側から表示、位置指定はできない
PUTL1
			movlw	080h		;1行目DDRAM先頭アドレス
			movwf	DSP_ADR		;DDRAMアドレス
			movf	MSAD0,W
			movwf	FSR0L
			movf	MSAD1,W
			movwf	FSR0H

PTL11
			moviw	FSR0++		;MSGアドレスよりデータを取得
			iorlw	0h			;エンドコードチェック
			btfsc	STATUS,Z
			bra		PTL12		;end of msg
			call	PUTW		;コマンドワード送信（W=DATA、DSP_ADR=CMD）
			incf	DSP_ADR,F
			movlw	090h		;データアドレス オーバー
			xorwf	DSP_ADR,W
			btfss	STATUS,Z
			bra		PTL11
PTL12		return				;
;
;	指定の文字列をＬＣＤ2行目に連続書込み
;
;		MSAD0	データアドレス下位8ビット
;		MSAD1	データアドレス上位7ビット
;
PUTL2
			movlw	0c0h		;２行目DDRAM先頭アドレス
			movwf	DSP_ADR		;DDRAMアドレス
			movf	MSAD0,W
			movwf	FSR0L
			movf	MSAD1,W
			movwf	FSR0H

PTL21
			moviw	FSR0++		;MSGアドレスよりデータを取得
			iorlw	0h			;エンドコードチェック
			btfsc	STATUS,Z
			bra		PTL22		;end of msg
			call	PUTW		;コマンドワード送信（W=DATA、DSP_ADR=CMD）
			incf	DSP_ADR,F
			movlw	0d0h		;データアドレス オーバー
			xorwf	DSP_ADR,W
			btfss	STATUS,Z
			bra		PTL21
PTL22		return				;

;
;	指定の文字列をＬＣＤに連続書込み
;	最大32文字
;		MSAD0	指定データ格納アドレス下位8ビット
;		MSAD1	指定データ格納アドレス上位7ビット
;		DSP_ADR	書き込み開始VRAMアドレス
;
PUTL
			movf	MSAD0,W
			movwf	FSR0L
			movf	MSAD1,W
			movwf	FSR0H

PTL01
			moviw	FSR0++		;MSGアドレスよりデータを取得
			iorlw	0h			;エンドコードチェック
			btfsc	STATUS,Z
			bra		PTL03		;end of msg
			call	PUTW		;コマンドワード送信（W=DATA、DSP_ADR=CMD）
			incf	DSP_ADR,F
			movlw	090h		;1行目データアドレス オーバー
			xorwf	DSP_ADR,W
			btfss	STATUS,Z
			bra		PTL11
			;
			movlw	0C0H		;2行目先頭VRAMアドレス
			movwf	DSP_ADR
PTL02		moviw	FSR0++		;MSGアドレスよりデータを取得
			iorlw	0h			;エンドコードチェック
			btfsc	STATUS,Z
			bra		PTL03		;end of msg
			call	PUTW		;コマンドワード送信（W=DATA、DSP_ADR=CMD）
			incf	DSP_ADR,F
			movlw	0D0h		;2行目データアドレス オーバー
			xorwf	DSP_ADR,W
			btfss	STATUS,Z
			bra		PTL11
PTL03		return				;




;
;		2(1)行目左シフト(2行16文字モードのみ有効)
;	Wregのデータを最右側に1文字表示（表示開始位置）
;	既存の表示データは左側にシフトされる
;	最左側のデータは破棄される
;
;	使用ワーク	BSLW0
L2BSL		;２行目
			movwf	BSLW0		;表示データ保存
			movlw	0C1H
			movwf	DSP_ADR		;シフト開始アドレス
L2BSL01
			call	GETW		;シフトデータ読み込み
			decf	DSP_ADR,F	;移動先アドレス
			call	PUTW		;シフトデータ書き込み
			incf	DSP_ADR,F
			incf	DSP_ADR,F	;次の読み込みアドレス
			movlw	0D0H
			xorwf	DSP_ADR,W	;最終アドレスチェック
			btfss	STATUS,Z
			bra		L2BSL01
;
L2BSL02		decf	DSP_ADR,F
			movf	BSLW0,W
			call	PUTW
			return

L1BSL		;１行目
			movwf	BSLW0		;表示データ保存
			movlw	081H
			movwf	DSP_ADR		;シフト開始アドレス
L1BSL01
			call	GETW		;シフトデータ読み込み
			decf	DSP_ADR,F	;移動先アドレス
			call	PUTW		;シフトデータ書き込み
			incf	DSP_ADR,F
			incf	DSP_ADR,F	;次の読み込みアドレス
			movlw	090H
			xorwf	DSP_ADR,W	;最終アドレスチェック
			btfss	STATUS,Z
			bra		L1BSL01
			bra		L2BSL02

;
;		2行目-1行目左シフト(2行16文字モードのみ有効)
;	Wregのデータを2行目最右側に1文字表示（表示開始位置）
;	既存の表示データは左側にシフトされる
;	2行目最左側のデータは1行目最右側にシフト
;	1行目最右側のデータは左側にシフト
;	左シフトは停止位置までで、それ以降は破棄される
;	停止位置アドレスは１行目のみ指定可能
;
;	スクロール停止位置	BSLSP
;	使用ワーク	BSLW0,BSLW1
L21BSL
			;１行目処理
			movwf	BSLW0		;表示データ保存
			movf	BSLSP,W		;スクロール停止位置VRAMアドレス
			iorlw	0H			;ゼロチェック
			btfsc	STATUS,Z
			movlw	080H
			movwf	DSP_ADR		;シフト開始アドレス
			incf	DSP_ADR,F
L21BSL01
			call	GETW		;シフトデータ読み込み
			decf	DSP_ADR,F	;移動先アドレス
			call	PUTW		;シフトデータ書き込み
			incf	DSP_ADR,F
			incf	DSP_ADR,F	;次の読み込みアドレス
			movlw	090H
			xorwf	DSP_ADR,W	;1行目最終アドレスチェック
			btfss	STATUS,Z
			bra		L21BSL01	;最終アドレス以下
			;行間処理
			movlw	0C0H
			movwf	DSP_ADR
			call	GETW
			movwf	BSLW1
			movlw	08FH
			movwf	DSP_ADR
			movf	BSLW1,W
			call	PUTW
			;２行目処理
			movlw	0C1H
			movwf	DSP_ADR		;シフト開始アドレス
L21BSL02
			call	GETW		;シフトデータ読み込み
			decf	DSP_ADR,F	;移動先アドレス
			call	PUTW		;シフトデータ書き込み
			incf	DSP_ADR,F
			incf	DSP_ADR,F	;次の読み込みアドレス
			movlw	0D0H
			xorwf	DSP_ADR,W	;最終アドレスチェック
			btfss	STATUS,Z
			bra		L21BSL02
			;
L21BSL03	decf	DSP_ADR,F
			movf	BSLW0,W
			call	PUTW
			return




;
;	Ｗｒｅｇのキャラクタデータをチェック
;	ヌルデータはスペース(20H)に置き換える
;
CKCW
			iorlw	0h
			btfsc	STATUS,Z
			retlw	020h
			return
;
;		ＬＣＤ画面クリア
;
CLRLCD		;全画面クリア
			movlw	01h			;画面クリアコマンド
			call	SEND8C
			call	wait5m
			return
CLRLCD1		;1行目クリア
			movlw	080H
			movwf	DSP_ADR
CLD11		movf	DSP_ADR,W
			call	SEND8C
			call	wait50u
			movlw	020H
			call	SEND8D
			call	wait50u
			movlw	090H
			incf	DSP_ADR,F
			xorwf	DSP_ADR,W
			btfss	STATUS,Z
			bra		CLD11
			return
CLRLCD2		;2行目クリア
			movlw	0C0H
			movwf	DSP_ADR
CLD21		movf	DSP_ADR,W
			call	SEND8C
			call	wait50u
			movlw	020H
			call	SEND8D
			call	wait50u
			movlw	0D0H
			incf	DSP_ADR,F
			xorwf	DSP_ADR,W
			btfss	STATUS,Z
			bra		CLD21
			return

;
;		指定の位置の文字をブリンク
;
;		位置指定	Wreg
BLINK_ON
			call	SEND8C		;VRAMアドレス移動
			movlw   0DH			;Display on、カーソルOFF、ブリンクON
			call    SEND8C		;
			return
BLINK_OFF
			movlw   0CH			;Display on、カーソルOFF、ブリンクON
			call    SEND8C		;
			return


;
;       ＳＣ１６０２Ｂ／Ｄイニシャライズ
;			８ビットモード用
;
;		16桁2行ノーマルフォント
;
SC1602_INIT8
			call	wait100m	;LCDパワーオン ウエイト
			movlw	038h		;ファンクションセット　8bitモード
			call	SEND8C	;
			movlw	038h		;ファンクションセット　8bitモード
			call	SEND8C	;
;			Display on / Cursor off
            movlw   0ch			;Display on、カーソルOFF、
            call    SEND8C	;カーソル ブリンクOFF
;			Display clear
            movlw   01h         ;クリアコマンド
            call    SEND8C
            call    wait5m
;			Entry mode set
            movlw   06h			;右インクリメント、表示シフトOFF
            call    SEND8C
            call    wait5m
            return

;
;		ＳＣ１６０２Ｂ／Ｄ　低レベル サブルーチン
;
;		使用ポート
;		RA5=Enable（L-H-L)
;		RA4=R/W
;			1=読み出し
;			0=書込み
;		RA2=RSレジスタ選択
;			1=データレジスタ
;			0=制御レジスタ
;		RC7-0=DB7-0
;
;		送信
;		事前にWregに8ビットデータを用意して呼び出し
;
;		8bitモード データ送信シークェンス
;
;		(1)DB7-DB0を提示（RC7-RC0)
;		(2)R/W=0（RA4)
;		(3)RS=1(RA2)
;		(4)ｳｪｲﾄ40ns以上
;		(5)E=0からE=1(RA5)
;		(6)ｳｪｲﾄ230ns以上
;		(7)E=1→E=0(RC2)
;		(8)ｳｪｲﾄ10ns以上
;		(9)RS=0
;
;
;		使用ワーク
;			wrk0	データ保存

;
;		Ｗレジスタの8ビット分送出（8bitモード）
;
;		RA2=RS bit	1=データレジスタ、0=コマンドレジスタ(ステータスレジスタ)
;		RA4=R/W bit	1=読み込み、0=書き込み
;		RA5=E bit	イネーブルビット
;
SEND8D		;データ送信
			movwf	wrk0		;push Wreg
			bcf		PORTA,5		;E=0
			nop
			bcf		PORTA,4		;R/W=0 書込みモードセット
			nop
			bsf		PORTA,2		;RS=1(データ選択)
			call	wait01u		;
			movf	wrk0,W		;pop Wreg
			movwf	PORTC		;データ提示
			call	wait01u		;
			bsf		PORTA,5		;E=1（データ イネーブル）
			call	wait01u
			bcf		PORTA,5		;E=0
			call	wait50u
			return

SEND8C		;コマンド送信
			movwf	wrk0		;push Wreg
			bcf		PORTA,5		;E=0
			nop
			bcf		PORTA,4		;R/W=0 書込みモードセット
			nop
			bcf		PORTA,2		;RS=0(コマンド選択)
			;R/W=0(WRITE)、RS=0(COMMAND)
			call	wait01u		;オフセット（RS=R/W=E=0)
			movf	wrk0,W		;pop Wreg
			movwf	PORTC		;データ提示
			call	wait01u		;
			bsf		PORTA,5		;E=1（データ イネーブル）
			call	wait01u
			bcf		PORTA,5		;E=0
			call	wait50u
			return

RECV8D
			;I/O転換
			movlb	01H			;BANK01
			movlw	0FFH		;RC7-0=READ
			movwf	TRISC		;
			clrf	BSR
			;
			bcf		PORTA,5		;E=0
			nop
			bsf		PORTA,4		;R/W=1 読み込みモードセット
			nop
			bsf		PORTA,2		;RS=1 データ
			call	wait01u		;
			bsf		PORTA,5		;E=1
			call	wait01u
			movf	PORTC,W		;データ読み込み
			movwf	wrk0
			bcf		PORTA,5		;E=0
			;I/O転換（戻し）
			movlb	01H			;BANK01
			movlw	0H			;TRISx=0は出力
			movwf	TRISC		;RC0-RC7出力
			clrf	BSR
			call	wait50u
			movf	wrk0,W
			return

RECV8C
			;I/O転換
			movlb	01H			;BANK01
			movlw	0FFH		;RC7-0は入力
			movwf	TRISC		;
			clrf	BSR
			;
			bcf		PORTA,5		;E=0
			nop
			bsf		PORTA,4		;R/W=1 読み込みモードセット
			nop
			bcf		PORTA,2		;RS=0　コマンド
			call	wait01u		;
			bsf		PORTA,5		;E=1
			call	wait01u
			movf	PORTC,W		;ステータスデータ読み込み
			movwf	wrk0
			bcf		PORTA,5		;E=0
			;I/O転換（戻し）
			movlb	01H			;BANK01
			movlw	0H			;TRISx=0は出力
			movwf	TRISC		;RC0-RC7出力
			clrf	BSR
			call	wait50u
			movf	wrk0,W
			return

;
;		16進8bitバイナリ数値をASCIIコードに変換
;
;		入力	Wreg:00H-FFH
;		出力	DBUF0:下位4bit分のASCIIコード
;			DBUF1:上位4bit分のASCIIコード
NUTOASC
			movwf	LDWR		;Wreg退避
			andlw	0fh
			addlw	030h
			movwf	wrk0
			;
			swapf	LDWR,W
			andlw	0fh
			addlw	030h
			movwf	wrk1
			return
			



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			遅延時間サブルーチン	32MHZ用
;									Ver 1.0
;		1cycle	= 0.125us
;		使用レジスタ	= cnt2,cnt3
;		BSR		=0(BANK0)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

wait100u						;呼び出しも含めて、100us
								;call is 2cycles
			clrf	BSR
			movlw	09h			;1
			movwf	cnt2		;1
			movlb	0h
;			nop
			nop					;3
w100u		nop					;
			call	wait10u		;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
			clrf	BSR
			call	wait10u
			call	wait10u
			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
			clrf	BSR
			movlw	05h
			movwf	cnt2
w5m			call	wait1m
			decfsz	cnt2,F
			goto	w5m
			return

wait10m							; 10ms
			clrf	BSR
			movlw	d'10'
			movwf	cnt2
w10m		call	wait1m
			decfsz	cnt2,F
			goto	w10m
			return

wait20m							; 20ms
			clrf	BSR
			movlw	d'20'
			movwf	cnt2
w20m		call	wait1m
			decfsz	cnt2,F
			goto	w20m
			return
wait50m							; 50ms
			clrf	BSR
			movlw	d'50'
			movwf	cnt2
w50m		call	wait1m
			decfsz	cnt2,F
			goto	w50m
			return

wait100m						; 100ms
			clrf	BSR
			movlw	d'100'
			movwf	cnt2
w100m		call	wait1m
			decfsz	cnt2,F
			goto	w100m
			return

wait500m						; 500ms
			clrf	BSR
			movlw	05h
			movwf	cnt3
w500m		call	wait100m
			decfsz	cnt3,F
			goto	w500m
			return

wait1s							; 1s
			clrf	BSR
			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
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
wait1m
			clrf	BSR
			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　wait10u)も含めて、10usとなる。
;
;		clock	= 32MHZ(0.03125us)
;		1cycle	= 0.125us
;		10us	= 0.125us * 80cycles
;		使用変数　cnt0,cnt1
;		'goto','call','return'は2サイクル消費する
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

wait10u
			clrf	BSR
			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

wait05u
			clrf	BSR
			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

wait02u
			clrf	BSR
			movlw	04h			;2us=0.125us*16cycles
			movwf	cnt0		;
w02u0		decfsz	cnt0,F		;2+3*3+2+1+2=16cycles
			goto	w02u0
;			nop
			return				;
wait01u
			clrf	BSR			;1us=0.125us*8cycles
			nop					;2+4+2=8cycles
			nop
			nop
			return

;
            END

