📄 ir_controller.asm
字号:
pgm_mode
movlw d'4'
movwf COUNT
rg_flash
LED_red ; flash bicolor LED alternately green/red
call delay_t6 ; (either for 250 ms) 4 times to indicate
LED_grn ; that the program mode has been entered
call delay_t6
decfsz COUNT
goto rg_flash
LED_off ; now ready to learn codes (LED off)
learn_1
call ir_chk1 ; wait for high level at IR_C_out, timeout if idle for > 5s
call rc5_rx ; call rc5_rx subroutinee
btfsc RC5_Flag ; RC5 code OK?
goto learn_1 ; no, try again
movfw RC5_CMD ; copy RC5_CMD to w and
andlw b'01111111' ; clear toggle bit
movwf TMP1 ; copy to TMP1 and TMP2
movwf TMP2 ;
bsf status,c ; check if command is 0...9
sublw d'9'
btfss status,c
goto learn_1 ; no, try again
LED_grn ; turn on green LED for 250ms if a
call delay_t6 ; valid code has been received
LED_off
movfw RC5_CMD ; copy RC5_CMD to temporary register
movwf RC5_CMD_TMP ; for the next toggle bit comparison
bcf status,c ; multiply TMP1 by 10
rlf TMP1,f ; for 10's of PWR_ON_DELAY
rlf TMP1,f
rlf TMP1,f
movfw TMP2
addwf TMP1,f
addwf TMP1,f
learn_2
call ir_chk1 ; wait for high level at IR_C_out, timeout if idle for > 5s
call rc5_rx ; call rc5_rx subroutine
btfsc RC5_Flag ; RC5 code OK?
goto learn_2 ; no, try again
movfw RC5_CMD ; check if toggle bit has changed
subwf RC5_CMD_TMP,w ;
btfsc status,z ;
goto learn_2 ; no, try again
movfw RC5_CMD ; copy RC5_CMD to w and
andlw b'01111111' ; clear toggle bit
movwf TMP2 ; copy to TMP2
bsf status,c ; check if command is 0...9
sublw d'9' ;
btfss status,c ;
goto learn_2 ; no, try again
movfw TMP1 ; add 10's and 1's
addwf TMP2,w ;
movwf EEDATA_TMP ; copy to EEDATA_TMP
movlw h'00' ; set EEADR_TMP to h'00'
movwf EEADR_TMP ;
call write_ee ; and write to EEPROM
LED_grn ; turn on green LED for 250ms if a
call delay_t6 ; valid code has been received
LED_off
movfw RC5_CMD ; copy RC5_CMD to temporary register
movwf RC5_CMD_TMP ; for the next toggle bit comparison
learn_3
call ir_chk1 ; wait for high level at IR_C_out, timeout if idle for > 5s
call rc5_rx ; call rc5_rx subroutine
btfsc RC5_Flag ; RC5 code OK?
goto learn_3 ; no, try again
movfw RC5_CMD ; check if toggle bit has changed
subwf RC5_CMD_TMP,w ;
btfsc status,z ;
goto learn_3 ; no, try again
movfw RC5_CMD ; copy RC5_CMD to w and
andlw b'01111111' ; clear toggle bit
bcf status,c ; check if command is 0...9
sublw d'9' ; which can not be assigned
btfsc status,c ; as pwr_key
goto learn_3 ; yes, try again
movfw RC5_ADR
movwf EEDATA_TMP ; copy to EEDATA_TMP
movlw h'01' ; set EEADR_TMP to h'01'
movwf EEADR_TMP ;
call write_ee ; and write to EEPROM
movfw RC5_CMD ; copy RC5_CMD to w and
andlw b'01111111' ; clear toggle bit
movwf EEDATA_TMP ; copy to EEDATA_TMP
movlw h'02' ; set EEADR_TMP to h'02'
movwf EEADR_TMP ;
call write_ee ; and write to EEPROM
call copy_ee ; copy new values to RAM
LED_grn ; turn on green LED for 250ms to indicate
call delay_t6 ; that a valid code has been received
LED_off
clrf KEYCOUNT_1 ; clear KEYCOUNT_1 to reset zero key detection delay
goto main_loop
ir_chk1 ; wait for high level at IR_C_out, timeout if idle for > 5s
clrf tmr1h ; clear timer1 registers
clrf tmr1l
movlw d'19' ; set COUNT to d'19', this makes 19 x 262ms = approx. 5 seconds
movwf COUNT
ir_chk2
btfsc IR_C_out ; wait for high level at IR_C_out
return ; and return
btfsc tmr1h,7 ; check timer1 h register bit 7 (set after 262ms)
goto dec_cnt
goto ir_chk2
dec_cnt
clrf tmr1h ; clear timer1 registers
clrf tmr1l
decfsz COUNT,f
goto ir_chk2 ; not yet 5s, loop
clrf KEYCOUNT_1 ; clear KEYCOUNT_1 to reset zero key detection delay
goto main_loop ; timeout after approx. 5s
;**************************************************************************************************
; RC5 transmit subroutine
;**************************************************************************************************
rc5_tx ; we have: RC5 address '000AAAAA' and command '0CCCCCCC'
bsf RC5_TX_2,7 ; set 1st start bit
btfss RC5_TX_1,6 ; check command bit #6 and
bsf RC5_TX_2,6 ; set 2nd start bit if necessary
bcf status,c ; clear carry bit
rlf RC5_TX_1 ; left shift RC5_TX_1 twice to bring command MSB to
bcf status,c ; left-most position
rlf RC5_TX_1 ; now the 16-bit shift register is ready for
; shifting out: RC5_TX_2 1S0AAAAA RC5_TX_1 CCCCCC00
bsf IRin ; set port register bit IRin high before setting to output
Bank_1 ; to avoid a 1祍 spike
bcf IRinTris ; set IRin as output
Bank_0 ;
call delay_t6 ; 250ms delay for time decoupling (LIRC might still be busy with
; processing IR codes from the receiver and would not react to the
; the code generated below)
movlw d'14' ; set BITCOUNT to 14
movwf BITCOUNT ;
bit_test
btfss RC5_TX_2,7 ; test all bits
goto out_low_high ; remember that we have to invert them
out_high_low
bsf IRin ; output a high-low sequence at IRin
call delay_t5 ; either state is 889祍
bcf IRin ;
call delay_t5 ;
goto next_bit ; goto next_bit
out_low_high
bcf IRin ; output a low-high sequence at IRin
call delay_t5 ; either state is 889祍
bsf IRin ;
call delay_t5 ;
next_bit
rlf RC5_TX_1 ; left shift the 16-bit register
rlf RC5_TX_2 ;
decfsz BITCOUNT ; until all 14 bits are out
goto bit_test ;
btfss IRin ; if the last bit was a high-low sequence, immediately set IRin
bsf IRin ; high to terminate the RC5 code after the correct time
call delay_t6 ; 250ms delay for time decoupling (IR codes from the receiver chip
; occuring directly after the code generated above would destroy
; the integrity of this code)
Bank_1
bsf IRinTris ; set IRin to input again
Bank_0
return
;**************************************************************************************************
; RC5 receive routine
;**************************************************************************************************
;
; in: 14 bit data from IRin resp. DTRin
;
; out: RC5_ADR (8 bit, 000AAAAA)
; RC5_CMD (8 bit, TCCCCCCC)
; RC5_Flag (1 bit) 0: RC5 code valid, 1: RC5 code invalid
;
; Self-synchronizing code which tolerates inaccurate RC5 timings.
; Tolerance is achieved by polling +/- approx. 250祍 around each expected level change. To mark the
; received code as valid, the level before and after the edges must be opposite, no timer0 overflow
; (512祍) occurred, and two samples taken at 1200祍 and 1500祍 after each edge must be equal.
rc5_rx
clrf DATA_1 ; clear input shift register
clrf DATA_2 ;
movlw d'13' ; set BITCOUNT to 13
movwf BITCOUNT ;
test ; 1祍 mark
call delay_t1a ; 1520祍 delay until approx. 256 祍 before next expected slope
call delay_t1b
pre_slope
test ; 1祍 mark
clrf tmr0 ; clear timer0 register
bcf intcon,t0if ; clear timer0 interrupt flag
btfss IR_C_out ; IR_C_out high?
goto poll_lo_hi ;
poll_hi_lo
btfsc intcon,t0if ; check for timer0 overflow (after 512祍)
goto set_flag ; and set 'invalid' flag
btfsc IR_C_out
goto poll_hi_lo
goto next_bit1
poll_lo_hi
bsf DATA_1,0 ; set lsb in DATA_1
btfsc intcon,t0if ; check for timer0 overflow (after 512祍)
goto set_flag ; and set 'invalid' flag
btfss IR_C_out
goto poll_lo_hi
next_bit1
decfsz BITCOUNT,1 ; if 0: all 14 bits received (1st was used for
goto shift ; trigger and has not been recorded); do not
goto cleanup ; shift any further and go on with cleanup
shift
bcf status,c ; clear carry bit
rlf DATA_1,1 ; left shift the 16-bit register DATA_2/DATA_1
rlf DATA_2,1 ;
call delay_t1a ; aquire sample #1
clrf DATA_TMP1 ; clear temporary register
btfss IR_C_out ; IR_C_out low?
bsf DATA_TMP1,0 ; then set lsb in DATA_TMP1
call delay_t1b ; aquire sample #2
clrf DATA_TMP2 ; clear temporary register
btfss IR_C_out ; IR_C_out low?
bsf DATA_TMP2,0 ; then set lsb in DATA_TMP2
check ; check if samples are equal
movfw DATA_TMP1 ; copy DATA_1 to w,
andlw b'00000001' ; keep only lsb in w,
xorwf DATA_TMP2,0 ; xor LSBs of DATA_TMP2 and w,
btfss status,z ; if not equal discard data and
goto set_flag ; goto set_flag -- no valid code has been received
goto pre_slope ; and loop
cleanup ; collected so far: DATA_2 000STAAA DATA_1 AACCCCCC
movfw DATA_1 ; copy DATA_1 to w
andlw b'00111111' ; clear bits 6 and 7
movwf RC5_CMD ; copy w to RC5_CMD
btfsc DATA_2,3 ; toggle bit is 0?
bsf RC5_CMD,7 ; if not, set bit 7 of RC5_CMD
btfss DATA_2,4 ; 2nd start bit is 1?
bsf RC5_CMD,6 ; if not, set bit 6 of RC5_CMD (extended RC5)
rlf DATA_2 ; left shift two times
rlf DATA_2 ;
movfw DATA_2 ; copy DATA_2 to w
andlw b'00011100' ; clear 3 MSB and 2 LSB
movwf RC5_ADR ; and copy to RC5_ADR
btfsc DATA_1,6 ; address bit 0 is 0?
bsf RC5_ADR,0 ; if not, set bit 0 of RC5_ADR
btfsc DATA_1,7 ; address bit 1 is 0?
bsf RC5_ADR,1 ; if not, set bit 1 of RC5_ADR
; now we have: RC5_ADR 000AAAAA RC5_CMD TCCCCCCC
bcf RC5_Flag ; clear RC5_Flag -- valid code has been received
return
set_flag
bsf RC5_Flag ; set RC5_Flag -- no valid code has been received
return
;**************************************************************************************************
; EEPROM read/write subroutines
;**************************************************************************************************
write_ee
Bank_0
movfw EEADR_TMP ; copy EEADR_TMP to eeadr
Bank_1
movwf eeadr
Bank_0
movfw EEDATA_TMP ; copy EEDATA_TMP to eedata
Bank_1
movwf eedata
bsf eecon1,wren ; enable write
movlw h'55' ; eeprom write unlock sequence
movwf eecon2 ;
movlw h'aa' ;
movwf eecon2 ;
bsf eecon1,wr ; write
w_ready
btfsc eecon1,wr ; write completed?
goto w_ready ;
Bank_0
return
;--------------------------------------------------------------------------------------------------
copy_ee ; reads address and command for assigned remote power key
; and turn on delay value from EEPROM and copies them to
; the RAM registers PWR_KEY_ADR, PWR_KEY_CMD, and PWR_ON_DELAY
Bank_1
movlw h'00'
movwf eeadr
bsf eecon1, rd
movfw eedata
Bank_0
movwf PWR_ON_DELAY
Bank_1
movlw h'01'
movwf eeadr
bsf eecon1, rd
movfw eedata
Bank_0
movwf PWR_KEY_ADR
Bank_1
movlw h'02'
movwf eeadr
bsf eecon1, rd
movfw eedata
Bank_0
movwf PWR_KEY_CMD
return
;**************************************************************************************************
; Delay routines (1 cycle equals 1祍 @ 4MC oscillator frequency)
;**************************************************************************************************
delay_t1a ; total: 1200 cycles
movlw 0xEE ; 1193 cycles
movwf d1
movlw 0x01
movwf d2
delay_t1a_0
decfsz d1, f
goto $+2
decfsz d2, f
goto delay_t1a_0
goto $+1 ; 3 cycles
nop
return ; 4 cycles (including call)
;----------------------------------------------------------
delay_t1b ; total: 320 cycles
movlw 0x69 ; 316 cycles
movwf d1
delay_t1b_0
decfsz d1, f
goto delay_t1b_0
return ; 4 cycles (including call)
;----------------------------------------------------------
delay_t2 ; total: 500 cycles
movlw h'A5' ; 496 cycles
movwf D1
delay_5
decfsz D1,f
goto delay_5
return ; 4 cycles (including call)
;----------------------------------------------------------
delay_t3 ; total: 1255 cycles
movlw h'F9' ; 1248 cycles
movwf D1
movlw h'01'
movwf D2
delay_6
decfsz D1,f
goto $+2
decfsz D2,f
goto delay_6
goto $+1 ; 3 cycles
nop
return ; 4 cycles (including call)
;----------------------------------------------------------
delay_t4 ; total: 50000 cycles
; 49993 cycles
movlw h'0E'
movwf D1
movlw h'28'
movwf D2
delay_7
decfsz D1,f
goto $+2
decfsz D2,f
goto delay_7
goto $+1 ; 3 cycles
nop
return ; 4 cycles (including call)
;----------------------------------------------------------
delay_t5 ; total: 886 cycles
movlw h'AF' ; 878 cycles
movwf D1
movlw h'01'
movwf D2
delay_8
decfsz D1,f
goto $+2
decfsz D2, f
goto delay_8
goto $+1 ; 4 cycles
goto $+1
return ; 4 cycles (including call)
;----------------------------------------------------------
delay_t6 ; total: 250000 cycles
movlw h'4E' ; 249993 cycles
movwf D1
movlw h'C4'
movwf D2
delay_9
decfsz D1,f
goto $+2
decfsz D2, f
goto delay_9
goto $+1 ; 3 cycles
nop
return ; 4 cycles (including call)
;----------------------------------------------------------
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -