Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 15:45 12 Nov 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : [MM2]DCF77 Decoder

Author Message
twofingers

Guru

Joined: 02/06/2014
Location: Germany
Posts: 1671
Posted: 01:56pm 10 Feb 2019
Copy link to clipboard 
Print this post

This is yet another DCF77 Decoder.
I fear it will only interest Europeans. Because of
  Quote  DCF77 is a German longwave time signal and standard-frequency radio station.
DCF77 on Wikipedia

The code is well commented and tested.
I used a very old (~30 years?) DCF77 module from Conrad Electronics in germany.



The red LED is pulsing at 1 Hz and indicates the DCF77 signal.
My module is connected to the MM2 with a 2m telephone cable.



'****************************************************
'*
'* Yet another DCF77-Decoder for MicroMites, Version 1.0
'*
'* System: MMBasic 5.0
'* Micromite 2 (PIC32MX170/28, Micks BP170 + 2.8" TFT)
'* by twofingers 1-2019 at TBS
'* --------------------------
'* f. Conrad-Modul
'* Pin1=GND Pin2=5V or 3.3V
'* Out=inverting output=Pin3 (connected to the MM with a 2m cable)
'*
'* LED (+2.7k) from Pin3 to Pin2
'* to make the 1 Hz pulses visible
'* --------------------------
'* MM Input = DCFPIN
'* --------------------------
'* Note:
'* In order to have a reliable result, at least
'* two successive times should be determined
'*
'* Ignored:
'* Summer time announcement (bit 16)
'* Leap second announcement (bit 19)
'*
'* https://en.wikipedia.org/wiki/DCF77
'*----------------------------------------------------
' This code may be freely distributed and changed.
' Provided AS IS without any warranty.
' Use it at your own risk. All information is provided for
' educational purposes only!
'------------------------------------------------------
' ++++++ Credit to Geoff for his great MMBasic ++++++
'******************************************************

Option EXPLICIT

Dim As integer pass=0
Dim As integer tGap(60) 'tGap() = Gap_length
Dim As integer DCF(60)'DCF-Telegramm in Bitform
' reverse bit order = least significant bit goes first.
Dim WT$(7) 'Weekdays
WT$(1)="Monday"
WT$(2)="Tuesday"
WT$(3)="Wednesday"
WT$(4)="Thursday"
WT$(5)="Friday"
WT$(6)="Saturday"
WT$(7)="Sunday"

Dim DST$(2) = ("","CET","CEST") 'german: MEZ,MESZ=Sommerzeit
Dim DCF_date$, DCF_time$

Dim VT100_Cup$=Chr$(27)+"[1A" 'VT100 Cursor up
Dim VT100_Del$=Chr$(27)+"[2K" 'VT100 erase cursorline

Const DCFPIN=15
Const TRUE=1, FALSE=0
Const THRESHOLD=150 'gap length threshold, between 100ms and 200ms
Const TOLERANCE=50
Const min_pw=1000-TOLERANCE
Const max_pw=1000+TOLERANCE 'limits of period duration of sec cycle
Const min_mmark=2000-TOLERANCE
Const max_mmark=2000+TOLERANCE 'limits of period duration of minute mark

Dim As integer BitN 'Sec_index
Dim As integer tSec 'tSec=Period length, rising edge to rising edge
Dim As integer SyncOK 'Minute mark found!
Dim As integer DCF_Time_OK=FALSE
Dim As integer DCF_error =FALSE


Do '***** Begin Main Loop ******
pass=pass+1
BitN=0
tSec=0
SyncOK=FALSE

SetPin DCFPIN,INTH,HiLevel

Print
Print "MM DCF77 Decoder V1.0 "Time$, "Pass: "pass
Print

Timer=0

' Let's see if we have a 1000ms pulse (1 Hz) signal
' The interrupt does the job. tSec=time of one period of the 1 Hz DCF signall
Do
Print "Waiting for 1 Hz Signal (1 cycle/1000ms) ",Str$(tSec,4)"ms";VT100_Cup$
Loop Until InRange(tSec,min_pw,max_pw)
' now we have probably a DCF77 signal
' Note: The better it matches the 1000 ms, the better the signal quality
Print VT100_Del$+"DCF77 signal available ... "
DCF_error=FALSE

Do '****************
If InRange(tSec,min_mmark,max_mmark) Then ' we found a 2000ms period
BitN=0:SyncOK=1:tSec=0
Print
Print "Minute mark found! Collecting DCF77 data ..."
Print "0 1 2 3 4 5 6 x10"
Print;
' Sub LoLevel does the job
EndIf
If BitN=59 And SyncOK=1 Then ' seems we are complete
DCF_error = Not DCF77_readout()
Exit Do
EndIf
If BitN >59 Then ' uff! No sync found. Let's start again ...
Print
Print "Error: Minute mark not found "
Exit Do
EndIf
If DCF_error Then
Print
Print "Error: DCF_error (Signal)"
Exit Do
EndIf
Loop

Loop While Not DCF_Time_OK'***** End Main Loop ******

' copy the DCF time into the MM if you like
'time$=DCF_time$
'date$=DCF_date$

End'--------------------------------------------------------

'* TWO interrupt routines

'* Setpin interrupt sub to detect the rising edge,
'* the time of one cycle, tSec = ~1000ms or ~2000ms
Sub HiLevel
SetPin DCFPIN,INTL,LoLevel
tSec=Timer:Timer=0
If tSec<min_pw Then DCF_error=TRUE 'we lost the DCF signal?
End Sub

'* Setpin interrupt sub to detect the falling edge
'* we get the gap length - tGap() = ~100 or ~200ms
Sub LoLevel ' Setpin interrupt sub, high to low
SetPin DCFPIN,INTH,HiLevel
tGap(BitN)=Timer
If SyncOK Then
Print Str$(tGap(BitN)>threshold,1);
Else
Print "Searching for minute mark" BitN, Str$(tSec,4)"ms"; VT100_Cup$
EndIf
If BitN<60 Then BitN=BitN+1 'just in case to prevent overflow
End Sub


' let's see what the DCF telegram says
' ****** readout, takes about 46ms ******
Function DCF77_readout()
Local min, hour, day, mon, year, i, tAs integer
Local weekday$

SetPin DCFPIN,OFF 'interrupt disable

' convert pulse widths (i.e. gaps) to bits
For i= 0 To 58
DCF(i)= tGap(i) >threshold
Next

DCF77_readout = TRUE
Print
' Some error checks:
' Bit 0 must be 0
' Bit20 must be 1
' Bit17 = not Bit18
If DCF(0)<>0 Then DCF77_readout = FALSE:Print "E1":Exit Function
If DCF(20)<>1 Then DCF77_readout = FALSE:Print "E2":Exit Function
If DCF(17)<>Not DCF(18) Then DCF77_readout = FALSE:Print "E3":Exit Function
' Parity check
If Parity(21,28) Or Parity(29,35) Or Parity(36,58) Then
DCF77_readout = FALSE
Print "E4"
Exit Function
EndIf

min = BCD_Sum(21,27)
hour = BCD_Sum(29,34)

day = BCD_Sum(36,41)
weekday$=wt$(BCD_Sum(42,44))

mon = BCD_Sum(45,49)
year = BCD_Sum(50,57)

DCF_date$=Str$(day,2,0,"0")+"-"+Str$(mon,2,0,"0")+"-"+Str$(2000+year,4,0,"0")
DCF_time$=Str$(hour,2,0,"0")+":"+Str$(min,2,0,"0")+":"+"00"

If ValidTime(DCF_time$) Then
Print "Success!"
Print DCF_date$,DCF_time$, weekday$, DST$(DCF(17)+1)
DCF_Time_OK=TRUE
Else
Print "DCFtime INVALID!"
DCF_Time_OK=FALSE
EndIf
Print String$( 80,"_")
' Print:Print "Press <Space> to continue"
' Do: Loop Until Inkey$ = " "
End Function


' check the parity
Function Parity(a,b) As integer
Local p,i
p=0
For i = a To b
p = p + DCF(i)
Next
Parity = p Mod 2
End Function


' Converts DCF() bits from BCD to decimal (max 9bit)
Function BCD_Sum(a,b) As integer
Local As integer bcd(9) = (0,1,2,4,8,10,20,40,80,100), i
For i = a To b
BCD_Sum = BCD_Sum + DCF(i)*bcd(i-a+1)
Next
End Function


Function ValidTime(tm$) As integer
Local legal(3)=(0,23,59,59), i As integer
ValidTime=TRUE
For i = 1 To 7 Step 3 '1,4,7
If Val(Mid$(tm$,i,2))>legal(i\3+1) Then ValidTime=FALSE: Exit For
Next i
End Function


Function InRange(x,min,max) As integer
InRange = x>=min And x<= max
End Function


' rBCD2Dec() converts a part of an array of bit numbers BCD to decimal,
' reverse bit order = least significant bit goes first.
' e.g. dcf(7)=(1,1,1,0,0,0,1,0) = 47
' // not used in this program //
Function rBCD2Dec(a,b) As integer
Local As integer i, d=1
Do
For i = 0 To 3
rBCD2Dec = rBCD2Dec + DCF(a)*2^i*d
If a=b Then Exit Do
a=a+1
Next
d=d*10
Loop
End Function



2019-02-10_233412_mm_dcf77.zip

Any comments welcome.
Regards
Michael

causality ≠ correlation ≠ coincidence
 
Frank N. Furter
Guru

Joined: 28/05/2012
Location: Germany
Posts: 983
Posted: 07:25pm 10 Feb 2019
Copy link to clipboard 
Print this post

Hi Michael,

thanks a lot!!!
My last DCF77 receiver I programmed under PBP over 10 years ago (with the same Conrad module) and it works since then in a roller blind control of my parents. I had long intended to realize a DCF77 clock with a Micromite - you came before me!
THANKS!

Frank
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025