===DCF77 DigiClock=== {{ :migratedattachments:mmbasic_original:digits.zip?linkonly}} //This module is part of the original MMBasic library. It is reproduced here with kind permission of Hugh Buckle and Geoff Graham. Be aware it may reference functionality which has changed or is deprecated in the latest versions of MMBasic.// ' -------------------------------------------------------------------------- ' ' 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 (tim@way2.net) ' ' 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 = 250 ' 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 Dim dcfbit(60) ' --- configure pin as input SetPin DCFPin, 2 cls ' ' ----------- welcome screen ' print "Welcome to DClock v2.0" 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 ' --- 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 PrintDigit DigitRX, DigitY, s2 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 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 PrintDigit DigitRX, DigitY, h2 Else PrintDigit DigitLX, DigitY, m1 PrintDigit DigitRX, DigitY, m2 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) bitmapname$ = Str$(v) + ".bmp" LoadBMP bitmapname$, x, y 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 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 ' --- 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 ' --- 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