Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add method to set split time #6

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 63 additions & 58 deletions DCF77.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
DCF77.c - DCF77 library
DCF77.c - DCF77 library
Copyright (c) Thijs Elenbaas 2012

This library is free software; you can redistribute it and/or
Expand All @@ -15,14 +15,14 @@
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11 Apr 2012 - initial release

11 Apr 2012 - initial release
23 Apr 2012 - added UTC support
2 Jul 2012 - minor bugfix and additional noise rejection
*/

#include <DCF77.h> //https://github.com/thijse/Arduino-Libraries/downloads
#include <Time.h> //http://playground.arduino.cc/code/time
#include <TimeLib.h> //http://playground.arduino.cc/code/time
#include <Utils.h>

#define _DCF77_VERSION 1_0_0 // software version of this library
Expand All @@ -32,14 +32,15 @@ using namespace Utils;
/**
* Constructor
*/
DCF77::DCF77(int DCF77Pin, int DCFinterrupt, bool OnRisingFlank)
DCF77::DCF77(int DCF77Pin, int DCFinterrupt, bool OnRisingFlank)
{
dCF77Pin = DCF77Pin;
dCFinterrupt = DCFinterrupt;
dCFinterrupt = DCFinterrupt;
pulseStart = OnRisingFlank ? HIGH : LOW;

if (!initialized) {
pinMode(dCF77Pin, INPUT);
dCFsplitTime = DCFSplitTime;

if (!initialized) {
pinMode(dCF77Pin, INPUT);
initialize();
}
initialized = true;
Expand All @@ -48,8 +49,8 @@ DCF77::DCF77(int DCF77Pin, int DCFinterrupt, bool OnRisingFlank)
/**
* Initialize parameters
*/
void DCF77::initialize(void)
{
void DCF77::initialize(void)
{
leadingEdge = 0;
trailingEdge = 0;
PreviousLeadingEdge = 0;
Expand All @@ -64,26 +65,31 @@ void DCF77::initialize(void)
CEST = 0;
}

void DCF77::setSplitTime(int shortPulseLength, int longPulseLength)
{
dCFsplitTime = (shortPulseLength+longPulseLength)/2;
}

/**
* Start receiving DCF77 information
*/
void DCF77::Start(void)
void DCF77::Start(void)
{
attachInterrupt(dCFinterrupt, int0handler, CHANGE);
}

/**
* Stop receiving DCF77 information
*/
void DCF77::Stop(void)
void DCF77::Stop(void)
{
detachInterrupt(dCFinterrupt);
detachInterrupt(dCFinterrupt);
}

/**
* Initialize buffer for next time update
*/
inline void DCF77::bufferinit(void)
inline void DCF77::bufferinit(void)
{
runningBuffer = 0;
bufferPosition = 0;
Expand All @@ -102,46 +108,46 @@ void DCF77::int0handler() {
LogLn("rCT");
return;
}

// If the detected pulse is too short it will be an
// incorrect pulse that we shall reject as well
if ((flankTime-leadingEdge)<DCFRejectPulseWidth) {
LogLn("rPW");
return;
}

if(sensorValue==pulseStart) {
if (!Up) {
// Flank up
leadingEdge=flankTime;
Up = true;
}
Up = true;
}
} else {
if (Up) {
// Flank down
trailingEdge=flankTime;
int difference=trailingEdge - leadingEdge;
int difference=trailingEdge - leadingEdge;

if ((leadingEdge-PreviousLeadingEdge) > DCFSyncTime) {
finalizeBuffer();
}
PreviousLeadingEdge = leadingEdge;
}
PreviousLeadingEdge = leadingEdge;
// Distinguish between long and short pulses
if (difference < DCFSplitTime) { appendSignal(0); } else { appendSignal(1); }
Up = false;
if (difference < dCFsplitTime) { appendSignal(0); } else { appendSignal(1); }
Up = false;
}
}
}
}

/**
* Add new bit to buffer
*/
inline void DCF77::appendSignal(unsigned char signal) {
Log(signal, DEC);
runningBuffer = runningBuffer | ((unsigned long long) signal << bufferPosition);
runningBuffer = runningBuffer | ((unsigned long long) signal << bufferPosition);
bufferPosition++;
if (bufferPosition > 59) {
// Buffer is full before at end of time-sequence
// Buffer is full before at end of time-sequence
// this may be due to noise giving additional peaks
LogLn("EoB");
finalizeBuffer();
Expand All @@ -160,12 +166,12 @@ inline void DCF77::finalizeBuffer(void) {
filledTimestamp = now();
// Reset running buffer
bufferinit();
FilledBufferAvailable = true;
FilledBufferAvailable = true;
} else {
// Buffer is not yet full at end of time-sequence
LogLn("EoM");
// Reset running buffer
bufferinit();
bufferinit();
}
}

Expand All @@ -183,8 +189,8 @@ bool DCF77::receivedTimeUpdate(void) {
LogLn("Invalid parity");
return false;
}
// Since the received signal is error-prone, and the parity check is not very strong,

// Since the received signal is error-prone, and the parity check is not very strong,
// we will do some sanity checks on the time
time_t processedTime = latestupdatedTime + (now() - processingTimestamp);
if (processedTime<MIN_TIME || processedTime>MAX_TIME) {
Expand All @@ -203,38 +209,38 @@ bool DCF77::receivedTimeUpdate(void) {
// Time can be further from internal clock for several reasons
// We will check if lag from internal clock is consistent
time_t shiftPrevious = (previousUpdatedTime - previousProcessingTimestamp);
time_t shiftCurrent = (latestupdatedTime - processingTimestamp);
time_t shiftCurrent = (latestupdatedTime - processingTimestamp);
time_t shiftDifference = abs(shiftCurrent-shiftPrevious);
storePreviousTime();
if(shiftDifference < 2*SECS_PER_MIN) {
LogLn("time lag consistent");
LogLn("time lag consistent");
return true;
} else {
LogLn("time lag inconsistent");
}
// If lag is inconsistent, this may be because of no previous stored date

// If lag is inconsistent, this may be because of no previous stored date
// This would be resolved in a second run.
return false;
}

/**
* Store previous time. Needed for consistency
* Store previous time. Needed for consistency
*/
void DCF77::storePreviousTime(void) {
previousUpdatedTime = latestupdatedTime;
previousProcessingTimestamp = processingTimestamp;
}

/**
* Calculate the parity of the time and date.
* Calculate the parity of the time and date.
*/
void DCF77::calculateBufferParities(void) {
// Calculate Parity
flags.parityFlag = 0;
void DCF77::calculateBufferParities(void) {
// Calculate Parity
flags.parityFlag = 0;
for(int pos=0;pos<59;pos++) {
bool s = (processingBuffer >> pos) & 1;
bool s = (processingBuffer >> pos) & 1;

// Update the parity bits. First: Reset when minute, hour or date starts.
if (pos == 21 || pos == 29 || pos == 36) {
flags.parityFlag = 0;
Expand All @@ -252,18 +258,18 @@ void DCF77::calculateBufferParities(void) {

/**
* Evaluates the information stored in the buffer. This is where the DCF77
* signal is decoded
* signal is decoded
*/
bool DCF77::processBuffer(void) {
bool DCF77::processBuffer(void) {

///// Start interaction with interrupt driven loop /////

// Copy filled buffer and timestamp from interrupt driven loop
processingBuffer = filledBuffer;
processingTimestamp = filledTimestamp;
// Indicate that there is no filled, unprocessed buffer anymore
FilledBufferAvailable = false;
FilledBufferAvailable = false;

///// End interaction with interrupt driven loop /////

// Calculate parities for checking buffer
Expand All @@ -278,16 +284,16 @@ bool DCF77::processBuffer(void) {
if (flags.parityMin == rx_buffer->P1 &&
flags.parityHour == rx_buffer->P2 &&
flags.parityDate == rx_buffer->P3 &&
rx_buffer->CEST != rx_buffer->CET)
{
//convert the received buffer into time
rx_buffer->CEST != rx_buffer->CET)
{
//convert the received buffer into time
time.Second = 0;
time.Minute = rx_buffer->Min-((rx_buffer->Min/16)*6);
time.Hour = rx_buffer->Hour-((rx_buffer->Hour/16)*6);
time.Day = rx_buffer->Day-((rx_buffer->Day/16)*6);
time.Day = rx_buffer->Day-((rx_buffer->Day/16)*6);
time.Month = rx_buffer->Month-((rx_buffer->Month/16)*6);
time.Year = 2000 + rx_buffer->Year-((rx_buffer->Year/16)*6) -1970;
latestupdatedTime = makeTime(time);
latestupdatedTime = makeTime(time);
CEST = rx_buffer->CEST;
//Parity correct
return true;
Expand All @@ -298,7 +304,7 @@ bool DCF77::processBuffer(void) {
}

/**
* Get most recently received time
* Get most recently received time
* Note, this only returns an time once, until the next update
*/
time_t DCF77::getTime(void)
Expand All @@ -313,7 +319,7 @@ time_t DCF77::getTime(void)
}

/**
* Get most recently received time in UTC
* Get most recently received time in UTC
* Note, this only returns an time once, until the next update
*/
time_t DCF77::getUTCTime(void)
Expand All @@ -333,6 +339,7 @@ time_t DCF77::getUTCTime(void)
*/
int DCF77::dCF77Pin=0;
int DCF77::dCFinterrupt=0;
int DCF77::dCFsplitTime=DCFSplitTime;
byte DCF77::pulseStart=HIGH;

// Parameters shared between interupt loop and main loop
Expand All @@ -359,5 +366,3 @@ time_t DCF77::processingTimestamp= 0;
time_t DCF77::previousProcessingTimestamp=0;
unsigned char DCF77::CEST=0;
DCF77::ParityFlags DCF77::flags = {0,0,0,0};


33 changes: 17 additions & 16 deletions DCF77.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
#define DCF77_h

#if ARDUINO >= 100
#include <Arduino.h>
#include <Arduino.h>
#else
#include <WProgram.h>
#include <WProgram.h>
#endif
#include <Time.h>
#include <TimeLib.h>

#define MIN_TIME 1334102400 // Date: 11-4-2012
#define MAX_TIME 4102444800 // Date: 1-1-2100

#define DCFRejectionTime 700 // Pulse-to-Pulse rejection time.
#define DCFRejectionTime 700 // Pulse-to-Pulse rejection time.
#define DCFRejectPulseWidth 50 // Minimal pulse width
#define DCFSplitTime 180 // Specifications distinguishes pulse width 100 ms and 200 ms. In practice we see 130 ms and 230
#define DCFSyncTime 1500 // Specifications defines 2000 ms pulse for end of sequence
Expand All @@ -20,23 +20,24 @@ class DCF77 {
private:

//Private variables
bool initialized;
bool initialized;
static int dCF77Pin;
static int dCFinterrupt;
static int dCFsplitTime;
static byte pulseStart;

// DCF77 and internal timestamps
static time_t previousUpdatedTime;
static time_t latestupdatedTime;
static time_t latestupdatedTime;
static time_t processingTimestamp;
static time_t previousProcessingTimestamp;
static time_t previousProcessingTimestamp;
static unsigned char CEST;
// DCF time format structure
struct DCF77Buffer {
//unsigned long long prefix :21;
unsigned long long prefix :17;
unsigned long long CEST :1; // CEST
unsigned long long CET :1; // CET
unsigned long long CEST :1; // CEST
unsigned long long CET :1; // CET
unsigned long long unused :2; // unused bits
unsigned long long Min :7; // minutes
unsigned long long P1 :1; // parity minutes
Expand All @@ -48,8 +49,8 @@ class DCF77 {
unsigned long long Year :8; // year (5 -> 2005)
unsigned long long P3 :1; // parity
};


// DCF Parity format structure
struct ParityFlags{
unsigned char parityFlag :1;
Expand All @@ -73,7 +74,7 @@ class DCF77 {
static int trailingEdge;
static int PreviousLeadingEdge;
static bool Up;

//Private functions
void static initialize(void);
void static bufferinit(void);
Expand All @@ -84,10 +85,11 @@ class DCF77 {
bool static processBuffer(void);
void static appendSignal(unsigned char signal);

public:
public:
// Public Functions
DCF77(int DCF77Pin, int DCFinterrupt, bool OnRisingFlank=true);

DCF77(int DCF77Pin, int DCFinterrupt, bool OnRisingFlank=true);
static void setSplitTime(int shortPulseLength, int longPulseLength);

static time_t getTime(void);
static time_t getUTCTime(void);
static void Start(void);
Expand All @@ -96,4 +98,3 @@ class DCF77 {
};

#endif

Loading