MCP7940  v1.2.0
Arduino Library for the MCP7940N and MCP7940M Real-time clocks
MCP7940.h
Go to the documentation of this file.
1 // clang-format off
100 // clang-format on
101 
102 #include "Arduino.h" // Arduino data type definitions
103 #include "Wire.h" // Standard I2C "Wire" library
104 #ifndef MCP7940_h
105 
106  #define MCP7940_h // Define the name inside guard code
107 /***************************************************************************************************
108 ** Declare classes used in within the class **
109 ***************************************************************************************************/
110 class TimeSpan;
111  /***************************************************************************************************
112  ** Declare constants used in the class **
113  ***************************************************************************************************/
114  #ifndef I2C_MODES // I2C related constants
115 
116  #define I2C_MODES
117 const uint32_t I2C_STANDARD_MODE{100000};
118 const uint32_t I2C_FAST_MODE{400000};
119  #endif
120  #if !defined(BUFFER_LENGTH) // The ESP32 Wire library doesn't currently define BUFFER_LENGTH
121 
122  #define BUFFER_LENGTH 32
123  #endif
124 
125 const uint8_t MCP7940_ADDRESS{0x6F};
126 const uint8_t MCP7940_EUI_ADDRESS{0x57};
127 const uint8_t MCP7940_RTCSEC{0x00};
128 const uint8_t MCP7940_RTCMIN{0x01};
129 const uint8_t MCP7940_RTCHOUR{0x02};
130 const uint8_t MCP7940_RTCWKDAY{0x03};
131 const uint8_t MCP7940_RTCDATE{0x04};
132 const uint8_t MCP7940_RTCMTH{0x05};
133 const uint8_t MCP7940_RTCYEAR{0x06};
134 const uint8_t MCP7940_CONTROL{0x07};
135 const uint8_t MCP7940_OSCTRIM{0x08};
136 const uint8_t MCP7940_EEUNLOCK{0x09};
137 const uint8_t MCP7940_ALM0SEC{0x0A};
138 const uint8_t MCP7940_ALM0MIN{0x0B};
139 const uint8_t MCP7940_ALM0HOUR{0x0C};
140 const uint8_t MCP7940_ALM0WKDAY{0x0D};
141 const uint8_t MCP7940_ALM0DATE{0x0E};
142 const uint8_t MCP7940_ALM0MTH{0x0F};
143 const uint8_t MCP7940_ALM1SEC{0x11};
144 const uint8_t MCP7940_ALM1MIN{0x12};
145 const uint8_t MCP7940_ALM1HOUR{0x13};
146 const uint8_t MCP7940_ALM1WKDAY{0x14};
147 const uint8_t MCP7940_ALM1DATE{0x15};
148 const uint8_t MCP7940_ALM1MTH{0x16};
149 const uint8_t MCP7940_PWRDNMIN{0x18};
150 const uint8_t MCP7940_PWRDNHOUR{0x19};
151 const uint8_t MCP7940_PWRDNDATE{0x1A};
152 const uint8_t MCP7940_PWRDNMTH{0x1B};
153 const uint8_t MCP7940_PWRUPMIN{0x1C};
154 const uint8_t MCP7940_PWRUPHOUR{0x1D};
155 const uint8_t MCP7940_PWRUPDATE{0x1E};
156 const uint8_t MCP7940_PWRUPMTH{0x1F};
157 const uint8_t MCP7940_RAM_ADDRESS{0x20};
158 const uint8_t MCP7940_EUI_RAM_ADDRESS{0xF0};
159 const uint8_t MCP7940_ST{7};
160 const uint8_t MCP7940_12_24{6};
161 const uint8_t MCP7940_AM_PM{5};
162 const uint8_t MCP7940_OSCRUN{5};
163 const uint8_t MCP7940_PWRFAIL{4};
164 const uint8_t MCP7940_VBATEN{3};
165 const uint8_t MCP7940_LPYR{5};
166 const uint8_t MCP7940_OUT{7};
167 const uint8_t MCP7940_SQWEN{6};
168 const uint8_t MCP7940_ALM1EN{5};
169 const uint8_t MCP7940_ALM0EN{4};
170 const uint8_t MCP7940_EXTOSC{3};
171 const uint8_t MCP7940_CRSTRIM{2};
172 const uint8_t MCP7940_SQWFS1{1};
173 const uint8_t MCP7940_SQWFS0{0};
174 const uint8_t MCP7940_SIGN{7};
175 const uint8_t MCP7940_ALMPOL{7};
176 const uint8_t MCP7940_ALM0IF{3};
177 const uint8_t MCP7940_ALM1IF{3};
178 const uint32_t SECS_1970_TO_2000{946684800};
179 
180 class DateTime {
187  public:
188  DateTime(uint32_t t = SECS_1970_TO_2000);
189  DateTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour = 0, uint8_t min = 0,
190  uint8_t sec = 0);
191  DateTime(const DateTime& copy);
192  DateTime(const char* date, const char* time);
193  DateTime(const __FlashStringHelper* date, const __FlashStringHelper* time);
194  uint16_t year() const {
195  return 2000U + yOff;
196  }
197  uint8_t month() const {
198  return m;
199  }
200  uint8_t day() const {
201  return d;
202  }
203  uint8_t hour() const {
204  return hh;
205  }
206  uint8_t minute() const {
207  return mm;
208  }
209  uint8_t second() const {
210  return ss;
211  }
212  uint8_t dayOfTheWeek() const;
213  long secondstime() const;
214  uint32_t unixtime(void) const;
215  bool equals(const DateTime* other);
216  DateTime operator+(const TimeSpan& span);
217  DateTime operator-(const TimeSpan& span);
219  const DateTime& right);
220  protected:
221  uint8_t yOff;
222  uint8_t m;
223  uint8_t d;
224  uint8_t hh;
225  uint8_t mm;
226  uint8_t ss;
227 }; // of class DateTime definition
228 class TimeSpan {
235  public:
236  TimeSpan(int32_t seconds = 0);
237  TimeSpan(int16_t days, int8_t hours, int8_t minutes, int8_t seconds);
238  TimeSpan(const TimeSpan& copy);
239  int16_t days() const { return _seconds / 86400L; }
240  int8_t hours() const { return _seconds / 3600 % 24; }
241  int8_t minutes() const { return _seconds / 60 % 60; }
242  int8_t seconds() const { return _seconds % 60; }
243  int32_t totalseconds() const { return _seconds; }
244  TimeSpan operator+(const TimeSpan& right);
245  TimeSpan operator-(const TimeSpan& right);
246  protected:
247  int32_t _seconds;
248 }; // of class TimeSpan definition
249 
255  public:
256  MCP7940_Class(){};
258  bool begin(const uint32_t i2cSpeed) const;
259  bool begin(const uint8_t sda = SDA, const uint8_t scl = SCL,
260  const uint32_t i2cSpeed = I2C_STANDARD_MODE) const;
261  bool deviceStatus() const;
262  bool deviceStart() const;
263  bool deviceStop() const;
264  DateTime now() const;
265  void adjust();
266  void adjust(const DateTime& dt);
267  int8_t calibrate() const;
268  int8_t calibrate(const int8_t newTrim);
269  int8_t calibrate(const DateTime& dt);
270  int8_t calibrate(const float fMeas) const;
271  int8_t getCalibrationTrim() const;
272  uint8_t weekdayRead() const;
273  uint8_t weekdayWrite(const uint8_t dow) const;
274  bool setMFP(const bool value) const;
275  uint8_t getMFP() const;
276  bool setAlarm(const uint8_t alarmNumber, const uint8_t alarmType, const DateTime& dt,
277  const bool state = true) const;
278  void setAlarmPolarity(const bool polarity) const;
279  DateTime getAlarm(const uint8_t alarmNumber, uint8_t& alarmType) const;
280  bool clearAlarm(const uint8_t alarmNumber) const;
281  bool setAlarmState(const uint8_t alarmNumber, const bool state) const;
282  bool getAlarmState(const uint8_t alarmNumber) const;
283  bool isAlarm(const uint8_t alarmNumber) const;
284  uint8_t getSQWSpeed() const;
285  bool setSQWSpeed(uint8_t frequency, bool state = true) const;
286  bool setSQWState(const bool state) const;
287  bool getSQWState() const;
288  bool setBattery(const bool state) const;
289  bool getBattery() const;
290  bool getPowerFail() const;
291  bool clearPowerFail() const;
292  DateTime getPowerDown() const;
293  DateTime getPowerUp() const;
294  int8_t calibrateOrAdjust(const DateTime& dt);
295  int32_t getPPMDeviation(const DateTime& dt) const;
296  void setSetUnixTime(uint32_t aTime);
297  uint32_t getSetUnixTime() const;
298 
299  /*************************************************************************************************
300  ** Template functions definitions are done in the header file **
301  ** ============================================================================================ **
302  ** readRAM read any number of bytes from the MCP7940 SRAM area **
303  ** writRAM write any number of bytes to the MCP7940 SRAM area **
304  ** readEUI read any number of bytes from the special protected SRAM area for 79400/401/402 **
305  *************************************************************************************************/
306  template <typename T>
307  uint8_t readRAM(const uint8_t& addr, T& value) const {
315  return I2C_read((addr % 64) + MCP7940_RAM_ADDRESS, value);
316  } // of method readRAM()
317  template <typename T>
318  uint8_t writeRAM(const uint8_t& addr, const T& value) const {
326  uint8_t i = I2C_write((addr % 64) + MCP7940_RAM_ADDRESS, value);
327  return i;
328  } // of method writeRAM()
329  template <typename T>
330  uint8_t readEUI(const uint8_t& addr, T& value) const {
339  uint8_t i{0}; // return number of bytes read
340  Wire.beginTransmission(MCP7940_EUI_ADDRESS); // Address the special I2C address
341  Wire.write((addr % 8) + MCP7940_EUI_RAM_ADDRESS); // Send register address to read from
342  if (Wire.endTransmission() == 0) { // Close transmission and check error code
343  Wire.requestFrom(MCP7940_EUI_ADDRESS, sizeof(T)); // Request a block of data, max 61 bits
344  uint8_t* bytePtr = (uint8_t*)&value; // Declare pointer to start of structure
345  for (i = 0; i < sizeof(T); i++) { // Loop for each byte to be read
346  *bytePtr++ = Wire.read(); // Read a byte
347  } // of for-next each byte
348  } // if-then success
349  return i; // return number of bytes read
350  } // of method readEUI()
351  template <typename T>
352  uint8_t writeEUI(const uint8_t& addr, T& value) const {
362  uint8_t i{0}; // return number of bytes read
363  Wire.beginTransmission(MCP7940_EUI_ADDRESS); // Address the special I2C address
364  Wire.write(MCP7940_EEUNLOCK); // Send special register address to write to
365  Wire.write(0x55); // Special write value to start unlock
366  i = Wire.endTransmission(); // close transmission of first byte
367  Wire.beginTransmission(MCP7940_EUI_ADDRESS); // Address the special I2C address
368  Wire.write(MCP7940_EEUNLOCK); // Send special register address to write to
369  Wire.write(0x55); // Special write value to complete unlock
370  i = Wire.endTransmission(); // close transmission of second byte
371  Wire.beginTransmission(MCP7940_EUI_ADDRESS); // Address the special I2C address
372  Wire.write((addr % 8) + MCP7940_EUI_RAM_ADDRESS); // Send register address to read from
373  Wire.write((uint8_t*)&value, sizeof(T)); // write the data
374  i = Wire.endTransmission(); // close transmission of actual write
375  if (i == 0) i = sizeof(T); // return number of bytes on success
376  return i; // return number of bytes read
377  } // of method writeEUI()
378 
379  private:
380  uint32_t _SetUnixTime{0};
381  /*************************************************************************************************
382  ** Template functions definitions are done in the header file **
383  ** ============================================================================================ **
384  ** **
385  ** I2C_read read any number of bytes from the MCP7940 **
386  ** I2C_write write any number of bytes to the MCP7940 **
387  *************************************************************************************************/
388  template <typename T>
389  uint8_t I2C_read(const uint8_t address, T& value) const {
400  uint8_t i{0}; // return number of bytes read
401  Wire.beginTransmission(MCP7940_ADDRESS); // Address the I2C device
402  Wire.write(address); // Send register address to read from
403  if (Wire.endTransmission() == 0) { // Close transmission and check error code
404  Wire.requestFrom(MCP7940_ADDRESS, sizeof(T)); // Request a block of data
405  uint8_t* bytePtr = (uint8_t*)&value; // Declare pointer to start of structure
406  for (i = 0; i < sizeof(T); i++) { // Loop for each byte to be read
407  *bytePtr++ = Wire.read(); // Read a byte
408  } // of for-next each byte
409  } // if-then success
410  return i; // return number of bytes read
411  } // end of template method "I2C_read"
412  template <typename T>
413  uint8_t I2C_write(const uint8_t address, const T& value) const {
423  Wire.beginTransmission(MCP7940_ADDRESS); // Address the I2C device
424  Wire.write(address); // Send register address to read from
425  Wire.write((uint8_t*)&value, sizeof(T)); // write the data
426  uint8_t i = Wire.endTransmission(); // close transmission and save status
427  if (i == 0) i = sizeof(T); // return number of bytes on success
428  return i; // return the number of bytes written
429  } // end of template method "I2C_write()"
430  uint8_t readByte(const uint8_t addr) const; // Read 1 byte from address on I2C
431  uint8_t bcd2int(const uint8_t bcd) const; // convert BCD digits to integer
432  uint8_t int2bcd(const uint8_t dec) const; // convert integer to BCD
433  void clearRegisterBit(const uint8_t reg, const uint8_t b) const; // Clear a bit, values 0-7
434  void setRegisterBit(const uint8_t reg, const uint8_t b) const; // Set a bit, values 0-7
435  void writeRegisterBit(const uint8_t reg, const uint8_t b,
436  bool bitvalue) const; // Clear a bit, values 0-7
437  uint8_t readRegisterBit(const uint8_t reg, const uint8_t b) const; // Read a bit, values 0-7
438 }; // of MCP7940 class definition
439 #endif
const uint8_t MCP7940_PWRDNHOUR
Power-Fail, PWRDNHOUR Register address.
Definition: MCP7940.h:150
const uint8_t MCP7940_EUI_RAM_ADDRESS
EUI - Start address for protected EEPROM.
Definition: MCP7940.h:158
const uint8_t MCP7940_CONTROL
Timekeeping, RTCCONTROL Register address.
Definition: MCP7940.h:134
DateTime(uint32_t t=SECS_1970_TO_2000)
Definition: MCP7940.cpp:56
const uint32_t I2C_FAST_MODE
Fast mode.
Definition: MCP7940.h:118
const uint8_t MCP7940_PWRDNDATE
Power-Fail, PWDNDATE Register address.
Definition: MCP7940.h:151
uint8_t ss
Internal seconds.
Definition: MCP7940.h:226
const uint8_t MCP7940_RTCDATE
Timekeeping, RTCDATE Register address.
Definition: MCP7940.h:131
const uint8_t MCP7940_LPYR
RTCMTH register.
Definition: MCP7940.h:165
uint8_t writeRAM(const uint8_t &addr, const T &value) const
Definition: MCP7940.h:318
const uint8_t MCP7940_SIGN
OSCTRIM register.
Definition: MCP7940.h:174
DateTime operator-(const TimeSpan &span)
Definition: MCP7940.cpp:204
const uint8_t MCP7940_ALM0MIN
Alarm 0, ALM0MIN Register address.
Definition: MCP7940.h:138
uint8_t d
Internal day value.
Definition: MCP7940.h:223
const uint8_t MCP7940_12_24
RTCHOUR, PWRDNHOUR & PWRUPHOUR.
Definition: MCP7940.h:160
Simple general-purpose date/time class.
Definition: MCP7940.h:180
const uint8_t MCP7940_OSCRUN
RTCWKDAY register.
Definition: MCP7940.h:162
const uint8_t MCP7940_RTCSEC
Timekeeping, RTCSEC Register address.
Definition: MCP7940.h:127
const uint8_t MCP7940_ALM1MTH
Alarm 1, ALM1MONTH Register address.
Definition: MCP7940.h:148
uint8_t dayOfTheWeek() const
Definition: MCP7940.cpp:158
const uint8_t MCP7940_ALM0SEC
Alarm 0, ALM0SEC Register address.
Definition: MCP7940.h:137
const uint8_t MCP7940_ALM0HOUR
Alarm 0, ALM0HOUR Register address.
Definition: MCP7940.h:139
const uint8_t MCP7940_ALM0DATE
Alarm 0, ALM0DATE Register address.
Definition: MCP7940.h:141
const uint8_t MCP7940_EEUNLOCK
Virtual unlock register on MCP7940x series.
Definition: MCP7940.h:136
const uint8_t MCP7940_SQWEN
CONTROL register.
Definition: MCP7940.h:167
const uint8_t MCP7940_SQWFS0
CONTROL register.
Definition: MCP7940.h:173
uint8_t day() const
Definition: MCP7940.h:200
const uint8_t MCP7940_OUT
CONTROL register.
Definition: MCP7940.h:166
uint8_t month() const
Definition: MCP7940.h:197
const uint8_t MCP7940_ALM1HOUR
Alarm 1, ALM1HOUR Register address.
Definition: MCP7940.h:145
const uint8_t MCP7940_RTCWKDAY
Timekeeping, RTCWKDAY Register address.
Definition: MCP7940.h:130
const uint8_t MCP7940_CRSTRIM
CONTROL register.
Definition: MCP7940.h:171
uint8_t readEUI(const uint8_t &addr, T &value) const
Definition: MCP7940.h:330
const uint8_t MCP7940_PWRUPMTH
Power-Fail, PWRUPMTH Register address.
Definition: MCP7940.h:156
const uint8_t MCP7940_EXTOSC
CONTROL register.
Definition: MCP7940.h:170
bool equals(const DateTime *other)
Definition: MCP7940.cpp:189
const uint8_t MCP7940_PWRUPMIN
Power-Fail, PWRUPMIN Register address.
Definition: MCP7940.h:153
const uint8_t MCP7940_PWRUPDATE
Power-Fail, PWRUPDATE Register address.
Definition: MCP7940.h:155
int32_t _seconds
Internal value for total seconds.
Definition: MCP7940.h:247
uint8_t second() const
Definition: MCP7940.h:209
const uint8_t MCP7940_RTCYEAR
Timekeeping, RTCYEAR Register address.
Definition: MCP7940.h:133
const uint8_t MCP7940_RTCHOUR
Timekeeping, RTCHOUR Register address.
Definition: MCP7940.h:129
const uint8_t MCP7940_PWRDNMIN
Power-Fail, PWRDNMIN Register address.
Definition: MCP7940.h:149
const uint8_t MCP7940_ALM0MTH
Alarm 0, ALM0MTH Register address.
Definition: MCP7940.h:142
uint8_t readRAM(const uint8_t &addr, T &value) const
Definition: MCP7940.h:307
long secondstime() const
Definition: MCP7940.cpp:180
uint8_t hour() const
Definition: MCP7940.h:203
const uint8_t MCP7940_OSCTRIM
Timekeeping, RTCOSCTRIM Register address.
Definition: MCP7940.h:135
const uint8_t MCP7940_PWRDNMTH
Power-Fail, PWRDNMTH Register address.
Definition: MCP7940.h:152
~MCP7940_Class()
Unused Class constructor.
Definition: MCP7940.h:257
const uint8_t MCP7940_ALM1EN
CONTROL register.
Definition: MCP7940.h:168
const uint8_t MCP7940_ALM1SEC
Alarm 1, ALM1SEC Register address.
Definition: MCP7940.h:143
int8_t minutes() const
return number of minutes
Definition: MCP7940.h:241
const uint32_t SECS_1970_TO_2000
Seconds between year 1970 and 2000.
Definition: MCP7940.h:178
uint32_t unixtime(void) const
Definition: MCP7940.cpp:170
uint8_t writeEUI(const uint8_t &addr, T &value) const
Definition: MCP7940.h:352
const uint8_t MCP7940_ALM0IF
ALM0WKDAY register.
Definition: MCP7940.h:176
Main class definition with forward declarations.
Definition: MCP7940.h:250
int8_t seconds() const
return number of seconds
Definition: MCP7940.h:242
const uint8_t MCP7940_AM_PM
RTCHOUR, PWRDNHOUR & PWRUPHOUR.
Definition: MCP7940.h:161
uint8_t m
Internal month value.
Definition: MCP7940.h:222
DateTime operator+(const TimeSpan &span)
Definition: MCP7940.cpp:197
const uint8_t MCP7940_VBATEN
RTCWKDAY register.
Definition: MCP7940.h:164
int8_t hours() const
return number of hours
Definition: MCP7940.h:240
const uint32_t I2C_STANDARD_MODE
Default normal I2C 100KHz speed.
Definition: MCP7940.h:117
const uint8_t MCP7940_PWRUPHOUR
Power-Fail, PWRUPHOUR Register address.
Definition: MCP7940.h:154
const uint8_t MCP7940_RTCMTH
Timekeeping, RTCMTH Register address.
Definition: MCP7940.h:132
const uint8_t MCP7940_ST
MCP7940 register bits. RTCSEC reg.
Definition: MCP7940.h:159
const uint8_t MCP7940_ALM1DATE
Alarm 1, ALM1DATE Register address.
Definition: MCP7940.h:147
int16_t days() const
return the number of days
Definition: MCP7940.h:239
uint8_t minute() const
Definition: MCP7940.h:206
const uint8_t MCP7940_RAM_ADDRESS
NVRAM - Start address for SRAM.
Definition: MCP7940.h:157
Timespan class which can represent changes in time with seconds accuracy.
Definition: MCP7940.h:228
uint16_t year() const
Definition: MCP7940.h:194
uint8_t hh
Internal hour value.
Definition: MCP7940.h:224
uint8_t mm
Internal minute value.
Definition: MCP7940.h:225
uint8_t yOff
Internal year offset value.
Definition: MCP7940.h:221
const uint8_t MCP7940_ADDRESS
Fixed I2C address, fixed.
Definition: MCP7940.h:125
const uint8_t MCP7940_ALM0WKDAY
Alarm 0, ALM0WKDAY Register address.
Definition: MCP7940.h:140
const uint8_t MCP7940_ALM1IF
ALM1WKDAY register.
Definition: MCP7940.h:177
const uint8_t MCP7940_PWRFAIL
RTCWKDAY register.
Definition: MCP7940.h:163
const uint8_t MCP7940_SQWFS1
CONTROL register.
Definition: MCP7940.h:172
const uint8_t MCP7940_ALMPOL
ALM0WKDAY register.
Definition: MCP7940.h:175
int32_t totalseconds() const
return total number of seconds
Definition: MCP7940.h:243
const uint8_t MCP7940_ALM1MIN
Alarm 1, ALM1MIN Register address.
Definition: MCP7940.h:144
const uint8_t MCP7940_ALM0EN
CONTROL register.
Definition: MCP7940.h:169
const uint8_t MCP7940_RTCMIN
Timekeeping, RTCMIN Register address.
Definition: MCP7940.h:128
const uint8_t MCP7940_EUI_ADDRESS
Fixed I2C address for accessing protected ROM.
Definition: MCP7940.h:126
const uint8_t MCP7940_ALM1WKDAY
Alarm 1, ALM1WKDAY Register address.
Definition: MCP7940.h:146