#define BIT_TIME 150 // this value should be between 100 and 200, it decides between 0 and 1
#define MINUTE_UP 1400 // the minute is up
#define DCF_INPUT 10 // DCF77 input pin
int8_t VALUES[] = {1, 2, 4, 8, 10, 20, 40, 80};
const char *WEEKDAYS[] = {"--", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"};
const char *CEST[] = {"CET", "CEST"};
unsigned long milli = 0; // global variables
uint8_t cest = 0;
uint8_t minute = 0;
uint8_t hour = 0;
uint8_t day = 0;
uint8_t weekday = 0;
uint8_t month = 0;
uint8_t year = 0;
uint8_t position = 0;
uint8_t parity = 0; // even parity in the time signal
uint8_t dcfPIN = 0; // status of the DCF77 input pin
void setup()
{
Serial.begin(115200); // init serial interface
while (!Serial)
delay(1);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(DCF_INPUT, INPUT);
Serial.println("Start...DCF77"); // 'Hello world'
}
void loop()
{
int _dcfPIN = digitalRead(DCF_INPUT); // read the DCF77 input
if (dcfPIN != _dcfPIN)
{ // the input has changed
dcfPIN = _dcfPIN; // remember the value
digitalWrite(LED_BUILTIN, dcfPIN); // update the onboard LED
unsigned long _milli = millis(); // increasing millisecond counter
unsigned long len = _milli - milli; // calculates the pulse length
milli = _milli; // remember the value
if (dcfPIN == 0) // this means that the signal was high and is now low
{
// Serial.println(len); // optional to see the bit length
if (len > BIT_TIME) // zero or one ?
{ // one !
parity += 1;
if (position >= 21 && position <= 27) // minute
minute += VALUES[position - 21];
else if (position >= 29 && position <= 34) // hour
hour += VALUES[position - 29];
else if (position >= 36 && position <= 41) // day
day += VALUES[position - 36];
else if (position >= 42 && position <= 44) // weekday
weekday += VALUES[position - 42];
else if (position >= 45 && position <= 49) // month
month += VALUES[position - 45];
else if (position >= 50 && position <= 57) // year
year += VALUES[position - 50]; // only the year, not the century
if (position == 17)
cest = 1; // Central European Summer Time
else if (position == 18)
{
if (cest == 1) // Central European Time
position = 0; // Error: sets the position to 0, making the time information invalid
}
else if (position == 20) // start of encoded time, always 1
parity = 0; // reset parity for the following bits
else if (position == 28 || position == 35 || position == 58)
{
if ((parity % 2) != 0) // even parity ?
position = 0; // Error: sets the position to 0, making the time information invalid
parity = 0; // reset parity for the following bits
}
}
else // zero
{
if (position == 28 || position == 35 || position == 58)
{
if ((parity % 2) != 0) // even parity ?
position = 0; // Error: sets the position to 0, making the time information invalid
parity = 0; // reset parity for the following bits
}
}
Serial.print("Bit: "); Serial.println(position); // optional
// char buf[100];
// sprintf(buf, "Timestamp: %d-%02d-%02d %02d:%02d %s %s", (year + 2000), month, day, hour, minute,
// WEEKDAYS[weekday], CEST[cest]);
// Serial.println(buf);
// enable the lines above to see how the date and time evolve
position += 1; // increment the bit counter
}
else
{
if (len > MINUTE_UP)
{
// the minute is up, the parity bit does not allow error correction,
// so some additional checks are performed
if (position == 59 && (minute >= 0 && minute <= 59 || hour >= 0 && hour <= 23 ||
day >= 1 && day <= 31 || weekday >= 1 && weekday <= 7 ||
month >= 1 && month <= 12 || year >= 25))
{
char buf[100];
sprintf(buf, "Timestamp: %d-%02d-%02d %02d:%02d %s %s", (year + 2000), month, day, hour,
minute, WEEKDAYS[weekday], CEST[cest]);
Serial.println(buf);
}
else
Serial.println("No valid timestamp");
cest = 0; // reset everything, preparing for the next minute
minute = 0;
hour = 0;
day = 0;
weekday = 0;
month = 0;
year = 0;
position = 0;
parity = 0;
}
}
}
delay(1);
}