AceTime  1.6
Date and time classes for Arduino that support timezones from the TZ Database, and a system clock that can synchronize from an NTP server or an RTC chip.
SystemClock.h
1 /*
2  * MIT License
3  * Copyright (c) 2018 Brian T. Park
4  */
5 
6 #ifndef ACE_TIME_SYSTEM_CLOCK_H
7 #define ACE_TIME_SYSTEM_CLOCK_H
8 
9 #include <stdint.h>
10 #include "Clock.h"
11 
12 extern "C" unsigned long millis();
13 class SystemClockLoopTest;
14 class SystemClockLoopTest_syncNow;
15 class SystemClockCoroutineTest;
16 
17 namespace ace_time {
18 namespace clock {
19 
52 class SystemClock: public Clock {
53  public:
54 
56  void setup() {
57  if (mBackupClock != nullptr) {
58  setNow(mBackupClock->getNow());
59  }
60  }
61 
62  acetime_t getNow() const override {
63  if (!mIsInit) return kInvalidSeconds;
64 
65  while ((uint16_t) ((uint16_t) clockMillis() - mPrevMillis) >= 1000) {
66  mPrevMillis += 1000;
67  mEpochSeconds += 1;
68  }
69  return mEpochSeconds;
70  }
71 
72  void setNow(acetime_t epochSeconds) override {
73  syncNow(epochSeconds);
74 
75  // Also set the reference clock if possible.
76  if (mReferenceClock != nullptr) {
77  mReferenceClock->setNow(epochSeconds);
78  }
79  }
80 
82  void forceSync() {
83  acetime_t nowSeconds = mReferenceClock->getNow();
84  setNow(nowSeconds);
85  }
86 
91  acetime_t getLastSyncTime() const {
92  return mLastSyncTime;
93  }
94 
96  bool isInit() const { return mIsInit; }
97 
98  protected:
99  friend class ::SystemClockLoopTest;
100  friend class ::SystemClockCoroutineTest;
101  friend class ::SystemClockLoopTest_syncNow;
102 
103  // disable copy constructor and assignment operator
104  SystemClock(const SystemClock&) = delete;
105  SystemClock& operator=(const SystemClock&) = delete;
106 
115  explicit SystemClock(
116  Clock* referenceClock /* nullable */,
117  Clock* backupClock /* nullable */):
118  mReferenceClock(referenceClock),
119  mBackupClock(backupClock) {}
120 
125  virtual unsigned long clockMillis() const { return ::millis(); }
126 
131  void keepAlive() {
132  getNow();
133  }
134 
139  void backupNow(acetime_t nowSeconds) {
140  if (mBackupClock != nullptr) {
141  mBackupClock->setNow(nowSeconds);
142  }
143  }
144 
155  void syncNow(acetime_t epochSeconds) {
156  if (epochSeconds == kInvalidSeconds) return;
157  mLastSyncTime = epochSeconds;
158  if (mEpochSeconds == epochSeconds) return;
159 
160  mEpochSeconds = epochSeconds;
161  mPrevMillis = clockMillis();
162  mIsInit = true;
163 
164  if (mBackupClock != mReferenceClock) {
165  backupNow(epochSeconds);
166  }
167  }
168 
169  Clock* const mReferenceClock;
170  Clock* const mBackupClock;
171 
172  mutable acetime_t mEpochSeconds = kInvalidSeconds;
173  acetime_t mLastSyncTime = kInvalidSeconds; // time when last synced
174  mutable uint16_t mPrevMillis = 0; // lower 16-bits of clockMillis()
175  bool mIsInit = false; // true if setNow() or syncNow() was successful
176 };
177 
178 }
179 }
180 
181 #endif
ace_time::clock::SystemClock::getLastSyncTime
acetime_t getLastSyncTime() const
Return the time (seconds since Epoch) of the last valid sync() call.
Definition: SystemClock.h:91
ace_time::clock::SystemClock::isInit
bool isInit() const
Return true if initialized by setNow() or syncNow().
Definition: SystemClock.h:96
ace_time::clock::Clock::getNow
virtual acetime_t getNow() const =0
Return the number of seconds since the AceTime epoch (2000-01-01T00:00:00Z).
ace_time::clock::SystemClock::syncNow
void syncNow(acetime_t epochSeconds)
Similar to setNow() except that backupNow() is called only if the backupClock is different from the r...
Definition: SystemClock.h:155
ace_time::clock::SystemClock::keepAlive
void keepAlive()
Call this (or getNow() every 65.535 seconds or faster to keep the internal counter in sync with milli...
Definition: SystemClock.h:131
ace_time::clock::SystemClock::SystemClock
SystemClock(Clock *referenceClock, Clock *backupClock)
Constructor.
Definition: SystemClock.h:115
ace_time::clock::Clock::setNow
virtual void setNow(acetime_t)
Set the time to the indicated seconds.
Definition: Clock.h:56
ace_time::clock::SystemClock::setNow
void setNow(acetime_t epochSeconds) override
Set the time to the indicated seconds.
Definition: SystemClock.h:72
ace_time::clock::SystemClock::setup
void setup()
Attempt to retrieve the time from the backupClock if it exists.
Definition: SystemClock.h:56
ace_time::clock::Clock
Base class for objects that provide and store time.
Definition: Clock.h:20
ace_time::clock::SystemClock::forceSync
void forceSync()
Force a sync with the mReferenceClock.
Definition: SystemClock.h:82
ace_time::clock::SystemClock::clockMillis
virtual unsigned long clockMillis() const
Return the Arduino millis().
Definition: SystemClock.h:125
ace_time::clock::SystemClock::backupNow
void backupNow(acetime_t nowSeconds)
Write the nowSeconds to the backupClock (which can be an RTC that has non-volatile memory,...
Definition: SystemClock.h:139
ace_time::clock::SystemClock
A Clock that uses the Arduino millis() function to advance the time returned to the user.
Definition: SystemClock.h:52
ace_time::clock::SystemClock::getNow
acetime_t getNow() const override
Return the number of seconds since the AceTime epoch (2000-01-01T00:00:00Z).
Definition: SystemClock.h:62