.EQU	Nec = 1
.EQU 	Adresse_vergleichen = 0 ;kommentieren um Vergleich auszublenden
;-------------------Nec
.ifdef Nec
.EQU	IR_Haeder = 0x43
.EQU	IR_Repeat = 0x42
.EQU	IR_Bits   = 32
.EQU	IR_Rep_all = 4
.endif
;-------------------Sony
.ifdef Sony
.EQU	IR_Haeder  = 0x32
.EQU	IR_Repeat  = 0x00
.EQU	IR_Bits    = 16
.EQU	IR_Rep_all = 2
.endif
;__________________________________________________________________
.EQU	Nec_Adresse_H = 0x01
.EQU	Nec_Adresse_L = 0xfe
.equ	IR_Rep_keys = 4 ; 4 Tasten mit repeat Funktion
IR_Repeat_Tab:	.db 0xEF,0xF7,0xC7,0xFF

;___________________IR_Variabeln___________________________________
.dseg
TCNT0_H:	.byte 1
TCNT0_old:	.byte 1
TCNT0_H_old:	.byte 1
IR_Cnt:	.byte 1
IR_Paar:	.byte 1
IR_Status:	.byte 1


;Status Bit0 = 1 Adresse und Daten empfanfen
.EQU	data2snd    =0
;Status Bit1 = 1 eneble Bits schieben
.EQU	move_bits   =1
;Status Bit2 = 1 skip stuff
.EQU	skip_stuff  =2
;Status Bit3 = 1 Haeder ist valide
.EQU	haeder_got  =3
;Status Bit4 = 1 Repeat wurde empfangen
.EQU	repeat_got  =4
;Status Bit7 = 1 Tastencode ist in der IR_Repeat_Tab
.EQU	repeat_eneb =7


IR_Byte_1:	.byte 1	
IR_Byte_2:	.byte 1
IR_Byte_3:	.byte 1	
IR_Byte_4:	.byte 1
Bits:	.byte 1
;------------------ Variabeln für Simulation ----------------------
.ifdef debug
Time_Dump_H:	.byte 1 
Time_Dump_L:	.byte 1 
.endif
.cseg
;-------------------Int 0 Interrupt Routine ------------------------
INT0_:	push r0	;Register auf Stack
	in   r0, SREG
	push r0
	push r16
	push r17
	push r18
	push r19
	push r20
	push zl
	push zh

	in r16,TCNT0        ;Timer neu nach R17:r16
	lds r17,TCNT0_H
	lds r18,TCNT0_old   ;Timer alt nach r19:r18
	lds r19,TCNT0_H_old
	sts TCNT0_old,r16
	sts TCNT0_H_old,r17
	sub r16,r18         ;Pulsdauer = Timer neu - Timer alt
	sbc r17,r19	;in r16:r17

.ifdef debug	;Pulsdauer aus IR_Dump laden
		lds zh,Time_Dump_H
		lds zl,Time_Dump_L
		lpm r16,z+
		lpm r17,z+
		sts Time_Dump_H,zh
		sts Time_Dump_L,zl


	
.endif
;------------------ Token suchen ------------------------------------
	lds r19,IR_cnt	;Pulszähler nach r19
	mov r0,r16	;Pulsdauer Low nach r0 kopieren
	ldi r20,0	;Tokenzähler auf 0

	ldi zh,high(2*IR_Tab) ;Zeiger auf Vergleichstabelle
	ldi zl,low (2*IR_Tab)

	tst r17 	;Pulsdauer high = 0 ?
	breq IR_search	;ja dann mit den zahlen bis Low_size vergleichen
	ldi r20,IR_Low_size ;Tokenzähler auf Vergleichstabelle high
	subi zl,256-IR_Low_size ;Zeiger "+" Low_size
	brcs PC+2	;Zeiger high falls nötig mit "addieren"
	dec zh
IR_search:	lpm r18,z+	;Vergleichswert aus Tabelle nach r18
	cpi r20,IR_Low_size ;Low oder High Tabelle ?
	brlo skip_high	;springe falls High Tabelle abgesucht wird
	mov r0,r17	;falls high Tome high nach r0 kopieren
skip_high:	cp r0,r18	;zeit mit Tabellenwert vergleichen
	brlo gen_IR_Paar	;wenn kleiner dann Token ggefunden
	inc r20	;sonst Token +1
	cpi r20,IR_High_size+1 ;Tabellenende erreicht ?
	brlo IR_search	;nein, dann weitersuchen
	
	ldi r19,0xff	;Pulszähler wird am Ende des IRQ 0
	
gen_IR_Paar:	lds r17,IR_Status
	sbrs r19,0	;Pulszähler ungerade dann skip
	rjmp IR_gerade	;springe mit geradem Pulszähler
	lds r18,IR_Paar	;Token Paar 	
	swap r18	;letztes Token nach links
	andi r18,0xf0	;rechte Seite ausblenden
	or r18,r20	;aktuelles Token nach rechts
	sts IR_Paar,r18	;und speichern	
;-------------------Puslzähler ist ungerade
	rjmp inc_IR_cnt		
;------------------ gen Paar gerade ----------------------------------------------
IR_gerade:	sbrc r17,skip_stuff	;skip stuff ??
	rjmp Auswerten	;ja
	lds r18,IR_Paar	;altes Token Paar nach r18
	swap r18	;die Token certauschen
	andi r18,0xf0	;rechte Seite ausblenden
	or r18,r20	;neues Token nach rechts
	sts IR_Paar,r18	;und das Paar speichern
;------------------ Pulszähler ist gerade (Paar in r18 cnt in r19)
	sbrc r17,skip_stuff	;skip stuff ??
	rjmp Auswerten	;ja
	mov r16,r18	;Token Paar kopieren
	andi r16,0x0f	;nur Puls
	cpi r16,2	;Daten Bits ??
	brlo Auswerten	;ja
	ori r17,(1<< skip_stuff) ;skip stuff ein schalten
	rjmp inc_IR_cnt
;------------------------------------------------------------------------
IR_Error:	ldi r17,0x00	;Status Reset
	ldi r19,0xff	;IR_cnt Reset
	rjmp inc_IR_cnt
;------------------------------------------------------------------------
Auswerten:	andi r17,255-(1<<skip_stuff);skip stuff abschalten
	lds r18,IR_Paar

	sbrc r17,repeat_got
	rjmp IR_1
	sbrc r17,haeder_got	;Haeder schon empfangen ??
	rjmp IR_1	;ja, dann Test überspringen
	cpi r18,IR_Haeder	;Token_Paar mit Haeder vergleichen
	brne IR_Error	;ungleich dann Error
	ori r17,(1<<move_bits|1<<haeder_got);Bits schieben Eneble, Haeder in Status setzen
	rjmp inc_IR_cnt	;Zähler hoch und IRQ Ende

IR_1:	sbrs r17,move_bits	;Bits schieben ?	
	rjmp inc_IR_cnt
	rcall IR_schieben		 

IR_Data_ok:	nop

inc_IR_cnt:	inc r19	;Zähler hoch und IRQ Ende
	sts IR_Status,r17
	sts IR_cnt,r19
	pop zh	;Register wierer vom Stack zurück
	pop zl
	pop r20
	pop r19
	pop r18
	pop r17
	pop r16
	pop r0
	out SREG, r0
	pop r0
	reti	;IRQ Ende
;------------------------------------------------------------------
IR_schieben:	sbrc r18,4	;Pulse_Width oder
	swap r18 	;Pulse_Distance oder ??
	lsr r18
	lds r18,IR_Byte_1
	rol r18
	sts IR_Byte_1,r18
	lds r18,IR_Byte_2
	rol r18
	sts IR_Byte_2,r18
	lds r18,IR_Byte_3
	rol r18
	sts IR_Byte_3,r18
	lds r18,IR_Byte_4
	rol r18
	sts IR_Byte_4,r18
	ret
;__________________________________________________________________

Key_get:	lds r16,IR_Status  	;IR_Status nach r16
	lsr r16	;Flag für gültiges Datenbyte ins Carry
	brcc PC+7	;springe zu ret wenn Daten ungültig
	lsl r16             ;Daten Flag im IR_Status löschen
	sts IR_Status,r16 	;und speichern
	lds r16,IR_Byte_1   ;Tasten Code nach r16
	sec                 ;Carry 1 = Code ist gültig
	ret
;__________________________________________________________________

IR_init:
.ifdef debug
;------------------ PCInt interrupt aktibieren --------------------
	in r16,gimsk
	ori r16,(1<<PCIE)
	out gimsk,r16
;------------------ für PB 7
	in r16,PCMSK
	ori r16,0b10000000
	out PCMSK,r16
.endif
;------------------ Variabeln vordefinieren -----------------------
	ldi r16,0
	sts IR_Status,r16
	ldi r16,0xff
	sts IR_cnt,r16
;-----------------  Timer 0 Vorteiler 64 -------------------------
	in r16,TCCR0
	andi r16,255-(1<<CS02|1<<CS01|1<<CS00)
	ori r16,(1<<CS02|0<<CS01|0<<CS00)
	out TCCR0,r16
;-----------------  Timer 0 overflow Interrupt aktivieren ---------
	in r16,TIMSK
	ori r16,(1<<TOIE0)
	out TIMSK,r16 
;-----------------  Ext. Interrupt für steigende und fallende Flanke 
	in r16,mcucr
	andi r16,255-(1<<ISC00|1<<ISC01)
	ori  r16,(1<<ISC00)
	out MCUCR,r16
;-----------------  Ext. Interrupt aktivieren ----------------------
	in r16,GIMSK
	andi r16,255-(1<<INT0)
	ori r16,(1<<INT0)
	out GIMSK,r16
	ret
;------------------- Timer 0 Overflow Interrupt Routine ------------
OVF0_:	push r0
	in   r0, SREG
	push r0
	push r16

	lds r16,TCNT0_H
	inc r16
	sts TCNT0_H,r16

	pop r16
	pop r0
	out SREG, r0
	pop r0
	reti

