;###################################################################
;   フォークリフト制御プログラム  2013.1.7  ver1.81
;          Koji Karasawa
;
;   RB0 : 赤外線受信モジュール割り込み用
;   RB1,2 : モータ1制御 (左車輪）
;   RB3,4 : モータ2制御（右車輪）
;   RB6,7 : モータ3制御（フォーク）
;   RA0   : LCD　RS
;   RA1   : LCD  R/W
;   RA2   : LCD  Enable
;   RC7,6,5,4 : LCD data bus
;  Ver0.04  赤外線の受信割り込みができる。
;  Ver0.08  SHARP,HITACHI,PANASONIC,SONYのリモコン検出成功2012.12.15
;  Ver0.40  HITACHI, PANA,SONY,SHARP 読み取り成功2012.12.15
;  Ver0.50  モータ制御工事中  コマンドジャンプテーブルできず
;  Ver0.51  ジャンプテーブルPCL(7ビット）のためロケーション変更、成功2012/12/24
;  Ver1.00 　完成2012/12/26
;  Ver1.01  スイッチON時の暴走防止対策
;  Ver1.20  リモコン認識を緻密にする, 右左折PWM制御　2012/12/30
;  Ver1.30  フォーク動作を移動と並行可      2012/12/30
;  Ver1.40  SHARP,SONYのリモコン誤動作を改修 20130104(完成度高い　保存版）
;  Ver1.72  駆動輪PWM HIGH  LOW　制御 20130105(完成度高い　保存版）
;  Ver1.81  メッセージを顔文字に変更 文字の表示位置乱れ修正20130107(保存版！）
;  リモンコンコマンド
;　　4左前進　　　5　前進　　　　6右前進
;　　7左回転　　　8 全ブレーキ　 9右回転
;   10左後進     11 後進        12右後進
;    15△(音量大)フォーク上
;    16▽(音量小)フォーク下
;
;####################################################################

    LIST   P=PIC16F886,ST=OFF,R=DEC
    INCLUDE  "p16f886.inc"

    __CONFIG _CONFIG1, _DEBUG_OFF & _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOREN_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
    __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF

;*********制御ビット************
LCD_RS	EQU	0	; LCD Register Select bit (RA0) 0:制御用 1:データ
LCD_RW	EQU	1	; LCD Read Write bit      (RA1) 0:書込み 1:読込み
LCD_E	EQU	2	; LCD Enable Signal       (RA2)
LCD_BSY EQU	7	; LCD Busy Flag bit
IR      EQU 0   ;   PORTB RB0 赤外線入力割り込みポート
RDF     EQU 7   ;   リモンコンRC_MAKER 検出フラグ
SHARP_F EQU 0   ;   リモコンSHARP
PANA_F  EQU 1   ;   リモコンPANA
SONY_F  EQU 2   ;   リモコンSONY
HITACHI_F EQU 3   ;   リモコンHITACHI
FFWD    EQU     0AH ;前進（左正転、右正転）
BBWD    EQU     14H   ;後進（左逆転、右逆転）
FFR     EQU     02H   ;右前進(左正転、右停止)
FFL     EQU     08H   ;左前進(左停止、右正転）
RSPIN    EQU    12H   ;右スピン(左正転、右逆転)
LSPIN    EQU    0CH   ;左スピン(左逆転、右正転)
BBR      EQU    04H   ;右バック（左逆転、右停止）
BBL      EQU    10H   ;左バック（左停止、右逆転）
BREAK_V    EQU  0DEH    ; ブレーキ　（左右停止　フォークも停止）

WD_MASK EQU 0C1H    ; フォークとIR以外のビットを0クリアするためのマスクパターン

FORKUP   EQU 40H    ; フォークアップ
FORKDN   EQU 80H     ; フォークダウン
FORKBIT EQU 0C0H    ; フォーク制御ビット
FUPBIT  EQU 6       ; フォークアップビット
FDOWNBIT EQU 7      ; フォークダウンビット
;
    CBLOCK	020H
        LCDWRK      ; LCDモジュール用ワーク
        LCDRBF      ; LCDリードバッファ
        LCDWBF      ; LCD書き込み用バッファ
        CNT0        ;タイマ用カウンタ
        CNT1		;タイマ用カウンタ
        CNT2		;タイマ用カウンタ
        CNT3		;汎用カウンタ、信号解析、LCD表示用など
        R_RCV_CNT   ; 赤外線受信カウンタ(デバッグ用)
        HEX2_WRK    ; HEX2LCDモジュールWRK
        LOOP_COUNTER  ; ループカウンター
        DUTYF       ; DUTY FLAG  MSB OFF  Duty HIGH  ,MSB ON Duty LOW

        RC_MAKER    ; リモコンフラグ
                    ;00 undetected 81H Sharp 82H Pana 84H Sony 88H Hitachi
        ERRCODE    ; for debug
        BIT_CNT     ; ビットカウンタ （信号解析用）
        DUTY_WRK    ; DUTY処理ワーク


        W_SAVE      ; 割り込み処理　W退避
        PL_SAVE     ; 割り込み処理　PCLATH 退避
        FS_SAVE     ; 割り込み処理  FSR退避
        S_SAVE      ; 割り込み処理  STATUS退避

        DATA5       ; CMD  make wrk
        DATA4       ;  CMD make wrk
        DATA3       ;  CMD make wrk
        DATA2       ;  CMD make wrk
        DATA1       ;  CMD make wrk
        DATA0       ;  CMD make wrk
        CMD_DATA    ; 赤外線リモコンから読み取ったコマンド（ボタン数値）
        CMD_DATA_OLD    ; 前回のコマンド DUTYボタンを押したときはまたここを
                        ; 参照して　DUTY比のみ変えてもとのコマンドに戻す

        SHARP_BUF   ; シャープバッファ（コード-->数値変換用）

        W_TAIHI     ; FOR DEBUG
    ENDC

BANK0	MACRO
            BCF	STATUS,RP0
            BCF	STATUS,RP1
        ENDM
BANK1	MACRO
            BSF	STATUS,RP0
            BCF	STATUS,RP1
        ENDM
BANK2   MACRO
            BCF STATUS,RP0
            BSF STATUS,RP1
        ENDM
BANK3   MACRO
            BSF STATUS,RP0
            BSF STATUS,RP1
        ENDM

;**************************************
;  START
;**************************************
	ORG	0
	GOTO	MAIN_START
;===================================
;  割り込みベクトル
;　　PICの割り込みはすべてここにくる
;==================================
	ORG	4
    GOTO    INTERRUPT

;-----------------------------
; 日立データ-->チャンネル番号
;　変換テーブル
;-----------------------------
H2CH_TBL
    ADDWF   PCL,F
    RETLW   0   ;00
    RETLW   0   ;01
    RETLW   0   ;02
    RETLW   0   ;03
    RETLW   8   ;04
    RETLW   9   ;05
    RETLW   10  ;06
    RETLW   11  ;07
    RETLW   0   ;08
    RETLW   0   ;09
    RETLW   0   ;0A
    RETLW   0   ;0B
    RETLW   12  ;0C
    RETLW   1   ;0D
    RETLW   2   ;0E
    RETLW   3   ;0F
    RETLW   0   ;10
    RETLW   0   ;11
    RETLW   15  ;12     ボリューム大ボタン
    RETLW   0   ;13
    RETLW   0   ;14
    RETLW   16  ;15     ボリューム小ボタン
    RETLW   0   ;16
    RETLW   0   ;17
    RETLW   14  ;18     選局下ボタン
    RETLW   13  ;19     選局上ボタン
    RETLW   0   ;1A
    RETLW   0   ;1B
    RETLW   4   ;1C
    RETLW   5   ;1D
    RETLW   6   ;1E
    RETLW   7   ;1F

;--------------------------------
; MAIN_LOOPのコマンドジャンプテーブル
;--------------------------------
CMD_JMP
    ADDWF   PCL,F
    GOTO    CMD_0       ; ボタン　0 （イレギュラ）全モータ停止
    GOTO    CMD_1       ; 1   全モータ停止
    GOTO    CMD_2       ; 2　 全モータ停止
    GOTO    CMD_3       ; 3　 全モータ停止
    GOTO    CMD_4       ; 4   左前
    GOTO    CMD_5       ; 5   前進
    GOTO    CMD_6       ; 6   右前
    GOTO    CMD_7       ; 7   左スピン
    GOTO    CMD_8       ; 8   全モータ停止
    GOTO    CMD_9       ; 9   右スピン
    GOTO    CMD_10      ; 10  左後
    GOTO    CMD_11      ; 11　後進
    GOTO    CMD_12      ; 12  右後
    GOTO    CMD_13      ; 13(選局△）　DUTY FULL (High スピード）
    GOTO    CMD_14      ; 14(選局▽)   DUTY HALF (Low スピード）
    GOTO    CMD_15      ; 15(音量大）　フォークup,またはdownのキャンセルしてCMD_17
    GOTO    CMD_16      ; 16(音量小）　フォークdown、またはupのキャンセルをしてCMD_17
    GOTO    CMD_17      ; なにも変更しない

;===================================
;　割り込み処理
;===================================
INTERRUPT
;-----レジスタ退避--------------------
	MOVWF	W_SAVE	;W 退避
	SWAPF	STATUS,W
	CLRF	STATUS		; バンク0に切り替え
	MOVWF	S_SAVE ;STATUS退避
	MOVF	PCLATH,W	; PCLATH取り出し
	MOVWF	PL_SAVE	; PCLATH保存
	CLRF	PCLATH		; ページ0で実行
	MOVF	FSR,W		; FSR取り出し
	MOVWF	FS_SAVE	; FSR保存

	BTFSC	INTCON,INTF
	GOTO	GAIBU_INT	; 外部割り込み

INTEND	; 割り込み処理の終了処理
    BCF     INTCON,INTF ; 割り込みフラグクリア
;-----レジスタ復帰-------------------
	MOVF	FS_SAVE,W	; バンク0から
	MOVWF	FSR		; FSR復旧
	MOVF	PL_SAVE,W
	MOVWF	PCLATH		; PCLATH復旧
	SWAPF	S_SAVE,W
	MOVWF	STATUS	; STATUS復帰
	SWAPF	W_SAVE,F
	SWAPF	W_SAVE,W ; W 復帰
;------------------------------------
	RETFIE	;	割り込み許可で戻る

;=============================
;  外部割り込み(赤外線）処理
;=============================
GAIBU_INT
    INCF    R_RCV_CNT,F ;赤外線受信カウンタ  for debug
    BTFSS   PORTB,IR ;
    GOTO    INTEND          ; 赤外線入力無かった

    BTFSC   RC_MAKER,RDF    ;
    GOTO    ANA_CMD         ; コマンド解析へ

;======================
; リモコン検査
;======================
    MOVLW   1       ; for debug
    MOVWF   ERRCODE ; for debug

    MOVLW   30          ; まず0.3ms以上Hが続くか。
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSS   PORTB,IR
    GOTO    DETECTMISS      ; 蛍光灯ノイズの可能性
    DECFSZ  CNT3,F
    GOTO    $-4
; ここまで割り込みから0.3ms経過
    MOVLW   10   ; 0.1ms以内にLになればたぶんSHARP
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSS   PORTB,IR
    GOTO    DETECT_SHARP     ; たぶんSHARP
    DECFSZ  CNT3,F
    GOTO    $-4
; ここまで割り込みから0.4ms経過
    MOVLW   2       ; for debug
    MOVWF   ERRCODE ; for debug
;
    MOVLW   160        ; あと1.6msHが続くか?
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSS   PORTB,IR
    GOTO    DETECTMISS  ; ノイズだった
    DECFSZ  CNT3,F
    GOTO    $-4
; ここまで割り込みから2ms経過
    MOVLW   80       ; 0.8ms以内にLになるか。
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSS   PORTB,IR   
    GOTO    DETECT_SONY ;  0.8ms以内にLなのでたぶんSONY
    DECFSZ  CNT3,F
    GOTO    $-4
; ここまで割り込みから2.8ms経過
    MOVLW   100       ; 1ms以内にLになればたぶんPANA
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSS   PORTB,IR
    GOTO    DETECT_PANA
    DECFSZ  CNT3,F
    GOTO    $-4
; ここまで割り込みから3.8ms経過
    MOVLW   3       ; for debug
    MOVWF   ERRCODE ; for debug
;
    MOVLW   40          ; 4ms以上Hが続くか
    MOVWF   CNT3
    CALL    TIM_100us
    BTFSS   PORTB,IR
    GOTO    DETECTMISS
    DECFSZ  CNT3,F
    GOTO    $-4
; ここまで割り込みから8ms経過
    MOVLW   4       ; for debug
    MOVWF   ERRCODE ; for debug
;
    MOVLW   150     ; 1.5ms以内にLになるか。
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSS   PORTB,IR
    GOTO    DETECT_HITACHI
    DECFSZ  CNT3,F
    GOTO    $-4
    GOTO    DETECTMISS

DETECT_PANA ;------------------------------
    MOVLW   5       ; for debug
    MOVWF   ERRCODE ; for debug
;
    MOVLW   120      ;1.2ms以上Lが続くか
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSC   PORTB,IR
    GOTO    DETECTMISS  ; 異常パターン
    DECFSZ  CNT3,F
    GOTO    $-4
;
    MOVLW   6       ; for debug
    MOVWF   ERRCODE ; for debug
;
    MOVLW   80     ; 0.8ms以内にHになるか
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSC   PORTB,IR
    GOTO    $+4
    DECFSZ  CNT3,F
    GOTO    $-4
    GOTO   DETECTMISS
;    PANASONICリモコン確定
    BSF     RC_MAKER,PANA_F
    CALL    PANA_DARO
    GOTO    DETECTEND

DETECTMISS  ; -------------------------------
    CLRF    RC_MAKER
    CALL    WAKANNAI
    GOTO    INTEND

DETECT_SONY ;-------------------------------
    MOVLW   7       ; for debug
    MOVWF   ERRCODE ; for debug
;
    MOVLW   30      ; 0.3ms以上Lが続くか
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSC   PORTB,IR
    GOTO    DETECTMISS
    DECFSZ  CNT3,F
    GOTO    $-4
;
    MOVLW   8       ; for debug
    MOVWF   ERRCODE ; for debug
;
    MOVLW   50      ; 0.5ms以内にHになるか
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSC   PORTB,IR
    GOTO    $+4
    DECFSZ CNT3,F
    GOTO    $-4
    GOTO    DETECTMISS
;   SONY リモコン確定
    BSF     RC_MAKER,SONY_F
    CALL    SONY_DARO
    GOTO    DETECTEND

DETECT_SHARP ;----------------------------
    MOVLW   9       ; for debug
    MOVWF   ERRCODE ; for debug
;
    MOVLW   120     ; 1.2ms以上Lが継続するか
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSC   PORTB,IR
    GOTO    DETECTMISS  ; 異常パターン
    DECFSZ  CNT3,F
    GOTO    $-4
;
    MOVLW   0AH       ; for debug
    MOVWF   ERRCODE ; for debug
;
    MOVLW   40      ; 0.4ms以内にHになるか
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSC   PORTB,IR
    GOTO    $+4
    DECFSZ  CNT3,F
    GOTO    $-4
    GOTO    DETECTMISS  ; 異常パターン
;　シャープリモコン確定
    BSF     RC_MAKER,SHARP_F ; SHARP　リモコン検出
    CALL    SHARP_DARO   ; SHARP表示
    GOTO    DETECTEND

DETECT_HITACHI  ;----------------------------------
    MOVLW   0BH       ; for debug
    MOVWF   ERRCODE ; for debug
    MOVLW   40      ; 4ms以上Lが継続するか
    MOVWF   CNT3
    CALL    TIM_100us
    BTFSC   PORTB,IR
    GOTO    DETECTMISS  ;　異常パターン
    DECFSZ  CNT3,F
    GOTO    $-4
;
    MOVLW   0CH       ; for debug
    MOVWF   ERRCODE ; for debug
;
    MOVLW   100     ; 1ms以内に Hになるか
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSC   PORTB,IR
    GOTO    $+4
    DECFSZ  CNT3,F
    GOTO    $-4
    GOTO    DETECTMISS  ; 異常パターン
;   日立リモコン確定
    BSF     RC_MAKER,HITACHI_F ;　HITACHI リモコン検出
    CALL    HITACHI_DARO
DETECTEND
    BSF     RC_MAKER,RDF ;Remocon Detected Flag
    GOTO    INTEND

;=================================
;　コマンド解析
;   メーカ毎にコマンドを解析する。
;=================================
ANA_CMD
; コマンド番号13,14は駆動輪のDUTY比の変更
; コマンド番号15,16はフォークの上げ下げのコマンド
; コマンド解析で抽出されたコマンド番号はCMD_DATAを介して
; メインループに渡される。メインループでは13,14のDUTY処理後
; CMD_DATA_OLD にある前回のコマンド番号をCMD_DATAに入れ直す。
; もしここで13 や14のときもCMD_DATA_OLDを更新するとどうなるか
; 例えばここで解析前のCMD_DATAに13が入っていてそのままそれを
; CMD_DATA_OLDに入れて更新してしまうと新、旧両方とも13という
; DUTY比変更コマンドになってもとのコマンドがわからなくなる。
; そこで下のANA_CMD1の手前までの処理が必要になる。
; リフトの上げ下げも同様
    MOVLW   13
    SUBWF   CMD_DATA,W  ; CMD_DATA - 13 --> W
    BTFSS   STATUS,C    ; CMD_DATA >= 13 then C on
    GOTO    ANA_CMD2    ; CMD_DATA < 13 ANA_CMD_UPDATE
    MOVLW   18
    SUBWF   CMD_DATA,W  ; CMD_DATA-18 --> W
    BTFSS   STATUS,C    ; CMD_DATA >=18 then C CON
    GOTO    ANA_CMD1    ; CMD_DATA <18 then C OFF
ANA_CMD2
;          ; 前回（解析前）のコマンドが0から12のときまたは18以上
    MOVF    CMD_DATA,W
    MOVWF   CMD_DATA_OLD
;
ANA_CMD1
    BTFSS   RC_MAKER,HITACHI_F
    GOTO    $+2
    GOTO    ANA_HITACHI
    BTFSS   RC_MAKER,PANA_F
    GOTO    $+2
    GOTO    ANA_PANA
    BTFSS   RC_MAKER,SONY_F
    GOTO    $+2
    GOTO    ANA_SONY
    BTFSS   RC_MAKER,SHARP_F
    GOTO    INTEND ;割り込み終了
;======================
;SHARPリモコンのコマンド解析
;======================
ANA_SHARP
    MOVLW   14          ; 14ビット
    MOVWF   BIT_CNT
SHARP_DATA_READ; SONY データリード処理
    MOVLW   50   ; 0.5ms以内にLになるか0.36ms以内にLになるはず
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSS   PORTB,IR
    GOTO    $+4
    DECFSZ  CNT3,F
    GOTO    $-4
    GOTO    INTEND ;0.5ms以内にLにならないので割り込み終了
; H ここから0.75msでHならビットデータ0, 1.75msでHならビットデータ1
    MOVLW   100   ;　1ms以内にHになるか
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSC   PORTB,IR
    GOTO   SH_BIT0 ; 1ms以内Hになった
    DECFSZ  CNT3,F
    GOTO    $-4
;さらにLが続くのでビットデータ1かも
    MOVLW   100          ;さらに1ms以内にHになるか。
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSC   PORTB,IR
    GOTO    SH_BIT1  ;1ms以内にHになった
    DECFSZ  CNT3,F
    GOTO    $-4
    GOTO    INTEND ;Lにならない　割り込み終了
;
SH_BIT1  ;データビット1を検出
    BSF     STATUS,C
    GOTO    SH_BITMAKE
;
SH_BIT0  ; データビット0を検出
    BCF     STATUS,C    ; Cフラグ0
SH_BITMAKE
    RRF     DATA1,F
    RRF     DATA0,F
    DECFSZ  BIT_CNT,F   ; 14ビット読んだらループから脱出
    GOTO    SHARP_DATA_READ
;
;  16bit中14ビットまでしかつまっていないので
;   0000をつめて16ビットにする。
    MOVF    DATA0,W
    ANDLW   0FCH  ;下2ビット0クリアしてDATA1の上4ビットへ回し込む
    MOVWF   DATA0
    BCF     STATUS,C
    CALL    RSHIFT1     ;2バイト右シフト
    CALL    RSHIFT1     ;2バイト右シフト
;
; SHARPのコードをボタン番号に変換
    SWAPF   DATA0,F
    MOVLW   0FH
    ANDWF   DATA0,F
    ANDWF   DATA1,F
    SWAPF   DATA1,W
    IORWF   DATA0,F  ; DATA0にDATA部を入れる
;
    MOVF    DATA0,W
    SUBLW   0   ; 0 - W  -> W
    MOVWF   SHARP_BUF
    BCF     STATUS,C
    RRF     SHARP_BUF,F ;
    DECF    SHARP_BUF,F

    MOVLW   13
    SUBWF   SHARP_BUF,W ; SHARP_BUF - W --> W
    BTFSS   STATUS,C
    GOTO    SH_END  ; 1〜12のボタン検出成功
;
    MOVF    DATA0,W     ; 選局ボタン▲
    SUBLW   0DCH
    BTFSS   STATUS,Z
    GOTO    $+3
    MOVLW   13
    GOTO    SH_END2
;
    MOVF    DATA0,W     ; 選局ボタン▼
    SUBLW   0DAH
    BTFSS   STATUS,Z
    GOTO    $+3
    MOVLW   14
    GOTO    SH_END2
;
    MOVF    DATA0,W     ; 音量　大
    SUBLW   0D6H
    BTFSS   STATUS,Z
    GOTO    $+3
    MOVLW   15
    GOTO    SH_END2
;
    MOVF    DATA0,W     ; 音量　小
    SUBLW   0D4H
    BTFSS   STATUS,Z
    GOTO    INTEND    ; 該当なし、シャープはイレギュラーはここで抜ける
    MOVLW   16
    GOTO    SH_END2
;
SH_END
    MOVF    SHARP_BUF,W
SH_END2
    MOVWF   CMD_DATA
    GOTO    INTEND

;======================
;SONYリモコンのコマンド解析
;======================
ANA_SONY
;SonyHeader処理
    MOVLW   20     ; 2ms以上Hが続くか。
    MOVWF   CNT3
    CALL    TIM_100us
    BTFSS   PORTB,IR
    GOTO    INTEND; 2ms以上続かないので割り込み終了
    DECFSZ  CNT3,F
    GOTO    $-4
;
    MOVLW   60        ; 0.6ms以内に0になるか。
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSS   PORTB,IR
    GOTO     $+4
    DECFSZ  CNT3,F
    GOTO     $-4
    GOTO    INTEND ; 0.6ms以内にLにならない
;
    MOVLW   12          ; 12ビット
    MOVWF   BIT_CNT
SO_DATA_READ; SONY データリード処理
    MOVLW   80   ; 0.8ms以内にHになるか06msHになるはず
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSC   PORTB,IR
    GOTO    $+4
    DECFSZ  CNT3,F
    GOTO    $-4
    GOTO    INTEND ;0.8ms以内にHにならないので割り込み終了
; H ここから0.6ms以内にLならビットデータ0, 1.2ms継続後Lならビットデータ1
    MOVLW   80   ;　0.8ms以内にLになるか
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSS   PORTB,IR
    GOTO   SO_BIT0 ; 0.8ms以内Lになった
    DECFSZ  CNT3,F
    GOTO    $-4
;さらにHが続くのでビットデータ1かも
    MOVLW   80          ;さらに0.8ms以内にLになるか。
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSS   PORTB,IR
    GOTO    SO_BIT1  ;0.8ms以内にLになった
    DECFSZ  CNT3,F
    GOTO    $-4
    GOTO    INTEND ;Lにならない　割り込み終了
;
SO_BIT1  ;データビット1を検出
    BSF     STATUS,C
    GOTO    SO_BITMAKE
;
SO_BIT0  ; データビット0を検出
    BCF     STATUS,C    ; Cフラグ0
SO_BITMAKE
    CALL    RSHIFT1     ;2バイト右シフト
    DECFSZ  BIT_CNT,F   ; 12ビット読んだらループから脱出
    GOTO    SO_DATA_READ
;
;  16bit中12ビットまでしかつまっていないので
;   0000をつめて16ビットにする。
    MOVF    DATA0,W
    ANDLW   0F0H  ;下4ビット0クリアしてDATA1の上4ビットへ回し込む
    MOVWF   DATA0
    BCF     STATUS,C
    CALL    RSHIFT1     ;2バイト右シフト
    CALL    RSHIFT1     ;2バイト右シフト
    CALL    RSHIFT1     ;2バイト右シフト
    CALL    RSHIFT1     ;2バイト右シフト
;
; SONYコードをボタン番号に変換
    MOVF    DATA0,W
    ANDLW   0F0H
    SUBLW   080H
    BTFSS   STATUS,Z    ; DATA5 上位4ビット8
    GOTO    SO_NOTNUM   ; DATA5 上位4ビット8ではない
;
    MOVF    DATA0,W     ;　1〜12 ボタン
    ANDLW   0FH
    ADDLW   1
    GOTO    SO_END

SO_NOTNUM
    MOVF    DATA0,W     ; 選局ボタン▲
    SUBLW   090H
    BTFSS   STATUS,Z
    GOTO    $+3
    MOVLW   13
    GOTO    SO_END
;
    MOVF    DATA0,W     ; 選局ボタン▼
    SUBLW   091H
    BTFSS   STATUS,Z
    GOTO    $+3
    MOVLW   14
    GOTO    SO_END
;
    MOVF    DATA0,W     ; 音量　大
    SUBLW   92H
    BTFSS   STATUS,Z
    GOTO    $+4
    CALL    TIM_100ms  ;  Ver1.40 追加
    MOVLW   15
    GOTO    SO_END
;
    MOVF    DATA0,W     ; 音量　大
    SUBLW   93H
    BTFSS   STATUS,Z
    GOTO    INTEND  ; イレギュラ信号
    CALL    TIM_100ms  ; Ver1.40 追加
    MOVLW   16
;
SO_END
    MOVWF   CMD_DATA
    GOTO    INTEND

;======================
;Panasonicリモコンのコマンド解析
;======================
ANA_PANA
; Panasonic Header 処理
    MOVLW   25  ;2.5mS以上Hが持続するか。
    MOVWF   CNT3
    CALL    TIM_100us
    BTFSS   PORTB,IR
    GOTO    INTEND  ; 持続しないので割り込み終了
    DECFSZ  CNT3,F
    GOTO    $-4
;
    MOVLW   20  ;2ms以内にLになるか。
    MOVWF   CNT3
    CALL    TIM_100us
    BTFSS   PORTB,IR
    GOTO    $+4
    DECFSZ  CNT3,F
    GOTO    $-4
    GOTO    INTEND  ; 2mS以内にLにならなので割り込み終了
;
    MOVLW   10  ; 1mS以上Lが持続するか
    MOVWF   CNT3
    CALL    TIM_100us
    BTFSC   PORTB,IR
    GOTO    INTEND ; 持続しないので割り込み終了
    DECFSZ  CNT3,F
    GOTO    $-4
;
    MOVLW   10  ; 1mS以内にHになるか。
    MOVF    CNT3,F
    CALL    TIM_100us
    BTFSC   PORTB,IR
    GOTO    $+4
    DECFSZ  CNT3,F
    GOTO    $-4
    GOTO    INTEND ; Hにならないので割り込み終了
;
    MOVLW   48          ; 48ビット
    MOVWF   BIT_CNT
P_DATA_READ    ; PANA データリード処理
    MOVLW   80   ; 0.8ms以内にLになるか0.23msでLになるはず
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSS   PORTB,IR
    GOTO    $+4
    DECFSZ  CNT3,F
    GOTO    $-4
    GOTO    INTEND ;1ms以内にLにならないので割り込み終了
; L ここから1ms以内にHならビットデータ0,1.3ms以上Lならビットデータ1
    MOVLW   80   ;　ということで0.8ms以内にHになるか。
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSC   PORTB,IR
    GOTO    P_BIT0 ; 0.8ms以内にHになった
    DECFSZ  CNT3,F
    GOTO    $-4
;さらにLが続くのでビットデータ1かも
    MOVLW   100          ;さらに1ms以内にHになるか。
    MOVWF   CNT3
    CALL    TIM_10us
    BTFSC   PORTB,IR
    GOTO    P_BIT1  ; 1ms以内にHになった
    DECFSZ  CNT3,F
    GOTO    $-4
    GOTO    INTEND ;Hにならない　割り込み終了
;データビット1を検出
P_BIT1
    BSF     STATUS,C
    GOTO    P_BITMAKE
;
P_BIT0  ; データビット0を検出
    BCF     STATUS,C    ; Cフラグ0
P_BITMAKE
    CALL    RSHIFT5     ; 6バイト右シフト
    DECFSZ  BIT_CNT,F   ; 48ビット読んだらループから脱出
    GOTO    P_DATA_READ

; Panasonic DATA5をチャンネル値に変換
    MOVF    DATA5,W
    ANDLW   0F0H
    SUBLW   090H
    BTFSS   STATUS,Z    ; DATA5 上位4ビット9
    GOTO    P_NOTNUM            ; DATA5 上位4ビット9ではない
;
    MOVF    DATA5,W     ;　1〜12 ボタン
    ANDLW   0FH
    ADDLW   1
    GOTO    P_END

P_NOTNUM
    MOVF    DATA5,W     ; 選局ボタン▲
    SUBLW   0B4H
    BTFSS   STATUS,Z
    GOTO    $+3
    MOVLW   13
    GOTO    P_END
;
    MOVF    DATA5,W     ; 選局ボタン▼
    SUBLW   0B5H
    BTFSS   STATUS,Z
    GOTO    $+3
    MOVLW   14
    GOTO    P_END
;
    MOVF    DATA5,W     ; 音量　大
    SUBLW   0A0H
    BTFSS   STATUS,Z
    GOTO    $+3
    MOVLW   15
    GOTO    P_END
;
    MOVF    DATA5,W     ; 音量　大
    SUBLW   0A1H
    BTFSS   STATUS,Z
    GOTO    INTEND       ;　イレギュラー信号
    MOVLW   16
;
P_END
    MOVWF   CMD_DATA
    GOTO    INTEND

;====================
;  日立リモコンのコマンド解析
;===================
ANA_HITACHI
;　日立Header 処理
    MOVLW   60 ; 6msec間以上Hが持続するか
    MOVWF   CNT3
    CALL    TIM_100us
    BTFSS   PORTB,IR
    GOTO    INTEND ; 持続しないので割り込み終了
    DECFSZ  CNT3,F
    GOTO    $-4
;
    MOVLW   60  ; 6msec以内にLになるか。
    MOVWF   CNT3
    CALL    TIM_100us
    BTFSS   PORTB,IR
    GOTO    $+4
    DECFSZ  CNT3,F
    GOTO    $-4
    GOTO    INTEND  ; Lにならないので割り込み終了
;
    MOVLW   30      ;3msec以上Lが持続するか
    MOVWF   CNT3
    CALL    TIM_100us
    BTFSC   PORTB,IR
    GOTO    INTEND  ; Lが持続しないので割り込み終了
    DECFSZ  CNT3,F
    GOTO    $-4
;
    MOVLW   30      ;3msec以内にHになるか
    MOVWF   CNT3
    CALL    TIM_100us
    BTFSC   PORTB,IR
    GOTO    $+4
    DECFSZ  CNT3,F
    GOTO    $-4
    GOTO    INTEND  ; 30msecオーバー　割り込み終了
; HITACHIは4バイト(32ビット）最初の2バイトが固定コード
;　　　3バイト目がデータ4バイト目が反転データ
    MOVLW   32       ; 32
    MOVWF   BIT_CNT  ;
; 日立データリード処理
H_DATA_READ
    MOVLW   8  ; 0.8ms以内にLになるか(0.55msで0になるはず）
    MOVWF   CNT3
    CALL    TIM_100us
    BTFSS   PORTB,IR
    GOTO    $+4
    DECFSZ  CNT3,F
    GOTO    $-4
    GOTO    INTEND ;1ms以内にLにならないので割り込み終了
; L ここから0.55ms以内に1ならビットデータ0  1.65ms継続後1ならビットデータ1
    MOVLW   8   ;　ということで0.8ms以内にHになるか。
    MOVWF   CNT3
    CALL    TIM_100us
    BTFSC   PORTB,IR
    GOTO    H_BIT0 ; 0.8ms以内に1になった
    DECFSZ  CNT3,F
    GOTO    $-4
;さらにLが続くのでビットデータ1かも
    MOVLW   14          ;1.4ms以内にHになるか。
    MOVWF   CNT3
    CALL    TIM_100us
    BTFSC   PORTB,IR
    GOTO    H_BIT1  ; 1.4ms以内にHになった
    DECFSZ  CNT3,F
    GOTO    $-4
    GOTO    INTEND ;Hにならない　割り込み終了
;
H_BIT1  ;データビット1を検出
    BSF     STATUS,C
    GOTO    H_BITMAKE
;
H_BIT0  ; データビット0を検出
    BCF     STATUS,C    ; Cフラグ0
H_BITMAKE
    CALL    RSHIFT3     ; 4バイト右シフト
    DECFSZ  BIT_CNT,F   ; 32ビット読んだらループから脱出
    GOTO    H_DATA_READ

    MOVF    DATA2,W     ;下5ビットを抽出
    ANDLW   1FH
    CALL    H2CH_TBL    ;ボタン番号に変換
    MOVWF   CMD_DATA    ; コマンドデータに格納

    GOTO    INTEND

;-----------------
; 右シフト
;-----------------
RSHIFT5
    RRF     DATA5,F
    RRF     DATA4,F
RSHIFT3
    RRF     DATA3,F
    RRF     DATA2,F
RSHIFT1
    RRF     DATA1,F
    RRF     DATA0,F
    RETURN

;**************************************
; 初期処理
;**************************************
MAIN_START
    BANKSEL INTCON
    BCF INTCON,GIE  ; 割り込み禁止
    BCF INTCON,PEIE ; 割り込み禁止

    BANKSEL  ANSELH
    CLRF    ANSELH  ; PORTBのアナログピン(RB0〜5)をデジタルモードにする。
    CLRF    ANSEL   ; PORTAのアナログピン(RA0,1,2,3,5)をデジタルモードにする
    BANKSEL TRISA   ;
    CLRF    TRISA    ; PORTA すべて出力
    MOVLW   01H
    MOVWF   TRISB   ; RB0のみ入力、残りは出力
    CLRF    TRISC   ; PORTC　すべて出力

    BANK1
    MOVLW   74H     ; 内部クロック8MHzの設定
    MOVWF   OSCCON

    BANK0
    CALL    BREAKING  ; モータすべて停止
;
    CLRF    CMD_DATA    ; コマンドデータ0クリア
    CLRF    LOOP_COUNTER    ; ループカウンター0クリア
    CLRF    DUTYF       ; デューティ100%(スピードHigh)
;
    CALL    LCD_INIT  ; LCD　初期処理
    CALL    LCD_OFF
    CALL    LCD_ON

    CALL    LCD_CLEAR   ; LCD クリア
    CALL    VERDISP     ;　Version 表示
    CALL    TIM_1S      ; 1.5秒待ち
    CALL    TIM_500ms
    CALL    LCD_CLEAR   ; LCD消去

    CLRF    R_RCV_CNT   ; 赤外線受信カウンタクリア
    CLRF    RC_MAKER    ; リモコンフラグクリア

    ; OPTION REGISTER セット
    ;   b7:1 RBPU Disable (PORTB pull ups are disable)
    ;   b6:1 Interrupt on rising edge of INT pin
    BANK1
    MOVLW   0C0H
    MOVWF   OPTION_REG
    ;
    ;割り込み許可
    BANKSEL  INTCON
    CLRF    INTCON
    BSF     INTCON,INTE ;外部割り込み許可
    BSF     INTCON,GIE  ;周辺割り込み許可
    BANK0

;*****************************
;   リモコン検出ループ
;*****************************
    CALL    PUSHONE     ; 1ヲオシテクダサイ
RC_DETECTING    ; リモコン検出ループ
    CALL    BREAKING    ; 安全対策
    BTFSS   RC_MAKER,RDF ; Remocon Detect FLAG
    GOTO    RC_DETECTING

    CALL    TIM_1S
    CALL    LCD_CLEAR  ;LCD　クリア
    CALL    TIM_1S

;*****************************
;   コマンドループ
;*****************************
MAIN_LOOP
    INCF    LOOP_COUNTER,F ; ループカウンター　+1
    MOVF    CMD_DATA,W
    GOTO    CMD_JMP

;--------------------------------------------
CMD_0    ; 無効ボタンはすべてCMD_0 停止処理
CMD_1    ; 1も停止
CMD_2    ; 2も停止
CMD_3    ; 3も停止
CMD_8   ;  8も停止
    CALL    BREAKING    ; 全モータ停止
    CALL   LCD_L1
    MOVLW  0BDH     ; ス
    CALL   LCD_WRITE
    MOVLW  0C4H     ; ト
    CALL    LCD_WRITE
    MOVLW   0AFH    ; ッ
    CALL    LCD_WRITE
    MOVLW   0CCH    ; フ
    CALL    LCD_WRITE
    MOVLW   0DFH    ; °
    CALL    LCD_WRITE
    CALL    SPACE3  ; スペース3個
;
    CALL    LCD_L2
    CALL    SPACE8
    GOTO    MAIN_LOOP
;---------------------------------------
CMD_4       ; 左前　（左弱正転、右正転）
    MOVF   PORTB,W
    ANDLW   WD_MASK   ; PORTB　フォーク制御ビットとIRビット以外落とす
    IORLW  FFL
    MOVWF  PORTB
;
    BTFSC   LOOP_COUNTER,4  ; 左PWM制御
    BSF     PORTB,1
;       \(^_^ )
    CALL    LCD_L1
    MOVLW   0A4H    ; \
    CALL    LCD_WRITE
    MOVLW   '('
    CALL    LCD_WRITE
    CALL    KAO         ; ^_^
    CALL    SPACE1
    MOVLW   ')'
    CALL    LCD_WRITE
    CALL    SPACE1  ; スペース1個
    GOTO    DUTY_CHECK

;---------------------------------------
CMD_5       ; 前進（左正転、右正転)
    MOVF   PORTB,W
    ANDLW   WD_MASK   ; PORTB　フォーク制御ビットとIRビット以外落とす
    IORLW  FFWD
    MOVWF  PORTB
;   \(^_^)/
    CALL    LCD_L1
    MOVLW   0A4H    ; \
    CALL    LCD_WRITE
    MOVLW   '('
    CALL    LCD_WRITE
    CALL    KAO     ; ^_^
    MOVLW   ')'
    CALL    LCD_WRITE
    MOVLW   '/'
    CALL    LCD_WRITE
    CALL    SPACE1  ; スペース1個
    GOTO    DUTY_CHECK

;---------------------------------------
CMD_6       ; 右前（左正転、右弱正転）
    MOVF   PORTB,W
    ANDLW   WD_MASK   ; PORTB　フォーク制御ビットとIRビット以外落とす
    IORLW  FFR
    MOVWF  PORTB
;
    BTFSC   LOOP_COUNTER,4  ; 右PWM制御
    BSF     PORTB,3
;      ( ^_^)/
    CALL    SPACE1
    CALL    LCD_L1
    MOVLW   '('
    CALL    LCD_WRITE
    CALL    SPACE1
    CALL    KAO      ;  ^_^
    MOVLW   ')'
    CALL    LCD_WRITE
    MOVLW   '/'
    CALL    LCD_WRITE
    GOTO    DUTY_CHECK

;---------------------------------------
CMD_7       ; 左スピン(左逆転、右正転）
    MOVF    PORTB,W
    ANDLW   WD_MASK   ; PORTB　フォーク制御ビットとIRビット以外落とす
    IORLW   LSPIN
    MOVWF   PORTB
;     \(@_@)\
    CALL    LCD_L1
    MOVLW   0A4H    ; \
    CALL    LCD_WRITE
    MOVLW   '('
    CALL    LCD_WRITE
    CALL    KAO2    ; @_@
    MOVLW   ')'
    CALL    LCD_WRITE
    MOVLW   0A4H    ; \
    CALL    LCD_WRITE
    CALL    SPACE1
    GOTO    DUTY_CHECK

;---------------------------------------
CMD_9       ; 右スピン（左正転、右逆転）
    MOVF    PORTB,W
    ANDLW   WD_MASK   ; PORTB　フォーク制御ビットとIRビット以外落とす
    IORLW   RSPIN
    MOVWF   PORTB
;    /(@_@)/
    CALL    LCD_L1
    MOVLW   '/'
    CALL    LCD_WRITE
    MOVLW   '('
    CALL    LCD_WRITE
    CALL    KAO2
    MOVLW   ')'
    CALL    LCD_WRITE
    MOVLW   '/'
    CALL    LCD_WRITE
    CALL    SPACE1
    GOTO    DUTY_CHECK

;---------------------------------------
CMD_10      ; 左後（左弱逆転、右逆転）
    MOVF   PORTB,W
    ANDLW   WD_MASK   ; PORTB　フォーク制御ビットとIRビット以外落とす
    IORLW  BBL
    MOVWF  PORTB
;
    BTFSC   LOOP_COUNTER,4  ; 左PWM制御
    BSF     PORTB,2
;       /(^_^ )
    CALL    LCD_L1
    MOVLW   '/'
    CALL    LCD_WRITE
    MOVLW   '('
    CALL    LCD_WRITE
    CALL    KAO
    CALL    SPACE1
    MOVLW   ')'
    CALL    LCD_WRITE
    CALL    SPACE1
    GOTO    DUTY_CHECK

;---------------------------------------
CMD_11      ; バック (左逆転、右逆転)
    MOVF   PORTB,W
    ANDLW   WD_MASK   ; PORTB　フォーク制御ビットとIRビット以外落とす
    IORLW  BBWD
    MOVWF  PORTB
    ;  /(^_^)\
    CALL    LCD_L1
    MOVLW   '/'
    CALL    LCD_WRITE
    MOVLW   '('
    CALL    LCD_WRITE
    CALL    KAO
    MOVLW   ')'
    CALL    LCD_WRITE
    MOVLW   0A4H  ; \
    CALL    LCD_WRITE
    CALL    SPACE1  ; スペース1個
    GOTO    DUTY_CHECK

;---------------------------------------
CMD_12      ; 右後（左逆転、右弱逆転）
    MOVF   PORTB,W
    ANDLW   WD_MASK   ; PORTB　フォーク制御ビットとIRビット以外落とす
    IORLW   BBR
    MOVWF   PORTB
;
    BTFSC   LOOP_COUNTER,4  ; 右PWM制御
    BSF     PORTB,4
;   ( ^_^)\
    CALL    LCD_L1
    MOVLW   '('
    CALL    LCD_WRITE
    CALL    SPACE1
    CALL    KAO
    MOVLW   ')'
    CALL    LCD_WRITE
    MOVLW   0A4H   ; \
    CALL    LCD_WRITE
    CALL    SPACE1  ; スペース1個
    GOTO    DUTY_CHECK
;-------------------------------------
CMD_13          ; 選局▲ ボタン　DUTY比100%
    BCF     DUTYF,7 ;DUTYFLAG クリア DUTY 100%
    MOVF    CMD_DATA_OLD,W ; コマンドを前回のに戻す
    MOVWF   CMD_DATA
    GOTO    DUTY_CHECK

 ;-------------------------------------
CMD_14          ; 選局▼ ボタン　DUTY比50%
    BSF     DUTYF,7;    DUTYFLAG ON
    MOVF    CMD_DATA_OLD,W ; コマンドを前回のに戻す
    MOVWF   CMD_DATA
    GOTO    DUTY_CHECK

;---------------------------------------
CMD_15      ; フォークアップ、またはダウンのキャンセル
;フォークをアップする。駆動輪の状態は変えない。
;現在フォークがダウンのときは停止処理
    MOVLW   8
    SUBWF   CMD_DATA_OLD,W
    BTFSC   STATUS,Z
    GOTO    CMD_15_3    ; CMD_DATA_OLDが停止ならコマンドは戻さない。
    MOVLW   4
    SUBWF   CMD_DATA_OLD,W ; CMD_DATA_OLD - 4 --> W
    BTFSS   STATUS,C ; CMD_DATA_OLD >= 4 then C on
    GOTO    CMD_15_3   ; CMD_DATA_OLD =<3は停止なのでこれらもコマンドは戻さない
;
    MOVF    CMD_DATA_OLD,W ; コマンドを前回のに戻す
    MOVWF   CMD_DATA
;
CMD_15_3
    BTFSS   PORTB,FDOWNBIT
    GOTO    CMD_15_1
    BTFSC   PORTB,FUPBIT
    GOTO    CMD_15_1
CMD_15_2 ; フォークダウン中なのでダウンキャンセル(停止）
    MOVLW   FORKBIT
    IORWF   PORTB,F
    CALL    LCD_L2
    CALL    SPACE8
    MOVLW   17       ; なにも変化しないコマンド
    MOVWF   CMD_DATA
    GOTO    DUTY_CHECK

CMD_15_1 ;
    BCF     PORTB,FDOWNBIT
    BSF     PORTB,FUPBIT
    CALL    LCD_L2
    MOVLW   0CCH    ; フ
    CALL    LCD_WRITE
    MOVLW   0ABH    ; ォ
    CALL    LCD_WRITE
    MOVLW   0B0H    ;　ー
    CALL    LCD_WRITE
    MOVLW   0B8H    ;　ク
    CALL    LCD_WRITE
    MOVLW   0B1H    ;　ア
    CALL    LCD_WRITE
    MOVLW   0AFH    ; ッ
    CALL    LCD_WRITE
    MOVLW   0CCH    ; フ
    CALL    LCD_WRITE
    MOVLW   0DFH    ; °
    CALL    LCD_WRITE
    GOTO    DUTY_CHECK

;---------------------------------------
CMD_16      ; フォークダウン、またはアップのキャンセル
;  フォークをダウンする。もしアップ中なら停止する。
;  駆動輪の動作には影響しない。

    MOVLW   8
    SUBWF   CMD_DATA_OLD,W
    BTFSC   STATUS,Z
    GOTO    CMD_16_3    ; CMD_DATA_OLDが停止ならコマンドは戻さない。
    MOVLW   4
    SUBWF   CMD_DATA_OLD,W ; CMD_DATA_OLD - 4 --> W
    BTFSS   STATUS,C ; CMD_DATA_OLD >= 4 then C on
    GOTO    CMD_16_3   ; CMD_DATA_OLD =<3は停止なのでこれらもコマンドは戻さない
;
    MOVF    CMD_DATA_OLD,W ; コマンドを前回のに戻す
    MOVWF   CMD_DATA
;
CMD_16_3
    BTFSS   PORTB,FUPBIT
    GOTO    CMD_16_1
    BTFSC   PORTB,FDOWNBIT
    GOTO    CMD_16_1
    GOTO    CMD_15_2  ; フォークダウン中なのでダウンキャンセル(停止）

CMD_16_1
    BCF     PORTB,FUPBIT
    BSF     PORTB,FDOWNBIT
    CALL    LCD_L2
    MOVLW   0CCH    ; フ
    CALL    LCD_WRITE
    MOVLW   0ABH    ; ォ
    CALL    LCD_WRITE
    MOVLW   0B0H    ; ー
    CALL    LCD_WRITE
    MOVLW   0B8H    ; ク
    CALL    LCD_WRITE
    MOVLW   0C0H    ; タ
    CALL    LCD_WRITE
    MOVLW   0DEH    ; "
    CALL    LCD_WRITE
    MOVLW   0B3H    ; ウ
    CALL    LCD_WRITE
    MOVLW   0DDH    ; ン
    CALL    LCD_WRITE
    GOTO    DUTY_CHECK

;---------------------------------------
CMD_17  ; なにも状態を変えない
    MOVF    CMD_DATA_OLD,W ; コマンドを前回のに戻す
    MOVWF   CMD_DATA
    GOTO    DUTY_CHECK

;-----------------------------------
; DUTY処理
;  　main ループの最後でDUTYFのb7がON
;　　のとき駆動輪のみPWM処理する
;----------------------------------
DUTY_CHECK
    BTFSS   DUTYF,7
    GOTO    DUTY_FULL
DUTY_HALF
; DUTY処理
    CALL    L_SPEED ; LOW を表示

    BTFSC   LOOP_COUNTER,2  ; ループカウンターb2 offのとき出力カット
    GOTO    MAIN_LOOP
;
    MOVF    PORTB,W
    MOVWF   DUTY_WRK  ; PORTBの値保存
;
    ANDLW   WD_MASK   ; PORTB　フォーク制御ビットとIRビット以外落とす
    MOVWF   PORTB
    CALL    TIM_5ms
;
    MOVF    DUTY_WRK,W ; PORTBの値戻す
    MOVWF   PORTB
    GOTO    MAIN_LOOP

DUTY_FULL
    CALL    H_SPEED    ; High  を表示
    GOTO    MAIN_LOOP

;**********************
;*  全モータ停止
;***********************
BREAKING
    MOVLW   BREAK_V
    IORWF   PORTB,F
    RETURN

;************************
;  16進数--> LCD　表示
;    例 3AH  --> 3A と
;      カレントのカーソル位置から表示
;    入力  W　レジスタ
;*************************
HEX2LCD
    MOVWF   HEX2_WRK    ; W　退避
    SWAPF   HEX2_WRK,W  ; 上位4ビット
    ANDLW   0FH        ;
    SUBLW   09H   ; 09H   - W --> W
    BTFSC   STATUS,C    ; 9よりおおきいとCはOffで次をスキップ
    GOTO    HEX2_01     ; 上位4bit9以下
    ;　上位4bit　10以上
    SUBLW   40H
    GOTO    HEX2_02

HEX2_01 ; 上位4ビット 9以下
    SUBLW   39H

HEX2_02
    CALL    LCD_WRITE

    MOVF    HEX2_WRK,W
    ANDLW   0FH
     SUBLW   09H   ; 09H   - W --> W
    BTFSC   STATUS,C    ; 9よりおおきいとCはOffで次をスキップ
    GOTO    HEX2_03     ; 上位4bit9以下
    ;　上位4bit　10以上
    SUBLW   40H
    GOTO    HEX2_04

HEX2_03 ; 上位4ビット 9以下
    SUBLW   39H
HEX2_04
    GOTO    LCD_WRITE

;*********************************
;  Version 表示
;*********************************
VERDISP
    CALL    LCD_L1
    MOVLW   'V'
    CALL    LCD_WRITE
    MOVLW   'e'
    CALL    LCD_WRITE
    MOVLW   'r'
    CALL    LCD_WRITE
    MOVLW   '1'
    CALL    LCD_WRITE
    MOVLW   '.'
    CALL    LCD_WRITE
    MOVLW   '8'
    CALL    LCD_WRITE
    MOVLW   '1'
    GOTO    LCD_WRITE

;******************************************
;  判定メッセージ　「1を押してください」
;******************************************
PUSHONE
    CALL    LCD_L1      ; 1行め先頭
    MOVLW   '1'
    CALL    LCD_WRITE
    MOVLW   0A6H    ; ヲ
    CALL    LCD_WRITE
    MOVLW   ' '
    CALL    LCD_WRITE
    MOVLW   0B5H    ; オ
    CALL    LCD_WRITE
    MOVLW   0BCH    ; シ
    CALL    LCD_WRITE
    MOVLW   0C3H    ; テ
    CALL    LCD_WRITE
    MOVLW   0B8H    ; ク
    CALL    LCD_WRITE
    MOVLW   0C0H    ; タ
    CALL    LCD_WRITE
    MOVLW   0DEH    ; "
    CALL    LCD_WRITE
    MOVLW   0BBH    ; サ
    CALL    LCD_WRITE
    MOVLW   0B2H    ; ｲ
    GOTO    LCD_WRITE

;******************************************
; たぶん　メッセージ
;******************************************
TABUN
    MOVLW   0C0H    ; タ
    CALL    LCD_SWRITE
    MOVLW   0CCH    ; フ
    CALL    LCD_SWRITE
    MOVLW   0DEH    ; "
    CALL    LCD_SWRITE
    MOVLW   0DDH    ;ン
    GOTO    LCD_SWRITE
;******************************************
;  SHARPだろうメッセージ 12文字
;******************************************
SHARP_DARO
    CALL    LCD_L2      ; 2行め先頭
    CALL    TABUN
    MOVLW   'S'
    CALL    LCD_WRITE
    MOVLW   'H'
    CALL    LCD_WRITE
    MOVLW   'A'
    CALL    LCD_WRITE
    MOVLW   'R'
    CALL    LCD_WRITE
    MOVLW   'P'
    CALL   LCD_WRITE
    GOTO    SPACE2

;******************************************
;  HITACHIだろうメッセージ　12文字
;******************************************
HITACHI_DARO
    CALL    LCD_L2      ; 2行め先頭
    CALL    TABUN
    MOVLW   'H'
    CALL    LCD_WRITE
    MOVLW   'I'
    CALL    LCD_WRITE
    MOVLW   'T'
    CALL    LCD_WRITE
    MOVLW   'A'
    CALL    LCD_WRITE
    MOVLW   'C'
    CALL    LCD_WRITE
    MOVLW   'H'
    CALL    LCD_WRITE
    MOVLW   'I'
    CALL    LCD_WRITE
    GOTO    SPACE1

;******************************************
;  SONYだろうメッセージ　12文字
;******************************************
SONY_DARO
    CALL    LCD_L2      ; 2行め先頭
    CALL    TABUN
    MOVLW   'S'
    CALL    LCD_WRITE
    MOVLW   'O'
    CALL    LCD_WRITE
    MOVLW   'N'
    CALL    LCD_WRITE
    MOVLW   'Y'
    CALL    LCD_WRITE
    GOTO    SPACE4

;******************************************
;  PANASONICだろうメッセージ　13文字
;******************************************
PANA_DARO
    CALL    LCD_L2      ; 2行め先頭
    CALL    TABUN
    MOVLW   'P'
    CALL    LCD_WRITE
    MOVLW   'A'
    CALL    LCD_WRITE
    MOVLW   'N'
    CALL    LCD_WRITE
    MOVLW   'A'
    CALL    LCD_WRITE
    MOVLW   'S'
    CALL    LCD_WRITE
    MOVLW   'O'
    CALL    LCD_WRITE
    MOVLW   'N'
    CALL    LCD_WRITE
    MOVLW   'I'
    CALL    LCD_WRITE
    MOVLW   'C'
    GOTO    LCD_WRITE

;******************************************
;  わかんないメッセージ 12文字
;******************************************
WAKANNAI
    CALL    LCD_L2      ; 1行め先頭
    MOVLW  '('    ;
    CALL    LCD_SWRITE
    MOVLW   0A5H    ; ・
    CALL    LCD_SWRITE
    MOVLW   '_'    ;
    CALL    LCD_SWRITE
    MOVLW   0A5H    ; ・
    CALL    LCD_SWRITE
    MOVLW   ')'    ;
    CALL    LCD_WRITE
    MOVLW   0B4H    ; エ
    CALL    LCD_WRITE
    MOVLW   0AFH    ; ッ
    CALL    LCD_WRITE
    MOVLW   ' '
    CALL    LCD_WRITE
    MOVLW   '('
    CALL    LCD_WRITE
    MOVF    ERRCODE,W
    CALL    HEX2LCD
    MOVLW   ')'
    GOTO    LCD_WRITE

;--------------
; スペース
;--------------
SPACE8
    MOVLW   20H
    CALL    LCD_WRITE
SPACE7
    MOVLW   20H
    CALL    LCD_WRITE
SPACE6
    MOVLW   20H
    CALL    LCD_WRITE
SPACE5
    MOVLW   020H    
    CALL    LCD_WRITE
SPACE4
    MOVLW   20H
    CALL    LCD_WRITE
SPACE3
    MOVLW   20H
    CALL    LCD_WRITE
SPACE2
    MOVLW   20H
    CALL    LCD_WRITE
SPACE1
    MOVLW   20H
    GOTO    LCD_WRITE

;******************
;  ^_^
;******************
KAO
    MOVLW   '^'
    CALL    LCD_WRITE
    MOVLW   '_'
    CALL    LCD_WRITE
    MOVLW   '^'
    GOTO    LCD_WRITE
;*******************
; @_@
;*******************
KAO2
    MOVLW   '@'
    CALL    LCD_WRITE
    MOVLW   '_'
    CALL    LCD_WRITE
    MOVLW   '@'
    GOTO    LCD_WRITE

;***************
;  H_SPEED
;***************
H_SPEED
    MOVLW   88H     ; DDRAM ADDRESS 8　（一行め9文字目）セット
    CALL    LCD_EXE
;
    CALL    SPACE4
    MOVLW   'H'
    CALL    LCD_WRITE
    MOVLW   'i'
    CALL    LCD_WRITE
    MOVLW   'g'
    CALL    LCD_WRITE
    MOVLW   'h'
    GOTO    LCD_WRITE

;***************
;   50%
;**************
L_SPEED
    MOVLW   88H     ; DDRAM ADDRESS 8　（一行め9文字目）セット
    CALL    LCD_EXE

    CALL    SPACE5
    MOVLW   'L'
    CALL    LCD_WRITE
    MOVLW   'o'
    CALL    LCD_WRITE
    MOVLW   'w'
    GOTO    LCD_WRITE

;=======================================================================
;     LCD制御モジュール群
;=======================================================================
;+++++++++++++++++++++++++++++++++++++++++++++
;+        LCD初期化処理                     +
;+++++++++++++++++++++++++++++++++++++++++++++
LCD_INIT
    CALL	TIM_5ms	; 15ms以上待つ
	CALL	TIM_5ms
	CALL	TIM_5ms

    BCF    PORTA,LCD_RW  ; LCD 書き込みモード
    BCF    PORTA,LCD_RS  ; LCD 制御レジスタ選択
    BCF    PORTA,LCD_E   ; LCD disenable

	; 次のモジュールでRS RW D7 D6 D5 D4 D3 D2 D1 D0
	;                 0  0  0  0  1  1  *  *  *  *
        ; を3回セットする。

	MOVLW	30H
	MOVWF	PORTC		;ファンクションセット1回目
	BSF     PORTA,LCD_E
	NOP
    NOP			;
	BCF     PORTA,LCD_E

	CALL	TIM_5ms	; 4.1m秒以上待つ

	MOVLW	30H
	MOVWF	PORTC		;ファンクションセット2回目
	BSF     PORTA,LCD_E
	NOP
    NOP
	BCF     PORTA,LCD_E
	CALL	TIM_100us	; 100μ秒以上待つ

	MOVLW	30H
	MOVWF	PORTC		;ファンクションセット3回目
	BSF     PORTA,LCD_E
	NOP
    NOP
	BCF     PORTA,LCD_E
	CALL	TIM_100us

    MOVLW   20H     ; 4ビットモードセット
    MOVWF   PORTC
    BSF     PORTA,LCD_E
    NOP
    NOP
    BCF     PORTA,LCD_E

    MOVLW   28H     ; 2行表示、5×8ドット
    CALL    LCD_EXE

	MOVLW	08H	; Display Off
	CALL	LCD_EXE

	MOVLW	06H	;Entry Mode set
	CALL	LCD_EXE

	RETURN

;+++++++++++++++++++++++++++++++
; LCD COMMAND 実行
; 入力 W : (コマンド値）
;+++++++++++++++++++++++++++++++
LCD_EXE
    MOVWF   LCDWBF          ;データ退避
	CALL    LCD_BUSY		; Busy解除待ち(Wは壊れない）
	BCF     PORTA,LCD_E	; LCD EnableをOFFにする。
	BCF     PORTA,LCD_RW	; LCD 書き込みモード
	BCF     PORTA,LCD_RS	; LCD 0:COMMAND1:DATA

	MOVWF	PORTC		; 上位4ビット書き込み
	BSF     PORTA,LCD_E	; LCD EnableをONにする。
	NOP			; 220ns以上待つ
 	BCF     PORTA,LCD_E	; LCD EnableをOFFにする。
     
    SWAPF   LCDWBF,W
    MOVWF   PORTC   ; 下位4ビットを書き込み
    BSF     PORTA,LCD_E ; LCD EnableをONにする。
	NOP			; 220ns以上待つ
    BCF     PORTA,LCD_E ; LCD EnableをOFFにする。

    GOTO    LCD_BUSY

;+++++++++++++++++++++++++++++++
; LCD DATA　WRITE
; 入力 W : (データ値）
;+++++++++++++++++++++++++++++++
LCD_WRITE
    MOVWF   LCDWBF          ;データ退避
	CALL    LCD_BUSY		; Busy解除待ち(Wは壊れない）
	BCF     PORTA,LCD_E	; LCD EnableをOFFにする。
	BCF     PORTA,LCD_RW	; LCD 書き込みモード
	BSF     PORTA,LCD_RS	; LCD 0:COMMAND1:DATA

	MOVWF	PORTC		; 上位4ビット書き込み
	BSF     PORTA,LCD_E	; LCD EnableをONにする。
	NOP			; 220ns以上待つ
	BCF     PORTA,LCD_E	; LCD EnableをOFFにする。

    SWAPF   LCDWBF,W
    MOVWF   PORTC   ; 下位4ビットを書き込み
    BSF     PORTA,LCD_E ; LCD EnableをONにする。
	NOP			; 220ns以上待つ
    BCF     PORTA,LCD_E ; LCD EnableをOFFにする。

    GOTO    LCD_BUSY

;++++++++++++++++++++++++++++++
; LCD DATA SLOW WRITE
;  入力 W : (データ値)
;++++++++++++++++++++++++++++++
LCD_SWRITE
    MOVWF   LCDWBF          ; データ退避
    CALL    TIM_250ms
    MOVF    LCDWBF,W
    GOTO    LCD_WRITE

;+++++++++++++++++++++++++++++++
; LCD OFF
;+++++++++++++++++++++++++++++++
LCD_OFF
	MOVLW	08H
	GOTO	LCD_EXE

;+++++++++++++++++++++++++++++++
; LCD ON
;    表示ON カーソルはoff （カーソルonの場合は0EHを設定）
;+++++++++++++++++++++++++++++++
LCD_ON
	MOVLW	0CH
	GOTO	LCD_EXE

;+++++++++++++++++++++++++++++++
; LCD CLEAR
;+++++++++++++++++++++++++++++++
LCD_CLEAR
	MOVLW	01H
	CALL	LCD_EXE
    CALL    TIM_600us
    GOTO    TIM_1ms

;+++++++++++++++++++++++++++++++++++
; カーソルの位置を1行目の先頭にセット
;+++++++++++++++++++++++++++++++++++
LCD_L1  ;MSB=1 +DDRAMADDRESS(000 0000)
    MOVLW   80H
    GOTO    LCD_EXE

;+++++++++++++++++++++++++++++++++++
; カーソルの位置を2行目の先頭にセット
;+++++++++++++++++++++++++++++++++++
LCD_L2 ; MSB=1 +DDRAMADDRESS(100 0000)
    MOVLW   0C0H
    GOTO    LCD_EXE

;+++++++++++++++++++++++++++++++++++
; カーソルの位置を右シフト(つかってないけど）
;+++++++++++++++++++++++++++++++++++
LCD_RIGHT
    MOVLW   14H
    CALL    LCD_EXE
    GOTO    TIM_50us

;+++++++++++++++++++++++++++++++
; LCD Busy WAIT
;   LCDがBusyの間Waitする
;	W REGは壊さない！
;*******************************
LCD_BUSY
	MOVWF	LCDWRK		; W 待避
	BANKSEL  TRISC
	 MOVLW	0FFH		;
	 MOVWF	TRISC		; PORTCを入力に設定
	BANK0	;BANK0へ切り替え
	BCF     PORTA,LCD_E	; LCD EnableをOFFにする。
	BCF     PORTA,LCD_RS	; Control
	BSF     PORTA,LCD_RW	; Read mode

LCD_BUSY1
	BSF     PORTA,LCD_E	;
    NOP
	MOVF	PORTC,W
	MOVWF	LCDRBF
	BCF     PORTA,LCD_E	;
	BTFSS	LCDRBF,LCD_BSY
	GOTO	LCD_BUSY2	; NOT BUSY
	;BUSY
	GOTO	LCD_BUSY1
LCD_BUSY2
	BANKSEL TRISC	;BANK1へ切り替え
	 CLRF	TRISC		; PORTCを出力に設定
	BANK0	;BANK0へ切り替え

	MOVF	LCDWRK,W	; W 復帰
	RETURN

;======================================================================
; タイマーモジュール群
;======================================================================
; 命令1cycleは4クロック 4/8MHz=0.5μS
; CALLやRETURN、DECFSZのスキップするときなどPCLを変化させる命令は2cyles
; 他の命令は1cyles
; 上位モジュールのCALL命令も考慮するとn μS　のウエイトでセットするときの
; カウンタの初期値はloop(a)の場合　(n/0.5 - 10)/3+1
;                   loop(b)の場合
;************************
;   TIM_10us 10μ秒待ち
;************************
TIM_10us
    MOVLW   5       ;1
    MOVWF   CNT0    ;1
    DECFSZ  CNT0,F  ;1(2)
    GOTO    $-1     ;2
    RETURN          ;2

;************************
;  TIM_50us  50μ秒待ち
;************************
TIM_50us
	MOVLW	31      ;1
    MOVWF   CNT0    ;1
    DECFSZ  CNT0,F  ;1(2)
    GOTO    $-1     ;2
    GOTO    $+1     ;2
    RETURN          ;2

;***************************
; TIM_100us   100μ秒待ち
;***************************
TIM_100us  ;100 micro sec timer
	MOVLW	65      ;1
    MOVWF   CNT0    ;1
    DECFSZ  CNT0,F  ;1(2)
    GOTO    $-1     ;2
    RETURN          ;2

;****************************
; TIM_170us     170μ秒待ち
;****************************
TIM_170us
	MOVLW	111     ;1
    MOVWF   CNT0    ;1
    DECFSZ  CNT0,F  ;1(2)
    GOTO    $-1     ;2
    GOTO    $+1     ;2
    RETURN          ;2

;****************************
; TIM_220us     220μ秒待ち
;****************************
TIM_220us
	MOVLW	91H     ;1
    MOVWF   CNT0    ;1
    DECFSZ  CNT0,F  ;1(2)
    GOTO    $-1     ;2
    RETURN          ;2

;****************************
; TIM_275us     275μ秒待ち
;****************************
TIM_275us
	MOVLW	0B5H     ;1
    MOVWF   CNT0    ;1
    DECFSZ  CNT0,F  ;1(2)
    GOTO    $-1     ;2
    GOTO    $+1     ;2
    RETURN          ;2

;****************************
; TIM_300us     300μ秒待ち
;****************************
TIM_300us
	MOVLW	0C6H     ;1
    MOVWF   CNT0    ;1
    DECFSZ  CNT0,F  ;1(2)
    GOTO    $-1     ;2
    NOP             ;1
    RETURN          ;2

;****************************
; TIM_450us     450μ秒待ち
;****************************
TIM_450us
	MOVLW   0B7H     ;1
    MOVWF   CNT0    ;1
    GOTO    $+1     ;2
    DECFSZ  CNT0,F  ;1(2)
    GOTO    $-2     ;2
    RETURN          ;2

;****************************
; TIM_500us     500μ秒待ち
;****************************
TIM_500us
	MOVLW   0C7H     ;1
    MOVWF   CNT0    ;1
    GOTO    $+1     ;2
    DECFSZ  CNT0,F  ;1(2)
    GOTO    $-2     ;2
    RETURN          ;2

;****************************
; TIM_550us     550μ秒待ち
;****************************
TIM_550us
	MOVLW   0DBH     ;1
    MOVWF   CNT0    ;1
    GOTO    $+1     ;2
    DECFSZ  CNT0,F  ;1(2)
    GOTO    $-2     ;2
    RETURN          ;2

;****************************
; TIM_600us     600μ秒待ち
;****************************
TIM_600us
	MOVLW   0EFH     ;1
    MOVWF   CNT0    ;1
    GOTO    $+1     ;2
    DECFSZ  CNT0,F  ;1(2)
    GOTO    $-2     ;2
    RETURN          ;2

;****************************
; TIM_900us     900μ秒待ち
;****************************
TIM_900us
 	MOVLW   0C7H     ;1
    MOVWF   CNT0    ;1
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    DECFSZ  CNT0,F  ;1(2)
    GOTO    $-4     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    RETURN          ;2

;*************************
;  TIM_1ms  1m秒待ち
;*************************
TIM_1ms
 	MOVLW   0DDH     ;1
    MOVWF   CNT0    ;1
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    DECFSZ  CNT0,F  ;1(2)
    GOTO    $-4     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    RETURN          ;2

;+++++++++++++++++++++++++
;  TIM_5ms   5m秒待ち
;*************************
TIM_5ms
 	MOVLW   0D9H     ;1
    MOVWF   CNT0    ;1
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    NOP             ;1
    DECFSZ  CNT0,F  ;1(2)
    GOTO    $-23     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    NOP             ;1
    RETURN          ;2

;***************************
; TIM_10ms   10mS秒待ち
;***************************
TIM_10ms  ; 10mili sec timer
	CALL    TIM_5ms
	GOTO    TIM_5ms

;***************************
; TIM_50ms   50mS秒待ち
;***************************
TIM_50ms  ; 50mili sec timer
   	MOVLW	10
	MOVWF	CNT1
	CALL    TIM_5ms
	DECFSZ  CNT1,F
	GOTO    $-2
	RETURN

;***************************
; TIM_100ms   100mS秒待ち
;***************************
TIM_100ms  ; 100ms timer
	MOVLW	20
	MOVWF	CNT1
	CALL    TIM_5ms
	DECFSZ  CNT1,F
	GOTO    $-2
	RETURN

;***************************
; TIM_250ms   250mS待ち
;***************************
TIM_250ms  ; 250msec timer
	MOVLW	50
	MOVWF	CNT1
	CALL    TIM_5ms
	DECFSZ  CNT1,F
	GOTO    $-2
	RETURN

;***************************
; TIM_500ms   500mS待ち
;***************************
TIM_500ms  ; 500msec timer
	MOVLW	100
	MOVWF	CNT1
	CALL    TIM_5ms
	DECFSZ  CNT1,F
	GOTO    $-2
	RETURN

;***************************
; TIM_1S   1秒待ち
;***************************
TIM_1S  ; 1sec timer
	MOVLW	0C8H
	MOVWF	CNT1
	CALL    TIM_5ms
	DECFSZ  CNT1,F
	GOTO    $-2
    RETURN
    END