;------------------ Fernbefienung :  NewLine HD22
.EQU 	Adresse_vergleichen = 0 ;kommentieren um Vergleich auszublenden
.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_High:	.byte 1
IR_Low:	.byte 1
IR_Cnt:	.byte 1
IR_Paar:	.byte 1
IR_Status:	.byte 1

IR_Byte_1:	.byte 1	
IR_Byte_2:	.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

IR_Error:	ldi r19,0xff	;Pulszähler wird am Ende des IRQ 0
	
gen_IR_Paar:	sbrs r19,0	;Pulszähler ungerade dann skip
	rjmp Auswerten	;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
	cpi r19,35   	;Adresse komplett ?
	brne Nec_4	;nein, dann springen
.ifdef	Adresse_vergleichen	
	lds r16,IR_Byte_2	;High Adress nach r16
	cpi r16,Nec_Adresse_H ;vergleichen
	brne IR_Error	;falls ungleich Error (Pulszähler auf "0"
	lds r16,IR_Byte_1	;das gleiche mit der Low Adresse
	cpi r16,Nec_Adresse_L
	brne IR_Error
.endif
Nec_4:	cpi r19,67	;16 Bit Daten empfangen ?
	brne Nec_1	;nein, dann springen
;------------------ Daten wurden empfangen
	lds r16,IR_Byte_1   ;Daten verifizieren
	lds r17,IR_Byte_2   ;IR_Byte_1 beinhaltet das Datenbyte
	com r17	;IR_Byte_2 = Datenbyte invers
	cp r16,r17	;und vergleichen
	brne IR_Error	;falls keine Übereinstimmung -->Error
	ldi r18,0x81	;Bit 7 = 1 Repeatflag aktiv, Bit_1 = für Datenbyte	
	ldi zl,low (2*IR_Repeat_Tab)  ; z aug Tabelle der Tasten, die 
	ldi zh,high(2*IR_Repeat_Tab)  ;wiederholt werden solle 
IR_Rep_search:	lpm r17,z+	;Byte aus Tabelle holen (zl dient als Zähler)
	cp r16,r17	;Datenbyte mit Repeatbyte vergleichen
	breq IR_Rep_yes	;gleich ? dann r18 mit Repeat und Datenflag nach IR_Status
	cpi zl,255 & (low(2*IR_Repeat_Tab)+IR_Rep_keys) ;Ende der Tabelle erreicht ?
	brne IR_Rep_search	;nein, dann nächstes Byte mit Datenbyte vergleichen
	ldi r18,1	;keines stimmt überein, --> IR_Status ohne Repeat setzen
IR_Rep_yes:	sts IR_Status,r18	;und speichern
	rjmp inc_IR_cnt	;zum Pulszähler erhöhrm ind IRQ Ende springen

Nec_1:	cpi r19,1	;Puslzähler bei 1 ? 
	brne Nec_2	;falls nicht --> springen
	cpi r18,0x43	;Signatur für Frame Start erhalten ?
	brne IR_Error	;nein, dann zu Error
Nec_2:	cpi r19,69	;Zähler bei Delay für Repeat ?
	breq inc_IR_cnt	;ja,dann Zähler um 1 hoch und IRQ Ende
	cpi r19,73	;Zähler auf 2. Repeatsignatur =
	breq Nec_3	;ja, dann springen
	rjmp inc_IR_cnt	;sonst wieder Zähler hoch und IRQ Ende

Nec_3:	cpi r18,0x42	;Signatur für Repeat erhalten?
	brne IR_Error	;falls nicht dann Error
;------------------ Repeat Signatur wurde empfangen	
	lds r16,IR_Status	;IR_Status nach r16
	sbrc r16,7	;Überspringe wenn Repeat Flag in IR_Status gelöscht 	
	ori r16,1	;Repeat Flag ist gesetzt --> IR_Byte gültig
	sts IR_Status,r16	;nach IR_status schreiben
	rjmp inc_IR_cnt	;und wieder Zähler hoch und IRQ Ende

;------------------ Pulszähler ist gerade
Auswerten:	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
;------------------ ab hier wird es individuell (Paar in r18 cnt in r19)
	cpi r19,4	;Zähler im noch vor der Startsignatur ?
	brlo inc_IR_cnt	;ja --> Zähler hoch und IRQ Ende
	cpi r19,68	;noch nicht alle 32 Bits empfangen ?
	brlo IR_schieben	;dann zum schieben
	cpi r19,74	;Repeatsignatur  wurde empfangen ?
	brne inc_IR_cnt	;nein --> Zähler hoch und IRQ Ende
	ldi r19,70	;ja --> Zähler auf 70
	rjmp inc_IR_cnt	;und zähler um eins erhöhen und zum IRQ Ende
	
IR_schieben:	swap r18	;Bit ist links und muss nach rechts
	cpi r18,2	;nur 0 und 1 sind Datenbits
	brlo PC+2	;bei gültigem Bit springen
	rjmp IR_Error	;sonst nach Error
	lsr r18	;empfangenes Bit ins Carry
	lds r16,IR_Byte_1	;Low Byte nach r16
	rol r16	;Carry links reinschieben, Bit 7 ins Carry
	sts IR_Byte_1,r16	;und wieder speichern
	lds r16,IR_Byte_2	;High Byte nach r16
	rol r16	;Carry links reinschieben
	sts IR_Byte_2,r16	;und speichern

inc_IR_cnt:	inc r19	;hier ist Zähler hoch und IRQ Ende
	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
;-------------------
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

