From 57cdf41098c45a594b5811a1eb6932497ba625aa Mon Sep 17 00:00:00 2001 From: Erich Eckner Date: Fri, 6 Nov 2020 08:26:56 +0100 Subject: Binäruhr-Quelle neu - bisher noch falscher Code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 + Binaeruhr.asm | 501 ++++++++++++++++++++++++++++++++++++++++++++ Makefile | 17 ++ tn2313def.inc | 660 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1183 insertions(+) create mode 100644 .gitignore create mode 100644 Binaeruhr.asm create mode 100644 Makefile create mode 100644 tn2313def.inc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..22acbed --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +Debug +Release +*.o +*.elf +*.hex diff --git a/Binaeruhr.asm b/Binaeruhr.asm new file mode 100644 index 0000000..af3a785 --- /dev/null +++ b/Binaeruhr.asm @@ -0,0 +1,501 @@ +/* + * Fernbedienung.asm + * + * Created: 08.10.2015 14:35:11 + * Author: Erich + */ + +.INCLUDE "tn2313def.inc" + +.EQU sbuff0, 0 ; serieller Puffer 0 bis +.EQU sbuff1, 1 +.EQU sbuff2, 2 +.EQU sbuff3, 3 +.EQU sbuff4, 4 ; 4 +.EQU lastB, 5 ; letzter Zustand von PINB +.EQU lt1p0l, 6 ; letzte Flankenposition PINB0 (Timer 1) low +.EQU lt1p0h, 7 ; dito high +.EQU lt1p1l, 8 ; dito PINB1 low +.EQU lt1p1h, 9 ; dito high +.EQU bcnt0, 10 ; Bitzähler PINB0 +.EQU bcnt1, 11 ; Bitzähler PINB1 +.EQU t1moml, 12 ; momentane Position Timer 1 low +.EQU t1momh, 13 ; dito high +.EQU aender, 14 ; Ä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,lo8(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 + + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..dc800c3 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ + +all: Binaeruhr.hex + +install: all + avrdude -c avrispmkII -p t24 -U flash:w:Binaeruhr.hex:i + +check: + avrdude -c avrispmkII -p t24 -U flash:v:Binaeruhr.hex:i + +%.o: %.asm *.inc + avr-as $< -mmcu=attiny2313 -o $@ + +%.elf: %.o + avr-ld -o $@ $< + +%.hex: %.elf + avr-objcopy --output-target=ihex $< $@ diff --git a/tn2313def.inc b/tn2313def.inc new file mode 100644 index 0000000..30335a2 --- /dev/null +++ b/tn2313def.inc @@ -0,0 +1,660 @@ +;***** THIS IS A MACHINE GENERATED FILE - DO NOT EDIT ******************** +;***** Created: 2011-02-09 12:04 ******* Source: ATtiny2313.xml ********** +;************************************************************************* +;* 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 : "tn2313def.inc" +;* Title : Register/Bit Definitions for the ATtiny2313 +;* Date : 2011-02-09 +;* Version : 2.35 +;* Support E-mail : avr@atmel.com +;* Target MCU : ATtiny2313 +;* +;* 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. +;* In addition, the six registers forming the three data pointers X, Y and +;* Z have been assigned names XL - ZH. Highest RAM address for Internal +;* SRAM is also defined +;* +;* The Register names are represented by their hexadecimal address. +;* +;* 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<