; *****************************************************************************
; RFID-Reader frei nach Martin Oßmann, ELEKTOR 06/2010 reader1.c
;
; RFID-Frequenz 125 kHz
; RFID-Reader-Chip EM4095 getestet mit der Schaltung auf 
; http://www.grzesina.de/avr/rfid/rfid.html
;
; Fuses
; external crystal 8.000.000 Hz startup 14 Clk + 4,1 ms
; No Brownout detector
;
; serialout with 19200-8-n-1
;
; (CC) auf den Assemblercode by J. Grzesina, KRS Neumarkt
; Durch die Codierung in Assembler wurde der Codeumfang von 67% auf 37% des
; Flashspeichervolumens des ATTiny2313 reduziert. Der Code ist in dieser Form
; wegen bausteinbezogener Vereinfachungen (SRAM-Volumen) auch nicht auf AVRs
; mehr als 256 Byte unmittelbar übertragbar. Eine diesbezügliche Anpassung 
; sollte allerdings nicht schwer fallen. Die Umsetzung des Original C-Codes von 
; Martin Oßmann erfolgte anlässlich einer Fortbildungsveranstaltung zum Thema
; RFID unter der Maßgabe der Vereinfachung und Straffung. Aus diesem Grund 
; wurden unwesentliche Teile entfernt und eine Umordnung vorgenommen, welche
; die Übersichtlichkeit des Programmtextes erhöht.
;
; Lokale Variablen aus dem Original-C-Text wurden weitestgehend durch Register 
; ersetzt. Nur wo das nicht möglich war, wurden vereizelt SRAM-Bereiche 
; herangezogen. Somit sind statt 72% nur 61% des SRAM-Bereichs belegt. 
; Die Parameterübergabe erfolgt ebenfalls weitgehend über Register, meist R16.
; Rückgabewerte werden auch in R16 übergeben. 
;
; Der Freigabeeingang SHD auf dem Readerchip EM4095 muss per Hardware auf
; Masse gelegt werden, ebenso der Modulationseingang MOD. Die Verwendung des 
; U2270B ist ebenfalls möglich, der Eingang CFE ist jedoch auf +5V zu legen, um 
; die Spulentreiber zu aktivieren.
; *****************************************************************************
;
.nolist
.include "tn2313def.inc"
.list
;
.equ takt = 8000000
;
; Assembler-Flags
; Kombination erlaubt verschiedene Fehlererkennungsmechanismen einzuschalten
.equ debuglevel = 0		; 1 = testpin   	- IRQ-Peak
						; 2 = syncpin 		- synchron-Peak
						; 4 = fehler1		- holebyte
						; 8 = fehler2
						; 16 = thebits in UFIFO (SUB)
;
; Konstanten
.equ cr = 13
.equ lf = 10
.equ blank = 32
.equ error = 1
.equ noerror = 0

; RFID
.equ demod_in = 2		; Pin 6 - Daten von der Readerplatine (INT0)
.equ takt_out = 5		; Pin 9 - 500kHz/125kHz PWM-Output (PD5=OC0B)
.equ rfidPIN = PIND
.equ rfidDDR = DDRD
.equ rfidPORT = PORTD

; LED
.equ led = 0			; Pin 12
.equ ledPORT = PORTB
.equ ledDDR = DDRB		; bedient eine LED wenn ein transponder gelesen wird

; RS232
.equ txdPORT = PORTD
.equ txdDDR = DDRD
.equ TXD = 1			; Pin 3

; Test
.equ testport = PORTD	; Puls während TOVL1-IRQ
.equ testDDR = DDRD
.equ testpin = 4		; Pin 8

; Präambel lesen
.equ syncPort = PortB	; Während des Empfangs einer Präambel = 1
.equ syncDDR = DDRB
.equ syncpin = 1		; Pin 13

; Fehlererkennung
.equ fehlerPORT = PORTB
.equ fehlerDDR  = DDRB
.equ fehler1	= 2		; Pin 14
.equ fehler2	= 3		; Pin 15

.equ ufifolen = 32		; der Wert muss stets 2^n sein (hier n=5)
.equ ufifomask = ufifolen-1	; lauter binäre 1-er
.equ rfifolen = 32
.equ rfifomask = rfifolen-1

; Variablen
; Register
.def theparitybit = r10	; Das Paritybit beim Einlesen eines Nibbels
.def thebits = r11		; Die Bits des Nibbels
.def hbit1 = r12		; Halbbit vom Port
.def hbit2 = r13		; folgendes Halbbit vom Port
;.def inbit = r14
.def oldbit	= r15		; zuvor gelesenes Halbbit
.def dauer = r25		; Beim Lesen bisher abgelaufene Zeit
.def uputpnt = r20		; RS232 Schreibzeiger
.def ugetpnt = r21		; RS232 Lesezeiger
.def rputpnt = r22		; RFID-Warteschlange Schreibzeiger
.def rgetpnt = r23		; RFID-Warteschlange Lesezeiger
.def tim3	= r24		; steuert Abläufe durch Zeitscheiben

; SRAM
.dseg
ufifo:
	.byte ufifolen		; RS232-Warteschlange
rfifo:
	.byte rfifolen		; RFID-Warteschlange
LEDcnt:
	.byte 2				; Leuchtdauer der LED
data:
	.byte 11			; Zwischenspeicher für die Nibbelfolge
theParityByte:
	.byte 1				; Spaltenparitäts-byte


; Code
.cseg
.org 0x0000				; RST-Einsprung
rjmp start

.org 0x0005				; TCNT1_OVL
rjmp TCNT1_OVL_ISR



.org 0x001a
start:
	ldi r16, ramend
	out spl, r16		; Stackpointer initialisieren

	sbi rfidDDR, takt_out; TXD(PD1) und takt_out(PD5) als Ausgänge
	sbi ledDDR, led		; LED-Leitung(PB0) auf Ausgang
	cbi ledPORT, led	; LED aus (lowaktiv)

.if (debuglevel & 1) == 1
	sbi testddr, testpin; IRQ-Testpin auf Ausgang
.endif ; = 1

.if (debuglevel & 2) == 2
	sbi syncddr, syncpin; Synchronbit auf Ausgang
	cbi syncport, syncpin; Bit = 0 (keine Präambel gelesen)
.endif ; = 2

.if (debuglevel & 4) == 4
	sbi fehlerddr, fehler1; Fehler1-Bit als Ausgang
	cbi fehlerPort,fehler1; Fehlerbit löschen
.endif ; = 4

.if (debuglevel & 8) == 8
	sbi fehlerddr, fehler2; Fehler1-Bit als Ausgang
	cbi fehlerPort,fehler2; Fehlerbit löschen
.endif ; = 8

	rcall init_v24		; Uart konfigurieren
	rcall init_tcnt1	; Timer1 initialisieren
	rcall init_tcnt0	; Timer0 als Taktgeber einrichten
	rcall init_ufifo	; v24-Buffer initialisieren

	sei					; Interrupts allgemein zulassen
	ldi zl, low(strHello*2)
	ldi zh, high(strHello*2); Die Adresse von Hallo-Text in den Zeiger
	rcall uflashstring	; und in die UART-FIFO (Warteschlange)
	
main:
	rcall empfangen		; Zur Endlosschleife des Empfangs vom Transponder
	rjmp main			; Eigentlich nutzlos, nur wegen der Form

; ==============================================================================
; Unterprogramme für alle möglichen Zwecke
; ==============================================================================
; -----------------------------------------------------------------------------
; Initialisierung
; -----------------------------------------------------------------------------
init_v24:
	sbi txdDDR, txd		; TXD-Leitung als Ausgang
	ldi r16, 1<<TXEN	; Uart-Sendebetrieb einschalten
	out UCSRB, r16		; 
	ldi r16, (1<<UCSZ1) | (1<<UCSZ0) | (0<<UMSEL) | (0<<USBS) | (0<<UPM1) | (0<<UPM0)
	out UCSRC, r16		; 8 Datenbits, No Parity, 1 Stopbit
	ldi r16, 0			; Baudrate einstellen
	out UBRRH, r16		; Highbyte
	ldi r16, 26-1		; Lowbyte
	out UBRRL, r16		; Baudrate auf 19200 (für 8KHz XTal)
						; 8000000/19200/16 -> 26,04

	ret
; -----------------------------------------------------------------------------


init_tcnt0:				; Fast PWM-Modus7- set OC0B @ comparematch- clear on TOP
	ldi r16, (1<<com0b1) | (1<<com0b0) | (1<<WGM01) | (1<<WGM00)
	out tccr0a, r16		; Ausgabe an OC0B (Pin 9)
	ldi r16, (1<<WGM02) | 001;(1<<CS00)	; kein Vorteiler, Timer anschalten
	out tccr0b, r16
	ldi r16, 64 - 1		; 8MHz / 16 = 500kHz (für 125 kHz -> 64-1)
	out OCR0A, r16
	ldi r16, 32			; (für 125 kHz -> 32)
	out OCR0B, r16		; 
	ret
; -----------------------------------------------------------------------------


init_tcnt1:
	ldi r16, (1<<WGM11) | (0<<WGM10)	; Fast PWM-Mode 14 vorbereiten
	; Möglichkeit der Ausgabe eines symmetrischen Rechtecks an Pin 15 für
	; Erzeugung einer negativen Versorgungsspannung eines LCD mit Ladungspumpe
	ori r16, ((1<<COM1A1) | (1<<COM1A0))
	out TCCR1A, r16						; ICR enthält TOP-Wert
	ldi r16,(1<<WGM13) | (1<<WGM12) | (1<<CS10) ; OCR1X set @ compare match
											    ; OCR1X clear @ TOP
	out TCCR1B, r16						; kein Vorteiler bei 8 MHz
	in r16, timsk
	sbr r16, 1<<TOIE1					; Timer1 
	out timsk, r16						; Timeroverflow-IRQ erlauben
	ldi r17, 0
	out OCR1AH, r17						; Highbyte 0 zuerst schreiben
	ldi r16, 128						; TOP/2
	out OCR1AL, r16						; Intervallmitte -> symm. Rechteck
	out ICR1H, R17						; Highbyte ist wieder 0
	ldi r16, 256-1						; 8 MHz / 256 = 125 kHz
	out ICR1L, r16						; TOP setzen
	clr rputpnt							; das HSB wird vor dem LSB geschrieben!
	clr rgetpnt							; IRQ-Warteschlangenzeiger=0 setzen ->
	clr tim3							; = Warteschlange ist leer 
	ret									; Zeitscheibenzähler tim3 auf Null
; -----------------------------------------------------------------------------


init_ufifo:
	; ufifo ist leer, wenn uputpnt=ugetpnt
	clr uputpnt							; Ausgabewarteschlange auf "leer" 
	clr ugetpnt							; setzen durch uputpnt = ugetpnt
	ret
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; RS232-Routinen
; -----------------------------------------------------------------------------

uput_c: 								; Zeichen in r16 in ufifo schreiben 
										; Eingabe: R16 enthält zu schreibendes Zeichen
	push zl								; beteiligte Register sichern
	push zh
	push r17
	in r17, sreg						; Statusregister sichern

	ldi zl, low(ufifo)					; Schreibadresse Basis holen
	ldi zh, high(ufifo)					;
	add zl, uputpnt						; Schreibzeiger addieren
	st z, r16							; Zeichen in ufifo schreiben
	inc uputpnt							; Schreibzeiger erhöhen
	andi uputpnt, ufifomask				; auf ufifo-Länge normieren

	out sreg, r17						; Statusregister restaurieren
	pop r17	
	pop zh
	pop zl								; beteiligte Register restaurieren
	ret									; Keine Ausgabe
; -----------------------------------------------------------------------------


udequeue:								; Rs232-Queue leeren
	push r16							; keine Eingabe
	push r17
	push zl
	push zh
	in r17, sreg
 
 	cp uputpnt, ugetpnt					; queue leer?
	breq udq_done						; ja
	sbis UCSRA, UDRE					; USART Dataregister empty?
	rjmp udq_done						; ja
	ldi zl, low(ufifo)					; 
	ldi zh, high(ufifo)					; UFIFO-Basisadressse
	add zl, ugetpnt						; Lesezeiger addieren -> Leseadresse
	ld r16,z							; Aus UFIFO byte lesen nach R16
	inc ugetpnt							; Lesezeiger erhöhen
	andi ugetpnt, ufifomask				; Auf UFIFO-Länge normieren
	out UDR, r16						; in USART_Senderegister schreiben

udq_done:
	out sreg, r17
	pop zh
	pop zl
	pop r17
	pop r16
	ret									; Keine Ausgabe
; -----------------------------------------------------------------------------


uflashstring: 				; Zeichenkette aus dem Programmspeicher ausgeben
	push r16; ZH:ZL enthält den Zeiger auf den Text (nullterminiert) im flash
	push r17
	in r17, sreg
	
ufs01:
	lpm r16, z+				; Auszugebendes Zeichen indirekt laden					; 
	tst r16					; auf 0 testen
	breq ufs_done			; fertig, wenn Zeichen = 0
	rcall uput_c			; sonst in die Warteschlange
	rjmp ufs01				; Wiederhoel, bis 0 gelesen

ufs_done:
	out sreg,r17
	pop r17
	pop r16
	ret
; -----------------------------------------------------------------------------


uhex:						; lownibble in r16 als Hexziffer ausgeben
	push r16
	push r17
	in r17, sreg

	andi r16, 0b00001111	; Highnibble ausmaskieren
	cpi r16, 10				; Vergleich mit 10
	brlo uhexlower			; <10, dann normale Ziffer
uhexupper:					; sonst ist es eine Hexziffer
	subi r16, 10			; 10 abziehen und mit Basis 'A' 
	ori r16, 'A'			; und Offset in R16 ausgeben
	rjmp uh_done
uhexlower:			
	ori r16, '0'			; mit Basis '0' und Offset in R16 ausgeben
uh_done:
	rcall uput_c			; in die Warteschleife des USART
	out sreg, r17
	pop r17
	pop r16
	ret

; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; RFID-Routinen
; -----------------------------------------------------------------------------

LEDtimer:					; Schaltet LED während erkanntem Tag an
	push r16				; mit Verzögerungseffekt von 16 ms
	push r17				; (läuft mit 31,250 kHz ab 500 Zählern nach 
	push r18				; Entfernung des Transponders)
	in r18, sreg
	push r18

	lds r16, ledcnt	       	; Countdownzähler für Leuchtdauer laden
	lds r17, ledcnt+1		; (läuft mit 31,250 kHz ab 500 Zählern nach )
	ldi r18, 0				; Vergleichs-Hilfsvariable
	cpi r16,1				; Vergleich mit 1
	cpc r17, r18			; Highbyte
	brsh lt01				; >= 1 dann ...
lt00:
	sbi ledport, led		; < 1, dann 
	rjmp lt_done			; LED aus und fertig
lt01:
	subi r16, 1				; Countdownzähler verringern
	sbc r17, r18			; 
	sts ledcnt, r16			; neu abspeichern
	sts ledcnt+1, r17
	cbi ledport, led		; LED an

lt_done:
	pop r18
	out sreg, r18
	pop r18
	pop r17
	pop r16
	ret
; -----------------------------------------------------------------------------


enqueue: 					; Halbbit in r16 in rfifo schreiben 
	push zl					; Eingabe: Wert des zu schreibenden Halbbits in R16
	push zh
	push r17
	in r17, sreg

	ldi zl, low(rfifo)		; RFIFO-Startadresse holen
	ldi zh, high(rfifo)		; eigentlich = 0
	add zl, rputpnt			; Schreibzeiger addieren
	st z, r16				; In die Warfeschlange schreiben
	inc rputpnt				; Schreibzeiger erhöhen
	andi rputpnt, rfifomask	; Auf RFIFO-Länge normieren

	out sreg, r17
	pop r17
	pop zh
	pop zl
	ret						; Ausgabe: keine
; -----------------------------------------------------------------------------


getHalfBit: 					; liest Halbbit aus RFID-FIFO, kein Eingabewert
	push r17				; (wird von IRQ-Routine via enqueue gefüllt)
	push zl
	push zh
	in r17,sreg

	ldi zl, low(rfifo)		; RFIFO-Startadresse holen
	ldi zh, high(rfifo)
	add zl, rgetpnt			; Lesezeiger addieren
gtb00:	
	cp rgetpnt, rputpnt		; Schreibzeiger = Lesezeiger?
	breq gtb00				; ja, dann wiederholen (auf Eintrag warten)
	ld r16, z				; Halbbit nach R16 holen
	inc rgetpnt				; Lesezeiger erhöhen
	andi rgetpnt, rfifomask	; Auf RFIFO-Länge normieren

	out sreg,r17
	pop zh
	pop zl
	pop r17
	ret						; der Rückgabewert aus rfifo steht in r16
; -----------------------------------------------------------------------------


holebit:					; Liest ein Bit aus der Warteschleife mit 
	push r17				; Fehlererkennung (Code-Konsistenz)
	in r17,sreg				; keine Eingabe

	rcall getHalfBit		; Halbbit holen
	mov hbit1, r16			; zwischenspeichern
	rcall getHalfBit		; nächstes Halbbit holen
	mov hbit2, r16			; merken
	mov r16, hbit1			; Halbbit 1 zum Vergleich in R16 zur Verarbeitung
	cp hbit1, hbit2			; Vergleich der Halbbits
	breq rxb_error			; zwei gleiche Halbbits gibt es nicht
	rjmp rxb_done			; das entscheidende Halbbit in R16 zurück geben
rxb_error:	
	ldi r16, 2				; falls Halbbits gleich waren wird 2 als
rxb_done:					; Fehlercode zurückgegeben
	out sreg, r17
	pop r17
	ret						; Rückgabe hbit1 oder Fehlercode (2) in R16
; -----------------------------------------------------------------------------

getnibb:					; 4 Bit als Nibble holen
							
	push r17				
	push r18
	push r19
	in r19, sreg			; sreg-Safe

    clr thebits				; Das Nibble steht am Ende in "thebits", putzen
	clr theparitybit		; auch das Paritybit zurücksetzen
	ldi r17, 1				; Muster für ein 1-Bit
	ldi r18, 4				; Zählschleifen-Counter
gf00:
	rcall holebit			; Rückgabe ist hbit1 oder Fehlercode 2 in r16
	cpi r16, 2				; Auf Fehler prüfen
	brne gf01				; kein Fehler, dann weiter
	ldi r16, ERROR			; Fehlercode laden (1)
	rjmp gf_done			; zurück, war wohl nix!
gf01:
	lsl thebits				; vorhandene Bits eins nach links schieben
	tst r16					; aktuelles Bit testen
	breq gf02				; wenn = 0, keine weiteren Maßnahmen
	or thebits, r17			; sonst das 1-Bit zum Nibble hinzufügen
	eor theparitybit, r17	; und die Prüfsumme aktualisieren
gf02:
	dec r18					; Zähler erniedrigen
	brne gf00				; wiederholen, falls noch nicht = 0
	; ende der Zählschleife 4..1
gf_noerror:
	ldi r16, noerror		; fehlerfreie Ausführung durch Rückgabe einer 
gf_done:					; 0 in R16 signalisieren
	out sreg, r19
	pop r19
	pop r18
	pop r17
	ret				; Rückgabe: Fehlercode in R16, thebits enthält 4 Datenbits
; -----------------------------------------------------------------------------


bittest:				; Zeilen-Paritätsbit testen		
	push r17
	push r18
	in r18, sreg

	ldi r17, 1			; Hilfsvariable besetzen (für EOR-Befehl)
	rcall holebit		; in R16 kommt das hbit1 oder der Fehlercode 2 zurück
	cpi r16, 2			; auf Fehlercode testen
	brne pet00			; kein Fehler, dann weiter
pet_error:
	ldi r16, error		; sonst Standard-Fehlercode nach R16 (1)
	rjmp pet_done		; fertig, Test negativ
pet00:
	tst r16				; kein Fehler, Bitwert feststellen
	breq pet02			; wenn der = 0 war, dann ohne Fehler zurück
	eor theparitybit, r17; Püfsumme aktualisieren
	tst theparitybit	; Prüfsumme testen
	brne pet_error		; Fehler, falls Prüfsumme <> 0
pet02:					
	ldi r16, noerror	; Kein Prüfsummenfehler, Ausführung als fehlerfrei
pet_done:				; rückmelden
	out sreg, r18
	pop r18
	pop r17
	ret					; gibt in R16 den Fehlercode (0/1) zurück
; -----------------------------------------------------------------------------


holedaten:			; 
	push r17
	push r18
	push r19
	push zl
	push zh
	in r19, sreg

.if (debuglevel & 4) == 4
	sbi fehlerport, fehler1	; Fehler1-Bit setzen !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.endif ; 4
	clr r17
	sts theparitybyte, r17	; Spalten-Parity-Byte löschen
	ldi r17, 10			; Es sind 10 mal 4 Bit mit Paritybit zu holen
	ldi zl, data		; Die Daten werden im Data-Array abgelegt
	ldi zh, data+1		; Zeiger stellen auf Data-Basis
gda00:
	rcall getnibb		; in r16 kommt der fehlercode retoure,4 Bits in thebits
	tst r16				; Fehlercode in R16 testen
;	rcall put_thebits	; Subroutine-Call nur zu Prüfzwecken bei Malfunction
	brne gda_done   	; Fehler, fertig, nimm den Fehlercode mit
	rcall bittest		; Zeilenparität testen,in r16 kommt Fehlercode zurück
	tst r16				; testen auf Prüfsummenfehler
	brne gda_done		; Fehler, fertig, nimm den Fehlercode mit
	st z+, thebits		; Alles paletti, Nibble im Dataarray abspeichern
	lds r18,theparitybyte; bisherigen Wert des Spaltenparitybytes laden
	eor r18, thebits	; aktualisieren durch EXOR mit dem Nibble
	sts theparitybyte, r18 ; abspeichern
	dec r17				; Rundenzähler verringern
	brne gda00			; falls noch nicht = 0, nochmal die Runde
	rcall getnibb		; Zum Schluss die Spaltenprüfsumme einlesen
	tst r16				; Auf Fehler testen (R16<>0)
	brne gda_done		; Fehler, fertig, nimm den Fehlercode mit
	lds r18,theparitybyte ; kein Einlesefehler, dann Spaltenparität
	eor r18, thebits	; aktualisieren
	sts theparitybyte, r18; wieder abspeichern
	tst r18				; paritybyte auf 0 testen
	brne gda_error		; Fehler, fertig, nimm den Fehlercode mit
	ldi zl, data		; Zeiger erneut auf Beginn des Data-Arrays
	ldi zh, data+1
	ldi r17, 10			; 10 Nibbles auslesen
gda01:
	ld r16, z+			; Wert holen
	rcall uhex			; Zahl in r16 als Hexziffer in UFIFO stellen
	dec r17				; Rundenzähler verringern
	brne gda01			; solange nicht = 0 wiederholen
;	ldi r16, '+'		; Trenner ausgeben
;	rcall uput_c
	ldi r16, 13			; CR in UFIFO
	rcall uput_c
	ldi r16, low(500)	; Zeitverzögerung für LED stellen
	sts ledcnt,r16
	ldi r16, high(500)
	sts ledcnt+1, r16	
gda04:
	ldi r16, noerror	; Ausgang ohne Fehler

.if (debuglevel & 4) == 4
	cbi fehlerport, fehler1	; Fehler2-Bit löschen !!!!!!!!!!!!!!!!!!!!!!!!!!!!
.endif ; 4
	rjmp gda_done
gda_error:				; Ausgang mit Fehler
	ldi r16, error

gda_done:	
	out sreg, r19
	pop zh
	pop zl
	pop r19
	pop r18
	pop r17
	ret
; -----------------------------------------------------------------------------


empfangen:			; Prüft auf Synchronisation und liest 1 Datensatz ein
					; Diese Schleife ist ein Dauerläufer.
					; R7,R8,R9 bilden ein 24-BitSchieberegister
	ldi r16, 1		; R6 als Hilsvariable via R16 mit 1 belegen
	mov r6,r16
dore00:
	rcall getHalfBit; aus rfifo ein Bit holen, Bit steht in R16
	ror r16			; R16.LSB nach rechts ins Carry schieben
	rol r7			; Schieberegister um eins nach links schieben
	rol r8			; Von R7.MSB nach R8.LSB
	rol r9			; dto
dore01:

.if (debuglevel & 2) == 2
	cbi syncport, syncpin	; Sync-Bit aus (PB.1=0)(zu Testzwecken mittes OSZI)
					; test auf 9 reingeschobene Einsen
.endif ; 2

	ldi r16, 0b00000011 ; dreistufiger Vergleich der 18 Halbbits
	and r9, r16		; MSByte auf 2 LSBits einschränken
	ldi r16, 0b10101010
	cp r7, r16		; dann Vergleich von unten beginnen
	cpc r8, r16		; mittleres Byte mit Carry
	ldi r16, 0b00000010
	cpc r9, r16		; höchstwertiges Byte auch mit Carry
	brne dore05		; keine 9 Einsen? -> Keine Präambel, weiter warten

.if (debuglevel & 2) == 2
	sbi syncport, syncpin	; Sync-Bit ein (PB.1=1) Präambel erkannt
.endif ; 2

	rcall holedaten			; 1 Satz Daten holen (10 Nibbels)
	clr R7					; Schieberegister = 0 für neuen Durchlauf
	clr R8
	clr R9
dore05:
	rjmp dore00
	ret
; -----------------------------------------------------------------------------

put_r16:			; Prüfroutine 1
;	push r16		; gibt Nibblewerte über RS232 aus
;	rcall uput_c	
;	pop r16
;	ret
	

.if (debuglevel & 16) == 16
put_thebits:		; Prüfroutine 2
	push r16		; gibt die Nibbelwerte als Hex-Code aus
	mov r16, thebits
	rcall uhex
	pop r16
	ret
.endif ; 16

; -----------------------------------------------------------------------------

; =============================================================================
; ISR

TCNT1_OVL_ISR:		; TCNT1 Überlauf Serviceroutine 
	push r16
	push r17
	push r18
	in r17, sreg

.if (debuglevel & 1) == 1
	sbi testport, testpin	; Testpin auf 1 - Test auf IRQ-Funktion mit OSZI
.endif ; 1

	clr r18			; gelesenes Bit schon mal auf 0 vorbelegen
	sbic rfidPIN, demod_in ; Nächsten Befehl überspringen, wenn DEMODin=0
	ldi r18, 1		; DEMOD=1 also Bit auf 1 setzen
	cp r18, oldbit	; mit dem vorher festgestellten Bit vergleichen
	brne change		; Bei Ungleichheit Wechsel bearbeiten
	inc dauer		; bei Gleichheit Zähler erhöhen, weitere Dienste checken
	rjmp tovl05		; siehe dort
change:
	mov r16, oldbit	; Pegelwechsel hat stattgefunden 
	cpi dauer, 12	; sind wir im 3. Viertel des Bit-Intervalls? 
	brlo tovl01		; nein
	rcall enqueue 	; ja, Oldbit als Halbbit speichern
tovl01:
	mov r16, oldbit	; Oldbit zur Übergabe vorbereiten
	cpi dauer, 4	; sind wir im ersten Viertel?
	brlo tovl05		; nein, zu niedrig, noch warten, erst mal andere Sachen
	rcall enqueue	; Ja ist OK, Halbbit ablegen
	ldi dauer, 1	; Dauer zurücksetzen
	mov oldbit, r18	; aktuelles Bit nach Oldbit umlagern
tovl05:
	inc tim3		; Zeitscheibenzähler erhöhen
	cpi tim3, 8		; Zeitscheibe 8 ?
	brne tovl06		; nein
	rcall udequeue	; ja, RS232-Queue bedienen
tovl06:
	cpi tim3, 12	; Zeitscheibe 12
	brne tovl07		; nein, 
	rcall ledtimer	; ja, LED-Timer bedienen
tovl07:	
	cpi tim3, 16	; Zeitschiebe 16?
	brne tovl_done	; nein, dann fertig
	clr tim3		; Zeitscheibenzähler zurücksetzen
tovl_done:

.if (debuglevel & 1) == 1
	cbi testport, testpin	; Testpin auf 0
.endif; 1

	out sreg, r17
	pop r18
	pop r17
	pop r16
	reti


; =============================================================================
; Stringkonstanten

strHello:
	.db "Reader gestartet",13, 0

