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

Implement RTC_Micros with tunable drift #112

Merged
merged 4 commits into from Jul 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
44 changes: 41 additions & 3 deletions RTClib.cpp
Expand Up @@ -337,17 +337,55 @@ void RTC_DS1307::writenvram(uint8_t address, uint8_t data) {
////////////////////////////////////////////////////////////////////////////////
// RTC_Millis implementation

long RTC_Millis::offset = 0;
// Alignment between the milis() timescale and the Unix timescale. These
// two variables are updated on each call to now(), which prevents
// rollover issues. Note that lastMillis is **not** the millis() value
// of the last call to now(): it's the millis() value corresponding to
// the last **full second** of Unix time.
uint32_t RTC_Millis::lastMillis;
uint32_t RTC_Millis::lastUnix;

void RTC_Millis::adjust(const DateTime& dt) {
offset = dt.unixtime() - millis() / 1000;
lastMillis = millis();
lastUnix = dt.unixtime();
}

// Note that computing (millis() - lastMillis) is rollover-safe as long
// as this method is called at least once every 49.7 days.
DateTime RTC_Millis::now() {
return (uint32_t)(offset + millis() / 1000);
uint32_t elapsedSeconds = (millis() - lastMillis) / 1000;
lastMillis += elapsedSeconds * 1000;
lastUnix += elapsedSeconds;
return lastUnix;
}

////////////////////////////////////////////////////////////////////////////////
// RTC_Micros implementation

// Number of microseconds reported by micros() per "true" (calibrated)
// second.
uint32_t RTC_Micros::microsPerSecond = 1000000;

// The timing logic is identical to RTC_Millis.
uint32_t RTC_Micros::lastMicros;
uint32_t RTC_Micros::lastUnix;

void RTC_Micros::adjust(const DateTime& dt) {
lastMicros = micros();
lastUnix = dt.unixtime();
}

// A positive adjustment makes the clock faster.
void RTC_Micros::adjustDrift(int ppm) {
microsPerSecond = 1000000 - ppm;
}

DateTime RTC_Micros::now() {
uint32_t elapsedSeconds = (micros() - lastMicros) / microsPerSecond;
lastMicros += elapsedSeconds * microsPerSecond;
lastUnix += elapsedSeconds;
return lastUnix;
}

////////////////////////////////////////////////////////////////////////////////
// RTC_PCF8563 implementation
Expand Down
23 changes: 21 additions & 2 deletions RTClib.h
Expand Up @@ -121,15 +121,34 @@ class RTC_PCF8523 {
};

// RTC using the internal millis() clock, has to be initialized before use
// NOTE: this clock won't be correct once the millis() timer rolls over (>49d?)
// NOTE: this is immune to millis() rollover events
class RTC_Millis {
public:
static void begin(const DateTime& dt) { adjust(dt); }
static void adjust(const DateTime& dt);
static DateTime now();

protected:
static long offset;
static uint32_t lastUnix;
static uint32_t lastMillis;
};

// RTC using the internal micros() clock, has to be initialized before
// use. Unlike RTC_Millis, this can be tuned in order to compensate for
// the natural drift of the system clock. Note that now() has to be
// called more frequently than the micros() rollover period, which is
// approximately 71.6 minutes.
class RTC_Micros {
public:
static void begin(const DateTime& dt) { adjust(dt); }
static void adjust(const DateTime& dt);
static void adjustDrift(int ppm);
static DateTime now();

protected:
static uint32_t microsPerSecond;
static uint32_t lastUnix;
static uint32_t lastMicros;
};

#endif // _RTCLIB_H_
2 changes: 2 additions & 0 deletions keywords.txt
Expand Up @@ -10,6 +10,7 @@ DateTime KEYWORD1
TimeSpan KEYWORD1
RTC_DS1307 KEYWORD1
RTC_Millis KEYWORD1
RTC_Micros KEYWORD1
Ds1307SqwPinMode KEYWORD1

#######################################
Expand All @@ -27,6 +28,7 @@ secondstime KEYWORD2
unixtime KEYWORD2
begin KEYWORD2
adjust KEYWORD2
adjustDrift KEYWORD2
isrunning KEYWORD2
now KEYWORD2
readSqwPinMode KEYWORD2
Expand Down