summaryrefslogtreecommitdiff
path: root/Binaeruhr.asm
blob: b9eb368b30e8bb70fff8bcff5cad5c13bc0ee8e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
/*
  * Binaeruhr.asm
  *
  *  Created: 09.11.2020
  *   Author: Erich
  */

.INCLUDE "tn2313def.inc"

.EQU Spalte, 31             ; die anzuzeigende Spalte (als Bitmaske fuer PORTD)
.EQU Tics, 30               ; 100Hz-Tics
.EQU nTics, 29              ; wann ist die naechste Sekunde gemessen in 100Hz-Tics
.EQU Status, 28             ; Bit 0: Funksignal
                            ; Bit 1: kein Fehler im aktuellen Empfang
                            ; Bit 2: kein Fehler in der aktuellen oder letzten Minute
                            ; Bit 3: MESZ <-> MEZ Umstellung am Ende der Stunde
                            ; Bit 4: Richtung: 0 = MEZ -> MESZ; 1 = MESZ -> MEZ
.EQU lHTics, 27             ; wann war die letzte Funk Low-High-Flanke in 100Hz-Tics
.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            ; Timer1 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,0xff
  out PORTB,r16             ; Zeilen (aus)
  ldi r16,0x7c
  out PORTD,r16             ; 1x n.d., 1x In (DCF77), 2x In mit Pull-up (Taster), 3x Spalten (aus), 1x n.d.
  ldi r16,0xff
  out DDRB,r16              ; Ausgaenge: PORTB (Zeilen)
  ldi r16,0x70
  out DDRD,r16              ; Ausgaenge: 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 nTics,100

  cbr Status,0xff

  sei

main_loop:

  bst Status,0
  brts high_low_Funkflanke

low_high_Funkflanke:

  mov r16,Tics
  sub r16,lHTics            ; die gemessene "low" Zeit ist der Abstand der letzten lh-Flanke
  cpi r16,205
  brcc Funkfehler           ; "low" >= 2050ms -- hierzu ist *keine* Flanke vonnoeten

  sbis PIND,1
  rjmp nach_Funkflanke

  sbr Status,0x01
  mov lHTics,Tics

  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,Tics
  sub r16,lHTics            ; 10 vs. 20 ( = 100ms vs. 200ms)
  cpi r16,26
  brcc Funkfehler           ; high > 250ms -- hierzu ist *keine* Flanke vonnoeten

  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      ; War die letzte Minute per Funk ok?

  mov r16,nTics
  sub r16,Tics              ; wie viele Tics bis zur naechsten Sekunde (nach Quarz)
  mov nTics,Tics            ; wir setzen es auf "jetzt"
  cpi r16,50                ; wurde die Sekunde durch den Quarz schon gezaehlt?
  brcs nach_Funkflanke      ; branch, wenn "noch nicht gezaehlt"
  subi nTics,(256-100)      ; wir setzen es jetz auf "in 100 Tics"

nach_Funkflanke:

  cp nTics,Tics
  brpl main_loop

neue_Sekunde:

  subi nTics,(256-100)      ; naechste Sekunde 100 Tics nach der aktuellen

  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 nTics,Tics
  subi nTics,(256-100)      ; die naechste Sekunde startet in genau 100 Tics

  bst Funk2,5               ; bit 16: MESZ <-> MEZ Umstellung
  bld Status,3
  bst Funk2,6               ; bit 17: MESZ (1) oder MEZ (0)
  bld Status,4

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
  sbrc Status,3             ; keine Zeitumstellung => skip
  sbrs Status,4             ; MESZ -> MEZ => kein Stundeninkrement
  inc Stunde
  mov r16,Stunde
  cpi r16,24
  brcc neuer_Tag
  sbrs Status,3             ; Zeitumstellung
  rjmp main_loop
  cbr Status,0x08           ; bitte nur ein Mal
  sbrc Status,4             ; MEZ -> MESZ => skip
  rjmp main_loop            ; wurde oben schon behandelt
  rjmp neue_Stunde          ; noch eine Stunde weiter vor

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 Tics
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