-
Notifications
You must be signed in to change notification settings - Fork 0
/
DCLOCK2.BAS
executable file
·561 lines (376 loc) · 11.7 KB
/
DCLOCK2.BAS
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
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
' --------------------------------------------------------------------------
'
' DigiClock for DynaMite / Maxmite
'
' One Maximite drives one screen, three screens make one DigiClock
' Each screen is displaying two digits, either HH, MM or SS.
'
' This program uses V4.4B of the MMBasic language, so the DuinomMites have
' to be flashed with the most recent firmware.
'
' The clock is automatically set via DCF77 (Conrad Receiver)
' http://www.conrad.de/ce/de/product/641138/C-Control-DCF-Empfaengerplatine
'
' Wiring: The first device (SECOND) needs to receive the DCF signal on Pin 1
' The other devices get their time via a UART connection on COM1. So connect Pin 16
' of the SECOND board to pin 15 on the MINUTE and HOUR board.
'
' (External View)
'
' + GND for DCF Board
' |
' |
' |
' | 1 DCF In for SECOND module
' + +
' o o o o o o o o o o o o o
'
' o o o o o o o o o o o o o
' ^ ^ +
' | | 15 Rx Connect to Tx of SECOND Module
' | +
' | 16 Tx Connect to Rx of MINUTE and HOUR Module
' |
' + 3.3V for DCF Board
'
' You will need a 10 kOhm Pullup between Vcc and the non-inverting output of
' the DCF module (pulling high to 3.3V) as the module has open collector
' outputs.
'
' Take a look at "DuinoMite MMBasic ReadMe.pdf" for more info.
'
' The bitmaps and all basic files have to be copied to the SD card, change
' the DisplayMode variable for each board accordingly.
'
' You can of course replace the clock images by your own ones, but stick to
' the size and the BMP format - some BMP sizes make ugly bit noise at the end.
'
' v2.0 written in 2014 by Tim Hagemann ([email protected])
'
' Use this code free of charge for private or educational uses. Ask for
' permission in case of commercial usage.
'
' --------------------------------------------------------------------------
DisplayMode = 2 ' 0: HH, 1: MM, 2:SS
DigitY = 50 ' Y pos of both digits
DigitLX = 53 ' X pos of left digit
DigitRX = 260 ' X pos of right digit
DCFPin = 1 ' Pin for the DCF77 signal
SignalY = 300 ' Position of the search signal line
SignalHeight = 20 ' Pulse height on screen
'
' ----------- initialization
'
WaitingForTime = 1
FirstSyncFound = 0
OldSignalY = SignalY
oldsignal = 1
olds1 = -1
olds2 = -1
oldm1 = -1
oldm2 = -1
oldh1 = -1
oldh2 = -1
Dim dcfbit(60)
' --- configure pin as input
SetPin DCFPin, 2
cls
'
' ----------- welcome screen
'
print "Welcome to DClock v2.1"
print "----------------------"
print
print "Starting time sync."
print
if DisplayMode = 2 then
print "This is the 'SECOND' and the DCF77 Unit"
endif
if DisplayMode = 1 then
print "This is the 'MINUTE' Unit"
endif
if DisplayMode = 0 then
print "This is the 'HOUR' Unit"
endif
'
' ----------- main program
'
if DisplayMode = 2 then
DisplaySecondAndSendDCF
else
DisplayDigitAndReceiveDCF
endif
' -----------------------------------------------------------------------
sub DisplaySecondAndSendDCF
' --- setup the ticker for the DCF signal
SetTick 10, CheckDCF77
' --- com1: Rx is pin 15, Tx is pin 16
OPEN "COM1:4800" AS #1
Do
watchdog 5000
' --- deferred actions
if DoCls = 1 then
cls
DoCls = 0
endif
if UpdateLastSync = 1 then
print @(0,415) "Last synced: ";LastSync$;" ";
UpdateLastSync = 0
endif
currt$ = Time$
' --- when time changed
If currt$ <> oldt$ Then
s1 = Val(Mid$(currt$,7,1))
s2 = Val(Mid$(currt$,8,1))
' --- main program
If WaitingForTime = 0 Then
print #1,"TT";currt$
' --- main display routine
PrintDigit DigitLX, DigitY, s1, olds1
PrintDigit DigitRX, DigitY, s2, olds2
EndIf
' --- save time for compare
oldt$ = currt$
EndIf
' --- wait a bit
Pause 50
Loop
end sub
' -----------------------------------------------------------------------
Sub DisplayDigitAndReceiveDCF
' --- com1: Rx is pin 15, Tx is pin 16
OPEN "COM1:4800" AS #1
do
watchdog 5000
if LOC(#1) <> 0 then
' ---- read serial input
a$ = input$(50,#1)
' ---- add to the receive uffer
r$ = r$ + a$
'print "'";r$;"'"
' ---- now process
chr13 = instr(r$,chr$(13))
if chr13 <> 0 then
' ---- we found a CR
command$ = left$(r$,chr13)
cmd$ = left$(command$,2)
param$ = mid$(command$,3)
commandfound = 0
if cmd$="TT" then
commandfound = 1
h1 = Val(Mid$(param$,1,1))
h2 = Val(Mid$(param$,2,1))
m1 = Val(Mid$(param$,4,1))
m2 = Val(Mid$(param$,5,1))
' --- main display routine
if FirstCLS = 0 then
cls
FirstCLS = 1
endif
If DisplayMode = 0 Then
PrintDigit DigitLX, DigitY, h1, oldh1
PrintDigit DigitRX, DigitY, h2, oldh2
Else
PrintDigit DigitLX, DigitY, m1, oldm1
PrintDigit DigitRX, DigitY, m2, oldm2
EndIf
endif
if commandfound = 0 then
'print "Error: command ";command$;" is invalid"
endif
r$ = ""
endif
else
Pause 50
endif
loop
end sub
' -----------------------------------------------------------------------
Sub PrintDigit (x,y,v,oldv)
if oldv <> v then
bitmapname$ = Str$(v) + ".bmp"
LoadBMP bitmapname$, x, y
oldv = v
endif
End Sub
' -----------------------------------------------------------------------
Sub CheckDCF77
' --- buffer the signal to avoid glitches
signal = Pin(DCFPin)
' --- update the counters
if signal = 1 or ignorepulse = 1 then
highcount = highcount + 1
else
lowcount = lowcount + 1
endif
' --- in search mode, display a fancy osci like graphic
if WaitingForTime = 1 then
' --- clear old line
Line (SignalX,SignalY) - (SignalX,SignalY-SignalHeight),0
' --- draw new line
NewSignalY = SignalY-signal*SignalHeight
Line (SignalX,OldSignalY) - (SignalX,NewSignalY),1
OldSignalY = NewSignalY
' --- do the X warp around
SignalX = SignalX + 1
if (SignalX > MM.HRES) then
SignalX = 0
endif
endif
' --- falling edge
if oldsignal = 1 and signal = 0 then
' --- this is the falling edge
'print "Lowcnt";lowcount;" Highcnt";highcount
' --- filter out very small pulses
if highcount < 7 then
ignorepulse = 1
'print "Ignore pulse - too small"
else
if lowcount > 120 then
'print "Lowcount detected"
' --- two cases: we found the sync and completed the full datagram
' or we found the first sync having read only rubbish
If FirstSyncFound = 1 Then
' --- the is then the 2nd, 3rd,... sync.
ProcessDCFTime
Else
' --- ok, now we got the first one!
FirstSyncFound = 1
if WaitingForTime = 1 then
print @(0,150) "First minute break found...now receiving time...";spc(40)
endif
EndIf
' --- the next bit will be bit 1, we ignore bit 60 --> anyway 0
bitindex = 1
else
'print "Pulse detected"
' --- only process, if we completed the first round
If FirstSyncFound = 1 Then
if WaitingForTime = 1 then
print @(0,150) "Receiving bit number";bitindex;" of 58";spc(40)
endif
If bitindex <= 60 Then
' --- more than 100 ms? The this is a "1"
If highcount > 10 Then
dcfbit(bitindex) = 1
Else
dcfbit(bitindex) = 0
EndIf
'Print "BIT :", dcfbit(bitindex)
bitindex = bitindex + 1
Else
if WaitingForTime = 1 then
print @(0,150) "Lost sync. Try again.";spc(40)
endif
' --- something was wrong. Restart sync
FirstSyncFound = 0
EndIf
EndIf
endif
lowcount = 0
highcount = 0
ignorepulse = 0
endif
endif
oldsignal = signal
End Sub
' -----------------------------------------------------------------------
Sub ProcessDCFTime
' --- get the current time in seconds since midnight
ch = Val(Mid$(time$,1,2))
cm = Val(Mid$(time$,4,2))
cs = Val(Mid$(time$,7,2))
sec_curr = cs + cm*60 + ch*60*60
' --- decode the dcf time from the bitarray
idx = 21
mm = dcfbit(idx) + dcfbit(idx+1)*2 + dcfbit(idx+2)*4 + dcfbit(idx+3)*8 + dcfbit(idx+4)*10 + dcfbit(idx+5)*20 + dcfbit(idx+6)*40
p1 = Party(21,28)
idx = 29
hh = dcfbit(idx) + dcfbit(idx+1)*2 + dcfbit(idx+2)*4 + dcfbit(idx+3)*8 + dcfbit(idx+4)*10 + dcfbit(idx+5)*20
p2 = Party(29,35)
idx = 36
dd = dcfbit(idx) + dcfbit(idx+1)*2 + dcfbit(idx+2)*4 + dcfbit(idx+3)*8 + dcfbit(idx+4)*10 + dcfbit(idx+5)*20
idx = 45
mo = dcfbit(idx) + dcfbit(idx+1)*2 + dcfbit(idx+2)*4 + dcfbit(idx+3)*8 + dcfbit(idx+4)*10
idx = 50
yy = dcfbit(idx) + dcfbit(idx+1)*2 + dcfbit(idx+2)*4 + dcfbit(idx+3)*8 + dcfbit(idx+4)*10 + dcfbit(idx+5)*20 + dcfbit(idx+6)*40 + dcfbit(idx+7)*80
p3 = Party(36,58)
'Print "//////////// time", hh , mm, dd,mo,yy,p1,p2,p3
' --- calc the dcftime in seconds since midnight
sec_dcf77 = mm*60 + hh*60*60
' --- now do some checks
dcferr = 0
If Fix(p1/2) <> p1/2 Then
dcferr = 1
EndIf
If Fix(p2/2) <> p2/2 Then
dcferr = 1
EndIf
If Fix(p3/2) <> p3/2 Then
dcferr = 1
EndIf
If mo<1 Or mo>12 Then
dcferr = 1
EndIf
If dd<1 Or dd>31 Then
dcferr = 1
EndIf
If mm>59 Then
dcferr = 1
EndIf
If hh>23 Then
dcferr = 1
EndIf
If yy>25 Then
dcferr = 1
EndIf
' --- check if the new time is more than 2 min away
small_val = min(sec_dcf77,sec_curr)
big_val = max(sec_dcf77,sec_curr)
max_val = 59 + 59*60 + 23*60*60
clockwise = big_val - small_val
counter_cw = max_val-big_val + small_val
diff_val = min(clockwise,counter_cw)
'print "small_val,big_val,max_val,clockwise,counter_cw,diff_val"
'print small_val, big_val, max_val, clockwise, counter_cw, diff_val
'print
If diff_val > 120 and WaitingForTime = 0 Then
dcferr = 1
EndIf
' --- now process
If dcferr = 0 Then
Time$ = Str$(hh)+":"+Str$(mm)+":00"
if WaitingForTime = 1 then
WaitingForTime = 0
' --- deferred CLS - will otherwise get us out of sync
DoCls = 1
endif
' --- deferred PRINT - will otherwise get us out of sync
UpdateLastSync = 1
LastSync$ = time$
EndIf
End Sub
' -----------------------------------------------------------------------
Function Party(idxa,idxe)
p = 0
For i = idxa To idxe
p = p + dcfbit(i)
Next i
Party = p
End Function
' -----------------------------------------------------------------------
Function min(a,b)
if (a<b) then
min = a
else
min = b
endif
End Function
' -----------------------------------------------------------------------
Function max(a,b)
if (a>b) then
max = a
else
max = b
endif
End Function