;***********************************************************
;
;  温度測定装置 Pith ( Pic Thermometer ) 
;	Version 2 & 1	2005/03/27	山本道成
;
;## 2005/02/12	制作開始 pith001.asm より派生 -> pith200.asm
;## 2005/03/19	制作開始 pith201.asm にVer1をマージン
;
; コンパイル
;   gpasm pith202.asm
; 
;  PIC2F675 (4MHz 内部クロック)
; 	
;  GP3 - RS232C IN      RS232C -> PIC
;  GP5 - RS232C OUT     RS232C <- PIC
;
;  GP0,1,2,4(AN0～3) A/D mode
; 
;  3番pinの内容(GP4 or AN3)変更が可能(Ver1)
;  5番pinの内容(GP2 or AN2)変更が可能(Ver2)
;
; RS232C  9600bps 8bit STOP1bit パリ無し
;
; Copyright(c)2003-2005 Michinari YAMAMOTO All rights reserved.
;
;***********************************************************
; Version の設定
; Version 1を作成する場合は、次の行のVERSIONを1に変更してコンパイルしてください。
;***********************************************************
	#DEFINE	VERSION	2	;
;***********************************************************

	LIST		P=PIC12F675	; PICプロセッサの種別指定
	INCLUDE		"p12f675.inc"	; インクルードファイルの指定
	__CONFIG	_WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _PWRTE_ON & _CPD_OFF&_CP_OFF&_BODEN_ON
			; _INTRC_OSC_CLKOUT	内部クロック(4MHz)外部出力
			; _INTRC_OSC_NOCLKOUT	内部クロック(4MHz)外部出力なし
			; _MCLRE_OFF		MCLRE端子OFF
	ERRORLEVEL	-302		; ワーニングメッセージを出さなくする(注意！)
;;	または gpasm -w 1 xxxx.asm とする。
;***********************************************************

;***********************************************************
; IOの設定
;; SW portの設定
	;; *********************
	IF	VERSION==1		;### Version 1 ###
	#DEFINE	ANSEL_SW	ANSEL,3	;### Version 1 ###
	#DEFINE	TRISIO_SW	TRISIO,4;### Version 1 ###
	#DEFINE	GPIO_SW		GPIO,4	;### Version 1 ###
	ENDIF				;
	;; *********************
	IF	VERSION==2		;### Version 2 ###
	#DEFINE	ANSEL_SW	ANSEL,2	;### Version 2 ###
	#DEFINE	TRISIO_SW	TRISIO,2;### Version 2 ###
	#DEFINE	GPIO_SW		GPIO,2	;### Version 2 ###
	ENDIF				;
	;; *********************
;;
;; RS232C 接続 port
	#DEFINE	RSIN		GPIO,3	; GP3 RS232Cから入力
	#DEFINE	RSOUT		GPIO,5	; GP5 RS232Cへ出力

	
;***********************************************************
;***********************************************************
;  変数定義とレジスタ割付
;***********************************************************
;変数定義
;; ウェイト関連
COUNT100        EQU     20H     ; １００μｓウェイト用カウンタ
COUNT10M        EQU     21H     ;   １０ｍｓウェイト用カウンタ
COUNT1S		EQU	22H	;       １ｓウェイト用カウンタ
COUNT20		EQU     23H     ; 20μｓウェイト用カウンタ(AD変換用)
;; Pithのステータス保存
PISTAT		EQU	24H	; Pithのステータス保存
AORD		SET	0	; モードの確認Analog(0) or Digital(1)
ECHOBK		SET	1	; エコーバックの有(0) or 無し(1)
;;割算ルーチン用
DANS            EQU     25H     ; 答え(商)
;; RS232C 関連 
;; RS232C ルーチン関連 
RSCNR		EQU	26H	; RS 受信 bit数カウンタ
RSCNS		EQU	RSCNR+1	; RS 送信 bit数カウンタ
RSRDATA		EQU	RSCNS+1	; RS 受信データ
RSSDATA		EQU	RSRDATA+1	; RS 送信データ
RSWAIT		EQU	RSSDATA+1	; RS ウェイト用カウンタ
;; 文字列をRS232Cへ出力するルーチン用 
TB1		EQU     RSWAIT+1	; 文字列テーブルのアドレス保存用
TB2		EQU     TB1+1		; カウンタ
;; 受信コマンド確認関連
CMDCN		EQU     TB2+1	; 受信コマンドの文字数
CMDDATA		EQU     CMDCN+1	; 36-3AH (4byte)利用(受信コマンドデータ)
CMDTBC		EQU     CMDDATA+4; TABLE オフセットカウンタ
CMDNO		EQU	CMDTBC+1; コマンド番号
; ADデータ
ADDATATB	EQU	CMDNO+1		; ADデータテーブル
ADTESF0		EQU	ADDATATB	; ADデータ（符号）
ADTEMP0		EQU	ADTESF0+1	; ADデータ（温度）
ADTESF1		EQU	ADTEMP0+1
ADTEMP1		EQU	ADTESF1+1
ADTESF2		EQU	ADTEMP1+1
ADTEMP2		EQU	ADTESF2+1
ADTESF3		EQU	ADTEMP2+1
ADTEMP3		EQU	ADTESF3+1
AH		EQU	ADTEMP3+1	; 計算用 
AL		EQU	AH+1		; 計算用 
BH		EQU	AL+1		; 計算用 
BL		EQU	BH+1		; 計算用 
ASF		EQU	BL+1		; 符号保存
ADCH		EQU	ASF+1		; ADチャンネル保存用
ADT		EQU	ADCH+1		; ワーク
;***********************************************************
;  	プログラムの開始番地の指定
;***********************************************************		
	ORG	0		; プログラムの開始番地の指定
	GOTO	START		; プログラムのスタートへジャンプ
;***********************************************************
;  	タイマー割り込み時の番地
;***********************************************************				
	ORG	4		; タイマー割り込み時の番地
	GOTO	INT
;***********************************************************
;	プログラムスタート
;***********************************************************
START
;***********************************************************
;  入出力ピン初期化
;***********************************************************
        BCF     STATUS,RP0      ; BANK0に切替
        CLRF    GPIO            ; GPIOをクリア
        MOVLW   B'00000111'     ; コンパレータOFF
        MOVWF   CMCON           ;
	BSF	STATUS,RP0	; Bank 1 へ切替
	;; 内部クロック(4MHz)のキャリブレーション
	CALL	3FFh		; Get the cal value 
	MOVWF	OSCCAL		; Calibrate
	;; A/D or IO の設定
	MOVLW   B'00111111'	; A/D RC,AN0,1,2,3 をセット
        MOVWF   ANSEL
	;; 入出力の設定
	MOVLW	B'00011111'	; GP0(AN0),1(AN1),2(AN2),3(RSin),4(AN3)入力、
				; GP5(RSout)を出力	
        MOVWF	TRISIO		; モード設定
	;; プルアップの設定
	MOVLW	B'00100000'	; GP5をプルアップ
        MOVWF	WPU		; プルアップ設定
	;; 
	BCF	STATUS,RP0	; Bank 0 へ戻す

;***********************************************************
; メインプログラム
;***********************************************************
MAIN
;***********************************************************
	;; ステータスの初期化
	CLRF	PISTAT		; Pithのステータスをクリア(ADモード,エコーバック無し)
CMDST	;; コマンド文字列の受信開始
        CLRF    CMDCN           ; テーブルのカウンタをクリア
MAINLP1	;; １文字、受信
        CALL    RS_RECEIVE      ; データを受信
        ; エコーバックＯＮの時、受信データを送信する
	BTFSS	PISTAT,ECHOBK	; エコーバックの有無
	GOTO	NOECHOBK
	MOVFW	RSRDATA
	CALL	RS_SEND		; データ送信
NOECHOBK
        ; 受信データがLFかどうかの確認
        MOVFW   RSRDATA         ; 
        SUBLW   D'10'           ; 受信データがLFかどうか
        BTFSC   STATUS,Z
        GOTO    MAINLP1		; 次のデータを受信
        ; 受信データがCRかどうかの確認
        MOVFW   RSRDATA         ; 
        SUBLW   D'13'           ; 受信データがCRかどうか
        BTFSC   STATUS,Z
        GOTO    CMD_CHE		; コマンドチェックへ
        ; 受信データがCRで無い場合
        ; コマンド確認用バッファがいっぱいかどうか確認
        MOVFW   CMDCN           ; CMDCN -> w
        SUBLW   D'4'            ; バッファーがいっぱいなら保存しない。
        BTFSC   STATUS,Z        ; Z:CMD_LP1  NZ:スキップ
        GOTO    MAINLP1         ; 次のデータを受信
        ; コマンド確認用バッファに保存する
        MOVLW   CMDDATA         ; CMDDATA のアドレスを W へ
        ADDWF   CMDCN,W         ; CMDCN分進める
        MOVWF   FSR             ; FSR にアドレスをいれる
        MOVFW   RSRDATA         ; RS受信データを Wへ
        MOVWF   INDF            ; W を 書き込む
        ;; 
        INCF    CMDCN,f         ; カウンタ＋１
        GOTO    MAINLP1         ; 次のデータを受信
;***********************************************************
; コマンド確認
;***********************************************************                  
CMD_CHE  ;; CR 確認、コマンドのチェック
        ; エコーバック時LFを返す(CR+LFで送られた場合、LFを読み落とすため)
	BTFSS	PISTAT,ECHOBK	; エコーバックの有無
	GOTO	NOLF
	MOVLW	D'10'		; LF
	CALL	RS_SEND		; データ送信
NOLF	; コマンド文字数の確認
        MOVFW   CMDCN           ; CMDCN -> w
        SUBLW   D'4'            ; 4文字以外(未満)なら、コマンドエラー 
        BTFSS   STATUS,Z        ; Z:スキップ  NZ:CMDST
        GOTO    CMDST   
        ;; 
	CLRF	CMDNO		; コマンド番号０
CMD_NEXT
        CLRF    CMDCN           ; 受信コマンドテーブルのカウンタをクリア
CMD_LP2 ;;
	MOVLW	CMDDATA		; CMDDATA のアドレスを W へ
	ADDWF	CMDCN,W		; CMDCN分進める
	MOVWF	FSR		; FSR にアドレスをいれる

	MOVFW	CMDNO		; コマンド番号０ -> W
	ADDWF	CMDNO,W		; コマンド文字数分スキップ
	ADDWF	CMDNO,W
	ADDWF	CMDNO,W		; X 4
        ADDWF	CMDCN,W		; テーブルのカウンタを W へ
        CALL    CMTABLE         ; テーブル読み込み
	;
        BCF     INDF,5          ; 小文字を大文字に変換
        SUBWF   INDF,W		; 比較
        BTFSS   STATUS,Z        ; 演算結果が0(STATUS が Z)かチェック
        GOTO    CMD_NOT		; コマンドでなかった 
        ;;
        INCF    CMDCN,F         ; 受信コマンドテーブルのカウンタを+1
        MOVFW   CMDCN           ;
        SUBLW   D'4'            ; 4文字目？
        BTFSS   STATUS,Z        ; Z:スキップ  NZ:CMDST
        GOTO    CMD_LP2		; 次の文字をチェック
	GOTO	CMD_RUN		;; コマンド実行
CMD_NOT	;; コマンドで無かった
	INCF	CMDNO,F
	MOVFW	CMDNO
	SUBLW	D'9'		; コマンドの数
	BTFSS	STATUS,Z	; 演算結果が0ならスキップ
	GOTO	CMD_NEXT	; 次のコマンド
	GOTO	CMDST		; 
CMTABLE
        ADDWF   PCL,F           ; プログラムカウンタ＋W、データをいれてリターン
	DT	"TEMP"		; 温度出力(コマンド０)
	DT      "VERS"		; バージョン表示(コマンド１)
	DT      "STAT"		; 3pinのステータス(コマンド２)
	DT      "SWON"		; スイッチＯＮ(コマンド３)
	DT      "SWOF"		; スイッチＯＦＦ(コマンド４)
	DT      "DIGI"		; digitalの設定(コマンド５)
	DT      "ANAL"		; analogの設定(コマンド６)
	DT      "ECHO"		; エコーバック(コマンド７)
	DT      "TRUN"		; テストラン(コマンド８)
;***********************************************************
; コマンドの実行
;***********************************************************    
CMD_RUN	; コマンドの実行
	MOVF	CMDNO,F		; コマンド番号０の確認
	BTFSC	STATUS,Z	; NZ:スキップ
	GOTO	CMD_NO0		; コマンド０へ
	;; 
	DECF	CMDNO,F		; コマンド番号１の確認
	BTFSC	STATUS,Z	; NZ:スキップ
	GOTO	CMD_NO1		; コマンド１へ
	;; 
	DECF	CMDNO,F		; コマンド番号２の確認
	BTFSC	STATUS,Z	; NZ:スキップ
	GOTO	CMD_NO2		; コマンド２へ
	;; 
	DECF	CMDNO,F		; コマンド番号３の確認
	BTFSC	STATUS,Z	; NZ:スキップ
	GOTO	CMD_NO3		; コマンド３へ
	;; 
	DECF	CMDNO,F		; コマンド番号４の確認
	BTFSC	STATUS,Z	; NZ:スキップ
	GOTO	CMD_NO4		; コマンド４へ
	;; 
	DECF	CMDNO,F		; コマンド番号５の確認
	BTFSC	STATUS,Z	; NZ:スキップ
	GOTO	CMD_NO5		; コマンド５へ
	;; 
	DECF	CMDNO,F		; コマンド番号６の確認
	BTFSC	STATUS,Z	; NZ:スキップ
	GOTO	CMD_NO6		; コマンド６へ
	;; 
	DECF	CMDNO,F		; コマンド番号７の確認
	BTFSC	STATUS,Z	; NZ:スキップ
	GOTO	CMD_NO7		; コマンド７へ
	;; 
	DECF	CMDNO,F		; コマンド番号８の確認
	BTFSC	STATUS,Z	; NZ:スキップ
	GOTO	CMD_NO8		; コマンド８へ
	;; 
	GOTO	CMDST
	;;
;***********************************************************
CMD_NO0	;; コマンド０ TEMP
	CALL	PRIAD		; 温度を返す
	GOTO	CMDST
;***********************************************************
CMD_NO1	;; コマンド１ VERS
	MOVLW	CM1TBL
	CALL	PRISTR
        GOTO    CMDST		; コマンド実行終わり	

CM1TBL
	IF	VERSION==1			;### Version 1 ###
	DT      "Pith Ver1.1",D'13',D'10',0	; データをいれてリターン
	ENDIF
	IF	VERSION==2		     	;### Version 2 ### 
	DT      "Pith Ver2",D'13',D'10',0    	; データをいれてリターン
	ENDIF

;***********************************************************
CMD_NO2	;; コマンド２ STAT
	BSF	STATUS,RP0	; Bank 1 へ切替
	BTFSC   ANSEL_SW		; AD or DIGITAL ?
	GOTO	CMD3_AN
CMD3_DI	;; デジタルの時の処理
	BCF	STATUS,RP0	; Bank 0 へ切替
	MOVLW	CMD3DIT		; Digital(を返す
	CALL	PRISTR
	;;
	MOVLW	CMD3DON
	BTFSS   GPIO_SW		; ON or OFF
	MOVLW	CMD3DOF
	;; 
	CALL	PRISTR	
        GOTO    CMDST		; コマンド実行終わり	
	
CMD3_AN	;; アナログの時の処理
	BCF	STATUS,RP0	; Bank 0 へ切替
	MOVLW	CMD3ANT		; Analog を返す
	CALL	PRISTR
        GOTO    CMDST		; コマンド実行終わり	
	
CMD3ANT	DT	"Analog",D'13',D'10',0	; Analog 時のデータ
CMD3DIT	DT	"Digital(",0		; Digital時のデータ
CMD3DON	DT	"ON)",D'13',D'10',0	; Digital(ON)時のデータ
CMD3DOF	DT	"OFF)",D'13',D'10',0	; Digital(OFF)時のデータ
;***********************************************************
CMD_NO3	;; コマンド３ SWON
	BSF	GPIO_SW		; ON 
        GOTO    CMDST		; コマンド実行終わり	
;***********************************************************
CMD_NO4	;; コマンド４ SWOF
	BCF	GPIO_SW		; OFF 
        GOTO    CMDST		; コマンド実行終わり	
;***********************************************************
CMD_NO5	;; コマンド５ DIGI
	BSF	STATUS,RP0	; Bank 1 へ切替
	BCF	ANSEL_SW		; DIGITAL へ
        BCF	TRISIO_SW	; GP4を入力
	BCF	STATUS,RP0	; Bank 0 へ切替
	BSF	PISTAT,AORD	; Digital モード設定
        GOTO    CMDST		; コマンド実行終わり	
;***********************************************************
CMD_NO6	;; コマンド６ ANAL
	BSF	STATUS,RP0	; Bank 1 へ切替
	BSF	ANSEL_SW		; AD へ
        BSF	TRISIO_SW	; GP4を出力
	BCF	STATUS,RP0	; Bank 0 へ切替
	BCF	PISTAT,AORD	; Analogモード設定
        GOTO    CMDST		; コマンド実行終わり	
;***********************************************************
CMD_NO7	;; コマンド７ ECHO
	MOVFW	PISTAT		; PISTAT -> W (待避)
	CLRF	PISTAT		; PISTATにマスクを作成する。
	BSF	PISTAT,ECHOBK	; エコーバックbitのみ１に(マスク作成)
	XORWF	PISTAT,F	; エコーバック部反転
        GOTO    CMDST		; コマンド実行終わり	
;***********************************************************
CMD_NO8	;; コマンド８ TRUN
	CALL	PRIAD		; 温度を返す
	CALL	TIME1S
	BTFSS	RSIN		; if RSIN = 0 then loop
	GOTO	CMD_NO8
        GOTO    CMDST		; コマンド実行終わり


;***********************************************************
;***********************************************************
;; 文字列をRS232Cに返す
;;  W に テーブルのアドレスをいれてCALL
;***********************************************************
PRISTR	;; 文字列をRS232Cに返す
	MOVWF	TB1		; 文字列テーブルのアドレスを退避
	CLRF	TB2		; カウンタをクリア
	;; 
PRS_LP	MOVFW	TB1		; テーブルのアドレスを W へ
	ADDWF	TB2,W		; カウンタ分を足す
	CALL	PRS_GET		; 1文字取得
	;; 
        ADDLW   0               ; 0 を足す
        BTFSC   STATUS,Z        ; 演算結果が0(STATUS が Z)かチェック
        RETURN			; Z:RETURN, NZ:スキップ ; コマンド実行終わり
	;; 
        CALL    RS_SEND         ; データ送信
	;; 
        INCF    TB2,f		; カウンタ＋１
	GOTO	PRS_LP

PRS_GET	MOVWF	PCL
	
;***********************************************************
; AD変換部
;***********************************************************
PRIAD	;; AD変換してRSに出力する
	;; 0 CH 測定
	MOVLW	B'10000001'	; 右詰,Vdd,AN0,A/D on
	CALL	ADGET		; AD取得(温度データ)
	MOVFW	BH
	MOVWF	ADTEMP0
	MOVFW	ASF
	MOVWF	ADTESF0
	;;
	;; 1 CH 測定
	MOVLW	B'10000101'	; 右詰,Vdd,AN1,A/D on
	CALL	ADGET		; AD取得(温度データ)
	MOVFW	BH
	MOVWF	ADTEMP1
	MOVFW	ASF
	MOVWF	ADTESF1
	;;
	;; for Version 2 
	IF	VERSION==2	;### Version 2 ###
	BTFSC	PISTAT,AORD	; Digitalモードなら
	GOTO	PR_AD2		; AN2 をスキップ
	ENDIF			;#################
	;; 
	;; 2 CH 測定
	MOVLW	B'10001001'	; 右詰,Vdd,AN2,A/D on
	CALL	ADGET		; AD取得(温度データ)
	MOVFW	BH
	MOVWF	ADTEMP2
	MOVFW	ASF
	MOVWF	ADTESF2
	;;
	;; for Version 1
	IF	VERSION==1	;### Version 1 ###
	BTFSC	PISTAT,AORD	; Digitalモードなら
	GOTO	PR_AD2		; AN2 をスキップ
	;; 
	;; 3 CH 測定
	MOVLW	B'10001101'	; 右詰,Vdd,AN3,A/D on
	CALL	ADGET		; AD取得(温度データ)
	MOVFW	BH
	MOVWF	ADTEMP3
	MOVFW	ASF
	MOVWF	ADTESF3
	ENDIF			;#################	
PR_AD2	;;
	;; 0 CH 出力
	MOVLW	0		; AN0 を出力
	CALL	PRIDATA
	;; 
	;; 1 CH 出力
	MOVLW	','		; , を出力
	CALL	RS_SEND
	MOVLW	1		; AN1 を出力
	CALL	PRIDATA	
	;;
	;; for Version 2
	IF	VERSION==2	;### Version 2 ###
	BTFSC	PISTAT,AORD	; Digitalモードなら
	GOTO	PR_AD1		; AN2 をスキップ
	ENDIF			;#################	
	;; 
	;; 2 CH 出力
	MOVLW	','		; , を出力
	CALL	RS_SEND
	MOVLW	2		; AN2 を出力
	CALL	PRIDATA
	;;
	;; for Version 1
	IF	VERSION==1	;### Version 1 ###
	BTFSC	PISTAT,AORD	; Digitalモードなら
	GOTO	PR_AD1		; AN2 をスキップ
	;; 
	;; 3 CH 出力
	MOVLW	','		; , を出力
	CALL	RS_SEND
	MOVLW	3		; AN3 を出力
	CALL	PRIDATA	
	ENDIF			;#################	
	;; 
PR_AD1	;; CR+LFの出力
	MOVLW	D'13'		; CR を出力
	CALL	RS_SEND
	MOVLW	D'10'		; LF を出力
	CALL	RS_SEND
	;; 
	RETURN
;***********************************************************
; ADデータ（温度）の取得
;  W に ADCON0 に渡すデータをセットしてCALL
;  AN3（かさ上げ分）との差を64回分測定
;  温度に変換(0.488倍 X500/1024)して
;  BH（数値）,ASF（符号）をセットしてRETURN(7-1:整数、0:小数)
;　xxxxxxx.x
;***********************************************************
ADGET	;; ADデータ取得
	MOVWF	ADCH		; ADのチャンネルを保存
	CLRF	BH		; 変数クリア、ADを足し続けた値
	CLRF	BL		;
	MOVLW	D'64'		; 64回繰り返す
	MOVWF	ADT		;
ADGLP1	;;
	MOVFW	ADCH
        MOVWF   ADCON0
	CALL	TIME20		; 20us待つ
	BSF	ADCON0,GO	; A/D変換スタート
ADLOOP  BTFSC	ADCON0,GO	; A/D変換完了チェック
	GOTO	ADLOOP
	BCF	ADCON0,ADON	; A/D変換OFF
	BSF	STATUS,RP0	; Bank 1 へ切替
	MOVF	ADRESL,W	;下位8ビットを取得
	MOVWF	AL		; とりあえず保存
	BCF	STATUS,RP0	; Bank 0 へ切替
	MOVF	ADRESH,W	;上位8ビットを取得
	MOVWF	AH		; とりあえず保存
	;; 下駄分測定 Versin 2
	IF	VERSION==2	;### Version 2 ###
	MOVLW	B'10001101'	; 右詰,Vdd,AN3,A/D on
        MOVWF   ADCON0
	CALL	TIME20		; 20us待つ
	BSF	ADCON0,GO	; A/D変換スタート
ADLOOP2	BTFSC	ADCON0,GO	; A/D変換完了チェック
	GOTO	ADLOOP2
	BCF	ADCON0,ADON	; A/D変換OFF
	BSF	STATUS,RP0	; Bank 1 へ切替
	MOVF	ADRESL,W	;下位8ビットを取得
	SUBWF	AL,F		; AL-W
	BTFSS	STATUS,C	;
	DECF	AH,F		;
	BCF	STATUS,RP0	; Bank 0 へ切替
	MOVF	ADRESH,W	;上位8ビットを取得
	SUBWF	AH,F		; AH-W
	ENDIF			;#################
	;; AD変換の値を足し続ける
	MOVFW	AL		; 
	ADDWF	BL,F		; BL=AL+BL
	BTFSC	STATUS,C	;
	INCF	BH,F		;
	MOVFW	AH
	ADDWF	BH,F
	;;
	DECFSZ	ADT,F		; Z then 次の命令スキップ
	GOTO	ADGLP1
	;;
	;;;;;;;;
	;;この時点で
	;;BH,BLに64個（倍）分のデータが入っている
	;;かさ上げ分は引いてある。
	;;    BH   |   BL
	;; xxxxxxxx|xx.xxxxxx  少数点の位置
	;;;;;;;;	
;***********************************************************
;***********************************************************
ADTOTEMP
	;; 符号の確認
	CLRF	ASF		; とりあえず符号セット（＋）	
	;; 
	BTFSS	BH,7		; プラスならジャンプ
	GOTO	ADT1
	;; 負の場合
	COMF	ASF,F		; 符号変更（－）
	;;
	CLRF	AL		; 正の数字にする
	CLRF	AH
	;; 
	MOVFW	BL		; BL->W
	SUBWF	AL,F		; AL-W -> AL (AL=0-BL)
	BTFSS	STATUS,C	; 答えが正ならスキップ
	DECF	AH,F		;
	MOVFW	BH		; BH->W
	SUBWF	AH,F		; AH-W -> AH (AH=0-BH)
	GOTO	ADT2
	;;
ADT1	;; 正の場合
	;;
	MOVFW	BL
	MOVWF	AL
	MOVFW	BH
	MOVWF	AH
	;;;;;;;;;;
	;; この時点で　AH,ALに値（正の数値）、ASFに符号（１：マイナス　０：プラス）
	;;;;;;;;;;
ADT2	;; 
	;; 500/1024=125/256=(1111101B/256)
	MOVFW	AL		;
	MOVWF	BL		; 
	MOVFW	AH		;
	MOVWF	BH		; 1		xxxxxxxx|xx.xxxxxx 
	BCF	STATUS,C	; 01		xxxxxxxx|xxx.xxxxx 
	RRF	BH,F		;
	RRF	BL,F
	CALL	ADTADD		; 101		xxxxxxxx|xxxx.xxxx 
	CALL	ADTADD		; 1101		xxxxxxxx|xxxxx.xxx 
	CALL	ADTADD		; 11101		xxxxxxxx|xxxxxx.xx 
	CALL	ADTADD		; 111101	xxxxxxxx|xxxxxxx.x 
	CALL	ADTADD		; 1111101	xxxxxxxx|xxxxxxxx. 
	;;
	;;;;;;;;;;
	;; この時点で　BH,BLに温度値、ASFに符号（１：マイナス　０：プラス）
	;; 少数点の位置
	;; xxxxxxxx|xxxxxxxx.|xxxxxxx  ×１２５
	;; xxxxxxxx.|xxxxxxxx|xxxxxxx  ÷２５６
	;;    BH    |   BL   | ここは捨てている
	;;;;;;;;;;
	;;
	MOVLW	B'01000000'	; 四捨五入用0.5単位にする（0.25を足す）
	ADDWF	BL,F
	BTFSC	STATUS,C
	INCF	BH,F
	;;
	RLF	BL,F		; 左へシフト
	RLF	BH,F		; xxxxxxx.x|xxxxxxxx
	;;;;;;;;;;
	;; この時点で少数点の位置
	;;    BH    |   BL
	;; xxxxxxx.x|xxxxxxxx
	;; ****************************
	;; BH  温度(数値のみ）
	;; ASF 符号
	;;;;;;;;;;
	BCF	STATUS,C
	RRF	BH,F		; 0.5℃データをキャリーフラグに押し出す
	RLF	ASF,F		; 0.5℃データを符号データの0bitに入れる
	;;;;;;;;;;
	;; この時点でのデータ
	;; BH  温度(整数数値のみ）
	;; 0xxxxxxx
	;; ****************************
	;; ASF 符号
	;; fffffff5 f:符号[1:マイナス　0:プラス]  5:0.5℃データ
	;;;;;;;;;;
	
	RETURN
ADTADD
	BCF	STATUS,C	; キャリーフラグをクリア
	RRF	BH,F		;
	RRF	BL,F
	;;
	MOVFW	AL
	ADDWF	BL,F
	BTFSC	STATUS,C
	INCF	BH,F
	MOVFW	AH
	ADDWF	BH,F
	RETURN
	;; ****************************
	
;***********************************************************
;***********************************************************
; 割算
;  
; INDF / w  
;  
; DANS = 商 
; INDF = 余り
; 0 で割る時のチェックはしていない
;***********************************************************
DIV
        CLRF    DANS            ; 商 0
DIVLP
        SUBWF   INDF,F          ; wを引く
        BTFSS   STATUS,C        ; マイナスになるまで繰り返す
        GOTO    DIVEND
        INCF    DANS,F          ; 商 +1
        GOTO    DIVLP
DIVEND
        ADDWF   INDF,F          ; Wを加えてプラスに戻す
        RETURN
;***********************************************************
; データを出力
; 
; W に データのアドレスをセットしてCALL
;***********************************************************
PRIDATA
        MOVWF	FSR		; W   -> FSRに保存
        ADDWF	FSR,F		; W*2 -> FSRに保存
	MOVLW	ADDATATB	; ADデータテーブル
	ADDWF	FSR,F		; ADデータの場所計算
	;;
	BTFSS	INDF,7		; 符号を確認
	GOTO	PRnnn		; プラスなら数字の送信
	MOVLW	'-'		; -符号を送信
        CALL    RS_SEND         ; データ送信
PRnnn
	INCF	FSR,F		; 温度データのアドレス	
PR100	;; 100の位
        MOVLW   D'100'          ; 100で割る
        CALL    DIV
        MOVF    DANS,W          ; 答えを
	BTFSC	STATUS,Z	; 0 なら 10の位へスキップ
	GOTO	PRD10
        ADDLW   '0'             ; CHARに直して
        CALL    RS_SEND         ; データ送信
PRD110	;; 100の位を出力したときの10の位
        MOVLW   D'10'           ; 10で割る
        CALL    DIV
        MOVF    DANS,W          ; 答えを
        ADDLW   '0'             ; CHARに直して
        CALL    RS_SEND         ; データ送信
	GOTO	PRD1
	
PRD10	;; 10の位
        MOVLW   D'10'           ; 10で割る
        CALL    DIV
        MOVF    DANS,W          ; 答えを
	BTFSC	STATUS,Z	; 0 なら 1の位へスキップ
	GOTO	PRD1
        ADDLW   '0'             ; CHARに直して
        CALL    RS_SEND         ; データ送信
PRD1	;; 1の位
        MOVF    INDF,W          ; 答えを
        ADDLW   '0'             ; CHARに直して
        CALL    RS_SEND         ; データ送信
PRDOT	;; 小数点の出力
	MOVLW	'.'
        CALL    RS_SEND         ; データ送信
PR05	;; 0.5℃の出力
	DECF	FSR,F
	MOVLW	'0'
	BTFSC	INDF,0		; 符号を確認
	MOVLW	'5'
        CALL    RS_SEND         ; データ送信	
        RETURN   
;***********************************************************
; RS232C 関連ルーチン
;***********************************************************
;  RS232C ドライバーICを使わない。
;  MAX232などを使う場合は、ビットを反転します。
;  コメントにしてある部分を修正します。
;***********************************************************
; RS232C 受信
; 
; CALL後、RSRDATAに受信データ
; RSデータ  8bit  ストップbit 1 
;***********************************************************
RS_RECEIVE	
        ;; 受信バッファをクリア
        CLRF    RSRDATA
RSR_NOP ;; RSの信号確認
;	BTFSS   RSIN		; if RSIN = 0 then loop (IC)
	BTFSC   RSIN		; if RSIN = 1 then loop
        GOTO    RSR_NOP         ;  RSは通常Hi(1)
RSR_STB ;; スタートビットの確認
;	BTFSC   RSIN		; if RSIN = 1 then loop (IC)
	BTFSS   RSIN		; if RSIN = 0 then loop
        GOTO    RSR_STB         ; StartBit(0)を検出
        
        CALL    RS_WT05B	; 0.5ビット分待つ

        ;; データ受信 
        MOVLW   8
        MOVWF   RSCNR           ; カウンターセット(8bit分読み込む)
	NOP			; 時間調整
	NOP			; 
	NOP
	NOP
	NOP
RSRLP
        CALL    RS_WT1B7	; 1bit分待つ
	BCF     STATUS,C        ; キャリーフラグをクリア
;	BTFSC   RSIN		; RS 0 or 1? (IC)
	BTFSS   RSIN		; RS 0 or 1?
	BSF     STATUS,C        ; キャリーフラグをセット
        RRF     RSRDATA,F       ; RS DATAを右へシフト

        DECFSZ  RSCNR,F         ; RSCN を１減算
        GOTO    RSRLP           ; 0以外ならループ ; 8bit分ループ
;	; ストップビットをチェックしない
;	処理時間を稼ぐために、ストップビットをチェックしない様にしてある。
;	; ストップビット受信確認
;	CALL    RS_WT1B7		; 1bit分待つ
;	;; 
;	BTFSS   RSIN		; ストップビットでなければ、ふりだしへもどる
;	GOTO    RS_RECEIVE
        ;; 終了
        RETURN
        
;***********************************************************
; RS232C 送信
; 
; W にデータをセットしてCALL
; RSデータ  8bit  ストップbit 1 
;***********************************************************
RS_SEND
	MOVWF	RSSDATA		; 送信データを退避
        ;; 8bit 送信
        MOVLW	8		; 送信bitカウンタ初期値
        MOVWF	RSCNS		; 送信bitセット

        ;; スタートビット出力
;	BCF     RSOUT		; 0 out (IC)
	BSF     RSOUT		; 1 out
        CALL    RS_WT1B		; 1bit分待つ
RSSLP   ;;データ送出 
        ; 1bit 読み込んで出力 ループする
        RRF     RSSDATA,F       ; 送信データシフト
        BTFSS   STATUS,C        ; 0か1か
;	BCF     RSOUT		; 0 out (IC)
	BSF     RSOUT		; 1 out
        BTFSC   STATUS,C        ; 
;	BSF     RSOUT		; 1 out (IC)
	BCF     RSOUT		; 0 out
	
	CALL    RS_WT1B8	; 1bit分待つ
        
        DECFSZ  RSCNS,F         ; RSCN を1減算 0以外ならループ ; 8bit分ループ
        GOTO    RSSLP		; 0以外ならループ ; 8bit分ループ

        ;; ストップビット出力
;	BSF     RSOUT		; 1 out (IC)
	BCF     RSOUT		; 0 out
        CALL    RS_WT1B		; 1bit分待つ
        ;終了
        RETURN
        
;***********************************************************
; RS232C 送信ポート初期化
;***********************************************************
RS_INT
;	BSF     RSOUT		; RS OUT イニシャライズ 1 (IC)
	BCF     RSOUT		; RS OUT イニシャライズ 0
        RETURN  
;***********************************************************
; RS232C 用ウェイトルーチン
; 0.5bit、1bit 分待つ
;       4MHz時、1サイクル＝(1/4M)X4=1^-6s=1us
; 9600bps ->      1bit = 104.17us = 104.17サイクル(102+呼出2サイクル)
;               0.5bit =  52.08us =  52.08サイクル( 50+呼出2サイクル)
;***********************************************************
RS_WT1B7; 95(+呼出2=97 7サイクル少なくしてある)
	NOP
RS_WT1B8; 94(+呼出2=96 7サイクル少なくしてある)
	NOP
RS_WT1B9; 93(+呼出2=95 9サイクル少なくしてある)
        MOVLW   01EH		; カウンターセット(1サイクル)01EH=30 )
        MOVWF   RSWAIT          ;                 (1サイクル)			2
RSWLP2
        DECFSZ  RSWAIT,F        ; カウンターダウン( 31=1×(30-1)＋2サイクル)
	GOTO    RSWLP2		;                 ( 58=2×(30-1)   サイクル)    
        RETURN                  ;                 (  2サイクル)                 91
	;; 
RS_WT1B	; 52+50=102サイクル+2(CALL分)
	CALL    RS_WT05B	; 52+50=102サイクル
RS_WT05B ; 46+4 =50サイクル+2(CALL分)
        MOVLW   0DH             ; カウンターセット(1サイクル)0FH=15 )
        MOVWF   RSWAIT          ;                 (1サイクル)
        NOP                     ;                 (1サイクル)                    
        NOP                     ;                 (1サイクル)                    4
	
RSWLP
        DECFSZ  RSWAIT,F        ; カウンターダウン( 16=1×(15-1)＋2サイクル)
        GOTO    RSWLP           ;                 ( 28=2×(15-1)   サイクル)    
        RETURN                  ;                 (  2サイクル)                 46
;***********************************************************
;***********************************************************
;***********************************************************
;       ウェイトルーチン
;       4MHz時、1サイクル＝(1/4M)X4=1^-6s=1us
;***********************************************************
; ２０μｓ
; 20/1 = 20 サイクル(18サイクル＋呼出2サイクル)
;***********************************************************
TIME20
        MOVLW   05H		; カウンターセット(1サイクル) 05H=5)
        MOVWF   COUNT20		;                 (1サイクル)			2
LOOP20
        DECFSZ  COUNT20,F	; カウンターダウン( 6=1×(5-1)＋2サイクル)
        GOTO    LOOP20		;                 ( 8=2×(5-1)   サイクル)    
        RETURN			;                 ( 2サイクル)                  16
	
;***********************************************************
; １００μｓ
; 100/1 = 100 サイクル(98サイクル＋呼出2サイクル)
;***********************************************************
TIME100                         ;
        MOVLW   01FH            ; カウンターセット(1サイクル) 1FH=31)
        MOVWF   COUNT100        ;                 (1サイクル)
        NOP                     ;                 (1サイクル)                     
        NOP                     ;                 (1サイクル)                     4
LOOP100
        DECFSZ  COUNT100,F      ; カウンターダウン( 32=1×(31-1)＋2サイクル)
        GOTO    LOOP100         ;                 ( 60=2×(31-1)   サイクル)    
        RETURN                  ;                 (  2サイクル)                 94
;***********************************************************
; １０ｍｓ
; 10,000/1 = 10000 サイクル(9998サイクル+呼出2サイクル)
;***********************************************************
TIME10M                         ;
        MOVLW   01FH            ; カウンターセット(1サイクル) 01FH=31)
        MOVWF   COUNT10M        ;                 (1サイクル)                    2
LOOP10M2        
        DECFSZ  COUNT10M,F      ; カウンターダウン( 32=1×(31-1)＋2サイクル)
        GOTO    LOOP10M2        ;                 ( 60=2×(31-1)   サイクル)	92
	;; 以下9904サイクル 以上 96 サイクル
        MOVLW   061H            ; カウンターセット(1サイクル) 61H=97)
        MOVWF   COUNT10M        ;                 (1サイクル)                       2
LOOP10M
        CALL    TIME100         ; 100umウェイト   (9700=(100)×97
        DECFSZ  COUNT10M,F      ; カウンターダウン(  98=1×(97-1)＋2サイクル)
        GOTO    LOOP10M         ;                 ( 192=2×(97-1)   サイクル)  
        RETURN                  ;                 (   2サイクル)               9902
;***********************************************************
; １ｓ
; 1,000,000/1 = 1000000 サイクル
;***********************************************************
TIME1S				;
        MOVLW   063H            ; カウンターセット(1サイクル) 63H=99)
        MOVWF   COUNT1S		;                 (1サイクル)			2
LOOP1S
	CALL	TIME10M		; 10mウェイト     (990000=(10000)×99
        DECFSZ  COUNT1S,F	; カウンターダウン(   100=1×(99-1)＋2サイクル)
        GOTO    LOOP1S		;                 (   196=2×(99-1)   サイクル) 990296
				;ここまでの計990298
        MOVLW   05EH            ; カウンターセット(1サイクル) 5EH=94)
        MOVWF   COUNT1S		;                 (1サイクル)			    2
LOOP1S2
	CALL	TIME100		; 100umウェイト	  ( 9400=(100)×(94)サイクル)
        DECFSZ  COUNT1S,F	; カウンターダウン(   95=1×(94-1)＋2サイクル)
        GOTO    LOOP1S2		;                 (  186=2×(94-1)   サイクル)	9881
				;;計999979(990298+9881+2)
        MOVLW   06H		; カウンターセット(1サイクル) 06H=6)
        MOVWF   COUNT1S		;                 (1サイクル)			 2
LOOP1S3
        DECFSZ  COUNT1S,F	; カウンターダウン(     7=1×(6-1)＋2サイクル)
        GOTO    LOOP1S3		;                 (    10=2×(6-1)   サイクル)	17
				;;計999998(999979+2+17)

        RETURN                  ;                 (  2サイクル)			2

;***********************************************************
;***********************************************************
;  	割り込みルーチン
;***********************************************************
INT	;; 何もせずに復帰
	RETFIE
;***********************************************************
;***********************************************************
;  	プログラムの最後
;***********************************************************	
	END

