From b7f1b8b54e86f12172ca66e4b64ed34694c558fd Mon Sep 17 00:00:00 2001 From: Erich Eckner Date: Sat, 8 Apr 2017 16:47:46 +0200 Subject: alte Version --- Fernbedienung.asm | 500 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 500 insertions(+) create mode 100644 Fernbedienung.asm 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 + + -- cgit v1.2.3-54-g00ecf