From cb0bf8da2a56bfebae8a6137e9e803869bdae107 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Thu, 30 Jul 2020 19:11:38 +0800 Subject: [PATCH 01/43] Wrote `isLeapYear()` function --- RTClib.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ RTClib.h | 10 ++++++++++ 2 files changed, 58 insertions(+) diff --git a/RTClib.cpp b/RTClib.cpp index b7562b04..45fa9cb0 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -118,6 +118,17 @@ static void write_i2c_register(uint8_t addr, uint8_t reg, uint8_t val) { const uint8_t daysInMonth[] PROGMEM = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30}; +/**************************************************************************/ +/*! + @brief checks if the year is a leap year + @param year The year to checks + @return true if a leap year, false otherwise +*/ +/**************************************************************************/ +bool isLeapYear(uint16_t year) { + return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0); +} + /**************************************************************************/ /*! @brief Given a date, return number of days since 2000/01/01, @@ -415,6 +426,43 @@ bool DateTime::isValid() const { mm == other.mm && ss == other.ss; } +/**************************************************************************/ +/*! + @author Harrison Outram + @brief Fixes DateTime object if invalid + + Determines if any date or time components are too high. + E.g. seconds == 65 + + Increments next component and reduces invalid component to fix. + E.g. if seconds == 125, then minutes goes up by 2 and seconds + goes down to 5. + + @warning Will still result in invalid DateTime if year is above 2099 + @return true if fixed, false if year becomes invalid +*/ +/**************************************************************************/ +bool DateTime::fixDateTime() { + uint8_t temp; + + if (ss >= 60) { + temp = ss / 60; + mm += temp; + ss -= 60 * temp; + } + if (mm >= 60) { + temp = mm / 60; + hh += temp; + mm -= 60 * temp; + } + if (hh >= 24) { + temp = hh / 24; + d += temp; + hh -= temp * 24; + } + +} + /**************************************************************************/ /*! @brief Writes the DateTime as a string in a user-defined format. diff --git a/RTClib.h b/RTClib.h index a1ba2a4b..66fd6421 100644 --- a/RTClib.h +++ b/RTClib.h @@ -55,6 +55,15 @@ class TimeSpan; #define SECONDS_FROM_1970_TO_2000 \ 946684800 ///< Unixtime for 2000-01-01 00:00:00, useful for initialization +/**************************************************************************/ +/*! + @brief checks if the year is a leap year + @param year The year to checks + @return true if a leap year, false otherwise +*/ +/**************************************************************************/ +bool isLeapYear(uint16_t year); + /**************************************************************************/ /*! @brief Simple general-purpose date/time class (no TZ / DST / leap @@ -81,6 +90,7 @@ class DateTime { DateTime(const __FlashStringHelper *date, const __FlashStringHelper *time); DateTime(const char *iso8601date); bool isValid() const; + bool fixDateTime(); char *toString(char *buffer); /*! From 0af4be5f1a5b17fb2b0dee667ed5429dd417a3a0 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Thu, 30 Jul 2020 19:31:47 +0800 Subject: [PATCH 02/43] Wrote `fixDateTime()` method to fix invalid DateTime objects --- RTClib.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++ RTClib.h | 8 +------- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index 45fa9cb0..fd83055d 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -129,6 +129,33 @@ bool isLeapYear(uint16_t year) { return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0); } +/**************************************************************************/ +/*! + @brief calculates the number of days in the month + + Considers leap years, e.g. if year == 2000 and month == 2 then + days in month is 29 + + @param year The year + @param month The month from 1-12 (1 being Jan and 12 being Dec) + @warning Will return 0 if month is invalid (i.e. month > 12) + @return The number of days in the month +*/ +/**************************************************************************/ +uint8_t getDaysInMonth(uint16_t year, uint8_t month) { + uint8_t days = 0; + + if (month == 12) { + days = 31; // needed since daysInMonth does have December days + } else if (month < 12) { + days += pgm_read_byte(daysInMonth + month - 1); + + if (month == 2 && isLeapYear(year)) days++; + } + + return days; +} + /**************************************************************************/ /*! @brief Given a date, return number of days since 2000/01/01, @@ -461,6 +488,26 @@ bool DateTime::fixDateTime() { hh -= temp * 24; } + // make month valid to prevent getDaysInMonth() returning 0 + // Otherwise, infinite loop possible + if (m > 12) { + temp = m % 12; + yOff += temp; + m -= temp * 12; + } + + temp = getDaysInMonth(yOff, m); + while (d > temp) { + d -= temp; + m++; + if (m > 12) { + yOff++; + m--; + } + temp = getDaysInMonth(yOff, m); + } + + return yOff <= 99; } /**************************************************************************/ diff --git a/RTClib.h b/RTClib.h index 66fd6421..89e4a3bc 100644 --- a/RTClib.h +++ b/RTClib.h @@ -55,14 +55,8 @@ class TimeSpan; #define SECONDS_FROM_1970_TO_2000 \ 946684800 ///< Unixtime for 2000-01-01 00:00:00, useful for initialization -/**************************************************************************/ -/*! - @brief checks if the year is a leap year - @param year The year to checks - @return true if a leap year, false otherwise -*/ -/**************************************************************************/ bool isLeapYear(uint16_t year); +uint8_t getDaysInMonth(uint16_t year, uint8_t month); /**************************************************************************/ /*! From 6f49b2b99828fbb84044498103749c367c042c2f Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Thu, 30 Jul 2020 19:35:05 +0800 Subject: [PATCH 03/43] Write additional comment specifying that if DateTime is already valid, `fixDateTime()` will do nothing --- RTClib.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RTClib.cpp b/RTClib.cpp index fd83055d..09fdf686 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -465,7 +465,9 @@ bool DateTime::isValid() const { E.g. if seconds == 125, then minutes goes up by 2 and seconds goes down to 5. - @warning Will still result in invalid DateTime if year is above 2099 + Does nothing if the DateTime object is already valid + + @warning Will still result in invalid DateTime object if year is above 2099 @return true if fixed, false if year becomes invalid */ /**************************************************************************/ From 7654480f58fd512e02dcaa2cda31232d674d1427 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Mon, 28 Dec 2020 17:00:37 +0800 Subject: [PATCH 04/43] Wrote RTC superclass --- utility/RTC.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 utility/RTC.h diff --git a/utility/RTC.h b/utility/RTC.h new file mode 100644 index 00000000..f7286b0f --- /dev/null +++ b/utility/RTC.h @@ -0,0 +1,43 @@ +/**************************************************************************/ +/*! + @file RTC.h + + Original library by JeeLabs http://news.jeelabs.org/code/, released to the + public domain + + License: MIT (see LICENSE) + + This is a fork of JeeLab's fantastic real time clock library for Arduino. + + For details on using this library with an RTC module like the DS1307, PCF8523, + or DS3231, see the guide at: + https://learn.adafruit.com/ds1307-real-time-clock-breakout-board-kit/overview + + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! +*/ +/**************************************************************************/ + +#ifndef _RTC_H_ +#define _RTC_H_ + +#include + +/**************************************************************************/ +/*! + @brief RTC superclass for all RTC chips +*/ +/**************************************************************************/ +class RTC { +public: + virtual boolean begin(void) = 0; + virtual static void adjust(const DateTime &dt) = 0; + virtual bool isrunning(void) = 0; + virtual bool lostPower(void) = 0; + virtual static DateTime now() = 0; + virtual static int readSqwPinMode() = 0; + virtual static void writeSqwPinMode(int mode) = 0; +} + +#endif \ No newline at end of file From e3757d3c5e8809b70583a6794ad3936e52673844 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Mon, 28 Dec 2020 18:26:39 +0800 Subject: [PATCH 05/43] Modified RTClib.h to use RTC.h --- RTClib.cpp | 91 ++++++++++++++++++++++++++++++++++++++++------- RTClib.h | 60 ++++++++++++++++++++++--------- utility/RTC.h | 43 ---------------------- utility/RTC/RTC.h | 88 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 211 insertions(+), 71 deletions(-) delete mode 100644 utility/RTC.h create mode 100644 utility/RTC/RTC.h diff --git a/RTClib.cpp b/RTClib.cpp index 12ae863e..9320823b 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -906,14 +906,17 @@ static uint8_t bin2bcd(uint8_t val) { return val + 6 * (val / 10); } /**************************************************************************/ /*! @brief Start I2C for the DS1307 and test succesful connection + @param dt DateTime object containing desired date/time @return True if Wire can find DS1307 or false otherwise. */ /**************************************************************************/ -boolean RTC_DS1307::begin(void) { +boolean RTC_DS1307::begin(const DateTime &dt) { Wire.begin(); Wire.beginTransmission(DS1307_ADDRESS); - if (Wire.endTransmission() == 0) + if (Wire.endTransmission() == 0) { + adjust(dt); return true; + } return false; } @@ -933,6 +936,18 @@ uint8_t RTC_DS1307::isrunning(void) { return !(ss >> 7); } +/**************************************************************************/ +/*! + @brief Check the status register Oscillator Stop flag to see if the DS1307 + stopped due to power loss + @return True if the bit is set (oscillator is or has stopped) and false only + after the bit is cleared, for instance with adjust() +*/ +/**************************************************************************/ +boolean RTC_DS1307::lostPower(void) { + return (read_i2c_register(DS1307_ADDRESS, 0) >> 7); +} + /**************************************************************************/ /*! @brief Set the date and time in the DS1307 @@ -952,6 +967,18 @@ void RTC_DS1307::adjust(const DateTime &dt) { Wire.endTransmission(); } +/**************************************************************************/ +/*! + @brief Adjust the RTC clock to compensate for system clock drift + @param drift Adjustment to make in seconds + @note Positive values make the clock go ahead in time and vice-versa +*/ +/**************************************************************************/ +void RTC_DS1307::adjustDrift(const int drift) { + DateTime newDt = DateTime(unixtime() + drift); + adjust(newDt); +} + /**************************************************************************/ /*! @brief Get the current date and time from the DS1307 @@ -1076,9 +1103,22 @@ void RTC_DS1307::writenvram(uint8_t address, uint8_t data) { 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::millisPerSecond = 1000; uint32_t RTC_Millis::lastMillis; uint32_t RTC_Millis::lastUnix; +/**************************************************************************/ +/*! + @brief Start the RTC_Millis date/time + @param dt DateTime object containing desired date/time + @return true +*/ +/**************************************************************************/ +boolean RTC_Millis::begin(const DateTime &dt) { + adjust(dt); + return true; +} + /**************************************************************************/ /*! @brief Set the current date/time of the RTC_Millis clock. @@ -1090,6 +1130,15 @@ void RTC_Millis::adjust(const DateTime &dt) { lastUnix = dt.unixtime(); } +/**************************************************************************/ +/*! + @brief Adjust the RTC clock to compensate for system clock drift + @param drift Adjustment to make in milliseconds + @note Positive values make the clock go ahead in time and vice-versa +*/ +/**************************************************************************/ +void RTC_Millis::adjustDrift(int drift) { lastMillis = 1000 - drift; } + /**************************************************************************/ /*! @brief Return a DateTime object containing the current date/time. @@ -1099,8 +1148,8 @@ void RTC_Millis::adjust(const DateTime &dt) { */ /**************************************************************************/ DateTime RTC_Millis::now() { - uint32_t elapsedSeconds = (millis() - lastMillis) / 1000; - lastMillis += elapsedSeconds * 1000; + uint32_t elapsedSeconds = (millis() - lastMillis) / millisPerSecond; + lastMillis += elapsedSeconds * millisPerSecond; lastUnix += elapsedSeconds; return lastUnix; } @@ -1113,6 +1162,18 @@ uint32_t RTC_Micros::microsPerSecond = 1000000; uint32_t RTC_Micros::lastMicros; uint32_t RTC_Micros::lastUnix; +/**************************************************************************/ +/*! + @brief Start the RTC_Micros date/time + @param dt DateTime object containing desired date/time + @return true +*/ +/**************************************************************************/ +boolean RTC_Micros::begin(const DateTime &dt) { + adjust(dt); + return true; +} + /**************************************************************************/ /*! @brief Set the current date/time of the RTC_Micros clock. @@ -1127,11 +1188,11 @@ void RTC_Micros::adjust(const DateTime &dt) { /**************************************************************************/ /*! @brief Adjust the RTC_Micros clock to compensate for system clock drift - @param ppm Adjustment to make + @param drift Adjustment to make in microseconds */ /**************************************************************************/ // A positive adjustment makes the clock faster. -void RTC_Micros::adjustDrift(int ppm) { microsPerSecond = 1000000 - ppm; } +void RTC_Micros::adjustDrift(int drift) { microsPerSecond = 1000000 - drift; } /**************************************************************************/ /*! @@ -1152,11 +1213,13 @@ DateTime RTC_Micros::now() { @return True if Wire can find PCF8523 or false otherwise. */ /**************************************************************************/ -boolean RTC_PCF8523::begin(void) { +boolean RTC_PCF8523::begin(const DateTime &dt) { Wire.begin(); Wire.beginTransmission(PCF8523_ADDRESS); - if (Wire.endTransmission() == 0) + if (Wire.endTransmission() == 0) { + adjust(dt); return true; + } return false; } @@ -1480,11 +1543,13 @@ void RTC_PCF8523::calibrate(Pcf8523OffsetMode mode, int8_t offset) { @return True if Wire can find PCF8563 or false otherwise. */ /**************************************************************************/ -boolean RTC_PCF8563::begin(void) { +boolean RTC_PCF8563::begin(const DateTime &dt) { Wire.begin(); Wire.beginTransmission(PCF8563_ADDRESS); - if (Wire.endTransmission() == 0) + if (Wire.endTransmission() == 0) { + adjust(dt); return true; + } return false; } @@ -1634,11 +1699,13 @@ static uint8_t dowToDS3231(uint8_t d) { return d == 0 ? 7 : d; } @return True if Wire can find DS3231 or false otherwise. */ /**************************************************************************/ -boolean RTC_DS3231::begin(void) { +boolean RTC_DS3231::begin(const DateTime &dt) { Wire.begin(); Wire.beginTransmission(DS3231_ADDRESS); - if (Wire.endTransmission() == 0) + if (Wire.endTransmission() == 0) { + adjust(dt); return true; + } return false; } diff --git a/RTClib.h b/RTClib.h index 82905a87..4a752ff5 100644 --- a/RTClib.h +++ b/RTClib.h @@ -23,6 +23,7 @@ #define _RTCLIB_H_ #include +#include "utility/RTC.h" class TimeSpan; /** Registers */ @@ -62,6 +63,8 @@ class TimeSpan; #define SECONDS_FROM_1970_TO_2000 \ 946684800 ///< Unixtime for 2000-01-01 00:00:00, useful for initialization +const DateTime COMPILE_DT = DateTime(__DATE__, __TIME__); + bool isLeapYear(uint16_t year); uint8_t getDaysInMonth(uint16_t year, uint8_t month); @@ -275,11 +278,13 @@ enum Ds1307SqwPinMode { @brief RTC based on the DS1307 chip connected via I2C and the Wire library */ /**************************************************************************/ -class RTC_DS1307 { +class RTC_DS1307 : RTC { public: - boolean begin(void); + boolean begin(const DateTime &dt = COMPILE_DT); static void adjust(const DateTime &dt); - uint8_t isrunning(void); + void adjustDrift(int drift); + bool isrunning(void); + bool lostPower(void); static DateTime now(); static Ds1307SqwPinMode readSqwPinMode(); static void writeSqwPinMode(Ds1307SqwPinMode mode); @@ -327,10 +332,12 @@ enum Ds3231Alarm2Mode { @brief RTC based on the DS3231 chip connected via I2C and the Wire library */ /**************************************************************************/ -class RTC_DS3231 { +class RTC_DS3231 : RTC { public: - boolean begin(void); + boolean begin(const DateTime &dt = COMPILE_DT); static void adjust(const DateTime &dt); + static void adjustDrift(const int drift); + bool isrunning(void); bool lostPower(void); static DateTime now(); static Ds3231SqwPinMode readSqwPinMode(); @@ -392,16 +399,17 @@ enum Pcf8523OffsetMode { @brief RTC based on the PCF8523 chip connected via I2C and the Wire library */ /**************************************************************************/ -class RTC_PCF8523 { +class RTC_PCF8523 : RTC { public: - boolean begin(void); + boolean begin(const DateTime &dt = COMPILE_DT); void adjust(const DateTime &dt); + boolean isrunning(void); boolean lostPower(void); boolean initialized(void); static DateTime now(); void start(void); void stop(void); - uint8_t isrunning(); + boolean isrunning(); Pcf8523SqwPinMode readSqwPinMode(); void writeSqwPinMode(Pcf8523SqwPinMode mode); void enableSecondTimer(void); @@ -429,9 +437,10 @@ enum Pcf8563SqwPinMode { */ /**************************************************************************/ -class RTC_PCF8563 { +class RTC_PCF8563 : RTC { public: - boolean begin(void); + boolean begin(const DateTime &dt = COMPILE_DT); + boolean isrunning(void); boolean lostPower(void); void adjust(const DateTime &dt); static DateTime now(); @@ -448,17 +457,26 @@ class RTC_PCF8563 { use. NOTE: this is immune to millis() rollover events. */ /**************************************************************************/ -class RTC_Millis { +class RTC_Millis : RTC { public: + static boolean begin(const DateTime &dt = COMPILE_DT); /*! - @brief Start the RTC - @param dt DateTime object with the date/time to set + @brief Simulate if the RTC is running + @return true */ - static void begin(const DateTime &dt) { adjust(dt); } + boolean isrunning(void) { return true; } + /*! + @brief Simulate if the RTC has lost power + @return false + */ + boolean lostPower(void) { return false; } static void adjust(const DateTime &dt); + static void adjustDrift(const int drift); static DateTime now(); protected: + static uint32_t millisPerSecond; ///< Number of milliseconds reported by + ///< millis() per "true" (calibrated) second static uint32_t lastUnix; ///< Unix time from the previous call to now() - ///< prevents rollover issues static uint32_t lastMillis; ///< the millis() value corresponding to the last @@ -474,13 +492,23 @@ class RTC_Millis { approximately 71.6 minutes. */ /**************************************************************************/ -class RTC_Micros { +class RTC_Micros : RTC { public: /*! @brief Start the RTC @param dt DateTime object with the date/time to set */ - static void begin(const DateTime &dt) { adjust(dt); } + static boolean begin(const DateTime &dt = COMPILE_DT); + /*! + @brief Simulate if the RTC is running + @return true + */ + boolean isrunning(void) { return true; } + /*! + @brief Simulate if the RTC has lost power + @return false + */ + boolean lostPower(void) { return false; } static void adjust(const DateTime &dt); static void adjustDrift(int ppm); static DateTime now(); diff --git a/utility/RTC.h b/utility/RTC.h deleted file mode 100644 index f7286b0f..00000000 --- a/utility/RTC.h +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************/ -/*! - @file RTC.h - - Original library by JeeLabs http://news.jeelabs.org/code/, released to the - public domain - - License: MIT (see LICENSE) - - This is a fork of JeeLab's fantastic real time clock library for Arduino. - - For details on using this library with an RTC module like the DS1307, PCF8523, - or DS3231, see the guide at: - https://learn.adafruit.com/ds1307-real-time-clock-breakout-board-kit/overview - - Adafruit invests time and resources providing this open source code, - please support Adafruit and open-source hardware by purchasing - products from Adafruit! -*/ -/**************************************************************************/ - -#ifndef _RTC_H_ -#define _RTC_H_ - -#include - -/**************************************************************************/ -/*! - @brief RTC superclass for all RTC chips -*/ -/**************************************************************************/ -class RTC { -public: - virtual boolean begin(void) = 0; - virtual static void adjust(const DateTime &dt) = 0; - virtual bool isrunning(void) = 0; - virtual bool lostPower(void) = 0; - virtual static DateTime now() = 0; - virtual static int readSqwPinMode() = 0; - virtual static void writeSqwPinMode(int mode) = 0; -} - -#endif \ No newline at end of file diff --git a/utility/RTC/RTC.h b/utility/RTC/RTC.h new file mode 100644 index 00000000..8be1dac6 --- /dev/null +++ b/utility/RTC/RTC.h @@ -0,0 +1,88 @@ +/**************************************************************************/ +/*! + @file RTC.h + + Original library by JeeLabs http://news.jeelabs.org/code/, released to the + public domain + + License: MIT (see LICENSE) + + This is a fork of JeeLab's fantastic real time clock library for Arduino. + + For details on using this library with an RTC module like the DS1307, PCF8523, + or DS3231, see the guide at: + https://learn.adafruit.com/ds1307-real-time-clock-breakout-board-kit/overview + + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! +*/ +/**************************************************************************/ + +#ifndef _RTC_H_ +#define _RTC_H_ + +#include + +class DateTime; + +/**************************************************************************/ +/*! + @brief RTC superclass for all RTC chips +*/ +/**************************************************************************/ +class RTC { +public: + /*! + @brief Start the RTC + @param dt DateTime object containing desired date/time + @return True if successful, false otherwise + */ + virtual boolean begin(DateTime &dt) = 0; + + /*! + @brief Adjust the RTC to the specified date/time + @param dt DateTime object containing desired date/time + */ + virtual void adjust(const DateTime &dt) = 0; + + /*! + @brief Adjust the RTC's date/time to account for RTC drift + @param drift The drift to adjust the date/time by + @note Positive values makes the clock go ahead in time and vice-versa + */ + virtual void adjustDrift(const int drift); + + /*! + @brief Check if the RTC is running or not + @return True if it is running, false otherwise + */ + virtual boolean isrunning(void) = 0; + + /*! + @brief Check if the RTC has lost power + @return True if the RTC has lost power, false otherwise + @note Equivelant to `!rtc.isrunning()` + */ + virtual boolean lostPower(void); + + /*! + @brief Get the current date/time from the RTC + @return The date/time + */ + virtual DateTime now() = 0; + + /*! + @brief Get the square wave mode + @return The square wave mode + */ + virtual int readSqwPinMode() = 0; + + /*! + @brief Set the square wave mode + @param mode The mode to set the square wave to + */ + virtual void writeSqwPinMode(int mode) = 0; +}; + +#endif \ No newline at end of file From 9dfa49b6191902f80e5518ed2815bb4853a8ce7c Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Mon, 28 Dec 2020 21:26:02 +0800 Subject: [PATCH 06/43] Fixed IDE errors --- RTClib.cpp | 805 +--------------------------------- RTClib.h | 266 ++--------- utility/DateTime/DateTime.cpp | 644 +++++++++++++++++++++++++++ utility/DateTime/DateTime.h | 163 +++++++ utility/RTC/RTC.h | 17 +- utility/TimeSpan/TimeSpan.cpp | 55 +++ utility/TimeSpan/TimeSpan.h | 55 +++ 7 files changed, 957 insertions(+), 1048 deletions(-) create mode 100644 utility/DateTime/DateTime.cpp create mode 100644 utility/DateTime/DateTime.h create mode 100644 utility/TimeSpan/TimeSpan.cpp create mode 100644 utility/TimeSpan/TimeSpan.h diff --git a/RTClib.cpp b/RTClib.cpp index 9320823b..3eae4dd9 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -42,6 +42,8 @@ */ /**************************************************************************/ +#include "RTClib.h" + #ifdef __AVR_ATtiny85__ #include #define Wire TinyWireM @@ -49,31 +51,6 @@ #include #endif -#include "RTClib.h" -#ifdef __AVR__ -#include -#elif defined(ESP8266) -#include -#elif defined(ARDUINO_ARCH_SAMD) -// nothing special needed -#elif defined(ARDUINO_SAM_DUE) -#define PROGMEM -#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) -#define Wire Wire1 -#endif - -#if (ARDUINO >= 100) -#include // capital A so it is error prone on case-sensitive filesystems -// Macro to deal with the difference in I2C write functions from old and new -// Arduino versions. -#define _I2C_WRITE write ///< Modern I2C write -#define _I2C_READ read ///< Modern I2C read -#else -#include -#define _I2C_WRITE send ///< Legacy I2C write -#define _I2C_READ receive ///< legacy I2C read -#endif - /**************************************************************************/ /*! @brief Read a byte from an I2C register @@ -106,784 +83,6 @@ static void write_i2c_register(uint8_t addr, uint8_t reg, uint8_t val) { Wire.endTransmission(); } -/**************************************************************************/ -// utility code, some of this could be exposed in the DateTime API if needed -/**************************************************************************/ - -/** - Number of days in each month, from January to November. December is not - needed. Omitting it avoids an incompatibility with Paul Stoffregen's Time - library. C.f. https://github.com/adafruit/RTClib/issues/114 -*/ -const uint8_t daysInMonth[] PROGMEM = {31, 28, 31, 30, 31, 30, - 31, 31, 30, 31, 30}; - -/**************************************************************************/ -/*! - @brief checks if the year is a leap year - @param year The year to checks - @return true if a leap year, false otherwise -*/ -/**************************************************************************/ -bool isLeapYear(uint16_t year) { - return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0); -} - -/**************************************************************************/ -/*! - @brief calculates the number of days in the month - - Considers leap years, e.g. if year == 2000 and month == 2 then - days in month is 29 - - @param year The year - @param month The month from 1-12 (1 being Jan and 12 being Dec) - @warning Will return 0 if month is invalid (i.e. month > 12) - @return The number of days in the month -*/ -/**************************************************************************/ -uint8_t getDaysInMonth(uint16_t year, uint8_t month) { - uint8_t days = 0; - - if (month == 12) { - days = 31; // needed since daysInMonth does have December days - } else if (month < 12) { - days += pgm_read_byte(daysInMonth + month - 1); - - if (month == 2 && isLeapYear(year)) days++; - } - - return days; -} - -/**************************************************************************/ -/*! - @brief Given a date, return number of days since 2000/01/01, - valid for 2000--2099 - @param y Year - @param m Month - @param d Day - @return Number of days -*/ -/**************************************************************************/ -static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) { - if (y >= 2000U) - y -= 2000U; - uint16_t days = d; - for (uint8_t i = 1; i < m; ++i) - days += pgm_read_byte(daysInMonth + i - 1); - if (m > 2 && y % 4 == 0) - ++days; - return days + 365 * y + (y + 3) / 4 - 1; -} - -/**************************************************************************/ -/*! - @brief Given a number of days, hours, minutes, and seconds, return the - total seconds - @param days Days - @param h Hours - @param m Minutes - @param s Seconds - @return Number of seconds total -*/ -/**************************************************************************/ -static uint32_t time2ulong(uint16_t days, uint8_t h, uint8_t m, uint8_t s) { - return ((days * 24UL + h) * 60 + m) * 60 + s; -} - -/**************************************************************************/ -/*! - @brief Constructor from - [Unix time](https://en.wikipedia.org/wiki/Unix_time). - - This builds a DateTime from an integer specifying the number of seconds - elapsed since the epoch: 1970-01-01 00:00:00. This number is analogous - to Unix time, with two small differences: - - - The Unix epoch is specified to be at 00:00:00 - [UTC](https://en.wikipedia.org/wiki/Coordinated_Universal_Time), - whereas this class has no notion of time zones. The epoch used in - this class is then at 00:00:00 on whatever time zone the user chooses - to use, ignoring changes in DST. - - - Unix time is conventionally represented with signed numbers, whereas - this constructor takes an unsigned argument. Because of this, it does - _not_ suffer from the - [year 2038 problem](https://en.wikipedia.org/wiki/Year_2038_problem). - - If called without argument, it returns the earliest time representable - by this class: 2000-01-01 00:00:00. - - @see The `unixtime()` method is the converse of this constructor. - - @param t Time elapsed in seconds since 1970-01-01 00:00:00. -*/ -/**************************************************************************/ -DateTime::DateTime(uint32_t t) { - t -= SECONDS_FROM_1970_TO_2000; // bring to 2000 timestamp from 1970 - - ss = t % 60; - t /= 60; - mm = t % 60; - t /= 60; - hh = t % 24; - uint16_t days = t / 24; - uint8_t leap; - for (yOff = 0;; ++yOff) { - leap = yOff % 4 == 0; - if (days < 365U + leap) - break; - days -= 365 + leap; - } - for (m = 1; m < 12; ++m) { - uint8_t daysPerMonth = pgm_read_byte(daysInMonth + m - 1); - if (leap && m == 2) - ++daysPerMonth; - if (days < daysPerMonth) - break; - days -= daysPerMonth; - } - d = days + 1; -} - -/**************************************************************************/ -/*! - @brief Constructor from (year, month, day, hour, minute, second). - @warning If the provided parameters are not valid (e.g. 31 February), - the constructed DateTime will be invalid. - @see The `isValid()` method can be used to test whether the - constructed DateTime is valid. - @param year Either the full year (range: 2000--2099) or the offset from - year 2000 (range: 0--99). - @param month Month number (1--12). - @param day Day of the month (1--31). - @param hour,min,sec Hour (0--23), minute (0--59) and second (0--59). -*/ -/**************************************************************************/ -DateTime::DateTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, - uint8_t min, uint8_t sec) { - if (year >= 2000U) - year -= 2000U; - yOff = year; - m = month; - d = day; - hh = hour; - mm = min; - ss = sec; -} - -/**************************************************************************/ -/*! - @brief Copy constructor. - @param copy DateTime to copy. -*/ -/**************************************************************************/ -DateTime::DateTime(const DateTime ©) - : yOff(copy.yOff), m(copy.m), d(copy.d), hh(copy.hh), mm(copy.mm), - ss(copy.ss) {} - -/**************************************************************************/ -/*! - @brief Convert a string containing two digits to uint8_t, e.g. "09" returns - 9 - @param p Pointer to a string containing two digits -*/ -/**************************************************************************/ -static uint8_t conv2d(const char *p) { - uint8_t v = 0; - if ('0' <= *p && *p <= '9') - v = *p - '0'; - return 10 * v + *++p - '0'; -} - -/**************************************************************************/ -/*! - @brief Constructor for generating the build time. - - This constructor expects its parameters to be strings in the format - generated by the compiler's preprocessor macros `__DATE__` and - `__TIME__`. Usage: - - ``` - DateTime buildTime(__DATE__, __TIME__); - ``` - - @note The `F()` macro can be used to reduce the RAM footprint, see - the next constructor. - - @param date Date string, e.g. "Apr 16 2020". - @param time Time string, e.g. "18:34:56". -*/ -/**************************************************************************/ -DateTime::DateTime(const char *date, const char *time) { - yOff = conv2d(date + 9); - // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec - switch (date[0]) { - case 'J': - m = (date[1] == 'a') ? 1 : ((date[2] == 'n') ? 6 : 7); - break; - case 'F': - m = 2; - break; - case 'A': - m = date[2] == 'r' ? 4 : 8; - break; - case 'M': - m = date[2] == 'r' ? 3 : 5; - break; - case 'S': - m = 9; - break; - case 'O': - m = 10; - break; - case 'N': - m = 11; - break; - case 'D': - m = 12; - break; - } - d = conv2d(date + 4); - hh = conv2d(time); - mm = conv2d(time + 3); - ss = conv2d(time + 6); -} - -/**************************************************************************/ -/*! - @brief Memory friendly constructor for generating the build time. - - This version is intended to save RAM by keeping the date and time - strings in program memory. Use it with the `F()` macro: - - ``` - DateTime buildTime(F(__DATE__), F(__TIME__)); - ``` - - @param date Date PROGMEM string, e.g. F("Apr 16 2020"). - @param time Time PROGMEM string, e.g. F("18:34:56"). -*/ -/**************************************************************************/ -DateTime::DateTime(const __FlashStringHelper *date, - const __FlashStringHelper *time) { - char buff[11]; - memcpy_P(buff, date, 11); - yOff = conv2d(buff + 9); - // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec - switch (buff[0]) { - case 'J': - m = (buff[1] == 'a') ? 1 : ((buff[2] == 'n') ? 6 : 7); - break; - case 'F': - m = 2; - break; - case 'A': - m = buff[2] == 'r' ? 4 : 8; - break; - case 'M': - m = buff[2] == 'r' ? 3 : 5; - break; - case 'S': - m = 9; - break; - case 'O': - m = 10; - break; - case 'N': - m = 11; - break; - case 'D': - m = 12; - break; - } - d = conv2d(buff + 4); - memcpy_P(buff, time, 8); - hh = conv2d(buff); - mm = conv2d(buff + 3); - ss = conv2d(buff + 6); -} - -/**************************************************************************/ -/*! - @brief Constructor for creating a DateTime from an ISO8601 date string. - - This constructor expects its parameters to be a string in the - https://en.wikipedia.org/wiki/ISO_8601 format, e.g: - - "2020-06-25T15:29:37" - - Usage: - - ``` - DateTime dt("2020-06-25T15:29:37"); - ``` - - @note The year must be > 2000, as only the yOff is considered. - - @param iso8601dateTime - A dateTime string in iso8601 format, - e.g. "2020-06-25T15:29:37". - -*/ -/**************************************************************************/ -DateTime::DateTime(const char *iso8601dateTime) { - char ref[] = "2000-01-01T00:00:00"; - memcpy(ref, iso8601dateTime, min(strlen(ref), strlen(iso8601dateTime))); - yOff = conv2d(ref + 2); - m = conv2d(ref + 5); - d = conv2d(ref + 8); - hh = conv2d(ref + 11); - mm = conv2d(ref + 14); - ss = conv2d(ref + 17); -} - -/**************************************************************************/ -/*! - @brief Check whether this DateTime is valid. - @return true if valid, false if not. -*/ -/**************************************************************************/ -bool DateTime::isValid() const { - if (yOff >= 100) - return false; - DateTime other(unixtime()); - return yOff == other.yOff && m == other.m && d == other.d && hh == other.hh && - mm == other.mm && ss == other.ss; -} - -/**************************************************************************/ -/*! - @author Harrison Outram - @brief Fixes DateTime object if invalid - - Determines if any date or time components are too high. - E.g. seconds == 65 - - Increments next component and reduces invalid component to fix. - E.g. if seconds == 125, then minutes goes up by 2 and seconds - goes down to 5. - - Does nothing if the DateTime object is already valid - - @warning Will still result in invalid DateTime object if year is above 2099 - @return true if fixed, false if year becomes invalid -*/ -/**************************************************************************/ -bool DateTime::fixDateTime() { - uint8_t temp; - - if (ss >= 60) { - temp = ss / 60; - mm += temp; - ss -= 60 * temp; - } - if (mm >= 60) { - temp = mm / 60; - hh += temp; - mm -= 60 * temp; - } - if (hh >= 24) { - temp = hh / 24; - d += temp; - hh -= temp * 24; - } - - // make month valid to prevent getDaysInMonth() returning 0 - // Otherwise, infinite loop possible - if (m > 12) { - temp = m % 12; - yOff += temp; - m -= temp * 12; - } - - temp = getDaysInMonth(yOff, m); - while (d > temp) { - d -= temp; - m++; - if (m > 12) { - yOff++; - m--; - } - temp = getDaysInMonth(yOff, m); - } - - return yOff <= 99; -} - -/**************************************************************************/ -/*! - @brief Writes the DateTime as a string in a user-defined format. - - The _buffer_ parameter should be initialized by the caller with a string - specifying the requested format. This format string may contain any of - the following specifiers: - - | specifier | output | - |-----------|--------------------------------------------------------| - | YYYY | the year as a 4-digit number (2000--2099) | - | YY | the year as a 2-digit number (00--99) | - | MM | the month as a 2-digit number (01--12) | - | MMM | the abbreviated English month name ("Jan"--"Dec") | - | DD | the day as a 2-digit number (01--31) | - | DDD | the abbreviated English day of the week ("Mon"--"Sun") | - | AP | either "AM" or "PM" | - | ap | either "am" or "pm" | - | hh | the hour as a 2-digit number (00--23 or 01--12) | - | mm | the minute as a 2-digit number (00--59) | - | ss | the second as a 2-digit number (00--59) | - - If either "AP" or "ap" is used, the "hh" specifier uses 12-hour mode - (range: 01--12). Otherwise it works in 24-hour mode (range: 00--23). - - The specifiers within _buffer_ will be overwritten with the appropriate - values from the DateTime. Any characters not belonging to one of the - above specifiers are left as-is. - - __Example__: The format "DDD, DD MMM YYYY hh:mm:ss" generates an output - of the form "Thu, 16 Apr 2020 18:34:56. - - @see The `timestamp()` method provides similar functionnality, but it - returns a `String` object and supports a limited choice of - predefined formats. - - @param[in,out] buffer Array of `char` for holding the format description - and the formatted DateTime. Before calling this method, the buffer - should be initialized by the user with the format string. The method - will overwrite the buffer with the formatted date and/or time. - - @return A pointer to the provided buffer. This is returned for - convenience, in order to enable idioms such as - `Serial.println(now.toString(buffer));` -*/ -/**************************************************************************/ - -char *DateTime::toString(char *buffer) { - uint8_t apTag = - (strstr(buffer, "ap") != nullptr) || (strstr(buffer, "AP") != nullptr); - uint8_t hourReformatted = 0, isPM = false; - if (apTag) { // 12 Hour Mode - if (hh == 0) { // midnight - isPM = false; - hourReformatted = 12; - } else if (hh == 12) { // noon - isPM = true; - hourReformatted = 12; - } else if (hh < 12) { // morning - isPM = false; - hourReformatted = hh; - } else { // 1 o'clock or after - isPM = true; - hourReformatted = hh - 12; - } - } - - for (size_t i = 0; i < strlen(buffer) - 1; i++) { - if (buffer[i] == 'h' && buffer[i + 1] == 'h') { - if (!apTag) { // 24 Hour Mode - buffer[i] = '0' + hh / 10; - buffer[i + 1] = '0' + hh % 10; - } else { // 12 Hour Mode - buffer[i] = '0' + hourReformatted / 10; - buffer[i + 1] = '0' + hourReformatted % 10; - } - } - if (buffer[i] == 'm' && buffer[i + 1] == 'm') { - buffer[i] = '0' + mm / 10; - buffer[i + 1] = '0' + mm % 10; - } - if (buffer[i] == 's' && buffer[i + 1] == 's') { - buffer[i] = '0' + ss / 10; - buffer[i + 1] = '0' + ss % 10; - } - if (buffer[i] == 'D' && buffer[i + 1] == 'D' && buffer[i + 2] == 'D') { - static PROGMEM const char day_names[] = "SunMonTueWedThuFriSat"; - const char *p = &day_names[3 * dayOfTheWeek()]; - buffer[i] = pgm_read_byte(p); - buffer[i + 1] = pgm_read_byte(p + 1); - buffer[i + 2] = pgm_read_byte(p + 2); - } else if (buffer[i] == 'D' && buffer[i + 1] == 'D') { - buffer[i] = '0' + d / 10; - buffer[i + 1] = '0' + d % 10; - } - if (buffer[i] == 'M' && buffer[i + 1] == 'M' && buffer[i + 2] == 'M') { - static PROGMEM const char month_names[] = - "JanFebMarAprMayJunJulAugSepOctNovDec"; - const char *p = &month_names[3 * (m - 1)]; - buffer[i] = pgm_read_byte(p); - buffer[i + 1] = pgm_read_byte(p + 1); - buffer[i + 2] = pgm_read_byte(p + 2); - } else if (buffer[i] == 'M' && buffer[i + 1] == 'M') { - buffer[i] = '0' + m / 10; - buffer[i + 1] = '0' + m % 10; - } - if (buffer[i] == 'Y' && buffer[i + 1] == 'Y' && buffer[i + 2] == 'Y' && - buffer[i + 3] == 'Y') { - buffer[i] = '2'; - buffer[i + 1] = '0'; - buffer[i + 2] = '0' + (yOff / 10) % 10; - buffer[i + 3] = '0' + yOff % 10; - } else if (buffer[i] == 'Y' && buffer[i + 1] == 'Y') { - buffer[i] = '0' + (yOff / 10) % 10; - buffer[i + 1] = '0' + yOff % 10; - } - if (buffer[i] == 'A' && buffer[i + 1] == 'P') { - if (isPM) { - buffer[i] = 'P'; - buffer[i + 1] = 'M'; - } else { - buffer[i] = 'A'; - buffer[i + 1] = 'M'; - } - } else if (buffer[i] == 'a' && buffer[i + 1] == 'p') { - if (isPM) { - buffer[i] = 'p'; - buffer[i + 1] = 'm'; - } else { - buffer[i] = 'a'; - buffer[i + 1] = 'm'; - } - } - } - return buffer; -} - -/**************************************************************************/ -/*! - @brief Return the hour in 12-hour format. - @return Hour (1--12). -*/ -/**************************************************************************/ -uint8_t DateTime::twelveHour() const { - if (hh == 0 || hh == 12) { // midnight or noon - return 12; - } else if (hh > 12) { // 1 o'clock or later - return hh - 12; - } else { // morning - return hh; - } -} - -/**************************************************************************/ -/*! - @brief Return the day of the week. - @return Day of week as an integer from 0 (Sunday) to 6 (Saturday). -*/ -/**************************************************************************/ -uint8_t DateTime::dayOfTheWeek() const { - uint16_t day = date2days(yOff, m, d); - return (day + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6 -} - -/**************************************************************************/ -/*! - @brief Return Unix time: seconds since 1 Jan 1970. - - @see The `DateTime::DateTime(uint32_t)` constructor is the converse of - this method. - - @return Number of seconds since 1970-01-01 00:00:00. -*/ -/**************************************************************************/ -uint32_t DateTime::unixtime(void) const { - uint32_t t; - uint16_t days = date2days(yOff, m, d); - t = time2ulong(days, hh, mm, ss); - t += SECONDS_FROM_1970_TO_2000; // seconds from 1970 to 2000 - - return t; -} - -/**************************************************************************/ -/*! - @brief Convert the DateTime to seconds since 1 Jan 2000 - - The result can be converted back to a DateTime with: - - ```cpp - DateTime(SECONDS_FROM_1970_TO_2000 + value) - ``` - - @return Number of seconds since 2000-01-01 00:00:00. -*/ -/**************************************************************************/ -uint32_t DateTime::secondstime(void) const { - uint32_t t; - uint16_t days = date2days(yOff, m, d); - t = time2ulong(days, hh, mm, ss); - return t; -} - -/**************************************************************************/ -/*! - @brief Add a TimeSpan to the DateTime object - @param span TimeSpan object - @return New DateTime object with span added to it. -*/ -/**************************************************************************/ -DateTime DateTime::operator+(const TimeSpan &span) { - return DateTime(unixtime() + span.totalseconds()); -} - -/**************************************************************************/ -/*! - @brief Subtract a TimeSpan from the DateTime object - @param span TimeSpan object - @return New DateTime object with span subtracted from it. -*/ -/**************************************************************************/ -DateTime DateTime::operator-(const TimeSpan &span) { - return DateTime(unixtime() - span.totalseconds()); -} - -/**************************************************************************/ -/*! - @brief Subtract one DateTime from another - - @note Since a TimeSpan cannot be negative, the subtracted DateTime - should be less (earlier) than or equal to the one it is - subtracted from. - - @param right The DateTime object to subtract from self (the left object) - @return TimeSpan of the difference between DateTimes. -*/ -/**************************************************************************/ -TimeSpan DateTime::operator-(const DateTime &right) { - return TimeSpan(unixtime() - right.unixtime()); -} - -/**************************************************************************/ -/*! - @author Anton Rieutskyi - @brief Test if one DateTime is less (earlier) than another. - @warning if one or both DateTime objects are invalid, returned value is - meaningless - @see use `isValid()` method to check if DateTime object is valid - @param right Comparison DateTime object - @return True if the left DateTime is earlier than the right one, - false otherwise. -*/ -/**************************************************************************/ -bool DateTime::operator<(const DateTime &right) const { - return (yOff + 2000U < right.year() || - (yOff + 2000U == right.year() && - (m < right.month() || - (m == right.month() && - (d < right.day() || - (d == right.day() && - (hh < right.hour() || - (hh == right.hour() && - (mm < right.minute() || - (mm == right.minute() && ss < right.second())))))))))); -} - -/**************************************************************************/ -/*! - @author Anton Rieutskyi - @brief Test if two DateTime objects are equal. - @warning if one or both DateTime objects are invalid, returned value is - meaningless - @see use `isValid()` method to check if DateTime object is valid - @param right Comparison DateTime object - @return True if both DateTime objects are the same, false otherwise. -*/ -/**************************************************************************/ -bool DateTime::operator==(const DateTime &right) const { - return (right.year() == yOff + 2000U && right.month() == m && - right.day() == d && right.hour() == hh && right.minute() == mm && - right.second() == ss); -} - -/**************************************************************************/ -/*! - @brief Return a ISO 8601 timestamp as a `String` object. - - The generated timestamp conforms to one of the predefined, ISO - 8601-compatible formats for representing the date (if _opt_ is - `TIMESTAMP_DATE`), the time (`TIMESTAMP_TIME`), or both - (`TIMESTAMP_FULL`). - - @see The `toString()` method provides more general string formatting. - - @param opt Format of the timestamp - @return Timestamp string, e.g. "2020-04-16T18:34:56". -*/ -/**************************************************************************/ -String DateTime::timestamp(timestampOpt opt) { - char buffer[25]; // large enough for any DateTime, including invalid ones - - // Generate timestamp according to opt - switch (opt) { - case TIMESTAMP_TIME: - // Only time - sprintf(buffer, "%02d:%02d:%02d", hh, mm, ss); - break; - case TIMESTAMP_DATE: - // Only date - sprintf(buffer, "%u-%02d-%02d", 2000U + yOff, m, d); - break; - default: - // Full - sprintf(buffer, "%u-%02d-%02dT%02d:%02d:%02d", 2000U + yOff, m, d, hh, mm, - ss); - } - return String(buffer); -} - -/**************************************************************************/ -/*! - @brief Create a new TimeSpan object in seconds - @param seconds Number of seconds -*/ -/**************************************************************************/ -TimeSpan::TimeSpan(int32_t seconds) : _seconds(seconds) {} - -/**************************************************************************/ -/*! - @brief Create a new TimeSpan object using a number of - days/hours/minutes/seconds e.g. Make a TimeSpan of 3 hours and 45 minutes: - new TimeSpan(0, 3, 45, 0); - @param days Number of days - @param hours Number of hours - @param minutes Number of minutes - @param seconds Number of seconds -*/ -/**************************************************************************/ -TimeSpan::TimeSpan(int16_t days, int8_t hours, int8_t minutes, int8_t seconds) - : _seconds((int32_t)days * 86400L + (int32_t)hours * 3600 + - (int32_t)minutes * 60 + seconds) {} - -/**************************************************************************/ -/*! - @brief Copy constructor, make a new TimeSpan using an existing one - @param copy The TimeSpan to copy -*/ -/**************************************************************************/ -TimeSpan::TimeSpan(const TimeSpan ©) : _seconds(copy._seconds) {} - -/**************************************************************************/ -/*! - @brief Add two TimeSpans - @param right TimeSpan to add - @return New TimeSpan object, sum of left and right -*/ -/**************************************************************************/ -TimeSpan TimeSpan::operator+(const TimeSpan &right) { - return TimeSpan(_seconds + right._seconds); -} - -/**************************************************************************/ -/*! - @brief Subtract a TimeSpan - @param right TimeSpan to subtract - @return New TimeSpan object, right subtracted from left -*/ -/**************************************************************************/ -TimeSpan TimeSpan::operator-(const TimeSpan &right) { - return TimeSpan(_seconds - right._seconds); -} - /**************************************************************************/ /*! @brief Convert a binary coded decimal value to binary. RTC stores time/date diff --git a/RTClib.h b/RTClib.h index 4a752ff5..5c45bd21 100644 --- a/RTClib.h +++ b/RTClib.h @@ -23,8 +23,7 @@ #define _RTCLIB_H_ #include -#include "utility/RTC.h" -class TimeSpan; +#include "utility/RTC/RTC.h" /** Registers */ #define PCF8523_ADDRESS 0x68 ///< I2C address for PCF8523 @@ -58,210 +57,17 @@ class TimeSpan; 0x11 ///< Temperature register (high byte - low byte is at 0x12), 10-bit ///< temperature value -/** Constants */ -#define SECONDS_PER_DAY 86400L ///< 60 * 60 * 24 -#define SECONDS_FROM_1970_TO_2000 \ - 946684800 ///< Unixtime for 2000-01-01 00:00:00, useful for initialization - -const DateTime COMPILE_DT = DateTime(__DATE__, __TIME__); - -bool isLeapYear(uint16_t year); -uint8_t getDaysInMonth(uint16_t year, uint8_t month); - -/**************************************************************************/ -/*! - @brief Simple general-purpose date/time class (no TZ / DST / leap - seconds). - - This class stores date and time information in a broken-down form, as a - tuple (year, month, day, hour, minute, second). The day of the week is - not stored, but computed on request. The class has no notion of time - zones, daylight saving time, or - [leap seconds](http://en.wikipedia.org/wiki/Leap_second): time is stored - in whatever time zone the user chooses to use. - - The class supports dates in the range from 1 Jan 2000 to 31 Dec 2099 - inclusive. -*/ -/**************************************************************************/ -class DateTime { -public: - DateTime(uint32_t t = SECONDS_FROM_1970_TO_2000); - DateTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour = 0, - uint8_t min = 0, uint8_t sec = 0); - DateTime(const DateTime ©); - DateTime(const char *date, const char *time); - DateTime(const __FlashStringHelper *date, const __FlashStringHelper *time); - DateTime(const char *iso8601date); - bool isValid() const; - bool fixDateTime(); - char *toString(char *buffer); - - /*! - @brief Return the year. - @return Year (range: 2000--2099). - */ - uint16_t year() const { return 2000U + yOff; } - /*! - @brief Return the month. - @return Month number (1--12). - */ - uint8_t month() const { return m; } - /*! - @brief Return the day of the month. - @return Day of the month (1--31). - */ - uint8_t day() const { return d; } - /*! - @brief Return the hour - @return Hour (0--23). - */ - uint8_t hour() const { return hh; } - - uint8_t twelveHour() const; - /*! - @brief Return whether the time is PM. - @return 0 if the time is AM, 1 if it's PM. - */ - uint8_t isPM() const { return hh >= 12; } - /*! - @brief Return the minute. - @return Minute (0--59). - */ - uint8_t minute() const { return mm; } - /*! - @brief Return the second. - @return Second (0--59). - */ - uint8_t second() const { return ss; } - - uint8_t dayOfTheWeek() const; - - /* 32-bit times as seconds since 2000-01-01. */ - uint32_t secondstime() const; - - /* 32-bit times as seconds since 1970-01-01. */ - uint32_t unixtime(void) const; - - /*! - Format of the ISO 8601 timestamp generated by `timestamp()`. Each - option corresponds to a `toString()` format as follows: - */ - enum timestampOpt { - TIMESTAMP_FULL, //!< `YYYY-MM-DDThh:mm:ss` - TIMESTAMP_TIME, //!< `hh:mm:ss` - TIMESTAMP_DATE //!< `YYYY-MM-DD` - }; - String timestamp(timestampOpt opt = TIMESTAMP_FULL); - - DateTime operator+(const TimeSpan &span); - DateTime operator-(const TimeSpan &span); - TimeSpan operator-(const DateTime &right); - bool operator<(const DateTime &right) const; - - /*! - @brief Test if one DateTime is greater (later) than another. - @warning if one or both DateTime objects are invalid, returned value is - meaningless - @see use `isValid()` method to check if DateTime object is valid - @param right DateTime object to compare - @return True if the left DateTime is later than the right one, - false otherwise - */ - bool operator>(const DateTime &right) const { return right < *this; } - - /*! - @brief Test if one DateTime is less (earlier) than or equal to another - @warning if one or both DateTime objects are invalid, returned value is - meaningless - @see use `isValid()` method to check if DateTime object is valid - @param right DateTime object to compare - @return True if the left DateTime is earlier than or equal to the - right one, false otherwise - */ - bool operator<=(const DateTime &right) const { return !(*this > right); } - - /*! - @brief Test if one DateTime is greater (later) than or equal to another - @warning if one or both DateTime objects are invalid, returned value is - meaningless - @see use `isValid()` method to check if DateTime object is valid - @param right DateTime object to compare - @return True if the left DateTime is later than or equal to the right - one, false otherwise - */ - bool operator>=(const DateTime &right) const { return !(*this < right); } - bool operator==(const DateTime &right) const; - - /*! - @brief Test if two DateTime objects are not equal. - @warning if one or both DateTime objects are invalid, returned value is - meaningless - @see use `isValid()` method to check if DateTime object is valid - @param right DateTime object to compare - @return True if the two objects are not equal, false if they are - */ - bool operator!=(const DateTime &right) const { return !(*this == right); } - -protected: - uint8_t yOff; ///< Year offset from 2000 - uint8_t m; ///< Month 1-12 - uint8_t d; ///< Day 1-31 - uint8_t hh; ///< Hours 0-23 - uint8_t mm; ///< Minutes 0-59 - uint8_t ss; ///< Seconds 0-59 -}; - -/**************************************************************************/ -/*! - @brief Timespan which can represent changes in time with seconds accuracy. -*/ -/**************************************************************************/ -class TimeSpan { -public: - TimeSpan(int32_t seconds = 0); - TimeSpan(int16_t days, int8_t hours, int8_t minutes, int8_t seconds); - TimeSpan(const TimeSpan ©); - - /*! - @brief Number of days in the TimeSpan - e.g. 4 - @return int16_t days - */ - int16_t days() const { return _seconds / 86400L; } - /*! - @brief Number of hours in the TimeSpan - This is not the total hours, it includes the days - e.g. 4 days, 3 hours - NOT 99 hours - @return int8_t hours - */ - int8_t hours() const { return _seconds / 3600 % 24; } - /*! - @brief Number of minutes in the TimeSpan - This is not the total minutes, it includes days/hours - e.g. 4 days, 3 hours, 27 minutes - @return int8_t minutes - */ - int8_t minutes() const { return _seconds / 60 % 60; } - /*! - @brief Number of seconds in the TimeSpan - This is not the total seconds, it includes the days/hours/minutes - e.g. 4 days, 3 hours, 27 minutes, 7 seconds - @return int8_t seconds - */ - int8_t seconds() const { return _seconds % 60; } - /*! - @brief Total number of seconds in the TimeSpan, e.g. 358027 - @return int32_t seconds - */ - int32_t totalseconds() const { return _seconds; } - - TimeSpan operator+(const TimeSpan &right); - TimeSpan operator-(const TimeSpan &right); - -protected: - int32_t _seconds; ///< Actual TimeSpan value is stored as seconds -}; +#if (ARDUINO >= 100) +#include // capital A so it is error prone on case-sensitive filesystems +// Macro to deal with the difference in I2C write functions from old and new +// Arduino versions. +#define _I2C_WRITE write ///< Modern I2C write +#define _I2C_READ read ///< Modern I2C read +#else +#include +#define _I2C_WRITE send ///< Legacy I2C write +#define _I2C_READ receive ///< legacy I2C read +#endif /** DS1307 SQW pin mode settings */ enum Ds1307SqwPinMode { @@ -280,14 +86,14 @@ enum Ds1307SqwPinMode { /**************************************************************************/ class RTC_DS1307 : RTC { public: - boolean begin(const DateTime &dt = COMPILE_DT); - static void adjust(const DateTime &dt); + boolean begin(const DateTime &dt = DateTime::COMPILE_DT); + void adjust(const DateTime &dt); void adjustDrift(int drift); bool isrunning(void); bool lostPower(void); - static DateTime now(); - static Ds1307SqwPinMode readSqwPinMode(); - static void writeSqwPinMode(Ds1307SqwPinMode mode); + DateTime now(); + Ds1307SqwPinMode readSqwPinMode(); + void writeSqwPinMode(Ds1307SqwPinMode mode); uint8_t readnvram(uint8_t address); void readnvram(uint8_t *buf, uint8_t size, uint8_t address); void writenvram(uint8_t address, uint8_t data); @@ -334,14 +140,14 @@ enum Ds3231Alarm2Mode { /**************************************************************************/ class RTC_DS3231 : RTC { public: - boolean begin(const DateTime &dt = COMPILE_DT); - static void adjust(const DateTime &dt); - static void adjustDrift(const int drift); + boolean begin(const DateTime &dt = DateTime::COMPILE_DT); + void adjust(const DateTime &dt); + void adjustDrift(const int drift); bool isrunning(void); bool lostPower(void); - static DateTime now(); - static Ds3231SqwPinMode readSqwPinMode(); - static void writeSqwPinMode(Ds3231SqwPinMode mode); + DateTime now(); + Ds3231SqwPinMode readSqwPinMode(); + void writeSqwPinMode(Ds3231SqwPinMode mode); bool setAlarm1(const DateTime &dt, Ds3231Alarm1Mode alarm_mode); bool setAlarm2(const DateTime &dt, Ds3231Alarm2Mode alarm_mode); void disableAlarm(uint8_t alarm_num); @@ -401,12 +207,12 @@ enum Pcf8523OffsetMode { /**************************************************************************/ class RTC_PCF8523 : RTC { public: - boolean begin(const DateTime &dt = COMPILE_DT); + boolean begin(const DateTime &dt = DateTime::COMPILE_DT); void adjust(const DateTime &dt); boolean isrunning(void); boolean lostPower(void); boolean initialized(void); - static DateTime now(); + DateTime now(); void start(void); void stop(void); boolean isrunning(); @@ -439,14 +245,14 @@ enum Pcf8563SqwPinMode { class RTC_PCF8563 : RTC { public: - boolean begin(const DateTime &dt = COMPILE_DT); + boolean begin(const DateTime &dt = DateTime::COMPILE_DT); boolean isrunning(void); boolean lostPower(void); void adjust(const DateTime &dt); - static DateTime now(); + DateTime now(); void start(void); void stop(void); - uint8_t isrunning(); + boolean isrunning(); Pcf8563SqwPinMode readSqwPinMode(); void writeSqwPinMode(Pcf8563SqwPinMode mode); }; @@ -459,7 +265,7 @@ class RTC_PCF8563 : RTC { /**************************************************************************/ class RTC_Millis : RTC { public: - static boolean begin(const DateTime &dt = COMPILE_DT); + boolean begin(const DateTime &dt = DateTime::COMPILE_DT); /*! @brief Simulate if the RTC is running @return true @@ -470,9 +276,9 @@ class RTC_Millis : RTC { @return false */ boolean lostPower(void) { return false; } - static void adjust(const DateTime &dt); - static void adjustDrift(const int drift); - static DateTime now(); + void adjust(const DateTime &dt); + void adjustDrift(const int drift); + DateTime now(); protected: static uint32_t millisPerSecond; ///< Number of milliseconds reported by @@ -498,7 +304,7 @@ class RTC_Micros : RTC { @brief Start the RTC @param dt DateTime object with the date/time to set */ - static boolean begin(const DateTime &dt = COMPILE_DT); + boolean begin(const DateTime &dt = DateTime::COMPILE_DT); /*! @brief Simulate if the RTC is running @return true @@ -509,9 +315,9 @@ class RTC_Micros : RTC { @return false */ boolean lostPower(void) { return false; } - static void adjust(const DateTime &dt); - static void adjustDrift(int ppm); - static DateTime now(); + void adjust(const DateTime &dt); + void adjustDrift(int ppm); + DateTime now(); protected: static uint32_t microsPerSecond; ///< Number of microseconds reported by diff --git a/utility/DateTime/DateTime.cpp b/utility/DateTime/DateTime.cpp new file mode 100644 index 00000000..a8db7c85 --- /dev/null +++ b/utility/DateTime/DateTime.cpp @@ -0,0 +1,644 @@ +#include "DateTime.h" + +#ifdef __AVR__ +#include +#elif defined(ESP8266) +#include +#elif defined(ARDUINO_ARCH_SAMD) +// nothing special needed +#elif defined(ARDUINO_SAM_DUE) +#define PROGMEM +#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) +#define Wire Wire1 +#endif + +/**************************************************************************/ +// utility code, some of this could be exposed in the DateTime API if needed +/**************************************************************************/ + +/** + Number of days in each month, from January to November. December is not + needed. Omitting it avoids an incompatibility with Paul Stoffregen's Time + library. C.f. https://github.com/adafruit/RTClib/issues/114 +*/ +const uint8_t daysInMonth[] PROGMEM = {31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30}; + +/**************************************************************************/ +/*! + @brief Given a date, return number of days since 2000/01/01, + valid for 2000--2099 + @param y Year + @param m Month + @param d Day + @return Number of days +*/ +/**************************************************************************/ +static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) { + if (y >= 2000U) + y -= 2000U; + uint16_t days = d; + for (uint8_t i = 1; i < m; ++i) + days += pgm_read_byte(daysInMonth + i - 1); + if (m > 2 && y % 4 == 0) + ++days; + return days + 365 * y + (y + 3) / 4 - 1; +} + +/**************************************************************************/ +/*! + @brief Given a number of days, hours, minutes, and seconds, return the + total seconds + @param days Days + @param h Hours + @param m Minutes + @param s Seconds + @return Number of seconds total +*/ +/**************************************************************************/ +static uint32_t time2ulong(uint16_t days, uint8_t h, uint8_t m, uint8_t s) { + return ((days * 24UL + h) * 60 + m) * 60 + s; +} + +const DateTime DateTime::COMPILE_DT = DateTime(F(__DATE__), F(__TIME__)); + +/**************************************************************************/ +/*! + @brief Constructor from + [Unix time](https://en.wikipedia.org/wiki/Unix_time). + + This builds a DateTime from an integer specifying the number of seconds + elapsed since the epoch: 1970-01-01 00:00:00. This number is analogous + to Unix time, with two small differences: + + - The Unix epoch is specified to be at 00:00:00 + [UTC](https://en.wikipedia.org/wiki/Coordinated_Universal_Time), + whereas this class has no notion of time zones. The epoch used in + this class is then at 00:00:00 on whatever time zone the user chooses + to use, ignoring changes in DST. + + - Unix time is conventionally represented with signed numbers, whereas + this constructor takes an unsigned argument. Because of this, it does + _not_ suffer from the + [year 2038 problem](https://en.wikipedia.org/wiki/Year_2038_problem). + + If called without argument, it returns the earliest time representable + by this class: 2000-01-01 00:00:00. + + @see The `unixtime()` method is the converse of this constructor. + + @param t Time elapsed in seconds since 1970-01-01 00:00:00. +*/ +/**************************************************************************/ +DateTime::DateTime(uint32_t t) { + t -= SECONDS_FROM_1970_TO_2000; // bring to 2000 timestamp from 1970 + + ss = t % 60; + t /= 60; + mm = t % 60; + t /= 60; + hh = t % 24; + uint16_t days = t / 24; + uint8_t leap; + for (yOff = 0;; ++yOff) { + leap = yOff % 4 == 0; + if (days < 365U + leap) + break; + days -= 365 + leap; + } + for (m = 1; m < 12; ++m) { + uint8_t daysPerMonth = pgm_read_byte(daysInMonth + m - 1); + if (leap && m == 2) + ++daysPerMonth; + if (days < daysPerMonth) + break; + days -= daysPerMonth; + } + d = days + 1; +} + +/**************************************************************************/ +/*! + @brief Constructor from (year, month, day, hour, minute, second). + @warning If the provided parameters are not valid (e.g. 31 February), + the constructed DateTime will be invalid. + @see The `isValid()` method can be used to test whether the + constructed DateTime is valid. + @param year Either the full year (range: 2000--2099) or the offset from + year 2000 (range: 0--99). + @param month Month number (1--12). + @param day Day of the month (1--31). + @param hour,min,sec Hour (0--23), minute (0--59) and second (0--59). +*/ +/**************************************************************************/ +DateTime::DateTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, + uint8_t min, uint8_t sec) { + if (year >= 2000U) + year -= 2000U; + yOff = year; + m = month; + d = day; + hh = hour; + mm = min; + ss = sec; +} + +/**************************************************************************/ +/*! + @brief Copy constructor. + @param copy DateTime to copy. +*/ +/**************************************************************************/ +DateTime::DateTime(const DateTime ©) + : yOff(copy.yOff), m(copy.m), d(copy.d), hh(copy.hh), mm(copy.mm), + ss(copy.ss) {} + +/**************************************************************************/ +/*! + @brief Convert a string containing two digits to uint8_t, e.g. "09" returns + 9 + @param p Pointer to a string containing two digits +*/ +/**************************************************************************/ +static uint8_t conv2d(const char *p) { + uint8_t v = 0; + if ('0' <= *p && *p <= '9') + v = *p - '0'; + return 10 * v + *++p - '0'; +} + +/**************************************************************************/ +/*! + @brief Constructor for generating the build time. + + This constructor expects its parameters to be strings in the format + generated by the compiler's preprocessor macros `__DATE__` and + `__TIME__`. Usage: + + ``` + DateTime buildTime(__DATE__, __TIME__); + ``` + + @note The `F()` macro can be used to reduce the RAM footprint, see + the next constructor. + + @param date Date string, e.g. "Apr 16 2020". + @param time Time string, e.g. "18:34:56". +*/ +/**************************************************************************/ +DateTime::DateTime(const char *date, const char *time) { + yOff = conv2d(date + 9); + // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec + switch (date[0]) { + case 'J': + m = (date[1] == 'a') ? 1 : ((date[2] == 'n') ? 6 : 7); + break; + case 'F': + m = 2; + break; + case 'A': + m = date[2] == 'r' ? 4 : 8; + break; + case 'M': + m = date[2] == 'r' ? 3 : 5; + break; + case 'S': + m = 9; + break; + case 'O': + m = 10; + break; + case 'N': + m = 11; + break; + case 'D': + m = 12; + break; + } + d = conv2d(date + 4); + hh = conv2d(time); + mm = conv2d(time + 3); + ss = conv2d(time + 6); +} + +/**************************************************************************/ +/*! + @brief Memory friendly constructor for generating the build time. + + This version is intended to save RAM by keeping the date and time + strings in program memory. Use it with the `F()` macro: + + ``` + DateTime buildTime(F(__DATE__), F(__TIME__)); + ``` + + @param date Date PROGMEM string, e.g. F("Apr 16 2020"). + @param time Time PROGMEM string, e.g. F("18:34:56"). +*/ +/**************************************************************************/ +DateTime::DateTime(const __FlashStringHelper *date, + const __FlashStringHelper *time) { + char buff[11]; + memcpy_P(buff, date, 11); + yOff = conv2d(buff + 9); + // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec + switch (buff[0]) { + case 'J': + m = (buff[1] == 'a') ? 1 : ((buff[2] == 'n') ? 6 : 7); + break; + case 'F': + m = 2; + break; + case 'A': + m = buff[2] == 'r' ? 4 : 8; + break; + case 'M': + m = buff[2] == 'r' ? 3 : 5; + break; + case 'S': + m = 9; + break; + case 'O': + m = 10; + break; + case 'N': + m = 11; + break; + case 'D': + m = 12; + break; + } + d = conv2d(buff + 4); + memcpy_P(buff, time, 8); + hh = conv2d(buff); + mm = conv2d(buff + 3); + ss = conv2d(buff + 6); +} + +/**************************************************************************/ +/*! + @brief Constructor for creating a DateTime from an ISO8601 date string. + + This constructor expects its parameters to be a string in the + https://en.wikipedia.org/wiki/ISO_8601 format, e.g: + + "2020-06-25T15:29:37" + + Usage: + + ``` + DateTime dt("2020-06-25T15:29:37"); + ``` + + @note The year must be > 2000, as only the yOff is considered. + + @param iso8601dateTime + A dateTime string in iso8601 format, + e.g. "2020-06-25T15:29:37". + +*/ +/**************************************************************************/ +DateTime::DateTime(const char *iso8601dateTime) { + char ref[] = "2000-01-01T00:00:00"; + memcpy(ref, iso8601dateTime, min(strlen(ref), strlen(iso8601dateTime))); + yOff = conv2d(ref + 2); + m = conv2d(ref + 5); + d = conv2d(ref + 8); + hh = conv2d(ref + 11); + mm = conv2d(ref + 14); + ss = conv2d(ref + 17); +} + +/**************************************************************************/ +/*! + @brief Check whether this DateTime is valid. + @return true if valid, false if not. +*/ +/**************************************************************************/ +bool DateTime::isValid() const { + if (yOff >= 100) + return false; + DateTime other(unixtime()); + return yOff == other.yOff && m == other.m && d == other.d && hh == other.hh && + mm == other.mm && ss == other.ss; +} + +/**************************************************************************/ +/*! + @brief Writes the DateTime as a string in a user-defined format. + + The _buffer_ parameter should be initialized by the caller with a string + specifying the requested format. This format string may contain any of + the following specifiers: + + | specifier | output | + |-----------|--------------------------------------------------------| + | YYYY | the year as a 4-digit number (2000--2099) | + | YY | the year as a 2-digit number (00--99) | + | MM | the month as a 2-digit number (01--12) | + | MMM | the abbreviated English month name ("Jan"--"Dec") | + | DD | the day as a 2-digit number (01--31) | + | DDD | the abbreviated English day of the week ("Mon"--"Sun") | + | AP | either "AM" or "PM" | + | ap | either "am" or "pm" | + | hh | the hour as a 2-digit number (00--23 or 01--12) | + | mm | the minute as a 2-digit number (00--59) | + | ss | the second as a 2-digit number (00--59) | + + If either "AP" or "ap" is used, the "hh" specifier uses 12-hour mode + (range: 01--12). Otherwise it works in 24-hour mode (range: 00--23). + + The specifiers within _buffer_ will be overwritten with the appropriate + values from the DateTime. Any characters not belonging to one of the + above specifiers are left as-is. + + __Example__: The format "DDD, DD MMM YYYY hh:mm:ss" generates an output + of the form "Thu, 16 Apr 2020 18:34:56. + + @see The `timestamp()` method provides similar functionnality, but it + returns a `String` object and supports a limited choice of + predefined formats. + + @param[in,out] buffer Array of `char` for holding the format description + and the formatted DateTime. Before calling this method, the buffer + should be initialized by the user with the format string. The method + will overwrite the buffer with the formatted date and/or time. + + @return A pointer to the provided buffer. This is returned for + convenience, in order to enable idioms such as + `Serial.println(now.toString(buffer));` +*/ +/**************************************************************************/ + +char *DateTime::toString(char *buffer) { + uint8_t apTag = + (strstr(buffer, "ap") != nullptr) || (strstr(buffer, "AP") != nullptr); + uint8_t hourReformatted = 0, isPM = false; + if (apTag) { // 12 Hour Mode + if (hh == 0) { // midnight + isPM = false; + hourReformatted = 12; + } else if (hh == 12) { // noon + isPM = true; + hourReformatted = 12; + } else if (hh < 12) { // morning + isPM = false; + hourReformatted = hh; + } else { // 1 o'clock or after + isPM = true; + hourReformatted = hh - 12; + } + } + + for (size_t i = 0; i < strlen(buffer) - 1; i++) { + if (buffer[i] == 'h' && buffer[i + 1] == 'h') { + if (!apTag) { // 24 Hour Mode + buffer[i] = '0' + hh / 10; + buffer[i + 1] = '0' + hh % 10; + } else { // 12 Hour Mode + buffer[i] = '0' + hourReformatted / 10; + buffer[i + 1] = '0' + hourReformatted % 10; + } + } + if (buffer[i] == 'm' && buffer[i + 1] == 'm') { + buffer[i] = '0' + mm / 10; + buffer[i + 1] = '0' + mm % 10; + } + if (buffer[i] == 's' && buffer[i + 1] == 's') { + buffer[i] = '0' + ss / 10; + buffer[i + 1] = '0' + ss % 10; + } + if (buffer[i] == 'D' && buffer[i + 1] == 'D' && buffer[i + 2] == 'D') { + static PROGMEM const char day_names[] = "SunMonTueWedThuFriSat"; + const char *p = &day_names[3 * dayOfTheWeek()]; + buffer[i] = pgm_read_byte(p); + buffer[i + 1] = pgm_read_byte(p + 1); + buffer[i + 2] = pgm_read_byte(p + 2); + } else if (buffer[i] == 'D' && buffer[i + 1] == 'D') { + buffer[i] = '0' + d / 10; + buffer[i + 1] = '0' + d % 10; + } + if (buffer[i] == 'M' && buffer[i + 1] == 'M' && buffer[i + 2] == 'M') { + static PROGMEM const char month_names[] = + "JanFebMarAprMayJunJulAugSepOctNovDec"; + const char *p = &month_names[3 * (m - 1)]; + buffer[i] = pgm_read_byte(p); + buffer[i + 1] = pgm_read_byte(p + 1); + buffer[i + 2] = pgm_read_byte(p + 2); + } else if (buffer[i] == 'M' && buffer[i + 1] == 'M') { + buffer[i] = '0' + m / 10; + buffer[i + 1] = '0' + m % 10; + } + if (buffer[i] == 'Y' && buffer[i + 1] == 'Y' && buffer[i + 2] == 'Y' && + buffer[i + 3] == 'Y') { + buffer[i] = '2'; + buffer[i + 1] = '0'; + buffer[i + 2] = '0' + (yOff / 10) % 10; + buffer[i + 3] = '0' + yOff % 10; + } else if (buffer[i] == 'Y' && buffer[i + 1] == 'Y') { + buffer[i] = '0' + (yOff / 10) % 10; + buffer[i + 1] = '0' + yOff % 10; + } + if (buffer[i] == 'A' && buffer[i + 1] == 'P') { + if (isPM) { + buffer[i] = 'P'; + buffer[i + 1] = 'M'; + } else { + buffer[i] = 'A'; + buffer[i + 1] = 'M'; + } + } else if (buffer[i] == 'a' && buffer[i + 1] == 'p') { + if (isPM) { + buffer[i] = 'p'; + buffer[i + 1] = 'm'; + } else { + buffer[i] = 'a'; + buffer[i + 1] = 'm'; + } + } + } + return buffer; +} + +/**************************************************************************/ +/*! + @brief Return the hour in 12-hour format. + @return Hour (1--12). +*/ +/**************************************************************************/ +uint8_t DateTime::twelveHour() const { + if (hh == 0 || hh == 12) { // midnight or noon + return 12; + } else if (hh > 12) { // 1 o'clock or later + return hh - 12; + } else { // morning + return hh; + } +} + +/**************************************************************************/ +/*! + @brief Return the day of the week. + @return Day of week as an integer from 0 (Sunday) to 6 (Saturday). +*/ +/**************************************************************************/ +uint8_t DateTime::dayOfTheWeek() const { + uint16_t day = date2days(yOff, m, d); + return (day + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6 +} + +/**************************************************************************/ +/*! + @brief Return Unix time: seconds since 1 Jan 1970. + + @see The `DateTime::DateTime(uint32_t)` constructor is the converse of + this method. + + @return Number of seconds since 1970-01-01 00:00:00. +*/ +/**************************************************************************/ +uint32_t DateTime::unixtime(void) const { + uint32_t t; + uint16_t days = date2days(yOff, m, d); + t = time2ulong(days, hh, mm, ss); + t += SECONDS_FROM_1970_TO_2000; // seconds from 1970 to 2000 + + return t; +} + +/**************************************************************************/ +/*! + @brief Convert the DateTime to seconds since 1 Jan 2000 + + The result can be converted back to a DateTime with: + + ```cpp + DateTime(SECONDS_FROM_1970_TO_2000 + value) + ``` + + @return Number of seconds since 2000-01-01 00:00:00. +*/ +/**************************************************************************/ +uint32_t DateTime::secondstime(void) const { + uint32_t t; + uint16_t days = date2days(yOff, m, d); + t = time2ulong(days, hh, mm, ss); + return t; +} + +/**************************************************************************/ +/*! + @brief Add a TimeSpan to the DateTime object + @param span TimeSpan object + @return New DateTime object with span added to it. +*/ +/**************************************************************************/ +DateTime DateTime::operator+(const TimeSpan &span) { + return DateTime(unixtime() + span.totalseconds()); +} + +/**************************************************************************/ +/*! + @brief Subtract a TimeSpan from the DateTime object + @param span TimeSpan object + @return New DateTime object with span subtracted from it. +*/ +/**************************************************************************/ +DateTime DateTime::operator-(const TimeSpan &span) { + return DateTime(unixtime() - span.totalseconds()); +} + +/**************************************************************************/ +/*! + @brief Subtract one DateTime from another + + @note Since a TimeSpan cannot be negative, the subtracted DateTime + should be less (earlier) than or equal to the one it is + subtracted from. + + @param right The DateTime object to subtract from self (the left object) + @return TimeSpan of the difference between DateTimes. +*/ +/**************************************************************************/ +TimeSpan DateTime::operator-(const DateTime &right) { + return TimeSpan(unixtime() - right.unixtime()); +} + +/**************************************************************************/ +/*! + @author Anton Rieutskyi + @brief Test if one DateTime is less (earlier) than another. + @warning if one or both DateTime objects are invalid, returned value is + meaningless + @see use `isValid()` method to check if DateTime object is valid + @param right Comparison DateTime object + @return True if the left DateTime is earlier than the right one, + false otherwise. +*/ +/**************************************************************************/ +bool DateTime::operator<(const DateTime &right) const { + return (yOff + 2000U < right.year() || + (yOff + 2000U == right.year() && + (m < right.month() || + (m == right.month() && + (d < right.day() || + (d == right.day() && + (hh < right.hour() || + (hh == right.hour() && + (mm < right.minute() || + (mm == right.minute() && ss < right.second())))))))))); +} + +/**************************************************************************/ +/*! + @author Anton Rieutskyi + @brief Test if two DateTime objects are equal. + @warning if one or both DateTime objects are invalid, returned value is + meaningless + @see use `isValid()` method to check if DateTime object is valid + @param right Comparison DateTime object + @return True if both DateTime objects are the same, false otherwise. +*/ +/**************************************************************************/ +bool DateTime::operator==(const DateTime &right) const { + return (right.year() == yOff + 2000U && right.month() == m && + right.day() == d && right.hour() == hh && right.minute() == mm && + right.second() == ss); +} + +/**************************************************************************/ +/*! + @brief Return a ISO 8601 timestamp as a `String` object. + + The generated timestamp conforms to one of the predefined, ISO + 8601-compatible formats for representing the date (if _opt_ is + `TIMESTAMP_DATE`), the time (`TIMESTAMP_TIME`), or both + (`TIMESTAMP_FULL`). + + @see The `toString()` method provides more general string formatting. + + @param opt Format of the timestamp + @return Timestamp string, e.g. "2020-04-16T18:34:56". +*/ +/**************************************************************************/ +String DateTime::timestamp(timestampOpt opt) { + char buffer[25]; // large enough for any DateTime, including invalid ones + + // Generate timestamp according to opt + switch (opt) { + case TIMESTAMP_TIME: + // Only time + sprintf(buffer, "%02d:%02d:%02d", hh, mm, ss); + break; + case TIMESTAMP_DATE: + // Only date + sprintf(buffer, "%u-%02d-%02d", 2000U + yOff, m, d); + break; + default: + // Full + sprintf(buffer, "%u-%02d-%02dT%02d:%02d:%02d", 2000U + yOff, m, d, hh, mm, + ss); + } + return String(buffer); +} + diff --git a/utility/DateTime/DateTime.h b/utility/DateTime/DateTime.h new file mode 100644 index 00000000..505b87d5 --- /dev/null +++ b/utility/DateTime/DateTime.h @@ -0,0 +1,163 @@ +#ifndef _DATETIME_H_ +#define _DATETIME_H_ + +#include +#include "../TimeSpan/TimeSpan.h" + +/** Constants */ +#define SECONDS_PER_DAY 86400L ///< 60 * 60 * 24 +#define SECONDS_FROM_1970_TO_2000 \ + 946684800 ///< Unixtime for 2000-01-01 00:00:00, useful for initialization + +uint8_t getDaysInMonth(uint16_t year, uint8_t month); + +/**************************************************************************/ +/*! + @brief Simple general-purpose date/time class (no TZ / DST / leap + seconds). + + This class stores date and time information in a broken-down form, as a + tuple (year, month, day, hour, minute, second). The day of the week is + not stored, but computed on request. The class has no notion of time + zones, daylight saving time, or + [leap seconds](http://en.wikipedia.org/wiki/Leap_second): time is stored + in whatever time zone the user chooses to use. + + The class supports dates in the range from 1 Jan 2000 to 31 Dec 2099 + inclusive. +*/ +/**************************************************************************/ +class DateTime { +public: + /*! + @brief The date/time at compile time + */ + const static DateTime COMPILE_DT; + + DateTime(uint32_t t = SECONDS_FROM_1970_TO_2000); + DateTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour = 0, + uint8_t min = 0, uint8_t sec = 0); + DateTime(const DateTime ©); + DateTime(const char *date, const char *time); + DateTime(const __FlashStringHelper *date, const __FlashStringHelper *time); + DateTime(const char *iso8601date); + bool isValid() const; + bool fixDateTime(); + char *toString(char *buffer); + + /*! + @brief Return the year. + @return Year (range: 2000--2099). + */ + uint16_t year() const { return 2000U + yOff; } + /*! + @brief Return the month. + @return Month number (1--12). + */ + uint8_t month() const { return m; } + /*! + @brief Return the day of the month. + @return Day of the month (1--31). + */ + uint8_t day() const { return d; } + /*! + @brief Return the hour + @return Hour (0--23). + */ + uint8_t hour() const { return hh; } + + uint8_t twelveHour() const; + /*! + @brief Return whether the time is PM. + @return 0 if the time is AM, 1 if it's PM. + */ + uint8_t isPM() const { return hh >= 12; } + /*! + @brief Return the minute. + @return Minute (0--59). + */ + uint8_t minute() const { return mm; } + /*! + @brief Return the second. + @return Second (0--59). + */ + uint8_t second() const { return ss; } + + uint8_t dayOfTheWeek() const; + + /* 32-bit times as seconds since 2000-01-01. */ + uint32_t secondstime() const; + + /* 32-bit times as seconds since 1970-01-01. */ + uint32_t unixtime(void) const; + + /*! + Format of the ISO 8601 timestamp generated by `timestamp()`. Each + option corresponds to a `toString()` format as follows: + */ + enum timestampOpt { + TIMESTAMP_FULL, //!< `YYYY-MM-DDThh:mm:ss` + TIMESTAMP_TIME, //!< `hh:mm:ss` + TIMESTAMP_DATE //!< `YYYY-MM-DD` + }; + String timestamp(timestampOpt opt = TIMESTAMP_FULL); + + DateTime operator+(const TimeSpan &span); + DateTime operator-(const TimeSpan &span); + TimeSpan operator-(const DateTime &right); + bool operator<(const DateTime &right) const; + + /*! + @brief Test if one DateTime is greater (later) than another. + @warning if one or both DateTime objects are invalid, returned value is + meaningless + @see use `isValid()` method to check if DateTime object is valid + @param right DateTime object to compare + @return True if the left DateTime is later than the right one, + false otherwise + */ + bool operator>(const DateTime &right) const { return right < *this; } + + /*! + @brief Test if one DateTime is less (earlier) than or equal to another + @warning if one or both DateTime objects are invalid, returned value is + meaningless + @see use `isValid()` method to check if DateTime object is valid + @param right DateTime object to compare + @return True if the left DateTime is earlier than or equal to the + right one, false otherwise + */ + bool operator<=(const DateTime &right) const { return !(*this > right); } + + /*! + @brief Test if one DateTime is greater (later) than or equal to another + @warning if one or both DateTime objects are invalid, returned value is + meaningless + @see use `isValid()` method to check if DateTime object is valid + @param right DateTime object to compare + @return True if the left DateTime is later than or equal to the right + one, false otherwise + */ + bool operator>=(const DateTime &right) const { return !(*this < right); } + bool operator==(const DateTime &right) const; + + /*! + @brief Test if two DateTime objects are not equal. + @warning if one or both DateTime objects are invalid, returned value is + meaningless + @see use `isValid()` method to check if DateTime object is valid + @param right DateTime object to compare + @return True if the two objects are not equal, false if they are + */ + bool operator!=(const DateTime &right) const { return !(*this == right); } + +protected: + uint8_t yOff; ///< Year offset from 2000 + uint8_t m; ///< Month 1-12 + uint8_t d; ///< Day 1-31 + uint8_t hh; ///< Hours 0-23 + uint8_t mm; ///< Minutes 0-59 + uint8_t ss; ///< Seconds 0-59 +}; + +#endif \ No newline at end of file diff --git a/utility/RTC/RTC.h b/utility/RTC/RTC.h index 8be1dac6..e401f16e 100644 --- a/utility/RTC/RTC.h +++ b/utility/RTC/RTC.h @@ -23,8 +23,7 @@ #define _RTC_H_ #include - -class DateTime; +#include "../DateTime/DateTime.h" /**************************************************************************/ /*! @@ -62,7 +61,7 @@ class RTC { /*! @brief Check if the RTC has lost power @return True if the RTC has lost power, false otherwise - @note Equivelant to `!rtc.isrunning()` + @note Equivalent to `!rtc.isrunning()` */ virtual boolean lostPower(void); @@ -71,18 +70,6 @@ class RTC { @return The date/time */ virtual DateTime now() = 0; - - /*! - @brief Get the square wave mode - @return The square wave mode - */ - virtual int readSqwPinMode() = 0; - - /*! - @brief Set the square wave mode - @param mode The mode to set the square wave to - */ - virtual void writeSqwPinMode(int mode) = 0; }; #endif \ No newline at end of file diff --git a/utility/TimeSpan/TimeSpan.cpp b/utility/TimeSpan/TimeSpan.cpp new file mode 100644 index 00000000..ea87f090 --- /dev/null +++ b/utility/TimeSpan/TimeSpan.cpp @@ -0,0 +1,55 @@ +#include "TimeSpan.h" + +/**************************************************************************/ +/*! + @brief Create a new TimeSpan object in seconds + @param seconds Number of seconds +*/ +/**************************************************************************/ +TimeSpan::TimeSpan(int32_t seconds) : _seconds(seconds) {} + +/**************************************************************************/ +/*! + @brief Create a new TimeSpan object using a number of + days/hours/minutes/seconds e.g. Make a TimeSpan of 3 hours and 45 minutes: + new TimeSpan(0, 3, 45, 0); + @param days Number of days + @param hours Number of hours + @param minutes Number of minutes + @param seconds Number of seconds +*/ +/**************************************************************************/ +TimeSpan::TimeSpan(int16_t days, int8_t hours, int8_t minutes, int8_t seconds) + : _seconds((int32_t)days * 86400L + (int32_t)hours * 3600 + + (int32_t)minutes * 60 + seconds) {} + +/**************************************************************************/ +/*! + @brief Copy constructor, make a new TimeSpan using an existing one + @param copy The TimeSpan to copy +*/ +/**************************************************************************/ +TimeSpan::TimeSpan(const TimeSpan ©) : _seconds(copy._seconds) {} + +/**************************************************************************/ +/*! + @brief Add two TimeSpans + @param right TimeSpan to add + @return New TimeSpan object, sum of left and right +*/ +/**************************************************************************/ +TimeSpan TimeSpan::operator+(const TimeSpan &right) { + return TimeSpan(_seconds + right._seconds); +} + +/**************************************************************************/ +/*! + @brief Subtract a TimeSpan + @param right TimeSpan to subtract + @return New TimeSpan object, right subtracted from left +*/ +/**************************************************************************/ +TimeSpan TimeSpan::operator-(const TimeSpan &right) { + return TimeSpan(_seconds - right._seconds); +} + diff --git a/utility/TimeSpan/TimeSpan.h b/utility/TimeSpan/TimeSpan.h new file mode 100644 index 00000000..75bceaa0 --- /dev/null +++ b/utility/TimeSpan/TimeSpan.h @@ -0,0 +1,55 @@ +#ifndef _TIMESPAN_H_ +#define _TIMESPAN_H_ + +/**************************************************************************/ +/*! + @brief Timespan which can represent changes in time with seconds accuracy. +*/ +/**************************************************************************/ +class TimeSpan { +public: + TimeSpan(int32_t seconds = 0); + TimeSpan(int16_t days, int8_t hours, int8_t minutes, int8_t seconds); + TimeSpan(const TimeSpan ©); + + /*! + @brief Number of days in the TimeSpan + e.g. 4 + @return int16_t days + */ + int16_t days() const { return _seconds / 86400L; } + /*! + @brief Number of hours in the TimeSpan + This is not the total hours, it includes the days + e.g. 4 days, 3 hours - NOT 99 hours + @return int8_t hours + */ + int8_t hours() const { return _seconds / 3600 % 24; } + /*! + @brief Number of minutes in the TimeSpan + This is not the total minutes, it includes days/hours + e.g. 4 days, 3 hours, 27 minutes + @return int8_t minutes + */ + int8_t minutes() const { return _seconds / 60 % 60; } + /*! + @brief Number of seconds in the TimeSpan + This is not the total seconds, it includes the days/hours/minutes + e.g. 4 days, 3 hours, 27 minutes, 7 seconds + @return int8_t seconds + */ + int8_t seconds() const { return _seconds % 60; } + /*! + @brief Total number of seconds in the TimeSpan, e.g. 358027 + @return int32_t seconds + */ + int32_t totalseconds() const { return _seconds; } + + TimeSpan operator+(const TimeSpan &right); + TimeSpan operator-(const TimeSpan &right); + +protected: + int32_t _seconds; ///< Actual TimeSpan value is stored as seconds +}; + +#endif \ No newline at end of file From 00075a4a0877fd36679835e65f3de0128301bcee Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Mon, 28 Dec 2020 21:48:35 +0800 Subject: [PATCH 07/43] Fixed compile errors --- RTClib.cpp | 8 ++++---- RTClib.h | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index 3eae4dd9..e18ba3a1 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -125,7 +125,7 @@ boolean RTC_DS1307::begin(const DateTime &dt) { @return 1 if the RTC is running, 0 if not */ /**************************************************************************/ -uint8_t RTC_DS1307::isrunning(void) { +boolean RTC_DS1307::isrunning(void) { Wire.beginTransmission(DS1307_ADDRESS); Wire._I2C_WRITE((byte)0); Wire.endTransmission(); @@ -174,7 +174,7 @@ void RTC_DS1307::adjust(const DateTime &dt) { */ /**************************************************************************/ void RTC_DS1307::adjustDrift(const int drift) { - DateTime newDt = DateTime(unixtime() + drift); + DateTime newDt = DateTime(now().unixtime() + drift); adjust(newDt); } @@ -532,7 +532,7 @@ void RTC_PCF8523::stop(void) { @return 1 if the RTC is running, 0 if not */ /**************************************************************************/ -uint8_t RTC_PCF8523::isrunning() { +boolean RTC_PCF8523::isrunning() { uint8_t ctlreg = read_i2c_register(PCF8523_ADDRESS, PCF8523_CONTROL_1); return !((ctlreg >> 5) & 1); } @@ -842,7 +842,7 @@ void RTC_PCF8563::stop(void) { @return 1 if the RTC is running, 0 if not */ /**************************************************************************/ -uint8_t RTC_PCF8563::isrunning() { +boolean RTC_PCF8563::isrunning() { uint8_t ctlreg = read_i2c_register(PCF8563_ADDRESS, PCF8563_CONTROL_1); return !((ctlreg >> 5) & 1); } diff --git a/RTClib.h b/RTClib.h index 5c45bd21..69b91351 100644 --- a/RTClib.h +++ b/RTClib.h @@ -215,7 +215,6 @@ class RTC_PCF8523 : RTC { DateTime now(); void start(void); void stop(void); - boolean isrunning(); Pcf8523SqwPinMode readSqwPinMode(); void writeSqwPinMode(Pcf8523SqwPinMode mode); void enableSecondTimer(void); @@ -252,7 +251,6 @@ class RTC_PCF8563 : RTC { DateTime now(); void start(void); void stop(void); - boolean isrunning(); Pcf8563SqwPinMode readSqwPinMode(); void writeSqwPinMode(Pcf8563SqwPinMode mode); }; From eaec4068d3c4c36727803bc448e9dabaf8c43b4b Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 29 Dec 2020 10:48:30 +0800 Subject: [PATCH 08/43] Moved _I2C_WRITE and _I2C_READ to RTClib.cpp --- RTClib.cpp | 12 ++++++++++++ RTClib.h | 12 ------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index e18ba3a1..f85e8752 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -51,6 +51,18 @@ #include #endif +#if (ARDUINO >= 100) +#include // capital A so it is error prone on case-sensitive filesystems +// Macro to deal with the difference in I2C write functions from old and new +// Arduino versions. +#define _I2C_WRITE write ///< Modern I2C write +#define _I2C_READ read ///< Modern I2C read +#else +#include +#define _I2C_WRITE send ///< Legacy I2C write +#define _I2C_READ receive ///< legacy I2C read +#endif + /**************************************************************************/ /*! @brief Read a byte from an I2C register diff --git a/RTClib.h b/RTClib.h index 69b91351..f77336d7 100644 --- a/RTClib.h +++ b/RTClib.h @@ -57,18 +57,6 @@ 0x11 ///< Temperature register (high byte - low byte is at 0x12), 10-bit ///< temperature value -#if (ARDUINO >= 100) -#include // capital A so it is error prone on case-sensitive filesystems -// Macro to deal with the difference in I2C write functions from old and new -// Arduino versions. -#define _I2C_WRITE write ///< Modern I2C write -#define _I2C_READ read ///< Modern I2C read -#else -#include -#define _I2C_WRITE send ///< Legacy I2C write -#define _I2C_READ receive ///< legacy I2C read -#endif - /** DS1307 SQW pin mode settings */ enum Ds1307SqwPinMode { DS1307_OFF = 0x00, // Low From 68bed4451d17e07c8f3b30de21e87223a066d299 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 29 Dec 2020 10:56:33 +0800 Subject: [PATCH 09/43] Wrote new keywords --- keywords.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/keywords.txt b/keywords.txt index d3082fef..0633744f 100644 --- a/keywords.txt +++ b/keywords.txt @@ -8,6 +8,7 @@ DateTime KEYWORD1 TimeSpan KEYWORD1 +RTC KEYWORD1 RTC_DS1307 KEYWORD1 RTC_DS3231 KEYWORD1 RTC_PCF8523 KEYWORD1 @@ -77,6 +78,7 @@ isEnabled32K KEYWORD2 ####################################### # Constants (LITERAL1) ####################################### +COMPILE_DT LITERAL1 TIMESTAMP_FULL LITERAL1 TIMESTAMP_DATE LITERAL1 TIMESTAMP_TIME LITERAL1 From 54fcd637c28e84e59a784fd28510a73bac0f750f Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 29 Dec 2020 11:13:56 +0800 Subject: [PATCH 10/43] Fixed usage of millisPerSecond and RTC_Millis::adjustDrift() --- RTClib.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index f85e8752..c792b7aa 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -343,12 +343,12 @@ void RTC_Millis::adjust(const DateTime &dt) { /**************************************************************************/ /*! - @brief Adjust the RTC clock to compensate for system clock drift + @brief Adjust the RTC clock speed to compensate for system clock drift @param drift Adjustment to make in milliseconds - @note Positive values make the clock go ahead in time and vice-versa + @note Positive values make the clock faster and vice-versa */ /**************************************************************************/ -void RTC_Millis::adjustDrift(int drift) { lastMillis = 1000 - drift; } +void RTC_Millis::adjustDrift(int drift) { millisPerSecond = 1000 - drift; } /**************************************************************************/ /*! @@ -398,11 +398,11 @@ void RTC_Micros::adjust(const DateTime &dt) { /**************************************************************************/ /*! - @brief Adjust the RTC_Micros clock to compensate for system clock drift + @brief Adjust the RTC_Micros clock speed to compensate for system clock drift @param drift Adjustment to make in microseconds + @note Positive values make the clock faster and vice-versa */ /**************************************************************************/ -// A positive adjustment makes the clock faster. void RTC_Micros::adjustDrift(int drift) { microsPerSecond = 1000000 - drift; } /**************************************************************************/ From 2b980095c988be232f59061cf5bc46c6b2b2492d Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 29 Dec 2020 11:16:51 +0800 Subject: [PATCH 11/43] Updated doxygen comments for adjustDrift() --- utility/RTC/RTC.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utility/RTC/RTC.h b/utility/RTC/RTC.h index e401f16e..e2766701 100644 --- a/utility/RTC/RTC.h +++ b/utility/RTC/RTC.h @@ -37,7 +37,7 @@ class RTC { @param dt DateTime object containing desired date/time @return True if successful, false otherwise */ - virtual boolean begin(DateTime &dt) = 0; + virtual boolean begin(DateTime &dt); /*! @brief Adjust the RTC to the specified date/time @@ -46,7 +46,7 @@ class RTC { virtual void adjust(const DateTime &dt) = 0; /*! - @brief Adjust the RTC's date/time to account for RTC drift + @brief Adjust the RTC time's rate of change to counter drift @param drift The drift to adjust the date/time by @note Positive values makes the clock go ahead in time and vice-versa */ From 4a253734e0edadc9ed571eb846506a5dd93169df Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 29 Dec 2020 11:36:24 +0800 Subject: [PATCH 12/43] Wrote second `begin()` function for RTC classes --- RTClib.cpp | 90 +++++++++++++++++++++++++++++++++++++++++++++++ RTClib.h | 22 ++++++------ utility/RTC/RTC.h | 12 +++++-- 3 files changed, 111 insertions(+), 13 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index c792b7aa..dc60ca92 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -117,6 +117,22 @@ static uint8_t bin2bcd(uint8_t val) { return val + 6 * (val / 10); } /**************************************************************************/ /*! @brief Start I2C for the DS1307 and test succesful connection + @return True if Wire can find DS1307 or false otherwise. + @note Preserves the date/time on the RTC +*/ +/**************************************************************************/ +boolean RTC_DS1307::begin(void) { + Wire.begin(); + Wire.beginTransmission(DS1307_ADDRESS); + if (Wire.endTransmission() == 0) + return true; + + return false; +} + +/**************************************************************************/ +/*! + @brief Start I2C for the DS1307, test succesful connection, then initialise the date/time @param dt DateTime object containing desired date/time @return True if Wire can find DS1307 or false otherwise. */ @@ -318,6 +334,17 @@ uint32_t RTC_Millis::millisPerSecond = 1000; uint32_t RTC_Millis::lastMillis; uint32_t RTC_Millis::lastUnix; +/**************************************************************************/ +/*! + @brief Start the RTC_Millis date/time + @return true + @note Equivalent to `begin(DateTime::COMPILE_DT)` +*/ +/**************************************************************************/ +boolean RTC_Millis::begin(void) { + adjust(DateTime::COMPILE_DT); + return true; +} /**************************************************************************/ /*! @brief Start the RTC_Millis date/time @@ -373,6 +400,18 @@ uint32_t RTC_Micros::microsPerSecond = 1000000; uint32_t RTC_Micros::lastMicros; uint32_t RTC_Micros::lastUnix; +/**************************************************************************/ +/*! + @brief Start the RTC_Micros date/time + @return true + @note Equivalent to `begin(DateTime::COMPILE_DT)` +*/ +/**************************************************************************/ +boolean RTC_Micros::begin(void) { + adjust(DateTime::COMPILE_DT); + return true; +} + /**************************************************************************/ /*! @brief Start the RTC_Micros date/time @@ -422,6 +461,23 @@ DateTime RTC_Micros::now() { /*! @brief Start I2C for the PCF8523 and test succesful connection @return True if Wire can find PCF8523 or false otherwise. + @note Preserves the date/time on the RTC +*/ +/**************************************************************************/ +boolean RTC_PCF8523::begin(void) { + Wire.begin(); + Wire.beginTransmission(PCF8523_ADDRESS); + if (Wire.endTransmission() == 0) + return true; + + return false; +} + +/**************************************************************************/ +/*! + @brief Start I2C for the PCF8523 and test succesful connection + @param dt DateTime object containing desired date/time + @return True if Wire can find PCF8523 or false otherwise. */ /**************************************************************************/ boolean RTC_PCF8523::begin(const DateTime &dt) { @@ -752,6 +808,23 @@ void RTC_PCF8523::calibrate(Pcf8523OffsetMode mode, int8_t offset) { /*! @brief Start I2C for the PCF8563 and test succesful connection @return True if Wire can find PCF8563 or false otherwise. + @note Preserves the date/time on the RTC +*/ +/**************************************************************************/ +boolean RTC_PCF8563::begin(void) { + Wire.begin(); + Wire.beginTransmission(PCF8563_ADDRESS); + if (Wire.endTransmission() == 0) + return true; + + return false; +} + +/**************************************************************************/ +/*! + @brief Start I2C for the PCF8563 and test succesful connection + @param dt DateTime object containing desired date/time + @return True if Wire can find PCF8563 or false otherwise. */ /**************************************************************************/ boolean RTC_PCF8563::begin(const DateTime &dt) { @@ -908,6 +981,23 @@ static uint8_t dowToDS3231(uint8_t d) { return d == 0 ? 7 : d; } /*! @brief Start I2C for the DS3231 and test succesful connection @return True if Wire can find DS3231 or false otherwise. + @note Preserves the date/time on the RTC +*/ +/**************************************************************************/ +boolean RTC_DS3231::begin(void) { + Wire.begin(); + Wire.beginTransmission(DS3231_ADDRESS); + if (Wire.endTransmission() == 0) + return true; + + return false; +} + +/**************************************************************************/ +/*! + @brief Start I2C for the DS3231 and test succesful connection + @param dt DateTime object containing desired date/time + @return True if Wire can find DS3231 or false otherwise. */ /**************************************************************************/ boolean RTC_DS3231::begin(const DateTime &dt) { diff --git a/RTClib.h b/RTClib.h index f77336d7..39e6277a 100644 --- a/RTClib.h +++ b/RTClib.h @@ -74,7 +74,8 @@ enum Ds1307SqwPinMode { /**************************************************************************/ class RTC_DS1307 : RTC { public: - boolean begin(const DateTime &dt = DateTime::COMPILE_DT); + boolean begin(void); + boolean begin(const DateTime &dt); void adjust(const DateTime &dt); void adjustDrift(int drift); bool isrunning(void); @@ -128,7 +129,8 @@ enum Ds3231Alarm2Mode { /**************************************************************************/ class RTC_DS3231 : RTC { public: - boolean begin(const DateTime &dt = DateTime::COMPILE_DT); + boolean begin(void); + boolean begin(const DateTime &dt); void adjust(const DateTime &dt); void adjustDrift(const int drift); bool isrunning(void); @@ -195,7 +197,8 @@ enum Pcf8523OffsetMode { /**************************************************************************/ class RTC_PCF8523 : RTC { public: - boolean begin(const DateTime &dt = DateTime::COMPILE_DT); + boolean begin(void); + boolean begin(const DateTime &dt); void adjust(const DateTime &dt); boolean isrunning(void); boolean lostPower(void); @@ -232,7 +235,8 @@ enum Pcf8563SqwPinMode { class RTC_PCF8563 : RTC { public: - boolean begin(const DateTime &dt = DateTime::COMPILE_DT); + boolean begin(void); + boolean begin(const DateTime &dt); boolean isrunning(void); boolean lostPower(void); void adjust(const DateTime &dt); @@ -251,7 +255,8 @@ class RTC_PCF8563 : RTC { /**************************************************************************/ class RTC_Millis : RTC { public: - boolean begin(const DateTime &dt = DateTime::COMPILE_DT); + boolean begin(void); + boolean begin(const DateTime &dt); /*! @brief Simulate if the RTC is running @return true @@ -286,11 +291,8 @@ class RTC_Millis : RTC { /**************************************************************************/ class RTC_Micros : RTC { public: - /*! - @brief Start the RTC - @param dt DateTime object with the date/time to set - */ - boolean begin(const DateTime &dt = DateTime::COMPILE_DT); + boolean begin(void); + boolean begin(const DateTime &dt); /*! @brief Simulate if the RTC is running @return true diff --git a/utility/RTC/RTC.h b/utility/RTC/RTC.h index e2766701..99e7e5cb 100644 --- a/utility/RTC/RTC.h +++ b/utility/RTC/RTC.h @@ -33,11 +33,17 @@ class RTC { public: /*! - @brief Start the RTC + @brief Start the RTC while preserving the RTC's date/time + @return True if successful, false otherwise + */ + virtual boolean begin(void) = 0; + + /*! + @brief Start the RTC and adjust the RTC's date/time @param dt DateTime object containing desired date/time @return True if successful, false otherwise */ - virtual boolean begin(DateTime &dt); + virtual boolean begin(DateTime &dt) = 0; /*! @brief Adjust the RTC to the specified date/time @@ -48,7 +54,7 @@ class RTC { /*! @brief Adjust the RTC time's rate of change to counter drift @param drift The drift to adjust the date/time by - @note Positive values makes the clock go ahead in time and vice-versa + @note Positive values makes the clock go faster and vice-versa */ virtual void adjustDrift(const int drift); From c1001bcb0e2fe0b8e9b2a6cce92d6fb0aac548b0 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 29 Dec 2020 16:08:29 +0800 Subject: [PATCH 13/43] Wrote adjustDraft() functions for RTC classes --- RTClib.cpp | 106 ++++++++++++++++++++++++++++++++++++++++------ RTClib.h | 26 ++++++++++-- utility/RTC/RTC.h | 4 +- 3 files changed, 117 insertions(+), 19 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index dc60ca92..5ef7f20d 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -197,13 +197,12 @@ void RTC_DS1307::adjust(const DateTime &dt) { /**************************************************************************/ /*! @brief Adjust the RTC clock to compensate for system clock drift - @param drift Adjustment to make in seconds - @note Positive values make the clock go ahead in time and vice-versa + @param ppm Parts per million to adjust the clock speed by + @note Positive values make the clock go faster and vice-versa */ /**************************************************************************/ -void RTC_DS1307::adjustDrift(const int drift) { - DateTime newDt = DateTime(now().unixtime() + drift); - adjust(newDt); +void RTC_DS1307::adjustDrift(const int ppm) { + skipPeriod = 1000000L / ppm; } /**************************************************************************/ @@ -225,8 +224,20 @@ DateTime RTC_DS1307::now() { uint8_t d = bcd2bin(Wire._I2C_READ()); uint8_t m = bcd2bin(Wire._I2C_READ()); uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000U; + DateTime currNow(y, m, d, hh, mm, ss); - return DateTime(y, m, d, hh, mm, ss); + if (skipPeriod != 0) { + if ((currNow - prevNow) * 1000000L > abs(skipPeriod)) { + if (skipPeriod > 0) + currNow = DateTime(currNow.unixtime() + 1); + else + currNow = DateTime(currNow.unixtime() - 1); + + adjust(currNow); + } + } + + return currNow; } /**************************************************************************/ @@ -371,11 +382,11 @@ void RTC_Millis::adjust(const DateTime &dt) { /**************************************************************************/ /*! @brief Adjust the RTC clock speed to compensate for system clock drift - @param drift Adjustment to make in milliseconds + @param ppm Parts per million to adjust clock speed by @note Positive values make the clock faster and vice-versa */ /**************************************************************************/ -void RTC_Millis::adjustDrift(int drift) { millisPerSecond = 1000 - drift; } +void RTC_Millis::adjustDrift(const int ppm) { millisPerSecond = (1000000UL - ppm) / 1000; } /**************************************************************************/ /*! @@ -438,11 +449,11 @@ void RTC_Micros::adjust(const DateTime &dt) { /**************************************************************************/ /*! @brief Adjust the RTC_Micros clock speed to compensate for system clock drift - @param drift Adjustment to make in microseconds + @param ppm Parts per million drift rate adjustment @note Positive values make the clock faster and vice-versa */ /**************************************************************************/ -void RTC_Micros::adjustDrift(int drift) { microsPerSecond = 1000000 - drift; } +void RTC_Micros::adjustDrift(const int ppm) { microsPerSecond = 1000000 - ppm; } /**************************************************************************/ /*! @@ -547,6 +558,17 @@ void RTC_PCF8523::adjust(const DateTime &dt) { Wire.endTransmission(); } +/**************************************************************************/ +/*! + @brief Adjust the RTC clock to compensate for system clock drift + @param ppm Parts per million to adjust the clock speed by + @note Positive values make the clock go faster and vice-versa +*/ +/**************************************************************************/ +void RTC_PCF8523::adjustDrift(const int ppm) { + skipPeriod = 1000000L / ppm; +} + /**************************************************************************/ /*! @brief Get the current date/time @@ -566,8 +588,20 @@ DateTime RTC_PCF8523::now() { Wire._I2C_READ(); // skip 'weekdays' uint8_t m = bcd2bin(Wire._I2C_READ()); uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000U; + DateTime currNow(y, m, d, hh, mm, ss); + + if (skipPeriod != 0) { + if ((currNow - prevNow) * 1000000L > abs(skipPeriod)) { + if (skipPeriod > 0) + currNow = DateTime(currNow.unixtime() + 1); + else + currNow = DateTime(currNow.unixtime() - 1); + + adjust(currNow); + } + } - return DateTime(y, m, d, hh, mm, ss); + return currNow; } /**************************************************************************/ @@ -873,6 +907,17 @@ void RTC_PCF8563::adjust(const DateTime &dt) { Wire.endTransmission(); } +/**************************************************************************/ +/*! + @brief Adjust the RTC clock to compensate for system clock drift + @param ppm Parts per million to adjust the clock speed by + @note Positive values make the clock go faster and vice-versa +*/ +/**************************************************************************/ +void RTC_PCF8563::adjustDrift(const int ppm) { + skipPeriod = 1000000L / ppm; +} + /**************************************************************************/ /*! @brief Get the current date/time @@ -893,8 +938,20 @@ DateTime RTC_PCF8563::now() { Wire._I2C_READ(); // skip 'weekdays' uint8_t m = bcd2bin(Wire._I2C_READ() & 0x1F); uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000; + DateTime currNow(y, m, d, hh, mm, ss); + + if (skipPeriod != 0) { + if ((currNow - prevNow) * 1000000L > abs(skipPeriod)) { + if (skipPeriod > 0) + currNow = DateTime(currNow.unixtime() + 1); + else + currNow = DateTime(currNow.unixtime() - 1); - return DateTime(y, m, d, hh, mm, ss); + adjust(currNow); + } + } + + return currNow; } /**************************************************************************/ @@ -1046,6 +1103,17 @@ void RTC_DS3231::adjust(const DateTime &dt) { write_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG, statreg); } +/**************************************************************************/ +/*! + @brief Adjust the RTC clock to compensate for system clock drift + @param ppm Parts per million to adjust the clock speed by + @note Positive values make the clock go faster and vice-versa +*/ +/**************************************************************************/ +void RTC_DS3231::adjustDrift(const int ppm) { + skipPeriod = 1000000L / ppm; +} + /**************************************************************************/ /*! @brief Get the current date/time @@ -1065,8 +1133,20 @@ DateTime RTC_DS3231::now() { uint8_t d = bcd2bin(Wire._I2C_READ()); uint8_t m = bcd2bin(Wire._I2C_READ()); uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000U; + DateTime currNow(y, m, d, hh, mm, ss); + + if (skipPeriod != 0) { + if ((currNow - prevNow) * 1000000L > abs(skipPeriod)) { + if (skipPeriod > 0) + currNow = DateTime(currNow.unixtime() + 1); + else + currNow = DateTime(currNow.unixtime() - 1); + + adjust(currNow); + } + } - return DateTime(y, m, d, hh, mm, ss); + return currNow; } /**************************************************************************/ diff --git a/RTClib.h b/RTClib.h index 39e6277a..8e99dbfd 100644 --- a/RTClib.h +++ b/RTClib.h @@ -77,7 +77,7 @@ class RTC_DS1307 : RTC { boolean begin(void); boolean begin(const DateTime &dt); void adjust(const DateTime &dt); - void adjustDrift(int drift); + void adjustDrift(const int ppm); bool isrunning(void); bool lostPower(void); DateTime now(); @@ -87,6 +87,10 @@ class RTC_DS1307 : RTC { void readnvram(uint8_t *buf, uint8_t size, uint8_t address); void writenvram(uint8_t address, uint8_t data); void writenvram(uint8_t address, uint8_t *buf, uint8_t size); + +protected: + int16_t skipPeriod; // period in us to skip a second + DateTime prevNow; }; /** DS3231 SQW pin mode settings */ @@ -132,7 +136,7 @@ class RTC_DS3231 : RTC { boolean begin(void); boolean begin(const DateTime &dt); void adjust(const DateTime &dt); - void adjustDrift(const int drift); + void adjustDrift(const int ppm); bool isrunning(void); bool lostPower(void); DateTime now(); @@ -147,6 +151,10 @@ class RTC_DS3231 : RTC { void disable32K(void); bool isEnabled32K(void); static float getTemperature(); // in Celcius degree + +protected: + int16_t skipPeriod; // period in us to skip a second + DateTime prevNow; }; /** PCF8523 INT/SQW pin mode settings */ @@ -200,6 +208,7 @@ class RTC_PCF8523 : RTC { boolean begin(void); boolean begin(const DateTime &dt); void adjust(const DateTime &dt); + void adjustDrift(const int ppm); boolean isrunning(void); boolean lostPower(void); boolean initialized(void); @@ -216,6 +225,10 @@ class RTC_PCF8523 : RTC { void disableCountdownTimer(void); void deconfigureAllTimers(void); void calibrate(Pcf8523OffsetMode mode, int8_t offset); + +protected: + int16_t skipPeriod; // period in us to skip a second + DateTime prevNow; }; /** PCF8563 CLKOUT pin mode settings */ @@ -240,11 +253,16 @@ class RTC_PCF8563 : RTC { boolean isrunning(void); boolean lostPower(void); void adjust(const DateTime &dt); + void adjustDrift(const int ppm); DateTime now(); void start(void); void stop(void); Pcf8563SqwPinMode readSqwPinMode(); void writeSqwPinMode(Pcf8563SqwPinMode mode); + +protected: + int16_t skipPeriod; // period in us to skip a second + DateTime prevNow; }; /**************************************************************************/ @@ -268,7 +286,7 @@ class RTC_Millis : RTC { */ boolean lostPower(void) { return false; } void adjust(const DateTime &dt); - void adjustDrift(const int drift); + void adjustDrift(const int ppm); DateTime now(); protected: @@ -304,7 +322,7 @@ class RTC_Micros : RTC { */ boolean lostPower(void) { return false; } void adjust(const DateTime &dt); - void adjustDrift(int ppm); + void adjustDrift(const int ppm); DateTime now(); protected: diff --git a/utility/RTC/RTC.h b/utility/RTC/RTC.h index 99e7e5cb..5f2f42f9 100644 --- a/utility/RTC/RTC.h +++ b/utility/RTC/RTC.h @@ -53,10 +53,10 @@ class RTC { /*! @brief Adjust the RTC time's rate of change to counter drift - @param drift The drift to adjust the date/time by + @param ppm Parts per million to adjust clock speed by @note Positive values makes the clock go faster and vice-versa */ - virtual void adjustDrift(const int drift); + virtual void adjustDrift(const int ppm); /*! @brief Check if the RTC is running or not From f00f0af5c42fc7bb45531eb18b282ea68ff4b816 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 29 Dec 2020 17:15:39 +0800 Subject: [PATCH 14/43] Removed adjustDrift() for future pull request --- RTClib.cpp | 114 ++++++----------------------------------------------- RTClib.h | 20 ---------- 2 files changed, 11 insertions(+), 123 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index 5ef7f20d..55874085 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -194,17 +194,6 @@ void RTC_DS1307::adjust(const DateTime &dt) { Wire.endTransmission(); } -/**************************************************************************/ -/*! - @brief Adjust the RTC clock to compensate for system clock drift - @param ppm Parts per million to adjust the clock speed by - @note Positive values make the clock go faster and vice-versa -*/ -/**************************************************************************/ -void RTC_DS1307::adjustDrift(const int ppm) { - skipPeriod = 1000000L / ppm; -} - /**************************************************************************/ /*! @brief Get the current date and time from the DS1307 @@ -224,20 +213,8 @@ DateTime RTC_DS1307::now() { uint8_t d = bcd2bin(Wire._I2C_READ()); uint8_t m = bcd2bin(Wire._I2C_READ()); uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000U; - DateTime currNow(y, m, d, hh, mm, ss); - - if (skipPeriod != 0) { - if ((currNow - prevNow) * 1000000L > abs(skipPeriod)) { - if (skipPeriod > 0) - currNow = DateTime(currNow.unixtime() + 1); - else - currNow = DateTime(currNow.unixtime() - 1); - adjust(currNow); - } - } - - return currNow; + return DateTime(y, m, d, hh, mm, ss); } /**************************************************************************/ @@ -341,7 +318,7 @@ void RTC_DS1307::writenvram(uint8_t address, uint8_t data) { 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::millisPerSecond = 1000; +uint32_t RTC_Millis::microsPerSecond = 1000000L; uint32_t RTC_Millis::lastMillis; uint32_t RTC_Millis::lastUnix; @@ -386,7 +363,7 @@ void RTC_Millis::adjust(const DateTime &dt) { @note Positive values make the clock faster and vice-versa */ /**************************************************************************/ -void RTC_Millis::adjustDrift(const int ppm) { millisPerSecond = (1000000UL - ppm) / 1000; } +void RTC_Millis::adjustDrift(const int ppm) { microsPerSecond = 1000000L - ppm; } /**************************************************************************/ /*! @@ -397,15 +374,15 @@ void RTC_Millis::adjustDrift(const int ppm) { millisPerSecond = (1000000UL - ppm */ /**************************************************************************/ DateTime RTC_Millis::now() { - uint32_t elapsedSeconds = (millis() - lastMillis) / millisPerSecond; - lastMillis += elapsedSeconds * millisPerSecond; + uint32_t elapsedSeconds = (millis() - lastMillis) * 1000 / microsPerSecond; + lastMillis += elapsedSeconds * microsPerSecond; lastUnix += elapsedSeconds; return lastUnix; } /** Number of microseconds reported by micros() per "true" (calibrated) second. */ -uint32_t RTC_Micros::microsPerSecond = 1000000; +uint32_t RTC_Micros::microsPerSecond = 1000000L; /** The timing logic is identical to RTC_Millis. */ uint32_t RTC_Micros::lastMicros; @@ -453,7 +430,7 @@ void RTC_Micros::adjust(const DateTime &dt) { @note Positive values make the clock faster and vice-versa */ /**************************************************************************/ -void RTC_Micros::adjustDrift(const int ppm) { microsPerSecond = 1000000 - ppm; } +void RTC_Micros::adjustDrift(const int ppm) { microsPerSecond = 1000000L - ppm; } /**************************************************************************/ /*! @@ -558,17 +535,6 @@ void RTC_PCF8523::adjust(const DateTime &dt) { Wire.endTransmission(); } -/**************************************************************************/ -/*! - @brief Adjust the RTC clock to compensate for system clock drift - @param ppm Parts per million to adjust the clock speed by - @note Positive values make the clock go faster and vice-versa -*/ -/**************************************************************************/ -void RTC_PCF8523::adjustDrift(const int ppm) { - skipPeriod = 1000000L / ppm; -} - /**************************************************************************/ /*! @brief Get the current date/time @@ -588,25 +554,13 @@ DateTime RTC_PCF8523::now() { Wire._I2C_READ(); // skip 'weekdays' uint8_t m = bcd2bin(Wire._I2C_READ()); uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000U; - DateTime currNow(y, m, d, hh, mm, ss); - if (skipPeriod != 0) { - if ((currNow - prevNow) * 1000000L > abs(skipPeriod)) { - if (skipPeriod > 0) - currNow = DateTime(currNow.unixtime() + 1); - else - currNow = DateTime(currNow.unixtime() - 1); - - adjust(currNow); - } - } - - return currNow; + return DateTime(y, m, d, hh, mm, ss); } /**************************************************************************/ /*! - @brief Resets the STOP bit in register Control_1 + @brief resets the stop bit in register control_1 */ /**************************************************************************/ void RTC_PCF8523::start(void) { @@ -907,17 +861,6 @@ void RTC_PCF8563::adjust(const DateTime &dt) { Wire.endTransmission(); } -/**************************************************************************/ -/*! - @brief Adjust the RTC clock to compensate for system clock drift - @param ppm Parts per million to adjust the clock speed by - @note Positive values make the clock go faster and vice-versa -*/ -/**************************************************************************/ -void RTC_PCF8563::adjustDrift(const int ppm) { - skipPeriod = 1000000L / ppm; -} - /**************************************************************************/ /*! @brief Get the current date/time @@ -938,20 +881,8 @@ DateTime RTC_PCF8563::now() { Wire._I2C_READ(); // skip 'weekdays' uint8_t m = bcd2bin(Wire._I2C_READ() & 0x1F); uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000; - DateTime currNow(y, m, d, hh, mm, ss); - - if (skipPeriod != 0) { - if ((currNow - prevNow) * 1000000L > abs(skipPeriod)) { - if (skipPeriod > 0) - currNow = DateTime(currNow.unixtime() + 1); - else - currNow = DateTime(currNow.unixtime() - 1); - - adjust(currNow); - } - } - return currNow; + return DateTime(y, m, d, hh, mm, ss); } /**************************************************************************/ @@ -1103,17 +1034,6 @@ void RTC_DS3231::adjust(const DateTime &dt) { write_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG, statreg); } -/**************************************************************************/ -/*! - @brief Adjust the RTC clock to compensate for system clock drift - @param ppm Parts per million to adjust the clock speed by - @note Positive values make the clock go faster and vice-versa -*/ -/**************************************************************************/ -void RTC_DS3231::adjustDrift(const int ppm) { - skipPeriod = 1000000L / ppm; -} - /**************************************************************************/ /*! @brief Get the current date/time @@ -1133,20 +1053,8 @@ DateTime RTC_DS3231::now() { uint8_t d = bcd2bin(Wire._I2C_READ()); uint8_t m = bcd2bin(Wire._I2C_READ()); uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000U; - DateTime currNow(y, m, d, hh, mm, ss); - - if (skipPeriod != 0) { - if ((currNow - prevNow) * 1000000L > abs(skipPeriod)) { - if (skipPeriod > 0) - currNow = DateTime(currNow.unixtime() + 1); - else - currNow = DateTime(currNow.unixtime() - 1); - - adjust(currNow); - } - } - return currNow; + return DateTime(y, m, d, hh, mm, ss); } /**************************************************************************/ diff --git a/RTClib.h b/RTClib.h index 8e99dbfd..ed893449 100644 --- a/RTClib.h +++ b/RTClib.h @@ -77,7 +77,6 @@ class RTC_DS1307 : RTC { boolean begin(void); boolean begin(const DateTime &dt); void adjust(const DateTime &dt); - void adjustDrift(const int ppm); bool isrunning(void); bool lostPower(void); DateTime now(); @@ -87,10 +86,6 @@ class RTC_DS1307 : RTC { void readnvram(uint8_t *buf, uint8_t size, uint8_t address); void writenvram(uint8_t address, uint8_t data); void writenvram(uint8_t address, uint8_t *buf, uint8_t size); - -protected: - int16_t skipPeriod; // period in us to skip a second - DateTime prevNow; }; /** DS3231 SQW pin mode settings */ @@ -136,7 +131,6 @@ class RTC_DS3231 : RTC { boolean begin(void); boolean begin(const DateTime &dt); void adjust(const DateTime &dt); - void adjustDrift(const int ppm); bool isrunning(void); bool lostPower(void); DateTime now(); @@ -151,10 +145,6 @@ class RTC_DS3231 : RTC { void disable32K(void); bool isEnabled32K(void); static float getTemperature(); // in Celcius degree - -protected: - int16_t skipPeriod; // period in us to skip a second - DateTime prevNow; }; /** PCF8523 INT/SQW pin mode settings */ @@ -208,7 +198,6 @@ class RTC_PCF8523 : RTC { boolean begin(void); boolean begin(const DateTime &dt); void adjust(const DateTime &dt); - void adjustDrift(const int ppm); boolean isrunning(void); boolean lostPower(void); boolean initialized(void); @@ -225,10 +214,6 @@ class RTC_PCF8523 : RTC { void disableCountdownTimer(void); void deconfigureAllTimers(void); void calibrate(Pcf8523OffsetMode mode, int8_t offset); - -protected: - int16_t skipPeriod; // period in us to skip a second - DateTime prevNow; }; /** PCF8563 CLKOUT pin mode settings */ @@ -253,16 +238,11 @@ class RTC_PCF8563 : RTC { boolean isrunning(void); boolean lostPower(void); void adjust(const DateTime &dt); - void adjustDrift(const int ppm); DateTime now(); void start(void); void stop(void); Pcf8563SqwPinMode readSqwPinMode(); void writeSqwPinMode(Pcf8563SqwPinMode mode); - -protected: - int16_t skipPeriod; // period in us to skip a second - DateTime prevNow; }; /**************************************************************************/ From 58e543219415cd0607a02841de2fbcf6191abe3b Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 29 Dec 2020 17:24:31 +0800 Subject: [PATCH 15/43] Made RTC superclass public for subclasses --- RTClib.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/RTClib.h b/RTClib.h index ed893449..bee2ecbf 100644 --- a/RTClib.h +++ b/RTClib.h @@ -24,6 +24,8 @@ #include #include "utility/RTC/RTC.h" +#include "utility/DateTime/DateTime.h" +#include "utility/TimeSpan/TimeSpan.h" /** Registers */ #define PCF8523_ADDRESS 0x68 ///< I2C address for PCF8523 @@ -72,7 +74,7 @@ enum Ds1307SqwPinMode { @brief RTC based on the DS1307 chip connected via I2C and the Wire library */ /**************************************************************************/ -class RTC_DS1307 : RTC { +class RTC_DS1307 : public RTC { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -126,7 +128,7 @@ enum Ds3231Alarm2Mode { @brief RTC based on the DS3231 chip connected via I2C and the Wire library */ /**************************************************************************/ -class RTC_DS3231 : RTC { +class RTC_DS3231 : public RTC { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -193,7 +195,7 @@ enum Pcf8523OffsetMode { @brief RTC based on the PCF8523 chip connected via I2C and the Wire library */ /**************************************************************************/ -class RTC_PCF8523 : RTC { +class RTC_PCF8523 : public RTC { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -231,7 +233,7 @@ enum Pcf8563SqwPinMode { */ /**************************************************************************/ -class RTC_PCF8563 : RTC { +class RTC_PCF8563 : public RTC { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -251,7 +253,7 @@ class RTC_PCF8563 : RTC { use. NOTE: this is immune to millis() rollover events. */ /**************************************************************************/ -class RTC_Millis : RTC { +class RTC_Millis : public RTC { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -270,7 +272,7 @@ class RTC_Millis : RTC { DateTime now(); protected: - static uint32_t millisPerSecond; ///< Number of milliseconds reported by + static uint32_t microsPerSecond; ///< Number of milliseconds reported by ///< millis() per "true" (calibrated) second static uint32_t lastUnix; ///< Unix time from the previous call to now() - ///< prevents rollover issues @@ -287,7 +289,7 @@ class RTC_Millis : RTC { approximately 71.6 minutes. */ /**************************************************************************/ -class RTC_Micros : RTC { +class RTC_Micros : public RTC { public: boolean begin(void); boolean begin(const DateTime &dt); From 161412076714da5727e22f6eea0229812a37f1e2 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 29 Dec 2020 17:29:22 +0800 Subject: [PATCH 16/43] Fixed compile error with begin(const DateTime&) --- utility/RTC/RTC.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utility/RTC/RTC.h b/utility/RTC/RTC.h index 5f2f42f9..a8151df6 100644 --- a/utility/RTC/RTC.h +++ b/utility/RTC/RTC.h @@ -43,7 +43,7 @@ class RTC { @param dt DateTime object containing desired date/time @return True if successful, false otherwise */ - virtual boolean begin(DateTime &dt) = 0; + virtual boolean begin(const DateTime &dt) = 0; /*! @brief Adjust the RTC to the specified date/time From de9a42e579e9dba3fefbfda8a7e2a803458ee616 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 29 Dec 2020 17:33:48 +0800 Subject: [PATCH 17/43] Removed fixDateTime() function --- utility/DateTime/DateTime.h | 1 - 1 file changed, 1 deletion(-) diff --git a/utility/DateTime/DateTime.h b/utility/DateTime/DateTime.h index 505b87d5..810454ec 100644 --- a/utility/DateTime/DateTime.h +++ b/utility/DateTime/DateTime.h @@ -42,7 +42,6 @@ class DateTime { DateTime(const __FlashStringHelper *date, const __FlashStringHelper *time); DateTime(const char *iso8601date); bool isValid() const; - bool fixDateTime(); char *toString(char *buffer); /*! From 189ddc90a354d2d1bcab7d3924226e5322288729 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 29 Dec 2020 18:03:39 +0800 Subject: [PATCH 18/43] Fixed file placement in utility folder --- RTClib.h | 6 +++--- utility/{DateTime => }/DateTime.cpp | 0 utility/{DateTime => }/DateTime.h | 2 +- utility/{RTC => }/RTC.h | 2 +- utility/{TimeSpan => }/TimeSpan.cpp | 0 utility/{TimeSpan => }/TimeSpan.h | 0 6 files changed, 5 insertions(+), 5 deletions(-) rename utility/{DateTime => }/DateTime.cpp (100%) rename utility/{DateTime => }/DateTime.h (99%) rename utility/{RTC => }/RTC.h (98%) rename utility/{TimeSpan => }/TimeSpan.cpp (100%) rename utility/{TimeSpan => }/TimeSpan.h (100%) diff --git a/RTClib.h b/RTClib.h index bee2ecbf..bbc4113f 100644 --- a/RTClib.h +++ b/RTClib.h @@ -23,9 +23,9 @@ #define _RTCLIB_H_ #include -#include "utility/RTC/RTC.h" -#include "utility/DateTime/DateTime.h" -#include "utility/TimeSpan/TimeSpan.h" +#include "utility/RTC.h" +#include "utility/DateTime.h" +#include "utility/TimeSpan.h" /** Registers */ #define PCF8523_ADDRESS 0x68 ///< I2C address for PCF8523 diff --git a/utility/DateTime/DateTime.cpp b/utility/DateTime.cpp similarity index 100% rename from utility/DateTime/DateTime.cpp rename to utility/DateTime.cpp diff --git a/utility/DateTime/DateTime.h b/utility/DateTime.h similarity index 99% rename from utility/DateTime/DateTime.h rename to utility/DateTime.h index 810454ec..e9930bc6 100644 --- a/utility/DateTime/DateTime.h +++ b/utility/DateTime.h @@ -2,7 +2,7 @@ #define _DATETIME_H_ #include -#include "../TimeSpan/TimeSpan.h" +#include "TimeSpan.h" /** Constants */ #define SECONDS_PER_DAY 86400L ///< 60 * 60 * 24 diff --git a/utility/RTC/RTC.h b/utility/RTC.h similarity index 98% rename from utility/RTC/RTC.h rename to utility/RTC.h index a8151df6..2d24de9a 100644 --- a/utility/RTC/RTC.h +++ b/utility/RTC.h @@ -23,7 +23,7 @@ #define _RTC_H_ #include -#include "../DateTime/DateTime.h" +#include "DateTime.h" /**************************************************************************/ /*! diff --git a/utility/TimeSpan/TimeSpan.cpp b/utility/TimeSpan.cpp similarity index 100% rename from utility/TimeSpan/TimeSpan.cpp rename to utility/TimeSpan.cpp diff --git a/utility/TimeSpan/TimeSpan.h b/utility/TimeSpan.h similarity index 100% rename from utility/TimeSpan/TimeSpan.h rename to utility/TimeSpan.h From 0975cc52a6e1539edaa68bc53b1638385d02d0c2 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 29 Dec 2020 18:09:57 +0800 Subject: [PATCH 19/43] Ensured that TimeSpan.h file includes Arduino.h --- utility/TimeSpan.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utility/TimeSpan.h b/utility/TimeSpan.h index 75bceaa0..924a6b77 100644 --- a/utility/TimeSpan.h +++ b/utility/TimeSpan.h @@ -1,6 +1,8 @@ #ifndef _TIMESPAN_H_ #define _TIMESPAN_H_ +#include + /**************************************************************************/ /*! @brief Timespan which can represent changes in time with seconds accuracy. From 3ab766926caf94abf9d88fa5330c279e8ba0c1b2 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 29 Dec 2020 18:28:22 +0800 Subject: [PATCH 20/43] Removed COMPILE_DT constant due to compile error --- RTClib.cpp | 8 ++++---- utility/DateTime.cpp | 2 -- utility/DateTime.h | 5 ----- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index 55874085..66707ac9 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -326,11 +326,11 @@ uint32_t RTC_Millis::lastUnix; /*! @brief Start the RTC_Millis date/time @return true - @note Equivalent to `begin(DateTime::COMPILE_DT)` + @note Equivalent to `begin(DateTime(F(__DATE__), F(__TIME__)))` */ /**************************************************************************/ boolean RTC_Millis::begin(void) { - adjust(DateTime::COMPILE_DT); + adjust(DateTime(F(__DATE__), F(__TIME__))); return true; } /**************************************************************************/ @@ -392,11 +392,11 @@ uint32_t RTC_Micros::lastUnix; /*! @brief Start the RTC_Micros date/time @return true - @note Equivalent to `begin(DateTime::COMPILE_DT)` + @note Equivalent to `begin(DateTime(F(__DATE__), F(__TIME__)))` */ /**************************************************************************/ boolean RTC_Micros::begin(void) { - adjust(DateTime::COMPILE_DT); + adjust(DateTime(F(__DATE__), F(__TIME__))); return true; } diff --git a/utility/DateTime.cpp b/utility/DateTime.cpp index a8db7c85..f140170e 100644 --- a/utility/DateTime.cpp +++ b/utility/DateTime.cpp @@ -60,8 +60,6 @@ static uint32_t time2ulong(uint16_t days, uint8_t h, uint8_t m, uint8_t s) { return ((days * 24UL + h) * 60 + m) * 60 + s; } -const DateTime DateTime::COMPILE_DT = DateTime(F(__DATE__), F(__TIME__)); - /**************************************************************************/ /*! @brief Constructor from diff --git a/utility/DateTime.h b/utility/DateTime.h index e9930bc6..04206a48 100644 --- a/utility/DateTime.h +++ b/utility/DateTime.h @@ -29,11 +29,6 @@ uint8_t getDaysInMonth(uint16_t year, uint8_t month); /**************************************************************************/ class DateTime { public: - /*! - @brief The date/time at compile time - */ - const static DateTime COMPILE_DT; - DateTime(uint32_t t = SECONDS_FROM_1970_TO_2000); DateTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour = 0, uint8_t min = 0, uint8_t sec = 0); From 37214918247b2f56c9b6af951e0a7414f1a12b49 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 29 Dec 2020 18:31:01 +0800 Subject: [PATCH 21/43] Removed adjustDrift() from RTC for future pull request --- utility/RTC.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/utility/RTC.h b/utility/RTC.h index 2d24de9a..b10fdc15 100644 --- a/utility/RTC.h +++ b/utility/RTC.h @@ -51,13 +51,6 @@ class RTC { */ virtual void adjust(const DateTime &dt) = 0; - /*! - @brief Adjust the RTC time's rate of change to counter drift - @param ppm Parts per million to adjust clock speed by - @note Positive values makes the clock go faster and vice-versa - */ - virtual void adjustDrift(const int ppm); - /*! @brief Check if the RTC is running or not @return True if it is running, false otherwise From 290bea293034241fe5b509c25e33e4f76c735c10 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 29 Dec 2020 22:00:48 +0800 Subject: [PATCH 22/43] Fixed build errors --- RTClib.cpp | 16 ++++++++++++++++ RTClib.h | 14 +++++++------- utility/{RTC.h => RTC_Super.h} | 8 ++++---- 3 files changed, 27 insertions(+), 11 deletions(-) rename utility/{RTC.h => RTC_Super.h} (95%) diff --git a/RTClib.cpp b/RTClib.cpp index 66707ac9..f94362ce 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -998,6 +998,22 @@ boolean RTC_DS3231::begin(const DateTime &dt) { return false; } +/**************************************************************************/ +/*! + @brief Is the DS3231 running? Check the Clock Halt bit in register 0 + @return 1 if the RTC is running, 0 if not +*/ +/**************************************************************************/ +bool RTC_DS3231::isrunning(void) { + Wire.beginTransmission(DS3231_ADDRESS); + Wire._I2C_WRITE((byte)0); + Wire.endTransmission(); + + Wire.requestFrom(DS3231_ADDRESS, 1); + uint8_t ss = Wire._I2C_READ(); + return !(ss >> 7); +} + /**************************************************************************/ /*! @brief Check the status register Oscillator Stop Flag to see if the DS3231 diff --git a/RTClib.h b/RTClib.h index bbc4113f..808eafc0 100644 --- a/RTClib.h +++ b/RTClib.h @@ -23,7 +23,7 @@ #define _RTCLIB_H_ #include -#include "utility/RTC.h" +#include "utility/RTC_Super.h" #include "utility/DateTime.h" #include "utility/TimeSpan.h" @@ -74,7 +74,7 @@ enum Ds1307SqwPinMode { @brief RTC based on the DS1307 chip connected via I2C and the Wire library */ /**************************************************************************/ -class RTC_DS1307 : public RTC { +class RTC_DS1307 : public RTC_Super { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -128,7 +128,7 @@ enum Ds3231Alarm2Mode { @brief RTC based on the DS3231 chip connected via I2C and the Wire library */ /**************************************************************************/ -class RTC_DS3231 : public RTC { +class RTC_DS3231 : public RTC_Super { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -195,7 +195,7 @@ enum Pcf8523OffsetMode { @brief RTC based on the PCF8523 chip connected via I2C and the Wire library */ /**************************************************************************/ -class RTC_PCF8523 : public RTC { +class RTC_PCF8523 : public RTC_Super { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -233,7 +233,7 @@ enum Pcf8563SqwPinMode { */ /**************************************************************************/ -class RTC_PCF8563 : public RTC { +class RTC_PCF8563 : public RTC_Super { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -253,7 +253,7 @@ class RTC_PCF8563 : public RTC { use. NOTE: this is immune to millis() rollover events. */ /**************************************************************************/ -class RTC_Millis : public RTC { +class RTC_Millis : public RTC_Super { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -289,7 +289,7 @@ class RTC_Millis : public RTC { approximately 71.6 minutes. */ /**************************************************************************/ -class RTC_Micros : public RTC { +class RTC_Micros : public RTC_Super { public: boolean begin(void); boolean begin(const DateTime &dt); diff --git a/utility/RTC.h b/utility/RTC_Super.h similarity index 95% rename from utility/RTC.h rename to utility/RTC_Super.h index b10fdc15..4fc4497d 100644 --- a/utility/RTC.h +++ b/utility/RTC_Super.h @@ -1,6 +1,6 @@ /**************************************************************************/ /*! - @file RTC.h + @file RTC_Super.h Original library by JeeLabs http://news.jeelabs.org/code/, released to the public domain @@ -19,8 +19,8 @@ */ /**************************************************************************/ -#ifndef _RTC_H_ -#define _RTC_H_ +#ifndef _RTC_SUPER_H_ +#define _RTC_SUPER_H_ #include #include "DateTime.h" @@ -30,7 +30,7 @@ @brief RTC superclass for all RTC chips */ /**************************************************************************/ -class RTC { +class RTC_Super { public: /*! @brief Start the RTC while preserving the RTC's date/time From 41b522d8ebda6a6a091b3498dc8dddfe2a75e6ff Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Wed, 30 Dec 2020 10:20:37 +0800 Subject: [PATCH 23/43] Fixed adjustDrift() for RTC_Millis --- RTClib.cpp | 8 +++++--- RTClib.h | 4 ++-- keywords.txt | 3 +-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index f94362ce..b24ffcd7 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -363,7 +363,9 @@ void RTC_Millis::adjust(const DateTime &dt) { @note Positive values make the clock faster and vice-versa */ /**************************************************************************/ -void RTC_Millis::adjustDrift(const int ppm) { microsPerSecond = 1000000L - ppm; } +void RTC_Millis::adjustDrift(const int ppm) { + millisPerSecond = (1000000L - ppm) / 1000; +} /**************************************************************************/ /*! @@ -374,8 +376,8 @@ void RTC_Millis::adjustDrift(const int ppm) { microsPerSecond = 1000000L - ppm; */ /**************************************************************************/ DateTime RTC_Millis::now() { - uint32_t elapsedSeconds = (millis() - lastMillis) * 1000 / microsPerSecond; - lastMillis += elapsedSeconds * microsPerSecond; + uint32_t elapsedSeconds = (millis() - lastMillis) / millisPerSecond; + lastMillis += elapsedSeconds * millisPerSecond; lastUnix += elapsedSeconds; return lastUnix; } diff --git a/RTClib.h b/RTClib.h index 808eafc0..27bd418c 100644 --- a/RTClib.h +++ b/RTClib.h @@ -272,8 +272,8 @@ class RTC_Millis : public RTC_Super { DateTime now(); protected: - static uint32_t microsPerSecond; ///< Number of milliseconds reported by - ///< millis() per "true" (calibrated) second + static uint32_t millisPerSecond; ///< Number of milliseconds reported by + ///< millis() per "true" (calibrated) kilosecond static uint32_t lastUnix; ///< Unix time from the previous call to now() - ///< prevents rollover issues static uint32_t lastMillis; ///< the millis() value corresponding to the last diff --git a/keywords.txt b/keywords.txt index 0633744f..12c26320 100644 --- a/keywords.txt +++ b/keywords.txt @@ -8,7 +8,7 @@ DateTime KEYWORD1 TimeSpan KEYWORD1 -RTC KEYWORD1 +RTC_Super KEYWORD1 RTC_DS1307 KEYWORD1 RTC_DS3231 KEYWORD1 RTC_PCF8523 KEYWORD1 @@ -78,7 +78,6 @@ isEnabled32K KEYWORD2 ####################################### # Constants (LITERAL1) ####################################### -COMPILE_DT LITERAL1 TIMESTAMP_FULL LITERAL1 TIMESTAMP_DATE LITERAL1 TIMESTAMP_TIME LITERAL1 From 2f99da8525802411055731740ef6261c014908df Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Thu, 31 Dec 2020 13:14:46 +0800 Subject: [PATCH 24/43] Fixed micro to milli typo --- RTClib.cpp | 2 +- RTClib.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index b24ffcd7..93c3ce95 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -318,7 +318,7 @@ void RTC_DS1307::writenvram(uint8_t address, uint8_t data) { 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::microsPerSecond = 1000000L; +uint16_t RTC_Millis::millisPerSecond = 1000; uint32_t RTC_Millis::lastMillis; uint32_t RTC_Millis::lastUnix; diff --git a/RTClib.h b/RTClib.h index 27bd418c..1d271ca1 100644 --- a/RTClib.h +++ b/RTClib.h @@ -272,7 +272,7 @@ class RTC_Millis : public RTC_Super { DateTime now(); protected: - static uint32_t millisPerSecond; ///< Number of milliseconds reported by + static uint16_t millisPerSecond; ///< Number of milliseconds reported by ///< millis() per "true" (calibrated) kilosecond static uint32_t lastUnix; ///< Unix time from the previous call to now() - ///< prevents rollover issues From edc0af4d06a844f3666eac2250b174053714e768 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Thu, 31 Dec 2020 14:37:45 +0800 Subject: [PATCH 25/43] Fixed clang formatting issues --- RTClib.cpp | 19 ++++++++++++------- RTClib.h | 7 ++++--- utility/DateTime.cpp | 1 - utility/DateTime.h | 2 +- utility/RTC_Super.h | 2 +- utility/TimeSpan.cpp | 1 - 6 files changed, 18 insertions(+), 14 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index 93c3ce95..8d7415fa 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -126,13 +126,14 @@ boolean RTC_DS1307::begin(void) { Wire.beginTransmission(DS1307_ADDRESS); if (Wire.endTransmission() == 0) return true; - + return false; } /**************************************************************************/ /*! - @brief Start I2C for the DS1307, test succesful connection, then initialise the date/time + @brief Start I2C for the DS1307, test succesful connection, then initialise + the date/time @param dt DateTime object containing desired date/time @return True if Wire can find DS1307 or false otherwise. */ @@ -358,7 +359,8 @@ void RTC_Millis::adjust(const DateTime &dt) { /**************************************************************************/ /*! - @brief Adjust the RTC clock speed to compensate for system clock drift + @brief Adjust the RTC clock speed to compensate for system clock + drift @param ppm Parts per million to adjust clock speed by @note Positive values make the clock faster and vice-versa */ @@ -427,12 +429,15 @@ void RTC_Micros::adjust(const DateTime &dt) { /**************************************************************************/ /*! - @brief Adjust the RTC_Micros clock speed to compensate for system clock drift + @brief Adjust the RTC_Micros clock speed to compensate for system clock + drift @param ppm Parts per million drift rate adjustment @note Positive values make the clock faster and vice-versa */ /**************************************************************************/ -void RTC_Micros::adjustDrift(const int ppm) { microsPerSecond = 1000000L - ppm; } +void RTC_Micros::adjustDrift(const int ppm) { + microsPerSecond = 1000000L - ppm; +} /**************************************************************************/ /*! @@ -459,7 +464,7 @@ boolean RTC_PCF8523::begin(void) { Wire.beginTransmission(PCF8523_ADDRESS); if (Wire.endTransmission() == 0) return true; - + return false; } @@ -806,7 +811,7 @@ boolean RTC_PCF8563::begin(void) { Wire.beginTransmission(PCF8563_ADDRESS); if (Wire.endTransmission() == 0) return true; - + return false; } diff --git a/RTClib.h b/RTClib.h index 1d271ca1..80d8c5bc 100644 --- a/RTClib.h +++ b/RTClib.h @@ -22,10 +22,10 @@ #ifndef _RTCLIB_H_ #define _RTCLIB_H_ -#include #include "utility/RTC_Super.h" #include "utility/DateTime.h" #include "utility/TimeSpan.h" +#include /** Registers */ #define PCF8523_ADDRESS 0x68 ///< I2C address for PCF8523 @@ -272,8 +272,9 @@ class RTC_Millis : public RTC_Super { DateTime now(); protected: - static uint16_t millisPerSecond; ///< Number of milliseconds reported by - ///< millis() per "true" (calibrated) kilosecond + static uint16_t + millisPerSecond; ///< Number of milliseconds reported by + ///< millis() per "true" (calibrated) kilosecond static uint32_t lastUnix; ///< Unix time from the previous call to now() - ///< prevents rollover issues static uint32_t lastMillis; ///< the millis() value corresponding to the last diff --git a/utility/DateTime.cpp b/utility/DateTime.cpp index f140170e..e25c04a2 100644 --- a/utility/DateTime.cpp +++ b/utility/DateTime.cpp @@ -639,4 +639,3 @@ String DateTime::timestamp(timestampOpt opt) { } return String(buffer); } - diff --git a/utility/DateTime.h b/utility/DateTime.h index 04206a48..330c2c22 100644 --- a/utility/DateTime.h +++ b/utility/DateTime.h @@ -1,8 +1,8 @@ #ifndef _DATETIME_H_ #define _DATETIME_H_ -#include #include "TimeSpan.h" +#include /** Constants */ #define SECONDS_PER_DAY 86400L ///< 60 * 60 * 24 diff --git a/utility/RTC_Super.h b/utility/RTC_Super.h index 4fc4497d..3225ecdd 100644 --- a/utility/RTC_Super.h +++ b/utility/RTC_Super.h @@ -22,8 +22,8 @@ #ifndef _RTC_SUPER_H_ #define _RTC_SUPER_H_ -#include #include "DateTime.h" +#include /**************************************************************************/ /*! diff --git a/utility/TimeSpan.cpp b/utility/TimeSpan.cpp index ea87f090..b0a668ce 100644 --- a/utility/TimeSpan.cpp +++ b/utility/TimeSpan.cpp @@ -52,4 +52,3 @@ TimeSpan TimeSpan::operator+(const TimeSpan &right) { TimeSpan TimeSpan::operator-(const TimeSpan &right) { return TimeSpan(_seconds - right._seconds); } - From fd67d3444460585fca658b0d319d23d68a6e668a Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Thu, 31 Dec 2020 21:02:22 +0800 Subject: [PATCH 26/43] Wrote adjustDrift() back in to enforce consistency --- utility/RTC_Super.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/utility/RTC_Super.h b/utility/RTC_Super.h index 3225ecdd..18f1cc41 100644 --- a/utility/RTC_Super.h +++ b/utility/RTC_Super.h @@ -51,18 +51,26 @@ class RTC_Super { */ virtual void adjust(const DateTime &dt) = 0; + /*! + @brief Adjust the RTC clock speed to compensate for system clock + drift + @param ppm Parts per million to adjust clock speed by + @note Positive values make the clock faster and vice-versa + */ + virtual void adjustDrift(const int ppm); + /*! @brief Check if the RTC is running or not @return True if it is running, false otherwise */ - virtual boolean isrunning(void) = 0; + virtual boolean isrunning(void); /*! @brief Check if the RTC has lost power @return True if the RTC has lost power, false otherwise @note Equivalent to `!rtc.isrunning()` */ - virtual boolean lostPower(void); + boolean lostPower(void); /*! @brief Get the current date/time from the RTC From 80b56500d17c25ee9b2f61c02a4e8a1dbd97c15a Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Thu, 31 Dec 2020 21:05:44 +0800 Subject: [PATCH 27/43] :w --- RTClib.cpp | 12 ------------ RTClib.h | 1 - 2 files changed, 13 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index 8d7415fa..f5bcf46c 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -357,18 +357,6 @@ void RTC_Millis::adjust(const DateTime &dt) { lastUnix = dt.unixtime(); } -/**************************************************************************/ -/*! - @brief Adjust the RTC clock speed to compensate for system clock - drift - @param ppm Parts per million to adjust clock speed by - @note Positive values make the clock faster and vice-versa -*/ -/**************************************************************************/ -void RTC_Millis::adjustDrift(const int ppm) { - millisPerSecond = (1000000L - ppm) / 1000; -} - /**************************************************************************/ /*! @brief Return a DateTime object containing the current date/time. diff --git a/RTClib.h b/RTClib.h index 80d8c5bc..274352f1 100644 --- a/RTClib.h +++ b/RTClib.h @@ -268,7 +268,6 @@ class RTC_Millis : public RTC_Super { */ boolean lostPower(void) { return false; } void adjust(const DateTime &dt); - void adjustDrift(const int ppm); DateTime now(); protected: From 7213586d68620284406aff845fcd0f7e12fafa9b Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Thu, 31 Dec 2020 21:11:54 +0800 Subject: [PATCH 28/43] Fixed clang formatting issues --- RTClib.cpp | 2 +- RTClib.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index f5bcf46c..be60b76b 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -972,7 +972,7 @@ boolean RTC_DS3231::begin(void) { Wire.beginTransmission(DS3231_ADDRESS); if (Wire.endTransmission() == 0) return true; - + return false; } diff --git a/RTClib.h b/RTClib.h index 274352f1..858f9158 100644 --- a/RTClib.h +++ b/RTClib.h @@ -22,9 +22,9 @@ #ifndef _RTCLIB_H_ #define _RTCLIB_H_ -#include "utility/RTC_Super.h" -#include "utility/DateTime.h" #include "utility/TimeSpan.h" +#include "utility/DateTime.h" +#include "utility/RTC_Super.h" #include /** Registers */ From 5eba8f65a36f1a0d03bb1c1f871c86f8db28d77f Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Thu, 31 Dec 2020 21:16:18 +0800 Subject: [PATCH 29/43] Removed millisPerSecond from RTC_Millis --- RTClib.cpp | 1 - RTClib.h | 3 --- 2 files changed, 4 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index be60b76b..85c8716f 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -319,7 +319,6 @@ void RTC_DS1307::writenvram(uint8_t address, uint8_t data) { 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. */ -uint16_t RTC_Millis::millisPerSecond = 1000; uint32_t RTC_Millis::lastMillis; uint32_t RTC_Millis::lastUnix; diff --git a/RTClib.h b/RTClib.h index 858f9158..d8dafb90 100644 --- a/RTClib.h +++ b/RTClib.h @@ -271,9 +271,6 @@ class RTC_Millis : public RTC_Super { DateTime now(); protected: - static uint16_t - millisPerSecond; ///< Number of milliseconds reported by - ///< millis() per "true" (calibrated) kilosecond static uint32_t lastUnix; ///< Unix time from the previous call to now() - ///< prevents rollover issues static uint32_t lastMillis; ///< the millis() value corresponding to the last From db255bfe6614d14f4c6461606a54dd47b8056f97 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Fri, 1 Jan 2021 09:03:43 +0800 Subject: [PATCH 30/43] Fixed compile error involving millisPerSecond --- RTClib.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index 85c8716f..2907d946 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -365,8 +365,8 @@ void RTC_Millis::adjust(const DateTime &dt) { */ /**************************************************************************/ DateTime RTC_Millis::now() { - uint32_t elapsedSeconds = (millis() - lastMillis) / millisPerSecond; - lastMillis += elapsedSeconds * millisPerSecond; + uint32_t elapsedSeconds = (millis() - lastMillis) / 1000; + lastMillis += elapsedSeconds * 1000; lastUnix += elapsedSeconds; return lastUnix; } From e2a981c7d9115b8e53ac62581e01ffd755c6e073 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Fri, 1 Jan 2021 09:04:46 +0800 Subject: [PATCH 31/43] Renamed RTC_Super to RTC to find RTC macro --- RTClib.h | 12 ++++++------ utility/RTC_Super.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/RTClib.h b/RTClib.h index d8dafb90..6641ac48 100644 --- a/RTClib.h +++ b/RTClib.h @@ -74,7 +74,7 @@ enum Ds1307SqwPinMode { @brief RTC based on the DS1307 chip connected via I2C and the Wire library */ /**************************************************************************/ -class RTC_DS1307 : public RTC_Super { +class RTC_DS1307 : public RTC { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -128,7 +128,7 @@ enum Ds3231Alarm2Mode { @brief RTC based on the DS3231 chip connected via I2C and the Wire library */ /**************************************************************************/ -class RTC_DS3231 : public RTC_Super { +class RTC_DS3231 : public RTC { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -195,7 +195,7 @@ enum Pcf8523OffsetMode { @brief RTC based on the PCF8523 chip connected via I2C and the Wire library */ /**************************************************************************/ -class RTC_PCF8523 : public RTC_Super { +class RTC_PCF8523 : public RTC { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -233,7 +233,7 @@ enum Pcf8563SqwPinMode { */ /**************************************************************************/ -class RTC_PCF8563 : public RTC_Super { +class RTC_PCF8563 : public RTC { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -253,7 +253,7 @@ class RTC_PCF8563 : public RTC_Super { use. NOTE: this is immune to millis() rollover events. */ /**************************************************************************/ -class RTC_Millis : public RTC_Super { +class RTC_Millis : public RTC { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -286,7 +286,7 @@ class RTC_Millis : public RTC_Super { approximately 71.6 minutes. */ /**************************************************************************/ -class RTC_Micros : public RTC_Super { +class RTC_Micros : public RTC { public: boolean begin(void); boolean begin(const DateTime &dt); diff --git a/utility/RTC_Super.h b/utility/RTC_Super.h index 18f1cc41..87b44deb 100644 --- a/utility/RTC_Super.h +++ b/utility/RTC_Super.h @@ -30,7 +30,7 @@ @brief RTC superclass for all RTC chips */ /**************************************************************************/ -class RTC_Super { +class RTC { public: /*! @brief Start the RTC while preserving the RTC's date/time From 8f7e6564f848c57d936866f8301bde54f34f5a09 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Sat, 2 Jan 2021 09:32:32 +0800 Subject: [PATCH 32/43] Changed begin(DateTime&) to non-pure virtual --- utility/RTC_Super.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/utility/RTC_Super.h b/utility/RTC_Super.h index 87b44deb..6b9bb462 100644 --- a/utility/RTC_Super.h +++ b/utility/RTC_Super.h @@ -30,7 +30,7 @@ @brief RTC superclass for all RTC chips */ /**************************************************************************/ -class RTC { +class RTC_Super { public: /*! @brief Start the RTC while preserving the RTC's date/time @@ -43,7 +43,7 @@ class RTC { @param dt DateTime object containing desired date/time @return True if successful, false otherwise */ - virtual boolean begin(const DateTime &dt) = 0; + virtual boolean begin(const DateTime &dt); /*! @brief Adjust the RTC to the specified date/time @@ -66,9 +66,8 @@ class RTC { virtual boolean isrunning(void); /*! - @brief Check if the RTC has lost power + @brief Check if the RTC has lost power since last adjust() @return True if the RTC has lost power, false otherwise - @note Equivalent to `!rtc.isrunning()` */ boolean lostPower(void); From c13d1c465b99776b3e3aaa9148297ca423b77f26 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Sat, 2 Jan 2021 09:34:08 +0800 Subject: [PATCH 33/43] Renamed RTC_Super to RTC_Base --- RTClib.h | 2 +- utility/{RTC_Super.h => RTC_Base.h} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename utility/{RTC_Super.h => RTC_Base.h} (99%) diff --git a/RTClib.h b/RTClib.h index 6641ac48..37fc559c 100644 --- a/RTClib.h +++ b/RTClib.h @@ -24,7 +24,7 @@ #include "utility/TimeSpan.h" #include "utility/DateTime.h" -#include "utility/RTC_Super.h" +#include "utility/RTC_Base.h" #include /** Registers */ diff --git a/utility/RTC_Super.h b/utility/RTC_Base.h similarity index 99% rename from utility/RTC_Super.h rename to utility/RTC_Base.h index 6b9bb462..75090350 100644 --- a/utility/RTC_Super.h +++ b/utility/RTC_Base.h @@ -30,7 +30,7 @@ @brief RTC superclass for all RTC chips */ /**************************************************************************/ -class RTC_Super { +class RTC_Base { public: /*! @brief Start the RTC while preserving the RTC's date/time From 56f34268f3dad863b5463c729dc67e4364e48573 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Sat, 2 Jan 2021 09:37:51 +0800 Subject: [PATCH 34/43] Changed begin(void) method for pseudo RTCs --- RTClib.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index 2907d946..03a310bb 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -326,11 +326,11 @@ uint32_t RTC_Millis::lastUnix; /*! @brief Start the RTC_Millis date/time @return true - @note Equivalent to `begin(DateTime(F(__DATE__), F(__TIME__)))` + @note Equivalent to `begin(DateTime())` */ /**************************************************************************/ boolean RTC_Millis::begin(void) { - adjust(DateTime(F(__DATE__), F(__TIME__))); + adjust(DateTime()); return true; } /**************************************************************************/ @@ -383,11 +383,11 @@ uint32_t RTC_Micros::lastUnix; /*! @brief Start the RTC_Micros date/time @return true - @note Equivalent to `begin(DateTime(F(__DATE__), F(__TIME__)))` + @note Equivalent to `begin(DateTime())` */ /**************************************************************************/ boolean RTC_Micros::begin(void) { - adjust(DateTime(F(__DATE__), F(__TIME__))); + adjust(DateTime()); return true; } From 678f814be29ffe7c8423870f4495af4cd5498d3c Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Sat, 2 Jan 2021 09:41:36 +0800 Subject: [PATCH 35/43] Updated doxygen comment --- utility/RTC_Base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utility/RTC_Base.h b/utility/RTC_Base.h index 75090350..401ffbea 100644 --- a/utility/RTC_Base.h +++ b/utility/RTC_Base.h @@ -27,7 +27,7 @@ /**************************************************************************/ /*! - @brief RTC superclass for all RTC chips + @brief RTC base class for all RTC chips */ /**************************************************************************/ class RTC_Base { From 2e664b4ac899e745be6e0f0a6cef71a161ee2dfc Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Sun, 3 Jan 2021 09:16:31 +0800 Subject: [PATCH 36/43] Renamed RTC_Base to RealTimeClock --- RTClib.h | 12 ++++++------ keywords.txt | 2 +- utility/RTC_Base.h | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/RTClib.h b/RTClib.h index 37fc559c..08c48ce9 100644 --- a/RTClib.h +++ b/RTClib.h @@ -74,7 +74,7 @@ enum Ds1307SqwPinMode { @brief RTC based on the DS1307 chip connected via I2C and the Wire library */ /**************************************************************************/ -class RTC_DS1307 : public RTC { +class RTC_DS1307 : public RealTimeClock { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -128,7 +128,7 @@ enum Ds3231Alarm2Mode { @brief RTC based on the DS3231 chip connected via I2C and the Wire library */ /**************************************************************************/ -class RTC_DS3231 : public RTC { +class RTC_DS3231 : public RealTimeClock { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -195,7 +195,7 @@ enum Pcf8523OffsetMode { @brief RTC based on the PCF8523 chip connected via I2C and the Wire library */ /**************************************************************************/ -class RTC_PCF8523 : public RTC { +class RTC_PCF8523 : public RealTimeClock { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -233,7 +233,7 @@ enum Pcf8563SqwPinMode { */ /**************************************************************************/ -class RTC_PCF8563 : public RTC { +class RTC_PCF8563 : public RealTimeClock { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -253,7 +253,7 @@ class RTC_PCF8563 : public RTC { use. NOTE: this is immune to millis() rollover events. */ /**************************************************************************/ -class RTC_Millis : public RTC { +class RTC_Millis : public RealTimeClock { public: boolean begin(void); boolean begin(const DateTime &dt); @@ -286,7 +286,7 @@ class RTC_Millis : public RTC { approximately 71.6 minutes. */ /**************************************************************************/ -class RTC_Micros : public RTC { +class RTC_Micros : public RealTimeClock { public: boolean begin(void); boolean begin(const DateTime &dt); diff --git a/keywords.txt b/keywords.txt index 12c26320..46bc0e9b 100644 --- a/keywords.txt +++ b/keywords.txt @@ -8,7 +8,7 @@ DateTime KEYWORD1 TimeSpan KEYWORD1 -RTC_Super KEYWORD1 +RealTimeClock KEYWORD1 RTC_DS1307 KEYWORD1 RTC_DS3231 KEYWORD1 RTC_PCF8523 KEYWORD1 diff --git a/utility/RTC_Base.h b/utility/RTC_Base.h index 401ffbea..f1628719 100644 --- a/utility/RTC_Base.h +++ b/utility/RTC_Base.h @@ -1,6 +1,6 @@ /**************************************************************************/ /*! - @file RTC_Super.h + @file RTC_Base.h Original library by JeeLabs http://news.jeelabs.org/code/, released to the public domain @@ -19,8 +19,8 @@ */ /**************************************************************************/ -#ifndef _RTC_SUPER_H_ -#define _RTC_SUPER_H_ +#ifndef _RTC_BASE_H +#define _RTC_BASE_H #include "DateTime.h" #include @@ -30,7 +30,7 @@ @brief RTC base class for all RTC chips */ /**************************************************************************/ -class RTC_Base { +class RealTimeClock { public: /*! @brief Start the RTC while preserving the RTC's date/time From 3151cf7525032e1647fb3d36a71cfab5b88fc64e Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Sun, 3 Jan 2021 09:21:34 +0800 Subject: [PATCH 37/43] Wrote note for RealTimeClock class --- utility/RTC_Base.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utility/RTC_Base.h b/utility/RTC_Base.h index f1628719..9f4d5900 100644 --- a/utility/RTC_Base.h +++ b/utility/RTC_Base.h @@ -28,6 +28,8 @@ /**************************************************************************/ /*! @brief RTC base class for all RTC chips + @note Called RealTimeClock as there is already a macro called RTC in + Arduino IDE install files */ /**************************************************************************/ class RealTimeClock { From b8d8b77df29b67e33930b81530ba37eee087e562 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Sun, 3 Jan 2021 11:59:14 +0800 Subject: [PATCH 38/43] Changed ppm to non-const --- RTClib.cpp | 2 +- RTClib.h | 2 +- utility/RTC_Base.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index 03a310bb..0b3cc412 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -422,7 +422,7 @@ void RTC_Micros::adjust(const DateTime &dt) { @note Positive values make the clock faster and vice-versa */ /**************************************************************************/ -void RTC_Micros::adjustDrift(const int ppm) { +void RTC_Micros::adjustDrift(int ppm) { microsPerSecond = 1000000L - ppm; } diff --git a/RTClib.h b/RTClib.h index 08c48ce9..92a61121 100644 --- a/RTClib.h +++ b/RTClib.h @@ -301,7 +301,7 @@ class RTC_Micros : public RealTimeClock { */ boolean lostPower(void) { return false; } void adjust(const DateTime &dt); - void adjustDrift(const int ppm); + void adjustDrift(int ppm); DateTime now(); protected: diff --git a/utility/RTC_Base.h b/utility/RTC_Base.h index 9f4d5900..0a036384 100644 --- a/utility/RTC_Base.h +++ b/utility/RTC_Base.h @@ -59,7 +59,7 @@ class RealTimeClock { @param ppm Parts per million to adjust clock speed by @note Positive values make the clock faster and vice-versa */ - virtual void adjustDrift(const int ppm); + virtual void adjustDrift(int ppm); /*! @brief Check if the RTC is running or not From 266cc6867b4127ee2f0fa39c32aa59eb86badcc0 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Mon, 4 Jan 2021 22:04:18 +0800 Subject: [PATCH 39/43] Made lostPower() virtual in base class --- utility/RTC_Base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utility/RTC_Base.h b/utility/RTC_Base.h index 0a036384..5280b60a 100644 --- a/utility/RTC_Base.h +++ b/utility/RTC_Base.h @@ -71,7 +71,7 @@ class RealTimeClock { @brief Check if the RTC has lost power since last adjust() @return True if the RTC has lost power, false otherwise */ - boolean lostPower(void); + virtual boolean lostPower(void); /*! @brief Get the current date/time from the RTC From 84fbf611d58584cffd080f515b9c23640c7d67d3 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Mon, 4 Jan 2021 22:07:24 +0800 Subject: [PATCH 40/43] Commented out adjustDrift() for future versions --- utility/RTC_Base.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utility/RTC_Base.h b/utility/RTC_Base.h index 5280b60a..d27cc2a2 100644 --- a/utility/RTC_Base.h +++ b/utility/RTC_Base.h @@ -53,13 +53,14 @@ class RealTimeClock { */ virtual void adjust(const DateTime &dt) = 0; - /*! + /* @brief Adjust the RTC clock speed to compensate for system clock drift @param ppm Parts per million to adjust clock speed by @note Positive values make the clock faster and vice-versa + @todo Implement function in future version */ - virtual void adjustDrift(int ppm); + //virtual void adjustDrift(int ppm); /*! @brief Check if the RTC is running or not From ad857534e7facefd530cf3daed49c10c2fdaab8b Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 5 Jan 2021 19:25:04 +0800 Subject: [PATCH 41/43] Fixed clang formatting issue --- utility/RTC_Base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utility/RTC_Base.h b/utility/RTC_Base.h index d27cc2a2..8cc8ef43 100644 --- a/utility/RTC_Base.h +++ b/utility/RTC_Base.h @@ -60,7 +60,7 @@ class RealTimeClock { @note Positive values make the clock faster and vice-versa @todo Implement function in future version */ - //virtual void adjustDrift(int ppm); + // virtual void adjustDrift(int ppm); /*! @brief Check if the RTC is running or not From 5cee6bacc60b93f5304cf5bff520c000de430b20 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Tue, 5 Jan 2021 19:43:49 +0800 Subject: [PATCH 42/43] Fixed clang formatting issue --- RTClib.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/RTClib.cpp b/RTClib.cpp index 0b3cc412..87dc3a64 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -422,9 +422,7 @@ void RTC_Micros::adjust(const DateTime &dt) { @note Positive values make the clock faster and vice-versa */ /**************************************************************************/ -void RTC_Micros::adjustDrift(int ppm) { - microsPerSecond = 1000000L - ppm; -} +void RTC_Micros::adjustDrift(int ppm) { microsPerSecond = 1000000L - ppm; } /**************************************************************************/ /*! From a5a037dc0d7beca5edd46ecbd8378ffbbfa4ef55 Mon Sep 17 00:00:00 2001 From: Harrison-O Date: Thu, 7 Jan 2021 18:11:38 +0800 Subject: [PATCH 43/43] Fixed clang formatting issue --- RTClib.h | 1 - 1 file changed, 1 deletion(-) diff --git a/RTClib.h b/RTClib.h index 92a61121..5ad08db8 100644 --- a/RTClib.h +++ b/RTClib.h @@ -22,7 +22,6 @@ #ifndef _RTCLIB_H_ #define _RTCLIB_H_ -#include "utility/TimeSpan.h" #include "utility/DateTime.h" #include "utility/RTC_Base.h" #include