
AVRASM ver. 1.30  FIR_NEU.ASM Mon May 28 15:29:11 2001


warning : Only one .device statement allowed (line ignored)
         ;+++++++++++++++++++++++++++++++++++++++++++++++++++
         ;IR-REMOTE FOR AVR-RISC AT90S2313 (4MHZ)
         ;by Johannes Ferber July 2000
         ;+++++++++++++++++++++++++++++++++++++++++++++++++++
          .list
         
          .include "2313def.inc"
         ;***************************************************************************
         ;* A P P L I C A T I O N   N O T E   F O R   T H E   A V R   F A M I L Y
         ;* 
         ;* Number		:AVR000
         ;* File Name		:"2313def.inc"
         ;* Title		:Register/Bit Definitions for the AT90S2313
         ;* Date	 		:99.01.28
         ;* Version		:1.30
         ;* Support telephone	:+47 72 88 43 88 (ATMEL Norway)
         ;* Support fax		:+47 72 88 43 99 (ATMEL Norway)
         ;* Support E-Mail	:avr@atmel.com
         ;* Target MCU		:AT90S2313
         ;*
         ;* DESCRIPTION
         ;* When including this file in the assembly program file, all I/O register
         ;* names and I/O register bit names appearing in the data book can be used.
         ;* 
         ;* The Register names are represented by their hexadecimal addresses.
         ;* 
         ;* The Register Bit names are represented by their bit number (0-7).
         ;* 
         ;* Please observe the difference in using the bit names with instructions
         ;* such as "sbr"/"cbr" (set/clear bit in register) and "sbrs"/"sbrc" 
         ;* (skip if bit in register set/cleared). The following example illustrates
         ;* this:
         ;* 
         ;* in	r16,PORTB		;read PORTB latch
         ;* sbr	r16,(1<<PB6)+(1<<PB5)	;set PB6 and PB5 (use masks, not bit#)
         ;* out  PORTB,r16		;output to PORTB
         ;*
         ;* in	r16,TIFR		;read the Timer Interrupt Flag Register
         ;* sbrc	r16,TOV0		;test the overflow flag (use bit#)
         ;* rjmp	TOV0_is_set		;jump if set
         ;* ...				;otherwise do something else
         ;***************************************************************************
         
         ;***** Specify Device
          .device AT90S2313
         
         ;***** I/O Register Definitions
          .equ	SREG	=$3f
          .equ	SPL	=$3d
          .equ	GIMSK	=$3b
          .equ	GIFR	=$3a
          .equ	TIMSK	=$39
          .equ	TIFR	=$38
          .equ	MCUCR	=$35
          .equ	TCCR0	=$33
          .equ	TCNT0	=$32
          .equ	TCCR1A	=$2f
          .equ	TCCR1B	=$2e
          .equ	TCNT1H	=$2d
          .equ	TCNT1L	=$2c
          .equ	OCR1AH	=$2b
          .equ	OCR1AL	=$2a
          .equ	ICR1H	=$25
          .equ	ICR1L	=$24
          .equ	WDTCR	=$21
          .equ	EEAR	=$1e
          .equ	EEARL	=$1e
          .equ	EEDR	=$1d
          .equ	EECR	=$1c
          .equ	PORTB	=$18
          .equ	DDRB	=$17
          .equ	PINB	=$16
          .equ	PORTD	=$12
          .equ	DDRD	=$11
          .equ	PIND	=$10
          .equ	UDR	=$0c
          .equ	USR	=$0b
          .equ	UCR	=$0a
          .equ	UBRR	=$09
          .equ	ACSR	=$08
         
         
         ;***** Bit Definitions
          .equ	SP7	=7
          .equ	SP6	=6
          .equ	SP5	=5
          .equ	SP4	=4
          .equ	SP3	=3
          .equ	SP2	=2
          .equ	SP1	=1
          .equ	SP0	=0
         
          .equ	INT1	=7
          .equ	INT0	=6
         
          .equ	INTF1	=7
          .equ	INTF0	=6
         
          .equ	TOIE1	=7
          .equ	OCIE1A	=6
          .equ	TICIE	=3
          .equ	TOIE0	=1
         
          .equ	TOV1	=7
          .equ	OCF1A	=6
          .equ	ICF1	=3
          .equ	TOV0	=1
         
          .equ	SE	=5
          .equ	SM	=4
          .equ	ISC11	=3
          .equ	ISC10	=2
          .equ	ISC01	=1
          .equ	ISC00	=0
         
          .equ	CS02	=2
          .equ	CS01	=1
          .equ	CS00	=0
         
          .equ	COM1A1	=7
          .equ	COM1A0	=6
          .equ	PWM11	=1
          .equ	PWM10	=0
         
          .equ	ICNC1	=7
          .equ	ICES1	=6
          .equ	CTC1	=3
          .equ	CS12	=2
          .equ	CS11	=1
          .equ	CS10	=0
         
          .equ	WDTOE	=4
          .equ	WDE	=3
          .equ	WDP2	=2
          .equ	WDP1	=1
          .equ	WDP0	=0
         
          .equ	EEMWE	=2
          .equ	EEWE	=1
          .equ	EERE	=0
         
          .equ	PB7	=7
          .equ	PB6	=6
          .equ	PB5	=5
          .equ	PB4	=4
          .equ	PB3	=3
          .equ	PB2	=2
          .equ	PB1	=1
          .equ	PB0	=0
         
          .equ	DDB7	=7
          .equ	DDB6	=6
          .equ	DDB5	=5
          .equ	DDB4	=4
          .equ	DDB3	=3
          .equ	DDB2	=2
          .equ	DDB1	=1
          .equ	DDB0	=0
         
          .equ	PINB7	=7
          .equ	PINB6	=6
          .equ	PINB5	=5
          .equ	PINB4	=4
          .equ	PINB3	=3
          .equ	PINB2	=2
          .equ	PINB1	=1
          .equ	PINB0	=0
         
          .equ	PD6	=6
          .equ	PD5	=5
          .equ	PD4	=4
          .equ	PD3	=3
          .equ	PD2	=2
          .equ	PD1	=1
          .equ	PD0	=0
         
          .equ	DDD6	=6
          .equ	DDD5	=5
          .equ	DDD4	=4
          .equ	DDD3	=3
          .equ	DDD2	=2
          .equ	DDD1	=1
          .equ	DDD0	=0
         
          .equ	PIND6	=6
          .equ	PIND5	=5
          .equ	PIND4	=4
          .equ	PIND3	=3
          .equ	PIND2	=2
          .equ	PIND1	=1
          .equ	PIND0	=0
         
          .equ	RXC	=7
          .equ	TXC	=6
          .equ	UDRE	=5
          .equ	FE	=4
          .equ	OR	=3
         
          .equ	RXCIE	=7
          .equ	TXCIE	=6
          .equ	UDRIE	=5
          .equ	RXEN	=4
          .equ	TXEN	=3
          .equ	CHR9	=2
          .equ	RXB8	=1
          .equ	TXB8	=0
         
          .equ	ACD	=7
          .equ	ACO	=5
          .equ	ACI	=4
          .equ	ACIE	=3
          .equ	ACIC	=2
          .equ	ACIS1	=1
          .equ	ACIS0	=0
         
          .def	XL	=r26
          .def	XH	=r27
          .def	YL	=r28
          .def	YH	=r29
          .def	ZL	=r30
          .def	ZH	=r31
         
          .equ    RAMEND  =$DF    ;Last On-Chip SRAM Location
          .equ	XRAMEND =$DF
          .equ	E2END	=$7F
          .equ	FLASHEND=$3FF
         
         
          .equ	INT0addr=$001	;External Interrupt0 Vector Address
          .equ	INT1addr=$002	;External Interrupt1 Vector Address
          .equ	ICP1addr=$003	;Input Capture1 Interrupt Vector Address
          .equ	OC1addr =$004	;Output Compare1 Interrupt Vector Address
          .equ	OVF1addr=$005	;Overflow1 Interrupt Vector Address
          .equ	OVF0addr=$006	;Overflow0 Interrupt Vector Address
          .equ	URXCaddr=$007	;UART Receive Complete Interrupt Vector Address
          .equ	UDREaddr=$008	;UART Data Register Empty Interrupt Vector Address
          .equ	UTXCaddr=$009	;UART Transmit Complete Interrupt Vector Address
          .equ	ACIaddr =$00a	;Analog Comparator Interrupt Vector Address
         
          .device AT90S2313
         
         ;Definitions
         
          .equ ir_input=2
          .equ tast_input=3
          .equ red=5
          .equ yellow=0
          .equ clkkeyb=6
          .equ datakeyb=7
          .equ clkpc=3
          .equ datapc=4
          .equ flash_enable=1				;Bit 0 wird maskiert
          .equ flash_en=0				;für Sprungbedingung
          .equ do_transmit=2				;Bit 1 wird maskiert
          .equ transmit_done=1			;für Sprungbedingung
          .equ learn_mode=2				;für Sprungbedingung
          
          .def S=r0
          .def ref1=r1
          .def ref2=r2
          .def bitcnt=r16
          .def timer=r17
          .def system=r18
          .def command=r19
          .def keyb_code_1=r20
          .def keyb_code_2=r21
          .def var_wait=r22
          .def modus=r23
          .def temp=r24
          .def transmit=r25
          .def watchdog_count=r26
          .def byte_count=r27
          .def flash=r28
          .def modus_save=r29
         
          .cseg
         
          .org 0
000000 c006      	rjmp reset
         
          .org int0addr
000001 c05a      	rjmp ir_rec
         
          .org int1addr
000002 c153      	rjmp touch
         
          .org OC1addr
000004 c0d7      	rjmp compare_int
         
         ;.org OVF1addr
         ;	rjmp tim1_int
         
          .org OVF0addr
000006 c0c5      	rjmp tim0_int
         
         
         
         
         ;INITIALISIERUNG
         ;******************
          reset:
000007 ed8f      	ldi temp, low(RAMEND)		;Stack-Pointer hochsetzen
000008 bf8d      	out SPL, temp
         
000009 2788      	clr temp
00000a bd8b      	out OCR1AH, temp
00000b eb84      	ldi temp, 180
00000c bd8a      	out OCR1AL, temp		;Lade Compare-register mit 180 (=45us)
         
00000d e085      	ldi temp, 5			;Timer0: Takt=Clock/1024
00000e bf83      	out TCCR0, temp
         
00000f 95a8      	wdr
000010 e08a      	ldi temp, 0b00001010		;Watchdog ist an und muß alle 60ms zurückgesetzt werden
000011 bd81      	out WDTCR, temp
         
000012 e880      	ldi temp, 1<<ACD
000013 b988      	out ACSR, temp			;Analog Comparator aus
         					;Timer 1 ist aus
         					;UART ist aus
         	
000014 e080      	ldi temp, 0b00000000		;alle Input
000015 bb87      	out DDRB, temp
000016 ef8f      	ldi temp, 0b11111111		;alle Pullup
000017 bb88      	out PORTB, temp
         	
         
000018 e281      	ldi temp, 0b00100001		;PB0+PB5 Output, der Rest Input
000019 bb81      	out DDRD, temp
00001a ef8f      	ldi temp, 0b11111111		;alle auf Pullup oder High
00001b bb82      	out PORTD, temp
         
00001c e080      	ldi temp, 0b00000000		;fallende Flanke an INT0 und INT1 für Interruptrequest
00001d bf85      	out MCUCR, temp
00001e ec80      	ldi temp, 0b11000000		;Interrupt enable für INT0 und INT1
00001f bf8b      	out GIMSK, temp
000020 e482      	ldi temp, 0b01000010 		;Timer0 Overflow + Timer1 Output Compare Interrupt enable
000021 bf89      	out TIMSK, temp
         
000022 9478      	sei				;global Interrupt enable
         
000023 2777      	clr modus			;Modus-Register gelöscht
000024 27aa      	clr watchdog_count
         ;*****************
         
         
          end:
000025 95a3      	inc watchdog_count
000026 36a4      	cpi watchdog_count, 100		;alle 100 Schleifen Watchdog-Reset
000027 f169      	breq clear_watchdog
         
000028 3012      	cpi timer, 2			;ca. 0,1 s nach letztem Low-Pegel wieder Aktivierung des IR-Empfangs
000029 f171      	breq ir_enable
         	
         
         ;LEITUNGSEMULATION:
         ;****************************
          clk_keyb:
00002a 99be      	sbic  DDRB, clkkeyb		;Ist clkkeyb Ausgang?
00002b c007      	rjmp data_keyb			;dann Pin-Abfrage überspringen
00002c 99b6      	sbic PINB, clkkeyb		;Clock-Leitung Keyboard auf Low?
00002d c01b      	rjmp clk_keyb_2
00002e 2788      	clr temp			;Interrupt disable für INT0 und INT1
00002f bf8b      	out GIMSK, temp
000030 2711      	clr timer
000031 98c3      	cbi PORTB, clkpc		;clkpc auf low(Tristate)
000032 9abb      	sbi DDRB, clkpc			;clkpc als Output
          data_keyb:
000033 99bf      	sbic  DDRB, datakeyb		;Ist datakeyb Ausgang?
000034 c004      	rjmp clk_pc			;dann Pin-Abfrage überspringen
000035 99b7      	sbic PINB, datakeyb		;Daten-Leitung Keyboard auf Low?
000036 c015      	rjmp data_keyb_2
000037 98c4      	cbi PORTB, datapc		;datapc auf low(Tristate)
000038 9abc      	sbi DDRB, datapc		;datapc als Output
          clk_pc:
000039 99bb      	sbic  DDRB, clkpc		;Ist clkpc Ausgang?
00003a c007      	rjmp data_pc			;dann Pin-Abfrage überspringen
00003b 99b3      	sbic PINB, clkpc		;Clock-Leitung PC auf Low?
00003c c012      	rjmp clk_pc_2
00003d 2788      	clr temp			;Interrupt disable für INT0 und INT1
00003e bf8b      	out GIMSK, temp
00003f 2711      	clr timer
000040 98c6      	cbi PORTB, clkkeyb		;clkkeyb auf low(Tristate)
000041 9abe      	sbi DDRB, clkkeyb		;clkkeyb als Output
          data_pc:
000042 99bc      	sbic  DDRB, datapc		;Ist datapc Ausgang?
000043 cfe1      	rjmp end			;dann Pin-Abfrage überspringen
000044 99b4      	sbic PINB, datapc		;Daten-Leitung PC auf Low?
000045 c00c      	rjmp data_pc_2
000046 98c7      	cbi PORTB, datakeyb		;datakeyb auf low(Tristate)
000047 9abf      	sbi DDRB, datakeyb		;datakeyb als Output
         
         
000048 cfdc      	rjmp end			;Endlosschleife auf der Stelle
         
         
          clk_keyb_2:
000049 98bb      	cbi DDRB, clkpc			;clkpc als Input(Tristate)
00004a 9ac3      	sbi PORTB, clkpc		;clkpc auf High(Pullup)
00004b cfe7      	rjmp data_keyb
         
         
          data_keyb_2:
00004c 98bc      	cbi DDRB, datapc		;datapc als Input(Tristate)
00004d 9ac4      	sbi PORTB, datapc		;datapc auf High(Pullup)
00004e cfea      	rjmp clk_pc
         
          clk_pc_2:
00004f 98be      	cbi DDRB, clkkeyb				
000050 9ac6      	sbi PORTB, clkkeyb			
000051 cff0      	rjmp data_pc
         
          data_pc_2:
000052 98bf      	cbi DDRB, datakeyb			
000053 9ac7      	sbi PORTB, datakeyb
000054 cfd0      	rjmp end
         ;***************************
         
         
         
         
          clear_watchdog:
000055 95a8      	wdr				;Watchdog zurücksetzen
000056 27aa      	clr watchdog_count
000057 cfd2      	rjmp clk_keyb
         
         
          ir_enable:
000058 ec80      	ldi temp, 0b11000000		;Interrupt enable für INT0 und INT1
000059 bf8b      	out GIMSK, temp
00005a e013      	ldi timer, 3
00005b cfce      	rjmp clk_keyb
         
         	
         
         
         
         
         
         
         ;IR-EMPFANG
         ;++++++++++++++++++++++++
          ir_rec:
00005c b60f      	in S, SREG			;Statusregister retten
         
00005d 27aa      	clr watchdog_count		;Schleifen-Zähler rückgesetzt, jedoch ohne "wdr", d.h. zwischen zwei
         					;Interruptroutinen müssen immer min. 100 Schleifen liegen, sonst Reset
00005e 2788      	clr temp			;externe Interrupts deaktivieren
00005f bf8b      	out GIMSK, temp
000060 9478      	sei				;globalen Interrupt aktivieren (wird von Hardware deaktiviert)
         	
000061 e081      	ldi temp, 1			;Timer0: Takt=Clock
000062 bf83      	out TCCR0, temp
         
000063 2711      	clr timer
000064 2fd7      	mov modus_save, modus
000065 6071      	sbr modus, flash_enable		;LED-Blinken aus
         
          start1:
000066 3111      	cpi timer, 17			;Startbit länger als 1,1ms?
000067 f550      	brsh fault			;dann Fehler
000068 9b82      	sbis PIND, ir_input
000069 cffc      	rjmp start1
         
00006a 2f81      	mov temp, timer			;halbe Dauer des Startbits wird gespeichert
00006b 2711      	clr timer
         
00006c 2e18      	mov ref1, temp
00006d 9416      	lsr ref1			;halbe Bitdauer/2 = viertel Bitdauer
00006e 2c21      	mov ref2, ref1
00006f 0e18      	add ref1, temp			;ref1 = 3/4 Bitdauer
000070 0f88      	lsl temp
000071 0e28      	add ref2, temp			;ref2 = 5/4 Bitdauer
         
          start2:
000072 1511      	cp timer, ref1			;High-Period von Startbit2 länger als 3/4 Bitdauer
000073 f4f0      	brsh fault			;dann Fehler
         	
000074 9982      	sbic PIND, ir_input
000075 cffc      	rjmp start2
         	
000076 2711      	clr timer
000077 e00c      	ldi bitcnt, 12
000078 2733      	clr command
000079 2722      	clr system
         
          sample:
00007a 1511      	cp timer, ref1
00007b f3f0      	brlo sample			;Warte 3/4 Bitdauer (Low-Period Startbit2+ 1/4 Bitdauer)
         
00007c 9982      	sbic PIND, ir_input		;Wenn 0, dann zu bit_is_a_0
00007d c009      	rjmp bit_is_a_1
         
          bit_is_a_0:
00007e 9488      	clc				;"0" speichern
00007f 1f33      	rol command
000080 1f22      	rol system			;wenn "command" voll, rollen die als erstes empfangenen			
         					;Bits ins "system"-Register
          bit_is_a_0a:
000081 1512      	cp timer, ref2
000082 f478      	brsh fault
000083 9b82      	sbis PIND, ir_input
000084 cffc      	rjmp bit_is_a_0a
         
000085 2711      	clr timer
000086 c008      	rjmp nextbit
         
         
          bit_is_a_1:
000087 9408      	sec				;"1" speichern
000088 1f33      	rol command
000089 1f22      	rol system
         
          bit_is_a_1a:
00008a 1512      	cp timer, ref2
00008b f430      	brsh fault
00008c 9982      	sbic PIND, ir_input
00008d cffc      	rjmp bit_is_a_1a
         
00008e 2711      	clr timer
         
          nextbit:
00008f 950a      	dec bitcnt			;wenn bitcnt>1
000090 f749      	brne sample			;empfange nächstes Bit
000091 c001      	rjmp ready
         
         
         ;FEHLERBEHANDLUNG
         ;*******************
          fault:
000092 c031      	rjmp irrec_end
         ;******************	
         
         
          ready:
000093 2f83      	mov temp, command
000094 1f88      	rol temp			;in "command" befinden sich 8 Bit, davon 2 Systembits
000095 1f22      	rol system			;diese werden ins "system"-Register gerollt
000096 1f88      	rol temp
000097 1f22      	rol system
         	
000098 fb25      	bst system, 5			;das "control"-Bit wird als Bit6 des "command"-Registers
000099 f936      	bld command, 6			;gespeichert
         
00009a 733f      	andi command, 0b00111111		
00009b 712f      	andi system, 0b00011111
         
         
         
         ;EMPFANGSBESTÄTIGUNG
         ;*******
00009c e290      	ldi transmit, 0b00100000	;rote LED ändert ihren Zustand bei jedem Durchlauf
00009d b382      	in temp, PORTD
00009e 2789      	eor temp, transmit		;transmit wird als Hilfsvariable ausgeliehen (gerade nicht benutzt)
00009f bb82      	out PORTD, temp
         ;*******
         
0000a0 ff72      	sbrs modus, learn_mode		;Programmiermodus?
0000a1 c002      	rjmp translate
0000a2 d0d4      	rcall learning
0000a3 c020      	rjmp irrec_end
         	
         
         
          translate:
0000a4 d121      	rcall decode
0000a5 3040      	cpi keyb_code_1, 0		;Ist überhaupt eine gültige Taste gedrückt?
0000a6 f0e9      	breq irrec_end
0000a7 3050      	cpi keyb_code_2, 0		;Spezialtaste oder Tastenkombination? (wenn ja, dann command ungleich 0)
0000a8 f0b9      	breq normal
0000a9 3e40      	cpi keyb_code_1, $E0		;Spezialtaste?
0000aa f059      	breq special
         
          kombi:
0000ab 2f34      	mov command, keyb_code_1
0000ac d072      	rcall make
0000ad 2f35      	mov command, keyb_code_2
0000ae d070      	rcall make
0000af d072      	rcall break_pre
0000b0 2f34      	mov command, keyb_code_1
0000b1 d06d      	rcall break
0000b2 d06f      	rcall break_pre
0000b3 2f35      	mov command, keyb_code_2
0000b4 d06a      	rcall break
         	
0000b5 c00e      	rjmp irrec_end
         
          special:
0000b6 2f34      	mov command, keyb_code_1
0000b7 d067      	rcall make
0000b8 2f35      	mov command, keyb_code_2
0000b9 d065      	rcall make
0000ba 2f34      	mov command, keyb_code_1
0000bb d063      	rcall break
0000bc d065      	rcall break_pre
0000bd 2f35      	mov command, keyb_code_2
0000be d060      	rcall break
         	
0000bf c004      	rjmp irrec_end
         	
          normal:
0000c0 2f34      	mov command, keyb_code_1
0000c1 d05d      	rcall make
0000c2 d05f      	rcall break_pre
0000c3 d05b      	rcall break
         
         
         
          irrec_end:
0000c4 2f7d      	mov modus, modus_save	
0000c5 e085      	ldi temp, 5			;Timer0: Takt=Clock/1024
0000c6 bf83      	out TCCR0, temp
0000c7 ef8f      	ser temp
0000c8 bf8a      	out GIFR, temp			;External Interrupt Flag löschen
0000c9 bf8b      	out GIMSK, temp			;External Interrupts aktivieren
0000ca be0f      	out sreg, S			;Statusregister wiederherstellen
0000cb 9518      reti
         ;+++++++++++++++++++++++++
         
         
         
         
         
         
         
         
         
         
         ;TIMER-ÜBERLAUF (alle 65ms, wenn Takt=4Mhz)	
         ;+++++++++++++++++
          tim0_int:
0000cc b60f      	in S, sreg
         
0000cd 9513      	inc timer
0000ce 956a      	dec var_wait
         
0000cf fd70      	sbrc modus, flash_en		;LED-Blinken ausgeschaltet?
0000d0 c009      	rjmp tim0_int_end		;dann LED-Blinken überspringen
         
0000d1 95c3      	inc flash
0000d2 30c8      	cpi flash, 8			;LED ändert ihren Zustand alle 8*65ms=500ms d.h. f=2Hz
0000d3 f009      	breq led_toggle
0000d4 c005      	rjmp tim0_int_end
         
          led_toggle:
0000d5 27cc      	clr flash
0000d6 e091      	ldi transmit, 0b00000001	;gelbe LED ändert ihren Zustand bei jedem Durchlauf
0000d7 b382      	in temp, PORTD
0000d8 2789      	eor temp, transmit		;transmit wird als Hilfsvariable ausgeliehen (gerade nicht benutzt)
0000d9 bb82      	out PORTD, temp
         	
          tim0_int_end:	
0000da be0f      	out sreg, S
0000db 9518      	reti	
         ;+++++++++++++++++
         
         
         
         
         
         
         
         ;AUSGABE EINES BYTES AN DEN PC
         ;+++++++++++++++++++++++++++++++++++
          compare_int:
0000dc b60f      	in S, sreg			;Statusregister retten, Interrupts sind inaktiv
         
0000dd 9bb3      	sbis PINB, clkpc		;Taktleitung High?
0000de c002      	rjmp setClk
         	
         
          clrClk:
0000df d039      	rcall clk_low
0000e0 c019      	rjmp compare_int_end
         
         ;******************
          setClk:
0000e1 d03a      	rcall clk_high			;dann auf High setzen
0000e2 e064      	ldi var_wait, 4			;4*5us = 20us
0000e3 d01d      	rcall waitshort
         	
0000e4 3008      	cpi bitcnt, 8			;alle 8 Bit gesendet?
0000e5 f051      	breq paritybit			;dann Paritätsbit senden
0000e6 3009      	cpi bitcnt, 9			;auch Paritätsbit gesendet?
0000e7 f069      	breq stopbit			;dann Stoppbit senden
0000e8 300a      	cpi bitcnt, 10			;auch Stoppbit gesendet?
0000e9 f069      	breq transmit_end		;dann Schluß
         	
0000ea 9597      	ror transmit
0000eb f010      	brcs setData
         
          		clrData:
0000ec d026      			rcall data_low
0000ed c00b      			rjmp nextbit1
         
          		setData:
0000ee d027      			rcall data_high
0000ef c009      			rjmp nextbit1
         
          		paritybit:				;Paritätsroutine
0000f0 f416      			brtc parity_low			;Parity-Bit low?
         			
0000f1 d024      			rcall data_high
0000f2 c006      			rjmp nextbit1
         	
          			parity_low:			;dann springen
0000f3 d01f      				rcall data_low
0000f4 c004      				rjmp nextbit1		
         
          		stopbit:
0000f5 d020      			rcall data_high
0000f6 c002      			rjmp nextbit1
         
          		transmit_end:
0000f7 7f7d      			cbr modus, do_transmit		;Transmission end
0000f8 c001      			rjmp compare_int_end
         
         
          	nextbit1:
0000f9 9503      		inc bitcnt				;wieder ein Bit gesendet
         ;*******************
         		
         	
          compare_int_end:
0000fa be0f      	out sreg, S
0000fb 9518      	reti
         ;++++++++++++++++++++++++++++++++
         
         
         
         
         
         
         
         ;WAITROUTINE (DAUER ABHÄNGIG VON CLOCKVORTEILER UND var_wait)
         ;+++++++++++++++++++++
          wait:
0000fc 95a8      	wdr
0000fd 3060      	cpi var_wait, 0
0000fe f009      	breq wait_end
0000ff cffc      	rjmp wait
         
          wait_end:
000100 9508      	ret
         ;+++++++++++++++++++++
         
         
         
         
         
         
         ;WARTESCHLEIFE 20us
         ;+++++++++++++++++++++
          waitshort:
000101 3060      	cpi var_wait, 0			;1 Cycle
000102 f079      	breq waitshort_end		;1 Cycle if false, 2 if true
000103 0000      	nop				;13*1 Cycle
000104 0000      	nop
000105 0000      	nop
000106 0000      	nop
000107 0000      	nop
000108 0000      	nop
000109 0000      	nop
00010a 0000      	nop
00010b 0000      	nop
00010c 0000      	nop
00010d 0000      	nop
00010e 0000      	nop
00010f 0000      	nop
000110 956a      	dec var_wait			;1 Cycle
000111 cfef      	rjmp waitshort			;2 Cycle
         
          waitshort_end:
000112 9508      	ret
         
         ;eine Schleife dauert 18 Cycle, d.h. knapp 5us. Die fehlende Cycle haben ihren
         ;Grund in der zusätzlichen Verzögerung von ca. 1us, die beim Ein- und Ausspringen aus der Routine
         ;entsteht, sowie in den Verzögerungen im Programmablauf der aufrufenden Routinen.
         ;+++++++++++++++++++++
         
         
         
         
         
         
          data_low:
000113 98c4      	cbi PORTB, datapc		;datapc auf low(Tristate)
000114 9abc      	sbi DDRB, datapc		;datapc als Output
000115 9508      ret
         
         
         
          data_high:
000116 98bc      	cbi DDRB, datapc		;datapc als Input(Tristate)
000117 9ac4      	sbi PORTB, datapc		;datapc auf High(Pullup)
000118 9508      ret
         	
         
          clk_low:
000119 98c3      	cbi PORTB, clkpc		;clkpc auf low(Tristate)
00011a 9abb      	sbi DDRB, clkpc			;clkpc als Output
00011b 9508      ret
         
         
         
         
          clk_high:
00011c 98bb      	cbi DDRB, clkpc			;clkpc als Input(Tristate)
00011d 9ac3      	sbi PORTB, clkpc		;clkpc auf High(Pullup)
00011e 9508      ret
         	
         
         
         
         
         
         
         
         
         ;PC-KOMMUNIKATION:
         ;++++++++++++++++++++++++++++++++++
         
          break:
          make:	
00011f d01f      	rcall find_parity
000120 2f93      	mov transmit, command		;lade command-Byte in Sendepuffer
000121 c002      	rjmp start
         
         
         
         
         ;BREAK-CODE SENDEN
         ;*******************
          break_pre:
000122 ef90      	ldi transmit, $F0		;lade Breakpräfix in Sendepuffer
000123 9468      	set				;Parity-Bit high
         ;*******************
         
         
         
         
          start:
000124 6072      	sbr modus, do_transmit
000125 2700      	clr bitcnt
         	
000126 9bb3      	sbis PINB, clkpc		;Ist der PC bereit?
000127 c016      	rjmp send_to_keyb_end		;wenn nicht, dann beenden
000128 9bb4      	sbis PINB, datapc
000129 c014      	rjmp send_to_keyb_end
         
00012a dfe8      	rcall data_low			;Datenleitung auf Low
         	
00012b e064      	ldi var_wait, 4			;4*5us = 20us
00012c dfd4      	rcall waitshort
         
00012d dfeb      	rcall clk_low			;Taktleitung auf Low
         	
00012e e089      	ldi temp, 0b00001001		;Timer1 Start, Clear Timer on Compare Match
00012f bd8e      	out TCCR1B, temp
          complete:
000130 fd71      	sbrc modus, transmit_done	;warten, bis Übertragung zu Ende
000131 cffe      	rjmp complete
         	
         	
         
         	;COMPARE-FUNKTION NEU INITIALISIEREN FÜR KORREKTES TIMING
         	;**********************
000132 e082      	ldi temp, 0b00000010
000133 bf89      	out TIMSK, temp			;Interrupt Compare Match disabled
000134 2788      	clr temp
000135 bd8e      	out TCCR1B, temp		;Timer1 anhalten
000136 2788      	clr temp
000137 bd8d      	out TCNT1H, temp
000138 2788      	clr temp
000139 bd8c      	out TCNT1L, temp		;Timer1 auf 0 setzen
00013a e482      	ldi temp, 0b01000010		;Interrupt enable
00013b bf89      	out TIMSK, temp
         	;*********************
         
         
00013c e164      	ldi var_wait, 20		;1,3ms warten, dann nächstes Byte (für Tastaturpuffer im PC)
00013d dfbe      	rcall wait
         
         
          send_to_keyb_end:
00013e 9508      	ret
         ;++++++++++++++++++++++++
         
         
         
         
         
         
         ;PARITÄT TESTEN
         ;****************
          find_parity:
00013f 2f93      	mov transmit, command
000140 2700      	clr bitcnt
000141 2788      	clr temp
000142 9488      	clc
         
          find_parity_1:
000143 3008      	cpi bitcnt, 8			;Schleife 8mal durchlaufen?
000144 f029      	breq find_parity_2		;dann springen
000145 1f99      	rol transmit			;Command durch C rollen
000146 f408      	brcc next			;bei jedem positiven Bit
         
000147 9583      	inc temp			;temp erhöhen
         
          		next:
000148 9503      			inc bitcnt
000149 cff9      			rjmp find_parity_1
         
          find_parity_2:
00014a 3081      	cpi temp, 1			;ist temp ungerade (1,3,5,7)?
00014b f041      	breq odd
00014c 3083      	cpi temp, 3
00014d f031      	breq odd
00014e 3085      	cpi temp, 5
00014f f021      	breq odd
000150 3087      	cpi temp, 7
000151 f011      	breq odd
         
000152 9468      	set
000153 9508      	ret
         
          odd:
000154 94e8      	clt				;dann Parität löschen
000155 9508      	ret
         ;*******************
         
         
         
         
         
         
         ;TASTENDRUCKBEHANDLUNGSROUTINE:
         ;++++++++++++++++++++++++++++++++++++++
          touch:
000156 b60f      	in S, sreg
000157 2788      	clr temp			;externe Interrupts deaktivieren
000158 bf8b      	out GIMSK, temp
         
000159 e081      	ldi temp, 1			;Timer0: Takt=Clock
00015a bf83      	out TCCR0, temp
         
00015b 9478      	sei				;globalen Interrupt aktivieren (wird von Hardware deaktiviert)
         	
00015c e46e      	ldi var_wait, 78		;5ms warten
00015d df9e      	rcall wait
         	
00015e 9983      	sbic PIND, tast_input		;springe, wenn High, zum Ende
00015f c00f      	rjmp touch_end
         
000160 e084      	ldi temp, 0b00000100		;Toggle Programmiermodus
000161 2778      	eor modus, temp
         
000162 fd72      	sbrc modus, learn_mode		;Programmiermodus?
000163 c002      	rjmp set_flash
         	
000164 7f7e      	cbr modus, flash_enable
000165 c002      	rjmp tremble
         
         
          set_flash:
000166 6071      	sbr modus, flash_enable		;LED-Blinken aus
000167 9890      	cbi PORTD, yellow		;gelbe LED dauerhaft an	
         
         
         
          tremble:
000168 95a8      	wdr
000169 9b83      	sbis PIND, tast_input
00016a cffd      	rjmp tremble
         	
00016b e46e      	ldi var_wait, 78		;5ms warten
00016c df8f      	rcall wait
         	
00016d 9b83      	sbis PIND, tast_input
00016e cff9      	rjmp tremble
         	
          touch_end:
00016f e085      	ldi temp, 5			;Timer0: Takt=Clock/1024
000170 bf83      	out TCCR0, temp
000171 ef8f      	ser temp
000172 bf8a      	out GIFR, temp			;External Interrupt Flag löschen
000173 ec80      	ldi temp, 0b11000000
000174 bf8b      	out GIMSK, temp			;External Interrupts aktivieren
000175 be0f      	out sreg, S
000176 9518      	reti
         ;+++++++++++++++++++++++++++++++++++++
         
         
         
         
         
         
         
         
         
         
         ;PROGRAMMIERMODUS;
         ;+++++++++++++++++++++++++++++++++++++++++++++++
          learning:
000177 99e1      	sbic EECR, EEWE			;warte, bis EEPROM bereit
000178 cffe      	rjmp learning
000179 e0b1      	ldi byte_count, 1	
         
          wait_for_touch:
00017a 95a8      	wdr	
00017b 99b7      	sbic PINB, datakeyb
00017c cffd      	rjmp wait_for_touch
         	
00017d 2744      	clr keyb_code_1
00017e 2700      	clr bitcnt
         
         
          real_query:
00017f 99b6      	sbic PINB, clkkeyb
000180 cffe      	rjmp real_query
         
         ;*************
         	
          clock_rise:				;warte auf positive Taktflanke
000181 9bb6      	sbis PINB, clkkeyb
000182 cffe      	rjmp clock_rise
         
          clock_fall:
000183 99b6      	sbic PINB, clkkeyb		;warte auf negative Taktflanke
000184 cffe      	rjmp clock_fall
         
000185 9bb7      	sbis PINB, datakeyb		;Ist die Datenleitung auf Low?
000186 c003      	rjmp bit_is_0
         
          bit_is_1:
000187 9408      	sec
000188 9547      	ror keyb_code_1
000189 c002      	rjmp nextb
         
          bit_is_0:
00018a 9488      	clc 
00018b 9547      	ror keyb_code_1
         	
         
          nextb:
00018c 9503      	inc bitcnt
00018d 3008      	cpi bitcnt, 8
00018e f011      	breq parity
         	
00018f 2711      	clr timer
000190 cff0      	rjmp clock_rise
         ;*************
         
         
          parity:
000191 933f      	push command		
000192 2f34      	mov command, keyb_code_1	;die Paritätsroutine funktioniert nur mit command
000193 dfab      	rcall find_parity		;erwartetes Paritätsbit ermitteln und in T speichern
000194 913f      	pop command	
         
          par_rise:				;warte auf positive Taktflanke
000195 9bb6      	sbis PINB, clkkeyb
000196 cffe      	rjmp par_rise
         
          par_fall:
         
000197 99b6      	sbic PINB, clkkeyb		;warte auf negative Taktflanke
000198 cffe      	rjmp par_fall
         
000199 9bb7      	sbis PINB, datakeyb		;Ist die Datenleitung, d.h. das Paritätsbit Low?
00019a c002      	rjmp parity_is_0
         
          parity_is_1:
00019b f02e      	brts rec_from_keyb_end		;wenn erwartete Parität mit empfangener übereinstimmt, dann Ende
00019c c001      	rjmp keyb_fault
         
          parity_is_0:
00019d f41e      	brtc rec_from_keyb_end
         
         	
          keyb_fault:
00019e e065      	ldi var_wait,5			;warte Stopbit ab
00019f df5c      	rcall wait
0001a0 9508      	ret
         
         
         	
          rec_from_keyb_end:
0001a1 30b2      	cpi byte_count, 2
0001a2 f039      	breq byte2
         
          byte1:
0001a3 2f54      	mov keyb_code_2, keyb_code_1	;lege eine Kopie in keyb_code_2 ab
         
0001a4 0f33      	lsl command			;command verdoppeln
0001a5 d019      	rcall write_EEPROM		;ins EEPROM schreiben
         
0001a6 e065      	ldi var_wait,5			;warte Stopbit ab
0001a7 df54      	rcall wait
0001a8 95b3      	inc byte_count			
0001a9 cfd0      	rjmp wait_for_touch		;wieder zum Anfang springen und zweites Byte lesen
         
          byte2:
0001aa e290      	ldi transmit, 0b00100000	;rote LED ändert ihren Zustand bei jedem Durchlauf
0001ab b382      	in temp, PORTD
0001ac 2789      	eor temp, transmit		;transmit wird als Hilfsvariable ausgeliehen
0001ad bb82      	out PORTD, temp
         
0001ae 3f40      	cpi keyb_code_1, $F0		;ist das zweite Byte nur das Breakpräfix?
0001af f069      	breq clear_EEPROM		;dann schreibe 0 in die zweite EEPROM-Adresse
0001b0 1745      	cp keyb_code_1, keyb_code_2	;ist das zweite Byte dasselbe wie das erste?
0001b1 f059      	breq clear_EEPROM		;dann schreibe 0 in die zweite EEPROM-Adresse
         
          write_byte2:
0001b2 99e1      	sbic EECR, EEWE			;warte, bis EEPROM bereit
0001b3 cffe      	rjmp write_byte2	
0001b4 9533      	inc command
0001b5 d009      	rcall write_EEPROM
         	
0001b6 e084      	ldi temp, 4			;Timer0: Takt=Clock/256
0001b7 bf83      	out TCCR0, temp
0001b8 e06c      	ldi var_wait, 12		;warte 200ms
0001b9 df42      	rcall wait
0001ba e081      	ldi temp, 1			;Timer0: Takt=Clock
0001bb bf83      	out TCCR0, temp
0001bc 9508      ret
         
         
         
          clear_EEPROM:
0001bd 2744      	clr keyb_code_1
0001be cff3      	rjmp write_byte2
         ;++++++++++++++++++++++++++++++++++++++++++++++++
         
         
         
         
         
         
         
         ;EEPROM BESCHREIBEN (Addresse in command, Daten in command1)
         ;++++++++++
          write_EEPROM:
0001bf bb3e      	out EEAR, command		;ins EEPROM-Adreßregister schreiben
0001c0 bb4d      	out EEDR, keyb_code_1		;schreibe das empfangene Byte ins EEPROM-Datenregister
0001c1 94f8      	cli				;global Interrupt disable
0001c2 9ae2      	sbi EECR, EEMWE			;master write enable
0001c3 9ae1      	sbi EECR, EEWE			;EEPROM write strobe
0001c4 9478      	sei				;global Interrupt enable
0001c5 9508      ret	
         ;+++++++++
         
         
         
         
         
         
         
         ;++++++++++++++++++++
          decode:
0001c6 99e1      	sbic EECR, EEWE			;warte, bis bereit
0001c7 cffe      	rjmp decode
         
0001c8 0f33      	lsl command			;verdopple command
0001c9 bb3e      	out EEAR, command		;und beschreibe damit das Adreßregister
0001ca 9ae0      	sbi EECR, EERE			;EEPROM read strobe
0001cb b34d      	in keyb_code_1, EEDR		;lade keyb_code_1 mit dem Datenregister
         
          decode_2:	
0001cc 99e1      	sbic EECR, EEWE			;nochmal dasselbe
0001cd cffe      	rjmp decode_2
         
0001ce 9533      	inc command
0001cf bb3e      	out EEAR, command
0001d0 9ae0      	sbi EECR, EERE
0001d1 b35d      	in keyb_code_2, EEDR
         					
0001d2 9508      	ret
         ;++++++++++++++++++++
Assembly complete with no errors.
