;###################################################################
;   リモコンプログラム  2013.03.09 　Ver0.03
;          Koji Karasawa
;
;  Ver0.01  2013.03.08  ブレーキ送信以外は成功
;  Ver0.02  2013.03.09  保存版　スイッチを離したときはSTOPを3回送る
;                          スイッチの状態のコードを連続3回送る
;  Ver0.03  2013.03.09  4MHz 省エネ版  (保存版）
;
; スイッチONの時 信号 Low
;   RA0 : 送信用赤外線LEDポート
;   RB2 : 右正転（前進）
;   RB3 : 右逆転(後進)
;   RB4 : リフトup
;   RB5 : リフトdown
;   RB6 : 左正転（前進）
;   RB7 : 左逆転(後進）
;   RE3 : スイッチ ONのときL (MCLRリセット用に使用予定）
;
;----------------------------------
;   b6  and b4  同時 L のときスピードHigh
;   b7  and b5  同時 L のときスピードLow
;  CPU　クロック  8MHz
;
;####################################################################

    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

;*********制御ビット************


;RDF     EQU 7   ;   リモンコンRC_MAKER 検出フラグ

;
    CBLOCK	020H
            W_SAVE      ; Wレジスタ退避用（割り込み）
            S_SAVE      ; STATUSレジスタ退避用(割り込み）
            PL_SAVE     ; PCLATH退避(割り込み）
            FS_SAVE     ; FSR退避(割り込み）
            CNT0        ; カウントレジスタ
            CNT1        ;
            CNT2        ;
            BCNT1       ; ビット用カウンタ
            INBUF       ; 入力バッファ RB7〜RB2のスイッチONのとき
                        ; ビットがON
            OUTBUF1     ; 送信用バッファ1
            OUTBUF2     ; 送信用ワーク（シフトされて壊れる）
            OUTBUF1_OLD ; OUTBUF1の1つ前のデータ
            TCNT        ; 送信用カウンタ
    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


;===================================
;　割り込み処理 (このプログラム割り込み使わない)
;===================================
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


;
;   割り込み処理をここに記述する。
;


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	;	割り込み許可で戻る


;**************************************
; 初期処理
;**************************************
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   0FCH
    MOVWF   TRISB   ; RB0,1のみ出力、残りは入力
    CLRF    TRISC   ; PORTC　すべて出力
    MOVLW   08H
    MOVWF   TRISE   ; RE3のみ入力
    BANK1
    MOVLW   64H     ; 内部クロック4MHzの設定
    MOVWF   OSCCON

    BANK0
    MOVLW   3
    MOVWF   TCNT    ; 送信カウンタ初期値
;

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


;*****************************
;   コマンドループ
;*****************************

MAIN_LOOP
    COMF    PORTB,W  ; 入力チェック
    ANDLW   0FCH
    BTFSC   STATUS,Z
    GOTO    MAIN_2  ; スイッチ押下なし、チャタ防止を飛ばす

    CALL    TIM_10ms    ;チャタリング防止の時間稼ぎ
    CALL    TIM_10ms
    CALL    TIM_10ms

MAIN_2
    COMF    PORTB,W  ; 再度入力チェック
    ANDLW   0FCH
    MOVWF   INBUF   ; スイッチの状態を入力バッファに入れる

    CALL    I2H_CODE  ; INBUF--> OUTBUT  コードへ変換

    MOVF    OUTBUF1,W
    SUBWF   OUTBUF1_OLD,W
    BTFSC   STATUS,Z
    GOTO    MAIN_3
;    OUTBUF1 <>  OUTBUF1_OLD
    MOVLW   3
    MOVWF   TCNT
MAIN_3
    MOVF    TCNT,W
    SUBLW   0
    BTFSC   STATUS,Z
    GOTO    MAIN_4  ; TCNTの値が0なら下の処理カット
    DECF    TCNT,F  ; TCNT -1 --> TCNT
    CALL    HEADER_BIT  ; ヘッダー送信
    CALL    DATA_BIT    ; データ送信
    COMF    OUTBUF1,F
    CALL    DATA_BIT
;
    CALL    ZERO_BIT   ; なぜか最後にダメ押しの１ビット送信する

    COMF    OUTBUF1,W
    MOVWF   OUTBUF1_OLD

MAIN_4

    CALL    TIM_100ms
    CALL    TIM_100ms
;    CALL    TIM_100ms

    GOTO MAIN_LOOP



;*******************************************************
; I2H_CODE
;  入力 INBUF  (スイッチ　ON のビットが1になっている）
;  出力 OUTBUF1  ( 日立リモコン用の送信データ)
;*******************************************************
I2H_CODE
;--------- ここからスイッチの入力状態チェック
    BTFSS   INBUF,4
    GOTO    B5CHK
    ; b4 ON
    BTFSS   INBUF,6
    GOTO    B4ONLY
    ; b4 ON ,b6 ON  スピードHigh
    MOVLW   19H
    GOTO    CHKEND

B4ONLY    ; b4 のみon フォークアップ
    MOVLW   12H
    GOTO    CHKEND

B5CHK   ; b5　のチェック
    BTFSS   INBUF,5
    GOTO    B2CHK
    ; b5 on
    BTFSS   INBUF,7
    GOTO    B5ONLY
    ; b5,b7 on スピードLow
    MOVLW   18H
    GOTO    CHKEND

B5ONLY   ; b5 のみon フォークダウン
    MOVLW   15H
    GOTO    CHKEND

B2CHK   ; b2 のチェック
    BTFSS   INBUF,2
    GOTO    B3CHK
    BTFSS   INBUF,6
    GOTO    B7CHK1
    ; b2,b6 on   前進
    MOVLW   1DH
    GOTO    CHKEND
B7CHK1
    BTFSS   INBUF,7
    GOTO    B2ONLY
    ; b2,b7 on 反時計まわり
    MOVLW   1FH
    GOTO    CHKEND

B2ONLY  ; b2　のみON 左前進
    MOVLW   1CH
    GOTO    CHKEND

B3CHK
    BTFSS   INBUF,3
    GOTO    B6CHK
    BTFSS   INBUF,6
    GOTO    B7CHK2
    ; b3,b6 on 時計回り
    MOVLW   05H
    GOTO    CHKEND

B7CHK2
    BTFSS   INBUF,7
    GOTO    B3ONLY
    ; b3,b7 ON  後進
    MOVLW   07H
    GOTO    CHKEND

B3ONLY  ; b3　のみON  左後進
    MOVLW   06H
    GOTO    CHKEND

B6CHK
    BTFSS   INBUF,6
    GOTO    B7CHK3
    ; b6 のみON 右前進
    MOVLW   1EH
    GOTO    CHKEND

B7CHK3
    BTFSS   INBUF,7
    GOTO    NO_BIT
    ; b7 のみon  右後進
    MOVLW   0CH
    GOTO    CHKEND

NO_BIT ; なにも立っていない。
    MOVLW   0
    GOTO    CHKEND

CHKEND
    MOVWF   OUTBUF1  ; 出力バッファに格納
    RETURN


;**********************************************
;  DATA_BIT  日立データ１バイト送信
;    入力   OUTBUF
;    OUTBUF をLSBからMSBまで順に送信
;*********************************************
DATA_BIT
    MOVF    OUTBUF1,W
    MOVWF   OUTBUF2   ; 送信用ワーク

    MOVLW   8
    MOVWF   TCNT

DATA_BLP
    RRF     OUTBUF2,F
    BTFSS   STATUS,C
    GOTO    $+3
; 1 送信
    CALL    ONE_BIT
    GOTO    $+2
; 0 送信
    CALL    ZERO_BIT
    DECFSZ  TCNT,F
    GOTO    DATA_BLP
    RETURN



;**************************************
; 赤外線信号ONのときの変調
;   Wの回数分 13usON,13usOffを繰り返す
;  入力 W　回数 最大255
;  ワークCNT2
;**************************************
IR_ON
    MOVWF   CNT2
IR_ON1
    BSF     PORTA,0 ;1
    GOTO    $+1      ;2
    GOTO    $+1      ;2
    GOTO    $+1      ;2
    GOTO    $+1      ;2
    GOTO    $+1      ;2
    GOTO    $+1      ;2
;    NOP

    BCF     PORTA,0
    GOTO    $+1      ;2
    GOTO    $+1      ;2
    GOTO    $+1      ;2
    GOTO    $+1      ;2
    GOTO    $+1      ;2
;    GOTO    $+1      ;2
    DECFSZ  CNT2,F
    GOTO    IR_ON1
    RETURN

;************************************
;  ヘッダー　（日立リモコン仕様）
;************************************
HEADER_BIT
   ;  9ms  ON
    MOVLW   100
    CALL    IR_ON
    MOVLW   246
    CALL    IR_ON
; 4.5ms OFF
    BCF     PORTA,0
    CALL    TIM_1ms
    CALL    TIM_1ms
    CALL    TIM_1ms
    CALL    TIM_1ms
    CALL    TIM_500us

    CALL    ZERO_BIT
    CALL    ZERO_BIT
    CALL    ZERO_BIT
    CALL    ZERO_BIT
;
    CALL    ONE_BIT
    CALL    ZERO_BIT
    CALL    ONE_BIT
    CALL    ZERO_BIT
;
    CALL    ONE_BIT
    CALL    ONE_BIT
    CALL    ONE_BIT
    CALL    ONE_BIT
;
    CALL    ZERO_BIT
    CALL    ONE_BIT
    CALL    ZERO_BIT
    CALL    ONE_BIT
;
    RETURN


;**************************************
;  コード0　　（日立リモコン仕様）
;      0.55ms H   0.55ms  L
;**************************************
ZERO_BIT
    MOVLW    21
    CALL    IR_ON
    BCF     PORTA,0
    GOTO    TIM_550us


;**************************************
;  コード1　　（日立リモコン仕様）
;   0.55ms  H   1.65ms  L
;**************************************
ONE_BIT
    MOVLW   21
    CALL    IR_ON
    BCF     PORTA,0
    CALL    TIM_1ms
    GOTO    TIM_550us

;======================================================================
; タイマーモジュール群
;======================================================================
; 命令1cycleは4クロック 4/4MHz=1μS
; CALLやRETURN、DECFSZのスキップするときなどPCLを変化させる命令は2cyles
; 他の命令は1cyles
; 
;
;************************
;   TIM_10us 10μ秒待ち
;************************
TIM_10us             ; CALL で2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    RETURN          ;2
;************************
;   TIM_13us  13μ秒待ち
;************************
TIM_13us    ; CALLで2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    GOTO    $+1     ;2
    NOP             ;1
    RETURN          ;2
;************************
;  TIM_50us  50μ秒待ち
;************************
TIM_50us             ;2
	MOVLW	15      ;1
    MOVWF   CNT0    ;1
    DECFSZ  CNT0,F  ;1(2)
    GOTO    $-1     ;2
    RETURN          ;2

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


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


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

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


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


;+++++++++++++++++++++++++
;  TIM_5ms   5m秒待ち
;*************************
TIM_5ms
 	MOVLW   192     ;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
    NOP             ;1
    DECFSZ  CNT0,F  ;1(2)
    GOTO    $-13    ;2
    NOP             ;1
    NOP             ;1
    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
    CALL    TIM_5ms
    CALL    TIM_5ms
    CALL    TIM_5ms
    CALL    TIM_5ms
    CALL    TIM_5ms
    CALL    TIM_5ms
    CALL    TIM_5ms
    CALL    TIM_5ms
    CALL    TIM_5ms
    GOTO    TIM_5ms


;***************************
; 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
