; http://monitor.net.ru/forum/nec-ir-decoder-attiny2313-lcd1110i-info-537446.html;
; grob übersetzt aus russisch
; Module für den Einsatz mit NEC IR -Fernbedienungen
; Das Ergebnis der Beendigung des Empfangs in
; vier Register Adresse L, H -Adresse , Daten Non-Inverted, Daten Inverted !
; Während die Taste , werden die Daten in den Registern gespeichert !
; wird über Interrupt ausgelöst, daher Anschluss von IR Pin an PD2!!!
; NEC DATA registers
.def bytei = R11 ; Inverted command byte
.def byten = R12 ; Normal command byte
.def adrh = R13 ; High Address
.def adrl = R14 ; Low Address
.def zero = R15 ; always = 0 !
.def tmp = R23 ; RON
.def flags_nec = R21 ; flags register
.def cnt = R22 ;
; all constants are true ms values !
.equ FCLK = XTAL ; global definierte Taktfrequenz, 16000000
.equ pre = 8 ; Preskaler Timer 1
.equ const = (FCLK / 10000) / pre ; 125 (1,25 real) 1 Timer-Tick 1,25 ms
.equ starth = (9000 * const) / 100 ; Die erste Prämisse 9,0ms
.equ startl = (4500 * const) / 100 ; zweite Prämisse 4,5ms
.equ log1 = (2250 * const) / 100 ; Empfang einer logischen 1 (2,250ms)
.equ restart = log1 ; Senden 4,5ms + 2.250ms = Wiederholungs
.equ log0 = (1125 * const) / 100 ; Empfangen einer logischen 0 (1,125ms)
.equ IRcL = (100 * const) / 100 ; Constant Fehler 100uS
.equ IRcH = (500 * const) / 100 ; Constant Fehler 200uS
.equ repeat = 65535 - ((110000 * const / / 100); Nach über 110 ms sendet die empfangenen Daten neu zu starten
;***********************************************************************************
IR_read: ; Register cnt,tmp,X,Z !
push tmp ; save tmp in STACK
in tmp,SREG ; Lesen Inhalt SREG in tmp
push tmp ; save tmp at STACK
push xl ; save XL at STACK
push xh ; save XH at STACK
push zl ; save ZL at STACK
push zh ; save ZH at STACK
cli ; disable interrupts
inc cnt ; INT0 counter + 1
cpi cnt,1 ; IF cnt = 1 -> goto IR_9ms
breq IR_9ms ; Reset T1, start counting , interrupt edge , catch 9ms !
cpi cnt,2 ; IF cnt = 2 -> goto IR_start
breq IR_start ; We accept Start 9 ms (+ - 200us) !
cpi cnt,3 ; IF cnt = 3 -> goto IR_repeat_OR_normal start !
breq IR_repeat ; Check the replay team! Or send the transmission data !
cpi cnt,4 ; IF cnt >= 4 -> goto IR_data
brsh GET_data ; that receives data
rjmp IR_error ; if 0 - interrupt exit
GET_data: ; escape transition
rjmp GET_IR_data ; receiving data 32 bits ! LSB first
IR_9ms: ;
in tmp,MCUCR ; MCUCR ist internes Register
ldi tmp,(1<<ISC01)|(1<<ISC00) ; INT0 - rising (0x03) (1<<ISC01)|(1<<ISC00)
;ori tmp,0x03 ;
out MCUCR,tmp ;
ldi flags_nec,0x01 ; Flags = 1
rcall read_T1 ; Z = TCNT1
rjmp IR_ok ; interrupt exit WAIT High level on INT0 !
IR_start: ; 9.136 ms NORMAL ! INT0 - rising cnt=1 !
in tmp,MCUCR ;
ldi tmp,(1<<ISC01)|(0<<ISC00) ; INT0 - falling (1<<ISC01)|(0<<ISC00)
;andi tmp,0xFC ;
;ori tmp,0x02 ;
out MCUCR,tmp ;
rcall read_T1 ; Z = TCNT1
ldi xl,byte1(starth-IRcH) ; load 9.000 ms - 200us
ldi xh,byte2(starth-IRcH) ;
cp zl,xl ; comparing TCNT1 with starth constant !
cpc zh,xh ;
brlo IR_error ; if it is less than 8.8 ms, then the error is not our protocol !
ldi xl,byte1(starth+IRcH) ; load 9.000 ms + 200us
ldi xh,byte2(starth+IRcH) ;
cp zl,xl ; comparing TCNT1 with starth constant !
cpc zh,xh ;
brsh IR_error ; if more than 9.25 ms, the error is not our protocol !
ldi flags_nec,0x02 ; Flags = 2
rjmp IR_ok ;
IR_repeat: ;
rcall read_T1 ; Z = TCNT1
ldi xl,byte1(restart-IRcL) ; 2.250 ms - 100us
ldi xh,byte2(restart-IRcL) ;
cp zl,xl ; comparing TCNT1 with starth constant !
cpc zh,xh ;
brlo IR_error ; if it is less than 8.8 ms, then the error is not our protocol !
ldi xl,byte1(restart+IRcL) ; 2.250 ms + 100us
ldi xh,byte2(restart+IRcL) ;
cp zl,xl ; comparing TCNT1 with starth constant !
cpc zh,xh ;
brsh IR_N_start ; If more than 2.375 ms then check the normal start
ldi flags_nec,0x03 ; Flags = 3 (REPEAT command)
rcall write_T1 ; T1 = f.osc / 64
rjmp IR_check ;
IR_N_start: ; NEC normal start 9 ms + 4.5 ms ! FLAGS = 3 !
ldi xl,byte1(startl-IRcH) ; load 4.500 ms - 200us
ldi xh,byte2(startl-IRcH) ;
cp zl,xl ; comparing TCNT1 with starth constant !
cpc zh,xh ;
brlo IR_error ; if it is less than 4.3 ms, then the error is not our protocol !
ldi xl,byte1(startl+IRcH) ; load 4.500 ms + 200us
ldi xh,byte2(startl+IRcH) ;
cp zl,xl ; comparing TCNT1 with starth constant !
cpc zh,xh ;
brsh IR_error ; if more than 4.7 ms, then the error is not our protocol !
ldi flags_nec,0x04 ; Flags = 4
IR_ok: ; Successful Reception
cpi cnt,35 ; the maximum number of interrupts sending remote = 35 ! Then, repeat 2 interrupt
brsh IR_check ; >= 35 - check the replay flag !
; IR ADDRESS CHECK !
ldi zl,low (IR_adr*2) ; IR address pointer
ldi zh,high(IR_adr*2) ;
lpm xl,z+ ; X = NEC IR ADR
lpm xh,z ; xl <-- ADRL, xh <-- ADRH
cp adrl,xl ;
cpc adrh,xh ;
brne IR_adr_err ; If it does not match with the specified at the program , the team at writing 255
Exit: ; marker label of interruption
pop zh ; extract ZH from STACK
pop zl ; extract ZL from STACK
pop xh ; extract XH from STACK
pop xl ; extract XL from STACK
pop tmp ; extract tmp from STACK
out SREG,tmp ; reestablish SREG
pop tmp ; extract tmp from STACK
; TEST NEC:
; Zwischenspeichern für LCD:
sts nec_adrl,adrl
sts nec_adrh,adrh
sts nec_flag_status,flags_nec
rcall _Update_LCD ; Ausgabe auf LCD
; Test ende
reti ; output from an external interrupt INT0
IR_adr_err: ; Error received address from the remote IR
;ser tmp ;
ldi tmp, 249 ; als debug
sts nec,tmp ; keep the operation at 255
rjmp Exit ; the output from the interrupt
IR_error: ; Not our protocol , a reception error !
clr cnt ; counter interrupt = 0
;ser tmp ;
ldi tmp, 111 ; als debug
mov bytei,tmp ; NEC IR Command_INV = FFH
mov byten,tmp ; NEC IR Command_Nor = FFH
mov adrh,tmp ; NEC IR Address High = FFH
mov adrl,tmp ; NEC IR Address Low = FFH
in tmp,MCUCR ;
ldi tmp,(1<<ISC01)|(0<<ISC00) ; INT0 - falling (1<<ISC01)|(0<<ISC00)
;andi tmp,0xFC ;
;ori tmp,0x02 ;
out MCUCR,tmp ;
ldi flags_nec,0b01000000 ; ERROR - 0x40, 0d64
out TCCR1B,zero ; STOP Timer1
out TCNT1H,zero ;
out TCNT1L,zero ; TCNT1=0
in tmp,TIFR ; tmp = TIFR
andi tmp,0xFD ; TOV1 --> 2 bit (FD)
out TIFR,tmp ; reset the overflow flag T1
rjmp Exit ; to the exit
IR_check: ; Checking the status of the console and addresses !!!
sts nec,byten ; retain command byte !
clr cnt ; ITNT0 counter = 0
cpi flags_nec,0x03 ; If the status = 0x03 then the received data
breq IR_ok ; got to OK
cpi flags_nec,0x05 ; If the status = 0x05 then the received data
breq IR_ok ; go to OK!
rjmp IR_error ; If checked , you will not erase the data
GET_IR_data: ; GET data
rcall read_T1 ; Z = TCNT1
IR_data_0: ; Receiving bit 0 (1.125ms)
ldi xl,byte1(log0-IRcL) ; load 1.125 ms - 100us
ldi xh,byte2(log0-IRcL) ;
cp zl,xl ; comparing TCNT1 with log0 constant !
cpc zh,xh ;
brlo IR_error ; if less than 1,025 is not our protocol error
ldi xl,byte1(log0+IRcL) ; load 1.125 ms + 100us
ldi xh,byte2(log0+IRcL) ;
cp zl,xl ; comparing TCNT1 with log0 constant !
cpc zh,xh ;
brsh IR_data_1 ; if more than 1,225 take the log 1
clc ;
lsr bytei ; DATA 32 bits = >> 1 LSB first
ror byten ;
ror adrh ;
ror adrl ;
ldi flags_nec,5 ; received bit 0 Flags = 5
rjmp IR_ok ; return
IR_data_1: ; Reception bit 1 (2,25ms)
ldi xl,byte1(log1-IRcL) ; load 2.25 ms - 100us
ldi xh,byte2(log1-IRcL) ;
cp zl,xl ; comparing TCNT1 with log0 constant !
cpc zh,xh ;
brlo IR_error ; if less than 2.15ms is not our protocol error
ldi xl,byte1(log1+IRcL) ; load 2.25 ms + 100us
ldi xh,byte2(log1+IRcL) ;
cp zl,xl ; comparing TCNT1 with log0 constant !
cpc zh,xh ;
brsh IR_error ; if more than 2.35ms is not our protocol error
ldi tmp,0b10000000 ; setting bit 7 at registers
clc ;
lsr bytei ; DATA 32 bits = >> 1 LSB first !
ror byten ;
ror adrh ;
ror adrl ;
or bytei,tmp ; DATA = | 1
ldi flags_nec,5 ; received bit 1 Flags = 5
rjmp IR_ok ; return
read_T1: ; We read the data and set Timer1 counter preskaler 8 !
in zl,TCNT1L ; Z = TCNT1
in zh,TCNT1H ; Low counter must be read FIRST !
out TCCR1B,zero ; STOP Timer1
out TCNT1H,zero ;
out TCNT1L,zero ; TCNT1=0
in tmp,TIFR ; tmp = TIFR
andi tmp,0xFD ; TOV1 --> 2 bit (FD)
out TIFR,tmp ; reset the overflow flag T1
ldi tmp,(1<<CS11) ; f.osc / 8
out TCCR1B,tmp ;
ret ; return
write_T1: ; Timer1 overflow through 110ms!
out TCCR1B,zero ; STOP Timer1
ldi zl,low (repeat) ;
ldi zh,high(repeat) ; Z = repeat ~(110ms)
out TCNT1H,zh ;
out TCNT1L,zl ; TCNT1=repeat
in tmp,TIFR ; tmp = TIFR
andi tmp,0xFD ; TOV1 --> 2 bit (FD)
out TIFR,tmp ; reset the overflow flag T1
ldi tmp,0x03 ; f.osc / 64
out TCCR1B,tmp ;
ret ; return
;************************;
; TIMER 1 Overflow ;
T1_ovf:
push tmp ; save tmp at STACK
in tmp,SREG ; read the contents of the SREG at tmp
push tmp ; save SREG at STACK
cli ; turn off interrupts
clr cnt ; CNT = 0
clr flags_nec ; FLAGS = 0
out TCCR1B,zero ; STOP Timer1
out TCNT1H,zero ;
out TCNT1L,zero ; TCNT1=0
in tmp,TIFR ; tmp = TIFR
andi tmp,0xFD ; TOV1 --> 2 bit (FD)
out TIFR,tmp ; reset the overflow flag T1
ser tmp ;
sts nec,tmp ; RAM NEC IR Command_Nor = FFH
mov bytei,tmp ; NEC IR Command_INV = FFH
mov byten,tmp ; NEC IR Command_Nor = FFH
mov adrh,tmp ; NEC IR Address High = FFH
mov adrl,tmp ; NEC IR Address Low = FFH
pop tmp ; extract tmp from STACK
out SREG,tmp ; restore SREG
pop tmp ; extract tmp from STACK
reti ; output from the interrupt T1_ovf
; END of NEC IR_receiver code
; NEC IR Address L H ;
IR_adr: .db 0x0A,0xF1 ; Remote Address first byte , second byte
Alles anzeigen