/* * Fernbedienung.asm * * Created: 08.10.2015 14:35:11 * Author: Erich */ .INCLUDE "tn2313def.inc" .EQU Spalte, 31 ; die anzuzeigende Spalte (als Bitmaske fuer PORTD) .EQU TicsH, 30 ; 300Hz-Tics High .EQU TicsL, 29 ; 300Hz-Tics Low .EQU nTicsL, 28 ; wann ist die naechste Sekunde gemessen in 300Hz-Tics Low .EQU Status, 27 ; Bit 0: Funksignal ; Bit 1: kein Fehler im aktuellen Empfang ; Bit 2: kein Fehler in der aktuellen oder letzten Minute .EQU lHTicsL, 26 ; wann war die letzte Funk Low-High-Flanke in 300Hz-Tics Low .EQU Stunde, 0 ; anzuzeigende Stunde .EQU Minute, 1 ; anzuzeigende Minute .EQU Sekunde, 2 ; anzuzeigende Sekunde .EQU Funk0, 3 .EQU Funk1, 4 .EQU Funk2, 5 .EQU Funk3, 6 .EQU Funk4, 7 .EQU Funk5, 8 .EQU Funk6, 9 .EQU Funk7, 10 rjmp RESET reti reti reti rjmp TIMER1COMPA ; Timer1 Compare Match A reti reti reti reti reti 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,0x00 out WDTCSR,r16 ; Watchdog aus ldi r17,0xd0 ldi r16,0x55 out OCR1AH,r17 out OCR1AL,r16 ; TimerB bis 0xd055 laufen lassen (= 300 Hz) ldi r16,0x09 out TCCR1B,r16 ; no prescaler ldi r16,0x40 out TIMSK,r16 ; Counter1 Output Compare A Match Interrupt Enable ldi r16,0x55 out PORTB,r16 ; Muster auf PORTB (Zeilen) ldi r16,0x7c out PORTD,r16 ; 2x n.d., 2x Pull-up (Taster), Muster auf Spalten ldi r16,0xff out DDRB,r16 ; Ausgänge: PORTB (Zeilen) ldi r16,0x70 out DDRD,r16 ; Ausgänge: PORTD4..6 (Spalten) ldi Spalte,0x10 ldi r16,0x12 mov Stunde,r16 ldi r16,0x34 mov Minute,r16 ldi r16,0x56 mov Sekunde,r16 ldi nTicsL,100 sei main_loop: bst Status,0 brts high_low_Funkflanke low_high_Funkflanke: mov r16,TicsL sub r16,lHTicsL ; die gemessene "low" Zeit ist der Abstand der letzten lh-Flanke cpi r16,205 brcc Funkfehler ; "low" > 2050ms -- hierzu ist *keine* Flanke vonnöten sbis PIND,1 rjmp nach_Funkflanke sbr Status,0x01 mov lHTicsL,TicsL cpi r16,95 brcs Funkfehler ; "low" < 950ms cpi r16,105 brcs neue_Funksekunde ; 950ms < "low" < 1050ms (= normale Sekunde) cpi r16,195 brcs Funkfehler ; 1050ms < "low" < 1950ms rjmp neue_Funkminute high_low_Funkflanke: mov r16,TicsL sub r16,lHTicsL ; 10 vs. 20 ( = 100ms vs. 200ms) cpi r16,26 brcc Funkfehler ; high > 250ms -- hierzu ist *keine* Flanke vonnöten sbic PIND,1 rjmp nach_Funkflanke cbr Status,0x01 cpi r16,5 brcs Funkfehler ; high < 50ms com r16 cpi r16,240 ror Funk7 ror Funk6 ror Funk5 ror Funk4 ror Funk3 ror Funk2 ror Funk1 ror Funk0 sbrs Funk0,3 ; zu viele Bits rjmp nach_Funkflanke Funkfehler: cbr Status,0x06 Funk_initialisieren: clr Funk0 clr Funk1 clr Funk2 clr Funk3 clr Funk4 clr Funk5 clr Funk6 ldi r16,0x80 mov Funk7,r16 rjmp nach_Funkflanke neue_Funksekunde: sbrs Status,2 rjmp nach_Funkflanke mov r16,nTicsL sub r16,TicsL ; wie viele TicsL bis zur nächsten Sekunde (nach Quarz) mov nTicsL,TicsL ; wir setzen es auf "jetzt" cpi r16,50 ; wurde die Sekunde durch den Quarz schon gezählt? brcs nach_Funkflanke ; branch, wenn "noch nicht gezählt" subi nTicsL,(256-100) ; wir setzen es jetz auf "in 100 TicsL" nach_Funkflanke: cp nTicsL,TicsL brcc main_loop mov r16,nTicsL subi r16,0x80 mov r17,TicsL subi r17,0x80 cp r16,r17 brcs neue_Sekunde rjmp main_loop neue_Sekunde: subi nTicsL,(256-100) sbis PIND,2 rjmp neue_Stunde sbis PIND,3 rjmp neue_Minute inc Sekunde mov r16,Sekunde cpi r16,60 brcc neue_Minute rjmp main_loop neue_Funkminute: bst Status,1 sbr Status,0x02 ; der nächstminütige Empfang ist bisher ok brtc Funk_initialisieren ; die letzte Minute enthielt schon Fehler sbrs Funk0,4 ; Bit -1: Start-bit da? rjmp Funk_initialisieren sbrc Funk0,5 ; Bit 0: 2.Start-bit da? rjmp Funk_initialisieren mov r16,Funk2 ; Bits 11..18 lsr r16 eor r16,Funk2 sbrs r16,6 ; Bit 17 xor Bit 18 -> ME(S)Z ok? rjmp Funk_initialisieren sbrs Funk3,1 ; Bit 20: Zeit-Start-bit rjmp Funk_initialisieren mov r16,Funk3 mov r17,Funk4 mov r18,Funk5 ror r18 ror r17 ror r16 ror r18 ror r17 ror r16 cbr r17,0x80 mov r18,r16 rcall checksum brts neue_Funkminute_Ende mov r18,r17 rcall checksum brts neue_Funkminute_Ende mov r18,r16 cbr r18,0x80 rcall bcd_to_bin mov Minute,r18 mov r18,r17 cbr r18,0xc0 rcall bcd_to_bin mov Stunde,r18 clr Sekunde sbr Status,0x04 ; die empfangene Minute ist ok mov nTicsL,TicsL subi nTicsL,(256-100) ; die nächste Sekunde startet in genau 100 TicsL neue_Funkminute_Ende: rjmp Funk_initialisieren neue_Minute: clr Sekunde inc Minute mov r16,Minute cpi r16,60 brcc neue_Stunde rjmp main_loop neue_Stunde: clr Sekunde clr Minute inc Stunde mov r16,Stunde cpi r16,24 brcc neuer_Tag rjmp main_loop neuer_Tag: clr Stunde rjmp main_loop TIMER1COMPA: push r16 in r16,SREG push r16 push r17 ldi r17,0x7c out PORTD,r17 mov r17,Spalte lsl Spalte sbrc Spalte,5 mov r16,Stunde sbrc Spalte,6 mov r16,Minute sbrs Spalte,7 rjmp anzeigen mov r16,Sekunde ldi Spalte,0x10 inc TicsL brne anzeigen inc TicsH anzeigen: com r16 sbrs Spalte,5 rjmp nach_Funkeinfuegung sbr r16,0x80 sbrc Status,0 cbr r16,0x80 sbrc Status,2 subi r16,0x80 nach_Funkeinfuegung: com r17 cbr r17,0x83 out PORTB,r16 out PORTD,r17 pop r17 pop r16 out SREG,r16 pop r16 reti bcd_to_bin: ; input/output: r18; tmp: r19 mov r19,r18 cbr r18,0xf0 swap r19 cbr r19,0xf0 lsl r19 add r18,r19 lsl r19 lsl r19 add r18,r19 ret checksum: ; input: r18; tmp: r19; output: T-Flag mov r19,r18 swap r19 eor r18,r19 mov r19,r18 ror r19 ror r19 eor r18,r19 mov r19,r18 ror r19 eor r18,r19 bst r18,0 ret