User Tools

Site Tools


mmbasic_original:digiclock

DCF77 DigiClock

digits.zip

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
mmbasic_original/digiclock.txt · Last modified: 2024/01/19 09:39 by 127.0.0.1