;--------------------------------------------------------------------------------
;	PIC16F88・3色表示表示温度計 Programmed by GRANADA
;
;	 Ver 1.0 桁単位ダイナミック表示版			2008/12/17-2009/02/28
;	 Ver 2.1 全セグメントダイナミック表示版		2009/03/02-2009/03/03
;	 Ver 2.2 割り算ルーチン自前開発版			2009/03/05-2009/03/06
;	 Ver 2.3 ダイナミック点灯サブルーチン化版	2009/03/12
;	 Ver 2.4 BODEN_ON 修正版					2009/08/17
;
;	製作記： http://www.asahi-net.or.jp/~SE1M-NITU/html/3color_thermometer.htm
;
;	（本ソースプログラムはタブを4文字に設定すると綺麗に整形されます）
;--------------------------------------------------------------------------------

	LIST		P=16F88
	INCLUDE		P16F88.INC

	ERRORLEVEL	-205
	ERRORLEVEL	-302

	__CONFIG  _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_ON & _MCLR_OFF & _PWRTE_OFF & _WDT_OFF & _INTRC_IO
	__CONFIG  _CONFIG2, _IESO_OFF & _FCMEN_OFF

;--------------------------------------------------------------------------------
;	ポート割り当て
;--------------------------------------------------------------------------------
;
;RA0	AN0		ANALOG  IN
;RA1	LED g	DIGITAL OUT
;RA2	H桁G	DIGITAL OUT
;RA3	未使用	DIGITAL OUT
;RA4	L桁G	DIGITAL OUT
;RA5	未使用	DIGITAL IN
;RA6	H桁R	DIGITAL OUT
;RA7	L桁R	DIGITAL OUT
;
;RB0	LED a	DIGITAL OUT
;RB1	LED b	DIGITAL OUT
;RB2	LED c	DIGITAL OUT
;RB3	LED d	DIGITAL OUT
;RB4	LED e	DIGITAL OUT
;RB5	LED f	DIGITAL OUT
;RB6	T1CKI	IN（使用不可）
;RB7	T1OSI	IN（使用不可）

;--------------------------------------------------------------------------------
;	変数アドレス定義
;--------------------------------------------------------------------------------

CBLOCK	H'20'		; ユーザー用ファイルレジスタ（変数領域）先頭アドレス

VOLTAGE				; A/D変換値ストア用
TEMPERATURE			; 温度（直読10進値）ストア用
COLOR_FLAG			; 色の制御用フラグ, bit = 1 → 点灯

PATTERN_H			; H桁ビットパターン・マスターパターン
PATTERN_L			; L桁ビットパターン・マスターパターン
LED_PATTERN_H		; H桁ビットパターン
LED_PATTERN_L		; L桁ビットパターン
SEGMENT				; 表示ビットパターン

EVENT_COUNTER		; 温度測定用カウンター用

BUNSHI				; 割り算の分子ストア用
BUNBO				; 割り算の分母ストア用
DIV_ANS				; 割り算の答え用
DIV_MOD				; 割り算の余り用
BCD_H				; BCD 変換値（上位）用
BCD_L				; BCD 変換値（下位）用

W_WORK				; 割り込み時の W レジスタ退避用
ST_WORK				; 割り込み時のステータスレジスタ退避用

COUNTER1			; 時間待ち用
COUNTER2			; 時間待ち用
COUNTER3			; 時間待ち用

ENDC

;--------------------------------------------------------------------------------
;	定数定義, DEFINE を使うと MPLAB SIM のファイルレジスタダンプ時に便利
;	（ファイルレジスタに定数が紛れ込まない）
;--------------------------------------------------------------------------------
;
;	表示色の閾値はここを変更する
;
								; 色分け条件（10進値温度）
#DEFINE		GREEN_V		D'5'	; 5以下はL, 6-18 は緑
#DEFINE		ORANGE_V	D'18'	; 19-24 は橙
#DEFINE		RED_V		D'24'	; 25以上は赤
#DEFINE		HIGH_V		D'48'	; 49以上は H

;
;	オペアンプのゲインを9.8倍に設定すると 50℃ -> 4.9V
;	Vref+ = 5V なら 250カウントで 50℃ だから 5カウント/℃ となる
;	理論上の最大測定可能温度は 255/5 = 51℃ となる
;

#DEFINE		TEMP_FACTOR		D'5'		; 1℃が A/D 変換値いくつに対応するか
#DEFINE		TEMP_MAX		D'51'		; 理論上の最大測定可能温度
#DEFINE		TEMP_IN			D'0'		; 温度値入力ポート RA0(AN0)

;
;
;

#DEFINE		INT_COUNTER		D'10'		; 何回の割り込みで温度を測定するか

#DEFINE		HIGH_PATTERN	B'01110110'	; H 表示のビットパターン
#DEFINE		LOW_PATTERN		B'00111000'	; L 表示のビットパターン
#DEFINE		E_PATTERN		B'01111001'	; E 表示のビットパターン
#DEFINE		R_PATTERN		B'01010000'	; R 表示のビットパターン

;
;	その他ポート定義等
;

#DEFINE		GREEN_BIT	COLOR_FLAG,0	; 色フラグのビット番号
#DEFINE		RED_BIT		COLOR_FLAG,1	; 色フラグのビット番号

#DEFINE		HG_PORT		PORTA,2			; H桁GREEN の制御ポート RA2, L = ON
#DEFINE		LG_PORT		PORTA,4			; H桁GREEN の制御ポート RA4, L = ON
#DEFINE		HR_PORT		PORTA,6			; H桁RED   の制御ポート RA6, L = ON
#DEFINE		LR_PORT		PORTA,7			; H桁RED   の制御ポート RA7, L = ON

#DEFINE		A_SEG	PORTB,0				; LED a セグメントのポート番号
#DEFINE		B_SEG	PORTB,1				; LED b セグメントのポート番号
#DEFINE		C_SEG	PORTB,2				; LED c セグメントのポート番号
#DEFINE		D_SEG	PORTB,3				; LED d セグメントのポート番号
#DEFINE		E_SEG	PORTB,4				; LED e セグメントのポート番号
#DEFINE		F_SEG	PORTB,5				; LED f セグメントのポート番号
#DEFINE		G_SEG	PORTA,1				; LED g セグメントのポート番号

;--------------------------------------------------------------------------------
;	プログラム先頭
;--------------------------------------------------------------------------------

	ORG		H'0'
	GOTO	INITIALIZE

;--------------------------------------------------------------------------------
;	割り込み処理 (240ms 毎に飛んでくる）
;--------------------------------------------------------------------------------

	ORG		H'4'			; 割り込み処理先頭アドレス

PUSH_REG:

	MOVWF	W_WORK			; レジスタ待避
	SWAPF	STATUS,W		; Z フラグが影響しないよう、MOVF ではなく SWAPF を使用
	MOVWF	ST_WORK

	DECFSZ	EVENT_COUNTER,F	; カウンタをチェックして
	GOTO	POP_REG			; 所定回数に達していなければ何もせずに割り込み終了

	CALL	SET_LED_DATA	; 温度を測定して LED パターンをセット
	CALL	CLEAR_EVENT		; 温度測定用カウンタを初期化

POP_REG:					; レジスタ復帰

	SWAPF	ST_WORK,W
	MOVWF	STATUS
	SWAPF	W_WORK,F
	SWAPF	W_WORK,W

	BCF		PIR1,TMR1IF		; TMR1割り込みフラグをクリアしておく
							; フラグをクリアしておかないと次回の割り込みがかからないので注意
	RETFIE					; 割り込み処理終了

;--------------------------------------------------------------------------------
;	1桁の数字→7セグメントビットパターンを返す
;--------------------------------------------------------------------------------

GET_7SEG_PATTERN:

	ADDWF	PCL,F

	RETLW	B'00111111'	;	0
	RETLW	B'00000110'	;	1
	RETLW	B'01011011'	;	2
	RETLW	B'01001111'	;	3
	RETLW	B'01100110'	;	4
	RETLW	B'01101101'	;	5
	RETLW	B'01111101'	;	6
	RETLW	B'00100111'	;	7
	RETLW	B'01111111'	;	8
	RETLW	B'01101111'	;	9

;--------------------------------------------------------------------------------
; 上記変換テーブルはアセンブル後アドレス100番地未満に収めること！
;--------------------------------------------------------------------------------

;--------------------------------------------------------------------------------
;	初期化
;--------------------------------------------------------------------------------

INITIALIZE:

	BANKSEL	OSCCON				; Bank 1
	MOVLW	B'01111100'			; 内部クロック 8MHz に設定
	MOVWF	OSCCON

	CLRF	PIE1				; Bank 1, 割り込みはひとまず全て不許可

	BANKSEL	ANSEL				; Bank 1, ANSEL 設定は TRISA/B 設定より前でないダメというウワサあり
	CLRF	ANSEL				; ひとまず全ポートをデジタルに設定
	BSF		ANSEL,TEMP_IN		; 温度計測ポートのみアナログポートに再指定

	CLRF	TRISA				; Bank 1, ひとまず全ポートを出力に指定
	CLRF	TRISB				; Bank 1

	BSF		TRISA,TEMP_IN		; 温度計測ポートを入力に再指定

	CLRF	ADCON1				; Bank 1, 左詰(8bit A/D変換)、32 Tosc（の最上位ビット）, Vref+ = Vdd, Vref- = Vss

	BANKSEL	CMCON				; Bank 1
	MOVLW	B'00000111'			; コンパレータ未使用
	MOVWF	CMCON				; Bank 0

	BANKSEL ADCON0				; Bank 0
	MOVLW	B'10000001'			; 32 Tosc, AN0 使用, AD コンバータ電源 ON
	MOVWF	ADCON0

	CALL	ALL_LED_OFF			; LED は全消灯にしておく

	CALL	CLEAR_EVENT			; 温度測定用カウンタを初期化
	CLRF	VOLTAGE				; 温度入力メモリをクリア
	CLRF	TEMPERATURE			; 温度変換値メモリをクリア

	CALL	WAIT_100ms			; 温度センサーが安定するまで少し待つ
	CALL	SET_LED_DATA		; 初期表示用温度を測定

	BANKSEL	PIE1				; Bank1
	BSF		PIE1,TMR1IE			; TMR1割り込み許可

	BANKSEL	TMR1H				; Bank0
	MOVLW	H'EA'				; 6万:EA60 (30ms), 3万:7530 (15ms), 2万:4E20 (10ms), 
	MOVWF	TMR1H				; 1万:2720 (5ms), 2000:07D0（1ms）, 1000:03E8（0.5ms）
	MOVLW	H'60'				; 8MHz時 1カウント = 0.5us なので
	MOVWF	TMR1L				; 30ms毎に割り込み発生

	CLRF	INTCON
	BSF		INTCON,PEIE			; Bank0, 周辺割り込み有効
	NOP
	BSF		INTCON,GIE			; グローバル割り込み許可

	MOVLW	B'00111000'			; プリスケース 1:8 で 240ms 毎に割り込み発生
	MOVWF	T1CON				; Bank0, タイマーレジスタ設定
	BSF		T1CON,TMR1ON		; TMR1 スタート

;--------------------------------------------------------------------------------
;	メインループ開始
;--------------------------------------------------------------------------------

MAIN_LOOP:

	CALL	DISPLAY				; LED ダイナミック表示
	GOTO	MAIN_LOOP

;--------------------------------------------------------------------------------
;	以下サブルーチン群
;--------------------------------------------------------------------------------

;--------------------------------------------------------------------------------
;	温度測定と LED 表示パターン、表示色の決定
;	メモリ COLOR_FLAG の GREEN_BIT, RED_BIT のたち方で色が決まる
;	メモリ PATTERN_H, PATTERN_L にビットパターンがセットされて戻る
;--------------------------------------------------------------------------------

SET_LED_DATA:

	CALL	READ_VOLTAGE	; 温度を測定する
	MOVF	VOLTAGE,W		; 温度（直読10進値）変換のため A/D 値を読み出す

	MOVWF	BUNSHI			; 割られる数セット
	MOVLW	TEMP_FACTOR	
	MOVWF	BUNBO			; ℃ factor
	CALL	DIV8			; 割り算して直読温度値へ変換
	MOVF	DIV_ANS,W
	MOVWF	TEMPERATURE		; 直読温度をストアしておく

							; 測定温度チェック

;	MOVF	TEMPERATURE,W	; 温度（10進）を読み出す。温度が最大測定可能温度を超えていないか念のためチェック
	SUBLW	TEMP_MAX		; 最大測定可能温度 - VOLTAGE -> W
	BTFSS	STATUS,C		; VOLTAGE <= 最大測定可能温度 → 借り入れ発生せず → C=1 → 次の命令スキップ
	GOTO	SET_ERROR		; ER 表示の設定へ

							; BCD 変換

	MOVF	TEMPERATURE,W	; 直読温度を読み出す
	MOVWF	BUNSHI			; 直読温度をセット
	MOVLW	D'10'			; 温度値は必ず2桁以下なので 10 で 1回割れば BCD 変換終了
	MOVWF	BUNBO
	CALL	DIV8			; 割り算実行
	MOVF	DIV_ANS,W
	MOVWF	BCD_H			; 商 = BCD上位桁
	MOVF	DIV_MOD,W
	MOVWF	BCD_L			; 余り = BCD下位桁

	CLRF	COLOR_FLAG		; 色ビットを初期化
	CLRF	PATTERN_H		; 表示パターン消去
	CLRF	PATTERN_L		; 表示パターン消去

							; BCD 変換値チェック

	MOVF	BCD_H,W			; 10の位を念のためチェック
	SUBLW	D'5'			; 5 - 変換値 -> W (10の位は5以上にはならない)
							; ただしオペアンプのゲインを変えて測定範囲を広げた場合は修正が必要
	BTFSS	STATUS,C		; 変換値 < 5 → 借り入れ発生しない → C=1 → 次の命令スキップ
	GOTO	SET_ERROR		; ER 表示設定へ

	MOVF	BCD_L,W			; 1の位を念のためチェック
	SUBLW	D'9'			; 9 - 変換値 -> W (1の位は9以上にはならない)
	BTFSS	STATUS,C		; 変換値 < 9 → 借り入れ発生しない → C=1 → 次の命令スキップ
	GOTO	SET_ERROR		; ER 表示設定へ

							; 色設定処理

	MOVF	TEMPERATURE,W	; 温度（10進）を読み出す
	SUBLW	GREEN_V			; GREEN_V - VOLTAGE -> W
	BTFSC	STATUS,C		; VOLTAGE > GREEN_V → 借り入れ発生 → C=0 → 次の命令スキップ
	GOTO	LOW_TEMP		; L表示の設定へ

	MOVF	TEMPERATURE,W	; 温度（10進）を読み出す
	SUBLW	ORANGE_V		; ORANGE_V - VOLTAGE -> W
	BTFSC	STATUS,C		; VOLTAGE > ORANGE_V → 借り入れ発生 → C=0 → 次の命令スキップ
	GOTO	GREEN			; 緑

	MOVF	TEMPERATURE,W	; 温度（10進）を読み出す
	SUBLW	RED_V			; RED_V - VOLTAGE -> W
	BTFSC	STATUS,C		; VOLTAGE > RED_V → 借り入れ発生 → C=0 → 次の命令スキップ
	GOTO	ORANGE			; 橙色

	MOVF	TEMPERATURE,W	; 温度（10進）を読み出す
	SUBLW	HIGH_V			; HIGH_V - VOLTAGE -> W
	BTFSS	STATUS,C		; HIGH_V > VOLTAGE → 借り入れ発生しない → C=1 → 次の命令スキップ
	GOTO	HIGH_TEMP		; H表示設定へ, それ以外は赤で温度表示

;--------------------------------------------------------------------------------
;	色のフラグ立て
;--------------------------------------------------------------------------------

RED:						; 赤

	CALL	SET_RED
	GOTO	GET_LED_PATTERN

GREEN:						; 緑

	CALL	SET_GREEN
	GOTO	GET_LED_PATTERN

ORANGE:						; 橙

	CALL	SET_RED
	CALL	SET_GREEN
	GOTO	GET_LED_PATTERN

LOW_TEMP:					; L

	CALL	SET_GREEN		; L は緑表示
	CLRF	PATTERN_H		; 上桁はクリア
	MOVLW	LOW_PATTERN
	MOVWF	PATTERN_L		; 下桁に直接 'L' パターンをセット

	RETURN

HIGH_TEMP:					; H

	CALL	SET_RED			; H は赤表示
	CLRF	PATTERN_H		; 上桁はクリア
	MOVLW	HIGH_PATTERN
	MOVWF	PATTERN_L		; 下桁に直接 'H' パターンをセット

	RETURN

SET_ERROR:

	CALL	SET_RED			; エラーは赤色表示
	MOVLW	E_PATTERN
	MOVWF	PATTERN_H		; 上桁に直接 'E' パターンをセット
	MOVLW	R_PATTERN
	MOVWF	PATTERN_L		; 下桁に直接 'R' パターンをセット

	RETURN

;--------------------------------------------------------------------------------
;	色ビットのセット
;--------------------------------------------------------------------------------

SET_RED:

	BSF		RED_BIT
	RETURN

SET_GREEN:

	BSF		GREEN_BIT
	RETURN

;--------------------------------------------------------------------------------
;	BCD 値に基づいて LED 表示パターンをメモリにセットする
;--------------------------------------------------------------------------------

GET_LED_PATTERN:

	MOVF	BCD_H,W				; 10の位を得る
	CALL	GET_7SEG_PATTERN	; 変換
	MOVWF	PATTERN_H			; パターンを保存

	MOVF	BCD_L,W				; 1の位を得る
	CALL	GET_7SEG_PATTERN	; 変換
	MOVWF	PATTERN_L			; パターンを保存

	RETURN

;--------------------------------------------------------------------------------
;	A/D 変換実行
;--------------------------------------------------------------------------------

READ_VOLTAGE:

	BANKSEL	PIR1			; Bank 0
	BCF		PIR1,ADIF		; ADIF を 0 に（A/D 変換終了時このビットが 1 になる）
	BSF		ADCON0,GO		; GO (start) bit を立てて A/D 変換開始

EXEC_AD:

	BTFSC	ADCON0,GO		; A/D 変換終了したか? 0 なら次をスキップ
	GOTO	EXEC_AD			; まだ変換中

	BANKSEL	ADRESH			; Bank 0
	MOVF	ADRESH,W		; A/D 変換値を読み出して
	MOVWF	VOLTAGE			; メモリにストアしておく

	RETURN

;--------------------------------------------------------------------------------
;	ダイナミック点灯
;--------------------------------------------------------------------------------

DISPLAY:
								; 表示中に割り込みが入ってもいいように表示パターンをワークエリアに読み出しておく

	MOVF	PATTERN_H,W			; 上位桁表示パターン読み出し
	MOVWF	LED_PATTERN_H

	MOVF	PATTERN_L,W			; 下位桁表示パターン読み出し
	MOVWF	LED_PATTERN_L

	CALL	ALL_LED_OFF			; 全消灯

	MOVF	BCD_H,W				; H桁の値は 0 か? （Zフラグ設定）
	BTFSC	STATUS,Z			; H桁は 0 以外 → Z=0 → 次の命令スキップ
	GOTO	L_COLUMN			; H桁が 0 なので H桁表示をスキップ

;--------------------------------------------------------------------------------
;	H 桁表示
;--------------------------------------------------------------------------------

H_COLUMN:

	BTFSC	GREEN_BIT			; 緑ビット 0 なら次をスキップ
	BCF		HG_PORT				; H 桁緑 ON (L=点灯)

	BTFSC	RED_BIT				; 赤ビット 0 なら次をスキップ
	BCF		HR_PORT				; H 桁赤 ON (L=点灯)

	MOVF	LED_PATTERN_H,W		; 上位桁パターンを読み出して
	CALL	SEG_A				; セグメント制御開始

	CALL	ALL_LED_OFF			; 全消灯

;--------------------------------------------------------------------------------
;	L 桁表示
;--------------------------------------------------------------------------------

L_COLUMN:

	BTFSC	GREEN_BIT			; 緑ビット 0 なら次をスキップ
	BCF		LG_PORT				; L 桁緑 ON (L=点灯)

	BTFSC	RED_BIT				; 赤ビット 0 なら次をスキップ
	BCF		LR_PORT				; L 桁赤 ON (L=点灯)

	MOVF	LED_PATTERN_L,W		; 下位桁パターンを読み出して
	CALL	SEG_A				; セグメント制御開始

	CALL	ALL_LED_OFF			; 全消灯

	RETURN

;--------------------------------------------------------------------------------
;	セグメント制御
;	IN: W = ビットパターン
;--------------------------------------------------------------------------------

SEG_A:

	MOVWF	SEGMENT				; ビットパターンを保存

	BTFSS	SEGMENT,0			; a セグメントビットが 1 なら次の命令をスキップ
	GOTO	SEG_B				; 次のセグメント処理へ

	BSF		A_SEG				; a セグメント点灯
	CALL	HOLD_LED
	BCF		A_SEG				; a セグメント消灯
	CALL	HOLD_LED_SHORT

SEG_B:

	BTFSS	SEGMENT,1			; b セグメントビットが 1 なら次の命令をスキップ
	GOTO	SEG_C				; 次のセグメント処理へ

	BSF		B_SEG				; b セグメント点灯
	CALL	HOLD_LED
	BCF		B_SEG				; b セグメント消灯
	CALL	HOLD_LED_SHORT

SEG_C:

	BTFSS	SEGMENT,2			; c セグメントビットが 1 なら次の命令をスキップ
	GOTO	SEG_D				; 次のセグメント処理へ

	BSF		C_SEG				; c セグメント点灯
	CALL	HOLD_LED
	BCF		C_SEG				; c セグメント消灯
	CALL	HOLD_LED_SHORT

SEG_D:

	BTFSS	SEGMENT,3			; d セグメントビットが 1 なら次の命令をスキップ
	GOTO	SEG_E				; 次のセグメント処理へ

	BSF		D_SEG				; d セグメント点灯
	CALL	HOLD_LED
	BCF		D_SEG				; d セグメント消灯
	CALL	HOLD_LED_SHORT

SEG_E:

	BTFSS	SEGMENT,4			; e セグメントビットが 1 なら次の命令をスキップ
	GOTO	SEG_F				; 次のセグメント処理へ

	BSF		E_SEG				; e セグメント点灯
	CALL	HOLD_LED
	BCF		E_SEG				; e セグメント消灯
	CALL	HOLD_LED_SHORT

SEG_F:

	BTFSS	SEGMENT,5			; f セグメントビットが 1 なら次の命令をスキップ
	GOTO	SEG_G				; 次のセグメント処理へ

	BSF		F_SEG				; f セグメント点灯
	CALL	HOLD_LED
	BCF		F_SEG				; f セグメント消灯
	CALL	HOLD_LED_SHORT

SEG_G:

	BTFSS	SEGMENT,6			; g セグメントビットが 1 なら次の命令をスキップ
	RETURN						; g セグメントが点灯しないなら戻る

	BSF		G_SEG				; g セグメント点灯
	CALL	HOLD_LED
	BCF		G_SEG				; g セグメント消灯

	RETURN

;--------------------------------------------------------------------------------
;	LED 全消灯
;--------------------------------------------------------------------------------

ALL_LED_OFF:

	MOVLW	B'11111100'			; 全桁 OFF（H=OFF）、gセグメント消灯
	MOVWF	PORTA
	CLRF	PORTB				; a-gセグメント消灯

	RETURN

;--------------------------------------------------------------------------------
;	LED 表示を一定時間保持（長め）
;--------------------------------------------------------------------------------

HOLD_LED:

	CALL	WAIT_1ms

	RETURN

;--------------------------------------------------------------------------------
;	LED 表示を一定時間保持（短め）
;--------------------------------------------------------------------------------

HOLD_LED_SHORT:

	CALL	WAIT_100us

	RETURN

;--------------------------------------------------------------------------------
;	温度測定カウンタの初期化
;--------------------------------------------------------------------------------

CLEAR_EVENT:

	MOVLW	INT_COUNTER			; 240ms の割り込み処理何回で温度を測定するか
	MOVWF	EVENT_COUNTER

	RETURN

;--------------------------------------------------------------------------------
;	8bit 除算ルーチン、要は分子が分母で何回引けるかをカウントすればよい
;	IN:     BUNSHI（割られる数）,	BUNBO（割る数）
;	RETURN: DIV_ANS（商）, 			DIV_MOD（余り）
;--------------------------------------------------------------------------------

DIV8:

	CLRF	DIV_ANS			; 答え用メモリををクリア
	CLRF	DIV_MOD			; 余り用メモリをクリア

DIV_LOOP:

	MOVF	BUNSHI,W		; 現時点の割られる数を読み出す
	MOVWF	DIV_MOD			; これ以上引けなかい場合はこの値がそのまま余りになる

	MOVF	BUNBO,W
	SUBWF	BUNSHI,F		; BUNSHI - W(BUNBO) -> BUNSHI

	BTFSS	STATUS,C		; まだ引けるならキャリーが立たないので C=1 となり次の行をスキップ
	RETURN					; もう引けないので終了

	BTFSC	STATUS,Z		; 割り切れなかった場合は Z=0 となり次の行をスキップ
	GOTO	CLEAR_MOD		; 割り切れた場合は余りをクリアする必要がある

	INCF	DIV_ANS,F		; 答えをカウントアップ
	GOTO	DIV_LOOP		; 引き算を続ける

CLEAR_MOD:

	INCF	DIV_ANS,F		; 答えをカウントアップ
	CLRF	DIV_MOD			; 余りをクリアする

	RETURN

;--------------------------------------------------------------------------------
;	時間待ちサブルーチン (for 8MHz clock)
;--------------------------------------------------------------------------------

WAIT_100us:

	MOVLW	D'50'		; 8MHz時だいたい 100us
	MOVWF	COUNTER2

WAIT_LOOP0:

	NOP
	DECFSZ	COUNTER2,F
	GOTO	WAIT_LOOP0

	RETURN

WAIT_500us:

	MOVLW	D'1'
	GOTO	SET_COUNTER

WAIT_1ms:

	MOVLW	D'2'
	GOTO	SET_COUNTER

WAIT_100ms:

	MOVLW	D'200'

;--------------------------------------------------------------------------------
;	時間待ちサブルーチン・コア部分、8MHz 時 500μs ループ
;	（クロック 8MHz 時 1 step = 1/8000000 x 4 (sec) = 0.5us）
;--------------------------------------------------------------------------------

SET_COUNTER:

	MOVWF	COUNTER1

WAIT_LOOP1:

	MOVLW	H'F9'		; 8MHz 時 F9H で 0.5ms のループになる
	MOVWF	COUNTER2

WAIT_LOOP2:

	NOP
	DECFSZ	COUNTER2,F
	GOTO	WAIT_LOOP2

	DECFSZ	COUNTER1,F
	GOTO	WAIT_LOOP1

	RETURN

;--------------------------------------------------------------------------------
;	プログラム終了
;--------------------------------------------------------------------------------

	END
