;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;		内蔵ＤＡＣによる低周波信号発生実験プログラム
;		
;		PIC12F1822DAC実験基板1用
;		DAC出力周波数をADC（ボリウム）で可変
;		タイマ0割込み使用
;
;		PIC12F1822 32MHZ（内部オシレータ）
;
;		ＪＡ０ＱＯＮ　
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



		LIST	P=PIC12F1822
		INCLUDE	P12F1822.INC

;		
;CONFIGURATION WORD 1(ADDRESS:8007H)マニュアル50ページ
;					設定
;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  １  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
;bit10		BORV	0	ブラウンアウト･リセット電圧選択ビット（Vbor参照)
;						1=低電圧で動作
;						0=高電圧で動作
;bit9		STVREN	0	スタック･オーバーフロー･リセット設定
;						1=有効
;						0=無効
;bit8		PLLEN	0	PLL設定
;						1=4xPLL有効
;						0=4xPLL無効
;bit7-5					Unimplemented
;bit4					Reserved
;bit3-2					Unimplemented
;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  0  0  0  0  0  0  0  0  0  0  1  1
;
;
	__CONFIG _CONFIG2,	B'0001000000000011'

;	PIC12F683からの重要変更点
;
;	STATUSレジスタの各フラグビット（マニュアルP24)
;
;bit7-5					unimplemented
;			__
;bit4		TO			タイムアウトビット
;						1=電源起動後、CLRWDT命令実行後、SLEEP命令実行後
;			__			0=WDTタイムアウト発生
;bit3		PD			パワーダウンビット
;						1=電源起動後、CLRW命令実行後
;						0=SLEEP命令実行
;bit2		Z			ゼロビット
;						1=演算結果がゼロ
;						0=演算結果がゼロ以外
;						          ____________
;bit1		DC			Ｄｉｇｉｔ Carry/Digit Borrow
;						1=キャリー発生、ボロー無
;						0=キャリー無、ボロー発生
;						　　　　　　______
;bit0		C			Carry/Borrow
;						1=キャリー発生、ボロー無
;						0=キャリー無、ボロー発生
;
;	SFRレジスタ アクセス方法
;
;	BSRレジスタ　xx08h
;	このレジスタの0-4ビットにバンクアドレス(0-1Fh)をセット
;	これが直接アドレッシングの7-11ビット(0-31バンク）に相当する
;	直接アドレッシングの下位0-6ビット(0-7Fh)はオペコードで指定
;
;
;	PORTへの入出力
;
;	PORT入出力方法は基本的には変わりません。
;	TRISA(C)で機能指定
;	PORTA(C)で入出力
;	以上で問題ありません。
;	しかし、PIC12F1822（16F1823)ではLATA(C)レジスタが見えるようになりました。
;	書き込み方法は下記2種類となり、どちらも結果は、ほぼ同じです。
;	PORTA(C)へ書き込む
;	LATA(C)へ書き込む
;
;	PORTの読込
;	PORTA(C)からの読込はPORTピンの状態を表現しています。
;	LATA(C)からの読込はその時点でのPORTピンの状態を表現してはいません。
;	LATA(C)レジスタの保持データ内容を読み込む事になります。
;	PORTA(C)とLATA(C)との詳細な違いはマニュアルを読んでください。


;		ワークエリア定義
;
;		BANK0	20h-7Fh
;
;		使用していないのもあります
;

hex0		equ		020h		;取得HEXデータ
hex1		equ		021h		;
hex2		equ		022h
hex3		equ		023h
cnt0		equ		024h		;時間待ちルーチン用
cnt1		equ		025h
cnt2		equ		026h
cnt3		equ		027h
tmp0		equ		028h		;雑用
tmp1		equ		029h
flg			equ		02ah		;エラー＆設定フラグ
mode		equ		02bh		;実行モード設定
TMC			equ		02ch		;タイマオーバーフローカウンタ
CYC0		equ		02dh		;呼び出し周期カウンタ
CYC1		equ		02eh		;呼び出し周期カウンタ
DCO			equ		02fh		;DAC逐次設定データ
IDC			equ		030h		;象限判定カウンタ
FRQ0		equ		031h		;周波数設定データ
FRQ1		equ		032h
;

			ORG		0h
			goto	init
			ORG		04h
			goto	INT

			org		05h
			
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			データ補正テーブル
;
;	注意			このルーチンのアドレス範囲の設定が必要
;				PCLATHにその上位アドレスを入れること
;	入力			Wレジスタに4ビットバイナリデータを入れてコール
;	出力			Wレジスタに補正データを入れてリターン
;
;				
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

get_rev
;			andlw	0fh		;下位4ビット取り出し
			addwf	PCL,F
			retlw	00h		;0
			retlw	00h		;1
			retlw	01h		;2
			retlw	02h		;3
			retlw	04h		;4
			retlw	06h		;5
			retlw	09h		;6
			retlw	0ch		;7
			retlw	0fh		;8
			retlw	012h	;9
			retlw	015h	;A
			retlw	017h	;B
			retlw	01ah	;C
			retlw	01ch	;D
			retlw	01eh	;E
			retlw	01fh	;F

			retlw	01fh	;10
			retlw	01fh	;11
			retlw	01eh	;12
			retlw	01ch	;13
			retlw	01ah	;14
			retlw	017h	;15
			retlw	015h	;16
			retlw	012h	;17
			retlw	0fh		;18
			retlw	0ch		;19
			retlw	09h		;1A
			retlw	06h		;1B
			retlw	04h		;1C
			retlw	02h		;1D
			retlw	01h		;1E
			retlw	00h		;1F
			retlw	00h		;20

;
;		割込み処理
;
;		INTCONレジスタ(#2)　コア　00BH　マニュアル93ページ
;			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設定する必要は無い
;
;		PORTA0	DAC出力
;		PORTA1	ADC入力
;		ここではDACにデータを出力する。
;		タイマ割込みによって飛んでくる
;		よって、タイマはここでリスタートする
;
;		リスタート時データ	FRQ0
;
;		割込み発生から割込みベクタまで4サイクル程度
;		ここに来るのに2サイクルで、計6サイクル
;



INT
			movlb	0h
			incf	DCO,F
			movf	DCO,W
			call	get_rev		;5サイクル
			movwf	INDF0
			movf	DCO,W
			xorlw	020h
			btfsc	STATUS,Z
			clrf	DCO
;			TMR0オーバーフロー処理
			movf	FRQ0,W
			movwf	TMR0
			bcf		INTCON,TMR0IF
			retfie				;ここまで18+6=24サイクル(3us)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			PIC12F1822　イニシャライズ
;
;		OSCCON(BANK1　099H) マニュアル69ページ
;			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は選択の余地が無い。
;							
;
;
;
;		CM1CON0(BANK2　0111H)　マニュアル172ページ
;			bit7	C1ON	コンパレータ イネーブルビット
;							1=有効
;							0=無効（リセット後）
;			bit6	C1OUT	コンパレータ出力ビット
;							反転極性
;							1=C1VP < C1VN
;							0=C1VP > C1VN
;							非反転極性
;							1=C1VP > C1VN
;							0=C1VP < C1VN
;			bit5	C1OE	コンパレータ出力イネーブルビット
;							1=C1OUTはC1OUTピンに出力される
;							0=C1OUTは内部のみ（ピンに出力されない）
;			bit4	C1POL	コンパレータ出力反転ビット
;							1=出力反転
;							0=出力非反転
;			bit3			Unimplemented(read=0)
;			bit2	C1SP	コンパレータスピード選択ビット
;							1=ハイスピードモード
;							0=ロースピードモード
;			bit1	C1HYS	コンパレータ ヒステリシス イネーブルビット
;							1=ヒステリスス有効
;							0=ヒステリシス無効
;			bit0	C1CYNC	コンパレータ同期出力設定ビット
;							1=有効
;							0=無効
;
;		CM1CON1(BANK2　0112H)　マニュアル173ページ　リセット時すべて0
;			bit7	C1INTP	コンパレータ +割込み設定ビット
;							1=有効
;							0=無効
;			bit6	C1INTN	コンパレータ -割込み設定ビット
;							1=有効
;							0=無効
;			bit5-4	C1PCH	コンパレータ+入力選択ビット
;							00=C1VPはC1INピンに接続
;							01=C1VPはDACに接続
;							11=C1VPはFVRバッファ2に接続
;			bit3-2			Unimplemented(read=0)
;			bit1-0	C1NCH	コンパレータ-入力選択ビット
;							0=C1VNはC1IN0ピンに接続
;							1=C1VNはC1IN1ピンに接続
;
;		PORTA(BANK0　00CH）　マニュアル126ページ
;			bit7-6	Unimplemented(read=0)
;			bit5-4	RA5-4	デジタルI/O、アナログ入力
;			bit3	RA3		デジタルInputのみ
;			bit2	RA2-1	デジタルI/O、アナログ入力
;			bit0	RA0		デジタル･アナログI/O,DAコンバータ出力
;
;		TRISA(BANK1　08CH)　マニュアル126ページ
;			bit7-6	Unimplemented(read=0)
;			bit5-4	RA5-4	1=入力、0=出力
;			bit3	RA3		常に1
;			bit2	RA2-0	1=入力、0=出力
;
;		LATA(BANK2　10CH)　データラッチﾚｼﾞｽﾀ　マニュアル127ページ
;			bit7-6	Unimplemented(read=0)
;			bit5-4	RA5-4	出力データ保持
;			bit3	Unimplemented(read=0)
;			bit2	RA2-0	出力データ保持
;							（このラッチデータはTRISAレジスタ設定で各ピンに反映される）
;
;
;		ANSELA(BANK3　18CH)　マニュアル127ページ
;			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(アナログ入力)となっている
;
;
;		WPUA(BANK4　20CH)　ポートAプルアップ設定ビット
;			bit7-6	Unimplemented(read=0)
;			bit5-0			1=PORTA各ビットプルアップ有効
;					 _____	0=PORTA各ビットプルアップ無効
;					*WPUENビットが有効の時のみ、設定有効となる。
;
;		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)12F1822/16F1823では常に"1"
;							#2)FVR電圧出力はVDDを超える事は出来ない
;
;		DACCON0レジスタ(BANK2　11AH)　マニュアル158ページ
;		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'
;
;
;		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-2	Unimplemented(read=0)
;		bit1-0	ADPREF	参照正電圧指定
;						00 = VDD
;						01 = Reserved
;						10 = 外部VREF+ (RA1)
;						11 = 内部FVRモジュール
;
;
;		OPTION_REG(BANK1　095H)　マニュアル177ページ
;					_____
;			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　マニュアル93ページ
;			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
;			各レジスタ初期設定
			movlw	020h		;00100000B
			movwf	INTCON		;全割込みOFF、TMR0割込み許可
			movlb	0h			;BANK0
;			clrf	PORTA		;Init PORT
			;クロック
			movlb	01h			;BANK１に切替
			movlw	0f0h		;1111000B
			movwf	OSCCON		;内部発振器は8MHZに設定
								;4xPLL=ON
			;TMR0およびプルアップ
			movlw	083H		;10000011b
			movwf	OPTION_REG	;プルアップOFF
								;割込みエッジ↓
								;クロックソース内部（Fosc/4）
								;TMR0カウントエッジ↓
								;プリスケーラ割当→TMR0
								;プリスケーラ分周1/16にセット
			;ADC
			movlw	020h		;0010000B
			movwf	ADCON1		;左詰め、基準電圧VDD
								;ADCクロック　Fosc/32=1us(32MHZ)
			;I/Oポート
			movlw	0ffh
			movwf	TRISA		;すべて入力
			movlb	03h			;BANK3
			movlw	03h			;00000011B
			movwf	ANSELA		;RA0-1,アナログ
								;RA2-5,デジタルI/O
								
			;FVR
			movlb	02h			;BANK2
			movlw	088h		;10001000B
			movwf	FVRCON		;FVRイネーブル
								;DACとCPSに2.048V
								;ADCにはOFF
			
			;DAC
			movlw	0a8h		;10101000B
			movwf	DACCON0		;DACイネーブル
			movlb	0h			;基準電圧はFVR
			
			
;			初期値セット
			clrf	DCO
        	clrf	flg
        	movlw	019h
        	movwf	FSR0L
        	movlw	01h
        	movwf	FSR0H		;FSR0=DACCON1
;        	goto	coldst3

;
;		メインルーチン（メインループ）
;
;		タイマ0インタバルタイマで割込み、DAC駆動
;		
;		使用変数
;		hex0	BANK0	ADC出力データ
;		FRQ0			TMR0プリセットデータ
;		FRQ1			PS(プリスケーラ)設定値
;

coldst
			movlw	0f0h		;暫定値設定
			movwf	hex0
			movwf	TMR0		;TMR0スタート
			bsf		INTCON,GIE	;GIE=1(割込みイネーブル)

mloop		;メインループ
			call	wait100m
			movlb	01h
			movlw	05h			;00000101b
								;左詰め、基準電圧VDD、
								;AN1(RA1)選択、ADON_ON
			movwf	ADCON0		;電圧サンプリング開始
			call	w10u		;サンプリング電圧安定化待ち
			call	w10u
			movlb	01h
			bsf		ADCON0,GO	;A/D変換開始指令
mlp01
			btfsc	ADCON0,GO	;A/D変換完了待ち 
			goto	mlp01		;GO=0ならば次へ
			movf	ADRESH,W	;データ上位８ビット
			bcf		ADCON0,ADON	;A/DコンバータOFF
			movlb	0h
			movwf	hex1		;上位８ビットをhex1に仮保存
			xorwf	hex0,W		;過去値と比較
			btfsc	STATUS,Z	;
			goto	mloop		;同じなので、何もしない
;			設定値が変更された
			movf	hex1,W		;取得値をhex0にロード
			movwf	hex0		;
			call	rev_tm		;取得値を変換,PS再設定
			movf	FRQ0,W		;
			movwf	TMR0		;TMR0リスタート
			goto	mloop
			
			
;デバッグ用メイン３

coldst3
			clrf	hex0
mloop3		;メインループ３
			call	rev_tm
			incf	hex0,F
			goto	mloop3			


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			データ最適化サブルーチン
;
;		インタバルタイマ割込みを想定
;		割込みルーチンが3us(32MHZ)ほど消費するので、
;		ここでは5usを上限となるようにADCデータを変換する
;		と同時にプリスケーラも最適化する。
;
;		入力		hex0
;		出力		FRQ0	TMR0設定指示値
;				FRQ1	プリスケール値（ルーチン内で設定済み）
;
;		最適化変換表
;		hex0		PS		TMR0
;	上限	F0H-FFH		1/1		D8H（約4KHZ)
;	高域	A0H-EFH		1/1		88H-D7H（約2KHZ-4KHZ)
;	中域	54H-9FH		1/2		78H-C3H(約900HZ-2KHZ)
;	低Ａ	38H-53H		1/8		C2H-DDH（約500HZ-900HZ)
;	低Ｂ	10H-37H		1/32	C9H-F0H(約140HZ-500HZ)
;	低Ｃ	00H-0FH		1/128	E2H-F1H（約70HZ-140HZ)
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rev_tm
;		振分け
			movf	hex0,W
			movwf	tmp0
			sublw	0efh		;
			btfss	STATUS,C	;
			goto	tmax		;上限値
		
			movf	tmp0,W
			sublw	09fh
			btfss	STATUS,C
			goto	thgt		;高域
		
			movf	tmp0,W
			sublw	053h
			btfss	STATUS,C
			goto	tmdl		;中域
		
			movf	tmp0,W
			sublw	037h
			btfss	STATUS,C
			goto	tlla		;低域Ａ
		
			movf	tmp0,W
			sublw	0fh
			btfss	STATUS,C
			goto	tllb		;低域Ｂ

;		低域Ｃ
tllc
			movlw	0e2h		;E2H-F1H（約60HZ-140HZ)
			addwf	tmp0,W		;00H-0FH→E2H-F1H
			movwf	FRQ0		;TMR0値
			movlb	01h
			movlw	096H		;10010110b
			movwf	OPTION_REG	;プルアップOFF
								;割込みエッジ↓
								;クロックソース内部（Fosc/4）
								;TMR0カウントエッジ↑
								;プリスケーラ割当→TMR0
								;プリスケーラ分周1/128にセット
			movlb	0h
			return
		
;		低域Ｂ
tllb
			movlw	0b9h		;C9H-F0H(約140HZ-500HZ)
			addwf	tmp0,W		;10H~37H→C9H~F0H
			movwf	FRQ0		;TMR0値
			movlb	01h
			movlw	094H		;10010100b
			movwf	OPTION_REG	;プルアップOFF
								;割込みエッジ↓
								;クロックソース内部（Fosc/4）
								;TMR0カウントエッジ↑
								;プリスケーラ割当→TMR0
								;プリスケーラ分周1/32にセット
			movlb	0h
			return
			
;		低域Ａ
tlla
			movlw	08ah		;C2H-DDH（約500HZ-900HZ)
			addwf	tmp0,W		;38H~53H→C2H~DDH
			movwf	FRQ0		;TMR0値
			movlb	01h
			movlw	092H		;10010010b
			movwf	OPTION_REG	;プルアップOFF
								;割込みエッジ↓
								;クロックソース内部（Fosc/4）
								;TMR0カウントエッジ↑
								;プリスケーラ割当→TMR0
								;プリスケーラ分周1/8にセット
			movlb	0h
			return
			
;		中域
tmdl
			movlw	024h		;78H-C3H(約900HZ-2KHZ)
			addwf	tmp0,W		;54H-9FH→78H-C3H
			movwf	FRQ0		;TMR0値
			movlb	01h
			movlw	090H		;10010000b
			movwf	OPTION_REG	;プルアップOFF
								;割込みエッジ↓
								;クロックソース内部（Fosc/4）
								;TMR0カウントエッジ↑
								;プリスケーラ割当→TMR0
								;プリスケーラ分周1/2にセット
			movlb	0h
			return

;		高域
thgt
			movlw	018h		;88H-D7H（約2KHZ-4KHZ)
			subwf	tmp0,W		;A0H-EFH→88H-D7H
			movwf	FRQ0		;TMR0値
			movlb	01h
			movlw	09fH		;10011111b
			movwf	OPTION_REG	;プルアップOFF
								;割込みエッジ↓
								;クロックソース内部（Fosc/4）
								;TMR0カウントエッジ↑
								;プリスケーラ割当→WDT
								;プリスケーラ分周1/256にセット
			movlb	0h
			return

;		上限域
tmax
			movlw	0d8h
			movwf	FRQ0		;TMR0値
			movlb	01h
			movlw	09fH		;10011111b
			movwf	OPTION_REG	;プルアップOFF
								;割込みエッジ↓
								;クロックソース内部（Fosc/4）
								;TMR0カウントエッジ↑
								;プリスケーラ割当→WDT
								;プリスケーラ分周1/256にセット
			movlb	0h
			return



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;			Ｄ／Ａ変換サブルーチン
;
;		アナログ出力ポート		AN0/RA0
;
;
;		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'
;
;
;		DACCON1レジスタ(BANK2　119H)
;		bit7-5	Un		Read as '0'
;		bit4-0	DACR	DAC出力電圧設定ビット
;
;
;
;		使用方法
;		このルーチンを呼び出す度に、DAC出力電圧を順次変化させていく。
;		このルーチンでは時間管理はしない。
;		呼び出す側で時間を管理する必要がある。
;		最大電圧はFVRの2.048V使用する。
;		最小電圧はGNDとなる。
;		アナログ入力、プルアップONにすると、出力波形がおかしくなります。
;
;		使用変数およびレジスタ
;		DCO			X軸進行カウンタ
;		DAC出力データ	00H-1FH（データテーブルより取得）
;		FSR0レジスタ	DACCON1（119H)アドレスを登録（初期設定）
;		INDF0レジスタ	DACCON1レジスタへの入出力窓口として使用
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;		消費サイクル　16cycles(2.0us)
;		call,returnを含む
put_dac
			incf	DCO,F
			movf	DCO,W
			call	get_rev		;5サイクル
			movwf	INDF0		;DACにデータセット
			movf	DCO,W
			xorlw	020h
			btfsc	STATUS,Z
			clrf	DCO			;DCO=20Hなのでリセット
			return
			
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
;			Ａ／Ｄ変換サブルーチン
;
;		アナログ入力ポート		RA1/AN1/CH1
;		結果格納方法		ADFM=0/左詰め/ADRESHのみ取得
;		出力データ			hex0
;
;		ADCON0レジスタ（BANK1　09DH)　マニュアル147ページ
;		bit7	Unimplemented(read=0)
;		bit6-2	CHSx	アナログチャンネル指定
;						00000 = AN0/RA0
;						00001 = AN1/RA1
;						00010 = AN2/RA2
;						00011 = AN3/RA3
;						00100 = AN4/RC0(#1)
;						00101 = AN5/RC1(#1)
;						00110 = AN6/RC2(#1)
;						00111 = AN7/RC3(#1)
;						01000 = Reserved.No channel connected
;						    ・
;						11100 = Reserved.No channel connected
;						11101 = 温度表示器(#4)
;						11110 = DAC出力(#2)
;						11111 = FVRバッファ1出力(#3)
;		bit1	GO/DONE	A/D変換ステータスビット
;						1=変換開始指令（１にすると変換動作開始）
;						0=変換完了(変換完了すると０になる）
;		bit0	ADON	A/D変換ステータスビット
;						1=A/Dコンバータ動作
;						0=A/Dコンバータ停止
;
;		(#1)PIC16F1823のみ
;		(#2)ADC入力はDAC出力に接続される。
;		(#3)ADC入力はFVRバッファ1に接続される。
;		(#4)ADC入力は温度表示モジュール出力に接続される。
;
;		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-2	Unimplemented(read=0)
;		bit1-0	ADPREF	参照正電圧指定
;						00 = VDD
;						01 = Reserved
;						10 = 外部VREF+ (RA1)
;						11 = 内部FVRモジュール
;
;		使用ワーク		;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;			VRによる分圧電圧取得

get_adc
			movlb	01h
			movlw	05h			;00000101b
								;左詰め、基準電圧VDD、
								;AN1(RA1)選択、ADON_ON
			movwf	ADCON0		;電圧サンプリング開始
			call	w10u		;サンプリング電圧安定化待ち
			call	w10u
			movlb	01h
			bsf		ADCON0,GO	;A/D変換開始指令
aloop
			btfsc	ADCON0,GO	;A/D変換完了待ち 
			goto	aloop		;GO=0ならば次へ
			movf	ADRESH,W	;データ上位８ビット
			bcf		ADCON0,ADON	;A/DコンバータOFF
			movlb	0h
			movwf	hex0		;上位８ビットをhex0に保存
			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
			
;
			END
			
