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
|
/*
* 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
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
|