summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Fernbedienung.asm500
1 files changed, 500 insertions, 0 deletions
diff --git a/Fernbedienung.asm b/Fernbedienung.asm
new file mode 100644
index 0000000..c0b3ae8
--- /dev/null
+++ b/Fernbedienung.asm
@@ -0,0 +1,500 @@
+/*
+ * Fernbedienung.asm
+ *
+ * Created: 08.10.2015 14:35:11
+ * Author: Erich
+ */
+
+
+.DEF sbuff0 = r0 ; serieller Puffer 0 bis
+.DEF sbuff1 = r1
+.DEF sbuff2 = r2
+.DEF sbuff3 = r3
+.DEF sbuff4 = r4 ; 4
+.DEF lastB = r5 ; letzter Zustand von PINB
+.DEF lt1p0l = r6 ; letzte Flankenposition PINB0 (Timer 1) low
+.DEF lt1p0h = r7 ; dito high
+.DEF lt1p1l = r8 ; dito PINB1 low
+.DEF lt1p1h = r9 ; dito high
+.DEF bcnt0 = r10 ; Bitzähler PINB0
+.DEF bcnt1 = r11 ; Bitzähler PINB1
+.DEF t1moml = r12 ; momentane Position Timer 1 low
+.DEF t1momh = r13 ; dito high
+.DEF aender = r14 ; Änderungen in PINB
+
+ rjmp RESET
+ reti
+ reti
+ reti
+ reti
+ reti
+ reti
+ reti
+ reti
+ rjmp TIMER0COMPA ; Timer0 Compare Match A
+ reti
+ reti
+ reti
+ reti
+ reti
+ reti
+ reti
+
+ RESET:
+ ldi r16,low(RAMEND) ; Stackpointer initialisieren
+ out SPL,r16
+
+ ldi r16,0x80
+ out CLKPR,r16
+ ldi r16,0x00
+ out CLKPR,r16 ; System-Vorteiler auf 1
+
+ ldi r16,0x03
+ out PRR,r16 ; Clocks: Timer/Counter 1 an, Timer/Counter 0 an, USI aus, ADC aus ... zum Stromsparen
+ ldi r16,0x00
+ out WDTCSR,r16 ; Watchdog aus
+
+ ldi r16,0x02
+ out PORTA,r16 ; 6x n.d., PORTA1 high (RS232-Sender), kein Pull-up an PORTA0 (RS232-Empfänger)
+ ldi r16,0x00
+ out PORTB,r16 ; 2x n.d., kein Pull-up an PORTB1 (IR-Empfänger 1) & PORTB0 (IR-Empfänger 0)
+ ldi r16,0x06
+ out DDRA,r16 ; Ausgänge: PORTA1 (RS232-Sender), PORTA2 (Test)
+ ldi r16,0x00
+ out DDRB,r16 ; keine Ausgänge auf PORTB
+
+ ldi r16,0x02 ; Timer0 Compare-Match-A Interrupt an
+ out TIMSK0,r16
+
+ ldi r16,104
+ out OCR0A,r16
+ ldi r16,0x02 ; CTC-Modus: Periode = OCR0A = 104 -> 9600 baud
+ out TCCR0A,r16
+ ldi r16,0x02 ; Vorteiler 8 für Timer 0
+ out TCCR0B,r16
+
+ ldi r16,0x02 ; Vorteiler 8 für Timer 1
+ out TCCR1B,r16
+
+ ldi r16,0x21 ; Start-Bit und
+ mov sbuff0,r16
+ ldi r16,0x15 ; 0x48 ('H') und Start-Bit und
+ mov sbuff1,r16
+ ldi r16,0x56 ; 0x61 ('a') und Start-Bit und
+ mov sbuff2,r16
+ ldi r16,0x48 ; 0x21 ('!') und Start-Bit
+ mov sbuff3,r16
+ ldi r16,0x0d ; und 0x0d (CR)
+ mov sbuff4,r16
+
+ in lt1p0l,TCNT1L
+ in lt1p0h,TCNT1H
+ movw lt1p1l,lt1p0l
+
+ in lastB,PINB
+ ldi r16,0x03
+ and lastB,r16
+
+ sei
+
+MAINLOOP:
+ in r16,PINB
+
+ andi r16,0x03
+ eor r16,lastB
+ breq MAINLOOP ; keine Änderung
+
+ eor lastB,r16 ; Änderung übernehmen
+ mov aender,r16 ; Änderungen merken
+
+ in t1moml,TCNT1L
+ in t1momh,TCNT1H ; Zählerstand holen
+ movw r16,t1moml ; und kopieren
+
+ sbrs aender,0
+ rjmp PIN0WACKELTNICHT
+
+ sub r16,lt1p0l
+ sbc r17,lt1p0h ; r17:r16 = TimeDiff
+
+ movw lt1p0l,t1moml ; aktuellen Zählerstand als alten setzen
+
+ subi r16,0xb1
+ sbci r17,0x01 ; - 865/2 = 0x01b1 = halbes Bit
+
+ brcs RESET0 ; zu kurzes Bit -> Fehler!
+
+ subi r16,0x61
+ sbci r17,0x03 ; - 865 = 0x0361 = kurzes Bit
+ brcc KEINKURZESBIT0
+
+ clr r16 ; wird einfach gespeichert!
+ inc bcnt0
+ rjmp WEITER0
+KEINKURZESBIT0:
+ subi r16,0x61
+ sbci r17,0x03 ; - 865 = 0x0361 = (noch ein) kurzes Bit (= langes Bit)
+ brcc RESET0 ; zu langes Bit -> Fehler
+
+ inc bcnt0
+ inc bcnt0
+ ldi r16,0x01 ; wird doppelt gespeichert!
+
+WEITER0:
+ clc
+ sbrs lastB,0 ; alten Pinzustand
+ sec ; nach C
+ lds r17,(0x0060) ; das erste der insgesamt vier Bytes von empfangenen Bits
+ rol r17
+ sts (0x0060),r17
+ lds r17,(0x0061)
+ rol r17
+ sts (0x0061),r17
+ lds r17,(0x0062)
+ rol r17
+ sts (0x0062),r17
+ lds r17,(0x0063)
+ rol r17
+ sts (0x0063),r17
+ brcs RESET0 ; es kamen mehr als 32 Bits an -> Fehler!
+
+ subi r16,0x01
+ brcc WEITER0
+
+ ldi r16,0x1a
+ cp bcnt0,r16
+
+ brcs ENDE0 ; noch keine 26 klein-Bits angekommen -> Ende
+
+ ldi r16,0x1c
+ cp bcnt0,r16
+ brcc RESET0 ; mehr als 27 klein-Bits angekommen -> Fehler!
+
+ sbrs lastB,0 ; jetziger Zustand ist high?
+ rjmp ENDE0 ; nein -> dann ist es auch nicht fertig!
+
+ lds r16,(0x0063) ; das letzte Byte
+ ori r16,0x40 ; die übrigen Bits (also die Bits, die eben nicht empfangen wurden)
+ sts (0x0063),r16 ; des zuerst "empfangenen" Bytes werden alternierend auf 1 gesetzt
+
+ ldi r26,0x60
+ ldi r27,0x00 ; Startadresse in den Speicher,
+ mov r16,bcnt0 ; Bitanzahl in r16
+ rcall VERSENDEN ; und ab durch die serielle Schnittstelle
+
+RESET0:
+ ldi r16,0x05 ; Startbit + '01'=0 (also 0. Empfänger)
+ sts (0x0060),r16
+ ldi r16,0x00
+ sts (0x0061),r16
+ sts (0x0062),r16
+ sts (0x0063),r16 ; empfangene Bits initialisieren
+ clr bcnt0 ; Bit-Zähler auf 0 setzen
+
+ENDE0:
+PIN0WACKELTNICHT:
+
+ sbrs aender,1
+ rjmp MAINLOOP
+ movw r16,t1moml ; Zählerstand rücksichern
+
+ sub r16,lt1p1l
+ sbc r17,lt1p1h ; r17:r16 = TimeDiff
+
+ movw lt1p1l,t1moml ; aktuellen Zählerstand als alten setzen
+
+ subi r16,0xb1
+ sbci r17,0x01 ; - 865/2 = 0x01b1 = halbes Bit
+
+ brcs RESET1 ; zu kurzes Bit -> Fehler!
+
+ subi r16,0x61
+ sbci r17,0x03 ; - 865 = 0x0361 = kurzes Bit
+ brcc KEINKURZESBIT1
+
+ clr r16 ; wird einfach gespeichert!
+ inc bcnt1
+ rjmp WEITER1
+KEINKURZESBIT1:
+ subi r16,0x61
+ sbci r17,0x03 ; - 865 = 0x0361 = (noch ein) kurzes Bit (= langes Bit)
+ brcc RESET1 ; zu langes Bit -> Fehler
+
+ inc bcnt1
+ inc bcnt1
+ ldi r16,0x01 ; wird doppelt gespeichert!
+
+WEITER1:
+ clc
+ sbrs lastB,1 ; alten Pinzustand
+ sec ; nach C
+ lds r17,(0x0064) ; das erste der insgesamt vier Bytes von empfangenen Bits
+ rol r17
+ sts (0x0064),r17
+ lds r17,(0x0065)
+ rol r17
+ sts (0x0065),r17
+ lds r17,(0x0066)
+ rol r17
+ sts (0x0066),r17
+ lds r17,(0x0067)
+ rol r17
+ sts (0x0067),r17
+ brcs RESET1 ; es kamen mehr als 32 Bits an -> Fehler!
+
+ subi r16,0x01
+ brcc WEITER1
+
+ ldi r16,0x1a
+ cp bcnt1,r16
+
+ brcs ENDE1 ; noch keine 26 klein-Bits angekommen -> Ende
+
+ ldi r16,0x1c
+ cp bcnt1,r16
+ brcc RESET1 ; mehr als 27 klein-Bits angekommen -> Fehler!
+
+ sbrs lastB,1 ; jetziger Zustand ist high?
+ rjmp ENDE1 ; nein -> dann ist es auch nicht fertig!
+
+ lds r16,(0x0067) ; das letzte Byte
+ ori r16,0x40 ; die übrigen Bits (also die Bits, die eben nicht empfangen wurden)
+ sts (0x0067),r16 ; des zuerst "empfangenen" Bytes werden alternierend auf 1 gesetzt
+
+ ldi r26,0x64
+ ldi r27,0x00 ; Startadresse in den Speicher,
+ mov r16,bcnt1 ; Bitanzahl in r16
+ rcall VERSENDEN ; und ab durch die serielle Schnittstelle
+
+RESET1:
+ ldi r16,0x03 ; Startbit + '10'=0 (also 1. Empfänger)
+ sts (0x0064),r16
+ ldi r16,0x00
+ sts (0x0065),r16
+ sts (0x0066),r16
+ sts (0x0067),r16 ; empfangene Bits initialisieren
+ clr bcnt1 ; Bit-Zähler auf 0 setzen
+
+ENDE1:
+PIN1WACKELTNICHT:
+
+ rjmp MAINLOOP
+
+TIMER0COMPA:
+ push r16
+ in r16,SREG
+ push r16
+
+ sbrc sbuff0,0
+ sbi PORTA,1
+ sbrs sbuff0,0
+ cbi PORTA,1
+
+; clc ; so werden die Daten zyklisch gesendet
+; sbrc r0,0
+ sec
+
+ ror sbuff4
+ ror sbuff3
+ ror sbuff2
+ ror sbuff1
+ ror sbuff0
+
+ pop r16
+ out SREG,r16
+ pop r16
+
+ reti ; TIMER0COMPA
+
+WARTEAUFSENDBUFFER: ; wartet, bis der Sende-Puffer leer ist
+ ldi r16,0xff
+ cp sbuff4,r16
+ brne WARTEAUFSENDBUFFER
+ cp sbuff3,r16
+ brne WARTEAUFSENDBUFFER
+ cp sbuff2,r16
+ brne WARTEAUFSENDBUFFER
+ cp sbuff1,r16
+ brne WARTEAUFSENDBUFFER
+ cp sbuff0,r16
+ brne WARTEAUFSENDBUFFER
+ ret ; WARTEAUFSENDBUFFER
+
+VERSENDEN: ; versendet r16/2+1 Bit Manchester-kodierte Daten
+ ; aus DRAM, Adresse r27:r26 (=X), base64-kodiert
+
+ movw r18,r26 ; Speicheradresse merken
+ sbrc r16,0
+ rjmp VERSENDENNICHTSCHIEBEN
+ sec
+ ld r17,X
+ rol r17
+ st X+,r17
+ ld r17,X
+ rol r17
+ st X+,r17
+ ld r17,X
+ rol r17
+ st X+,r17
+ ld r17,X
+ rol r17
+ st X+,r17
+ movw r26,r18
+VERSENDENNICHTSCHIEBEN:
+ lsr r16
+ ldi r17,0x0d
+ cpse r16,r17 ; nicht 26 halb-Bits?
+ ret ; -> Fehler!
+
+; ld r18,X+
+; ld r18,X+
+; ld r18,X+
+; ld r17,X+
+; clr r16
+; rjmp AUSLESESCHLEIFENENDE
+
+ ldi r20,0x03
+ALTERNIERENDTESTSCHLEIFE:
+ ld r16,X+
+ mov r17,r16
+ lsr r16
+ eor r16,r17
+ andi r16,0x55
+ ldi r17,0x55
+ cpse r16,r17 ; Bits alternierend?
+ ret ; nein -> Ende!
+
+ subi r20,0x01
+ brcs ALTERNIERENDTESTSCHLEIFEENDE
+ rjmp ALTERNIERENDTESTSCHLEIFE
+ALTERNIERENDTESTSCHLEIFEENDE:
+
+ movw r26,r18
+ clr r18
+ clr r17
+ clr r16
+
+ ldi r19,0x10 ; 16 Bits zu lesen (13 reale Bits + 3 Geistbits)
+AUSZENSCHLEIFE:
+ ld r20,X+
+ ldi r21,0x04 ; 4 Bits je Byte
+INNENSCHLEIFE:
+ ror r20
+ ror r20
+ rol r18
+ rol r17
+ rol r16
+ subi r19,0x01
+ breq AUSLESESCHLEIFENENDE
+ subi r21,0x01
+ brne INNENSCHLEIFE
+ rjmp AUSZENSCHLEIFE
+AUSLESESCHLEIFENENDE:
+
+ ; die zu sendenden 18 Bit Informationen liegen in r16(2):r17(8):r18(8)
+
+ rol r18
+ rol r17
+ rol r16
+ rol r18
+ rol r17
+ rol r16
+
+ lsr r18
+ lsr r18
+
+ rol r17
+ rol r16
+ rol r17
+ rol r16
+
+ lsr r17
+ lsr r17
+
+ rcall TOBASE64
+ push r16
+ mov r16,r17
+ rcall TOBASE64
+ push r16
+ mov r16,r18
+ rcall TOBASE64
+ push r16
+ ; die zu sendenden Zeichen liegen auf dem Stack (3., 2., 1.)
+ rcall WARTEAUFSENDBUFFER
+
+ cli
+
+ clc
+
+ ; aus logistischen Gründen füllen wir den Puffer von hinten nach vorne
+
+ ldi r16,0x0d ; 0x0d (CR)
+ mov sbuff4,r16
+
+ pop r17
+ ldi r16,0x40
+ sec
+ ror r17
+ ror r16
+ ror r17
+ ror r16
+ mov sbuff3,r17
+
+ pop r17
+ swap r17
+ mov r18,r17
+ andi r18,0x0f
+ or r16,r18
+ mov sbuff2,r16
+
+ andi r17,0xf0
+ ori r17,0x04
+ pop r18
+ clr r16
+ clc
+ rol r18
+ rol r16
+ sec
+ rol r18
+ rol r16
+ or r16,r17
+ mov sbuff1,r16
+
+ mov sbuff0,r18
+
+ sei
+
+VERSENDENENDE:
+ ret ; VERSENDEN
+
+TOBASE64: ; konvertiert Bit 0-5 von r16 in base64
+ ; 0-25: A-Z: +0x41 (=-0xbf)
+ ; 26-51: a-z: +0x47 (=-0xb9)
+ ; 52-61: 0-9: -0x04
+ ; 62: +: -0x13
+ ; 63: /: -0x10
+ andi r16,0x3f ; zur Sicherheit
+ cpi r16,26
+ brcc NICHT0BIS25
+ subi r16,0xbf
+ ret ; TOBASE64
+NICHT0BIS25:
+ cpi r16,52
+ brcc NICHT26BIS51
+ subi r16,0xb9
+ ret ; TOBASE64
+NICHT26BIS51:
+ cpi r16,62
+ brcc NICHT52BIS61
+ subi r16,0x04
+ ret ; TOBASE64
+NICHT52BIS61:
+ cpi r16,63
+ brcc NICHT62
+ subi r16,0x13
+ ret ; TOBASE64
+NICHT62:
+ subi r16,0x10
+ ret ; TOBASE64
+
+