mirror of
https://github.com/adafruit/RTClib.git
synced 2026-07-28 04:05:31 +00:00
Merge pull request #244 from caternuson/iss243_busio
Convert to BusIO and refactor
This commit is contained in:
@@ -44,7 +44,7 @@ STM32F2 | | | X |
|
||||
Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
|
||||
|
||||
# Dependencies
|
||||
* [TinyWireM](https://github.com/adafruit/TinyWireM)
|
||||
* [Adafruit BusIO](https://github.com/adafruit/Adafruit_BusIO)
|
||||
|
||||
# Contributing
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
name=RTClib
|
||||
version=1.14.2
|
||||
version=2.0.0
|
||||
author=Adafruit
|
||||
maintainer=Adafruit <info@adafruit.com>
|
||||
sentence=A fork of Jeelab's fantastic RTC library
|
||||
@@ -7,4 +7,4 @@ paragraph=Works with DS1307, DS3231, PCF8523, PCF8563 on multiple architectures
|
||||
category=Timing
|
||||
url=https://github.com/adafruit/RTClib
|
||||
architectures=*
|
||||
depends=TinyWireM
|
||||
depends=Adafruit BusIO
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
#include "RTClib.h"
|
||||
|
||||
#define DS1307_ADDRESS 0x68 ///< I2C address for DS1307
|
||||
#define DS1307_CONTROL 0x07 ///< Control register
|
||||
#define DS1307_NVRAM 0x08 ///< Start of RAM registers - 56 bytes, 0x08 to 0x3f
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Start I2C for the DS1307 and test succesful connection
|
||||
@param wireInstance pointer to the I2C bus
|
||||
@return True if Wire can find DS1307 or false otherwise.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
boolean RTC_DS1307::begin(TwoWire *wireInstance) {
|
||||
if (i2c_dev)
|
||||
delete i2c_dev;
|
||||
i2c_dev = new Adafruit_I2CDevice(DS1307_ADDRESS, wireInstance);
|
||||
if (!i2c_dev->begin())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Is the DS1307 running? Check the Clock Halt bit in register 0
|
||||
@return 1 if the RTC is running, 0 if not
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint8_t RTC_DS1307::isrunning(void) { return !(read_register(0) >> 7); }
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Set the date and time in the DS1307
|
||||
@param dt DateTime object containing the desired date/time
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_DS1307::adjust(const DateTime &dt) {
|
||||
uint8_t buffer[8] = {0,
|
||||
bin2bcd(dt.second()),
|
||||
bin2bcd(dt.minute()),
|
||||
bin2bcd(dt.hour()),
|
||||
0,
|
||||
bin2bcd(dt.day()),
|
||||
bin2bcd(dt.month()),
|
||||
bin2bcd(dt.year() - 2000U)};
|
||||
i2c_dev->write(buffer, 8);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Get the current date and time from the DS1307
|
||||
@return DateTime object containing the current date and time
|
||||
*/
|
||||
/**************************************************************************/
|
||||
DateTime RTC_DS1307::now() {
|
||||
uint8_t buffer[7];
|
||||
buffer[0] = 0;
|
||||
i2c_dev->write_then_read(buffer, 1, buffer, 7);
|
||||
|
||||
return DateTime(bcd2bin(buffer[6]) + 2000U, bcd2bin(buffer[5]),
|
||||
bcd2bin(buffer[4]), bcd2bin(buffer[2]), bcd2bin(buffer[1]),
|
||||
bcd2bin(buffer[0] & 0x7F));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Read the current mode of the SQW pin
|
||||
@return Mode as Ds1307SqwPinMode enum
|
||||
*/
|
||||
/**************************************************************************/
|
||||
Ds1307SqwPinMode RTC_DS1307::readSqwPinMode() {
|
||||
return static_cast<Ds1307SqwPinMode>(read_register(DS1307_CONTROL) & 0x93);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Change the SQW pin mode
|
||||
@param mode The mode to use
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_DS1307::writeSqwPinMode(Ds1307SqwPinMode mode) {
|
||||
write_register(DS1307_CONTROL, mode);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Read data from the DS1307's NVRAM
|
||||
@param buf Pointer to a buffer to store the data - make sure it's large
|
||||
enough to hold size bytes
|
||||
@param size Number of bytes to read
|
||||
@param address Starting NVRAM address, from 0 to 55
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_DS1307::readnvram(uint8_t *buf, uint8_t size, uint8_t address) {
|
||||
uint8_t addrByte = DS1307_NVRAM + address;
|
||||
i2c_dev->write_then_read(&addrByte, 1, buf, size);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Write data to the DS1307 NVRAM
|
||||
@param address Starting NVRAM address, from 0 to 55
|
||||
@param buf Pointer to buffer containing the data to write
|
||||
@param size Number of bytes in buf to write to NVRAM
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_DS1307::writenvram(uint8_t address, uint8_t *buf, uint8_t size) {
|
||||
uint8_t addrByte = DS1307_NVRAM + address;
|
||||
i2c_dev->write(buf, size, true, &addrByte, 1);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Shortcut to read one byte from NVRAM
|
||||
@param address NVRAM address, 0 to 55
|
||||
@return The byte read from NVRAM
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint8_t RTC_DS1307::readnvram(uint8_t address) {
|
||||
uint8_t data;
|
||||
readnvram(&data, 1, address);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Shortcut to write one byte to NVRAM
|
||||
@param address NVRAM address, 0 to 55
|
||||
@param data One byte to write
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_DS1307::writenvram(uint8_t address, uint8_t data) {
|
||||
writenvram(address, &data, 1);
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
#include "RTClib.h"
|
||||
|
||||
#define DS3231_ADDRESS 0x68 ///< I2C address for DS3231
|
||||
#define DS3231_TIME 0x00 ///< Time register
|
||||
#define DS3231_ALARM1 0x07 ///< Alarm 1 register
|
||||
#define DS3231_ALARM2 0x0B ///< Alarm 2 register
|
||||
#define DS3231_CONTROL 0x0E ///< Control register
|
||||
#define DS3231_STATUSREG 0x0F ///< Status register
|
||||
#define DS3231_TEMPERATUREREG \
|
||||
0x11 ///< Temperature register (high byte - low byte is at 0x12), 10-bit
|
||||
///< temperature value
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Start I2C for the DS3231 and test succesful connection
|
||||
@param wireInstance pointer to the I2C bus
|
||||
@return True if Wire can find DS3231 or false otherwise.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
boolean RTC_DS3231::begin(TwoWire *wireInstance) {
|
||||
if (i2c_dev)
|
||||
delete i2c_dev;
|
||||
i2c_dev = new Adafruit_I2CDevice(DS3231_ADDRESS, wireInstance);
|
||||
if (!i2c_dev->begin())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Check the status register Oscillator Stop Flag to see if the DS3231
|
||||
stopped due to power loss
|
||||
@return True if the bit is set (oscillator stopped) or false if it is
|
||||
running
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool RTC_DS3231::lostPower(void) {
|
||||
return read_register(DS3231_STATUSREG) >> 7;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Set the date and flip the Oscillator Stop Flag
|
||||
@param dt DateTime object containing the date/time to set
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_DS3231::adjust(const DateTime &dt) {
|
||||
uint8_t buffer[8] = {DS3231_TIME,
|
||||
bin2bcd(dt.second()),
|
||||
bin2bcd(dt.minute()),
|
||||
bin2bcd(dt.hour()),
|
||||
bin2bcd(dowToDS3231(dt.dayOfTheWeek())),
|
||||
bin2bcd(dt.day()),
|
||||
bin2bcd(dt.month()),
|
||||
bin2bcd(dt.year() - 2000U)};
|
||||
i2c_dev->write(buffer, 8);
|
||||
|
||||
uint8_t statreg = read_register(DS3231_STATUSREG);
|
||||
statreg &= ~0x80; // flip OSF bit
|
||||
write_register(DS3231_STATUSREG, statreg);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Get the current date/time
|
||||
@return DateTime object with the current date/time
|
||||
*/
|
||||
/**************************************************************************/
|
||||
DateTime RTC_DS3231::now() {
|
||||
uint8_t buffer[7];
|
||||
buffer[0] = 0;
|
||||
i2c_dev->write_then_read(buffer, 1, buffer, 7);
|
||||
|
||||
return DateTime(bcd2bin(buffer[6]) + 2000U, bcd2bin(buffer[5]),
|
||||
bcd2bin(buffer[4]), bcd2bin(buffer[2]), bcd2bin(buffer[1]),
|
||||
bcd2bin(buffer[0] & 0x7F));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Read the SQW pin mode
|
||||
@return Pin mode, see Ds3231SqwPinMode enum
|
||||
*/
|
||||
/**************************************************************************/
|
||||
Ds3231SqwPinMode RTC_DS3231::readSqwPinMode() {
|
||||
int mode;
|
||||
mode = read_register(DS3231_CONTROL) & 0x1C;
|
||||
if (mode & 0x04)
|
||||
mode = DS3231_OFF;
|
||||
return static_cast<Ds3231SqwPinMode>(mode);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Set the SQW pin mode
|
||||
@param mode Desired mode, see Ds3231SqwPinMode enum
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_DS3231::writeSqwPinMode(Ds3231SqwPinMode mode) {
|
||||
uint8_t ctrl = read_register(DS3231_CONTROL);
|
||||
|
||||
ctrl &= ~0x04; // turn off INTCON
|
||||
ctrl &= ~0x18; // set freq bits to 0
|
||||
|
||||
write_register(DS3231_CONTROL, ctrl | mode);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Get the current temperature from the DS3231's temperature sensor
|
||||
@return Current temperature (float)
|
||||
*/
|
||||
/**************************************************************************/
|
||||
float RTC_DS3231::getTemperature() {
|
||||
uint8_t buffer[2] = {DS3231_TEMPERATUREREG, 0};
|
||||
i2c_dev->write_then_read(buffer, 1, buffer, 2);
|
||||
return (float)buffer[0] + (buffer[1] >> 6) * 0.25f;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Set alarm 1 for DS3231
|
||||
@param dt DateTime object
|
||||
@param alarm_mode Desired mode, see Ds3231Alarm1Mode enum
|
||||
@return False if control register is not set, otherwise true
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool RTC_DS3231::setAlarm1(const DateTime &dt, Ds3231Alarm1Mode alarm_mode) {
|
||||
uint8_t ctrl = read_register(DS3231_CONTROL);
|
||||
if (!(ctrl & 0x04)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t A1M1 = (alarm_mode & 0x01) << 7; // Seconds bit 7.
|
||||
uint8_t A1M2 = (alarm_mode & 0x02) << 6; // Minutes bit 7.
|
||||
uint8_t A1M3 = (alarm_mode & 0x04) << 5; // Hour bit 7.
|
||||
uint8_t A1M4 = (alarm_mode & 0x08) << 4; // Day/Date bit 7.
|
||||
uint8_t DY_DT = (alarm_mode & 0x10)
|
||||
<< 2; // Day/Date bit 6. Date when 0, day of week when 1.
|
||||
uint8_t day = (DY_DT) ? dowToDS3231(dt.dayOfTheWeek()) : dt.day();
|
||||
|
||||
uint8_t buffer[5] = {DS3231_ALARM1, uint8_t(bin2bcd(dt.second()) | A1M1),
|
||||
uint8_t(bin2bcd(dt.minute()) | A1M2),
|
||||
uint8_t(bin2bcd(dt.hour()) | A1M3),
|
||||
uint8_t(bin2bcd(day) | A1M4 | DY_DT)};
|
||||
i2c_dev->write(buffer, 5);
|
||||
|
||||
write_register(DS3231_CONTROL, ctrl | 0x01); // AI1E
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Set alarm 2 for DS3231
|
||||
@param dt DateTime object
|
||||
@param alarm_mode Desired mode, see Ds3231Alarm2Mode enum
|
||||
@return False if control register is not set, otherwise true
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool RTC_DS3231::setAlarm2(const DateTime &dt, Ds3231Alarm2Mode alarm_mode) {
|
||||
uint8_t ctrl = read_register(DS3231_CONTROL);
|
||||
if (!(ctrl & 0x04)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t A2M2 = (alarm_mode & 0x01) << 7; // Minutes bit 7.
|
||||
uint8_t A2M3 = (alarm_mode & 0x02) << 6; // Hour bit 7.
|
||||
uint8_t A2M4 = (alarm_mode & 0x04) << 5; // Day/Date bit 7.
|
||||
uint8_t DY_DT = (alarm_mode & 0x08)
|
||||
<< 3; // Day/Date bit 6. Date when 0, day of week when 1.
|
||||
uint8_t day = (DY_DT) ? dowToDS3231(dt.dayOfTheWeek()) : dt.day();
|
||||
|
||||
uint8_t buffer[4] = {DS3231_ALARM2, uint8_t(bin2bcd(dt.minute()) | A2M2),
|
||||
uint8_t(bin2bcd(dt.hour()) | A2M3),
|
||||
uint8_t(bin2bcd(day) | A2M4 | DY_DT)};
|
||||
i2c_dev->write(buffer, 4);
|
||||
|
||||
write_register(DS3231_CONTROL, ctrl | 0x02); // AI2E
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Disable alarm
|
||||
@param alarm_num Alarm number to disable
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_DS3231::disableAlarm(uint8_t alarm_num) {
|
||||
uint8_t ctrl = read_register(DS3231_CONTROL);
|
||||
ctrl &= ~(1 << (alarm_num - 1));
|
||||
write_register(DS3231_CONTROL, ctrl);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Clear status of alarm
|
||||
@param alarm_num Alarm number to clear
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_DS3231::clearAlarm(uint8_t alarm_num) {
|
||||
uint8_t status = read_register(DS3231_STATUSREG);
|
||||
status &= ~(0x1 << (alarm_num - 1));
|
||||
write_register(DS3231_STATUSREG, status);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Get status of alarm
|
||||
@param alarm_num Alarm number to check status of
|
||||
@return True if alarm has been fired otherwise false
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool RTC_DS3231::alarmFired(uint8_t alarm_num) {
|
||||
return (read_register(DS3231_STATUSREG) >> (alarm_num - 1)) & 0x1;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Enable 32KHz Output
|
||||
@details The 32kHz output is enabled by default. It requires an external
|
||||
pull-up resistor to function correctly
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_DS3231::enable32K(void) {
|
||||
uint8_t status = read_register(DS3231_STATUSREG);
|
||||
status |= (0x1 << 0x03);
|
||||
write_register(DS3231_STATUSREG, status);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Disable 32KHz Output
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_DS3231::disable32K(void) {
|
||||
uint8_t status = read_register(DS3231_STATUSREG);
|
||||
status &= ~(0x1 << 0x03);
|
||||
write_register(DS3231_STATUSREG, status);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Get status of 32KHz Output
|
||||
@return True if enabled otherwise false
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool RTC_DS3231::isEnabled32K(void) {
|
||||
return (read_register(DS3231_STATUSREG) >> 0x03) & 0x01;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "RTClib.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Set the current date/time of the RTC_Micros clock.
|
||||
@param dt DateTime object with the desired date and time
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_Micros::adjust(const DateTime &dt) {
|
||||
lastMicros = micros();
|
||||
lastUnix = dt.unixtime();
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Adjust the RTC_Micros clock to compensate for system clock drift
|
||||
@param ppm Adjustment to make. A positive adjustment makes the clock faster.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_Micros::adjustDrift(int ppm) { microsPerSecond = 1000000 - ppm; }
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Get the current date/time from the RTC_Micros clock.
|
||||
@return DateTime object containing the current date/time
|
||||
*/
|
||||
/**************************************************************************/
|
||||
DateTime RTC_Micros::now() {
|
||||
uint32_t elapsedSeconds = (micros() - lastMicros) / microsPerSecond;
|
||||
lastMicros += elapsedSeconds * microsPerSecond;
|
||||
lastUnix += elapsedSeconds;
|
||||
return lastUnix;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "RTClib.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Set the current date/time of the RTC_Millis clock.
|
||||
@param dt DateTime object with the desired date and time
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_Millis::adjust(const DateTime &dt) {
|
||||
lastMillis = millis();
|
||||
lastUnix = dt.unixtime();
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Return a DateTime object containing the current date/time.
|
||||
Note that computing (millis() - lastMillis) is rollover-safe as long
|
||||
as this method is called at least once every 49.7 days.
|
||||
@return DateTime object containing current time
|
||||
*/
|
||||
/**************************************************************************/
|
||||
DateTime RTC_Millis::now() {
|
||||
uint32_t elapsedSeconds = (millis() - lastMillis) / 1000;
|
||||
lastMillis += elapsedSeconds * 1000;
|
||||
lastUnix += elapsedSeconds;
|
||||
return lastUnix;
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
#include "RTClib.h"
|
||||
|
||||
#define PCF8523_ADDRESS 0x68 ///< I2C address for PCF8523
|
||||
#define PCF8523_CLKOUTCONTROL 0x0F ///< Timer and CLKOUT control register
|
||||
#define PCF8523_CONTROL_1 0x00 ///< Control and status register 1
|
||||
#define PCF8523_CONTROL_2 0x01 ///< Control and status register 2
|
||||
#define PCF8523_CONTROL_3 0x02 ///< Control and status register 3
|
||||
#define PCF8523_TIMER_B_FRCTL 0x12 ///< Timer B source clock frequency control
|
||||
#define PCF8523_TIMER_B_VALUE 0x13 ///< Timer B value (number clock periods)
|
||||
#define PCF8523_OFFSET 0x0E ///< Offset register
|
||||
#define PCF8523_STATUSREG 0x03 ///< Status register
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Start I2C for the PCF8523 and test succesful connection
|
||||
@param wireInstance pointer to the I2C bus
|
||||
@return True if Wire can find PCF8523 or false otherwise.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
boolean RTC_PCF8523::begin(TwoWire *wireInstance) {
|
||||
if (i2c_dev)
|
||||
delete i2c_dev;
|
||||
i2c_dev = new Adafruit_I2CDevice(PCF8523_ADDRESS, wireInstance);
|
||||
if (!i2c_dev->begin())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Check the status register Oscillator Stop flag to see if the PCF8523
|
||||
stopped due to power loss
|
||||
@details When battery or external power is first applied, the PCF8523's
|
||||
crystal oscillator takes up to 2s to stabilize. During this time adjust()
|
||||
cannot clear the 'OS' flag. See datasheet OS flag section for details.
|
||||
@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_PCF8523::lostPower(void) {
|
||||
return read_register(PCF8523_STATUSREG) >> 7;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Check control register 3 to see if we've run adjust() yet (setting
|
||||
the date/time and battery switchover mode)
|
||||
@return True if the PCF8523 has been set up, false if not
|
||||
*/
|
||||
/**************************************************************************/
|
||||
boolean RTC_PCF8523::initialized(void) {
|
||||
return (read_register(PCF8523_CONTROL_3) & 0xE0) != 0xE0;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Set the date and time, set battery switchover mode
|
||||
@param dt DateTime to set
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_PCF8523::adjust(const DateTime &dt) {
|
||||
uint8_t buffer[8] = {3, // start at location 3
|
||||
bin2bcd(dt.second()),
|
||||
bin2bcd(dt.minute()),
|
||||
bin2bcd(dt.hour()),
|
||||
bin2bcd(dt.day()),
|
||||
bin2bcd(0), // skip weekdays
|
||||
bin2bcd(dt.month()),
|
||||
bin2bcd(dt.year() - 2000U)};
|
||||
i2c_dev->write(buffer, 8);
|
||||
|
||||
// set to battery switchover mode
|
||||
write_register(PCF8523_CONTROL_3, 0x00);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Get the current date/time
|
||||
@return DateTime object containing the current date/time
|
||||
*/
|
||||
/**************************************************************************/
|
||||
DateTime RTC_PCF8523::now() {
|
||||
uint8_t buffer[7];
|
||||
buffer[0] = 3;
|
||||
i2c_dev->write_then_read(buffer, 1, buffer, 7);
|
||||
|
||||
return DateTime(bcd2bin(buffer[6]) + 2000U, bcd2bin(buffer[5]),
|
||||
bcd2bin(buffer[3]), bcd2bin(buffer[2]), bcd2bin(buffer[1]),
|
||||
bcd2bin(buffer[0] & 0x7F));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Resets the STOP bit in register Control_1
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_PCF8523::start(void) {
|
||||
uint8_t ctlreg = read_register(PCF8523_CONTROL_1);
|
||||
if (ctlreg & (1 << 5))
|
||||
write_register(PCF8523_CONTROL_1, ctlreg & ~(1 << 5));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Sets the STOP bit in register Control_1
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_PCF8523::stop(void) {
|
||||
write_register(PCF8523_CONTROL_1,
|
||||
read_register(PCF8523_CONTROL_1) | (1 << 5));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Is the PCF8523 running? Check the STOP bit in register Control_1
|
||||
@return 1 if the RTC is running, 0 if not
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint8_t RTC_PCF8523::isrunning() {
|
||||
return !((read_register(PCF8523_CONTROL_1) >> 5) & 1);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Read the mode of the INT/SQW pin on the PCF8523
|
||||
@return SQW pin mode as a #Pcf8523SqwPinMode enum
|
||||
*/
|
||||
/**************************************************************************/
|
||||
Pcf8523SqwPinMode RTC_PCF8523::readSqwPinMode() {
|
||||
int mode = read_register(PCF8523_CLKOUTCONTROL);
|
||||
mode >>= 3;
|
||||
mode &= 0x7;
|
||||
return static_cast<Pcf8523SqwPinMode>(mode);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Set the INT/SQW pin mode on the PCF8523
|
||||
@param mode The mode to set, see the #Pcf8523SqwPinMode enum for options
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_PCF8523::writeSqwPinMode(Pcf8523SqwPinMode mode) {
|
||||
write_register(PCF8523_CLKOUTCONTROL, mode << 3);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Enable the Second Timer (1Hz) Interrupt on the PCF8523.
|
||||
@details The INT/SQW pin will pull low for a brief pulse once per second.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_PCF8523::enableSecondTimer() {
|
||||
uint8_t ctlreg = read_register(PCF8523_CONTROL_1);
|
||||
uint8_t clkreg = read_register(PCF8523_CLKOUTCONTROL);
|
||||
// TAM pulse int. mode (shared with Timer A), CLKOUT (aka SQW) disabled
|
||||
write_register(PCF8523_CLKOUTCONTROL, clkreg | 0xB8);
|
||||
// SIE Second timer int. enable
|
||||
write_register(PCF8523_CONTROL_1, ctlreg | (1 << 2));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Disable the Second Timer (1Hz) Interrupt on the PCF8523.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_PCF8523::disableSecondTimer() {
|
||||
write_register(PCF8523_CONTROL_1,
|
||||
read_register(PCF8523_CONTROL_1) & ~(1 << 2));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Enable the Countdown Timer Interrupt on the PCF8523.
|
||||
@details The INT/SQW pin will be pulled low at the end of a specified
|
||||
countdown period ranging from 244 microseconds to 10.625 days.
|
||||
Uses PCF8523 Timer B. Any existing CLKOUT square wave, configured with
|
||||
writeSqwPinMode(), will halt. The interrupt low pulse width is adjustable
|
||||
from 3/64ths (default) to 14/64ths of a second.
|
||||
@param clkFreq One of the PCF8523's Timer Source Clock Frequencies.
|
||||
See the #PCF8523TimerClockFreq enum for options and associated time ranges.
|
||||
@param numPeriods The number of clkFreq periods (1-255) to count down.
|
||||
@param lowPulseWidth Optional: the length of time for the interrupt pin
|
||||
low pulse. See the #PCF8523TimerIntPulse enum for options.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_PCF8523::enableCountdownTimer(PCF8523TimerClockFreq clkFreq,
|
||||
uint8_t numPeriods,
|
||||
uint8_t lowPulseWidth) {
|
||||
// Datasheet cautions against updating countdown value while it's running,
|
||||
// so disabling allows repeated calls with new values to set new countdowns
|
||||
disableCountdownTimer();
|
||||
|
||||
// Leave compatible settings intact
|
||||
uint8_t ctlreg = read_register(PCF8523_CONTROL_2);
|
||||
uint8_t clkreg = read_register(PCF8523_CLKOUTCONTROL);
|
||||
|
||||
// CTBIE Countdown Timer B Interrupt Enabled
|
||||
write_register(PCF8523_CONTROL_2, ctlreg |= 0x01);
|
||||
|
||||
// Timer B source clock frequency, optionally int. low pulse width
|
||||
write_register(PCF8523_TIMER_B_FRCTL, lowPulseWidth << 4 | clkFreq);
|
||||
|
||||
// Timer B value (number of source clock periods)
|
||||
write_register(PCF8523_TIMER_B_VALUE, numPeriods);
|
||||
|
||||
// TBM Timer B pulse int. mode, CLKOUT (aka SQW) disabled, TBC start Timer B
|
||||
write_register(PCF8523_CLKOUTCONTROL, clkreg | 0x79);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@overload
|
||||
@brief Enable Countdown Timer using default interrupt low pulse width.
|
||||
@param clkFreq One of the PCF8523's Timer Source Clock Frequencies.
|
||||
See the #PCF8523TimerClockFreq enum for options and associated time ranges.
|
||||
@param numPeriods The number of clkFreq periods (1-255) to count down.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_PCF8523::enableCountdownTimer(PCF8523TimerClockFreq clkFreq,
|
||||
uint8_t numPeriods) {
|
||||
enableCountdownTimer(clkFreq, numPeriods, 0);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Disable the Countdown Timer Interrupt on the PCF8523.
|
||||
@details For simplicity, this function strictly disables Timer B by setting
|
||||
TBC to 0. The datasheet describes TBC as the Timer B on/off switch.
|
||||
Timer B is the only countdown timer implemented at this time.
|
||||
The following flags have no effect while TBC is off, they are *not* cleared:
|
||||
- TBM: Timer B will still be set to pulsed mode.
|
||||
- CTBIE: Timer B interrupt would be triggered if TBC were on.
|
||||
- CTBF: Timer B flag indicates that interrupt was triggered. Though
|
||||
typically used for non-pulsed mode, user may wish to query this later.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_PCF8523::disableCountdownTimer() {
|
||||
// TBC disable to stop Timer B clock
|
||||
write_register(PCF8523_CLKOUTCONTROL,
|
||||
~1 & read_register(PCF8523_CLKOUTCONTROL));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Stop all timers, clear their flags and settings on the PCF8523.
|
||||
@details This includes the Countdown Timer, Second Timer, and any CLKOUT
|
||||
square wave configured with writeSqwPinMode().
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_PCF8523::deconfigureAllTimers() {
|
||||
disableSecondTimer(); // Surgically clears CONTROL_1
|
||||
write_register(PCF8523_CONTROL_2, 0);
|
||||
write_register(PCF8523_CLKOUTCONTROL, 0);
|
||||
write_register(PCF8523_TIMER_B_FRCTL, 0);
|
||||
write_register(PCF8523_TIMER_B_VALUE, 0);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Compensate the drift of the RTC.
|
||||
@details This method sets the "offset" register of the PCF8523,
|
||||
which can be used to correct a previously measured drift rate.
|
||||
Two correction modes are available:
|
||||
|
||||
- **PCF8523\_TwoHours**: Clock adjustments are performed on
|
||||
`offset` consecutive minutes every two hours. This is the most
|
||||
energy-efficient mode.
|
||||
|
||||
- **PCF8523\_OneMinute**: Clock adjustments are performed on
|
||||
`offset` consecutive seconds every minute. Extra adjustments are
|
||||
performed on the last second of the minute is `abs(offset)>60`.
|
||||
|
||||
The `offset` parameter sets the correction amount in units of
|
||||
roughly 4 ppm. The exact unit depends on the selected mode:
|
||||
|
||||
| mode | offset unit |
|
||||
|---------------------|----------------------------------------|
|
||||
| `PCF8523_TwoHours` | 4.340 ppm = 0.375 s/day = 2.625 s/week |
|
||||
| `PCF8523_OneMinute` | 4.069 ppm = 0.352 s/day = 2.461 s/week |
|
||||
|
||||
See the accompanying sketch pcf8523.ino for an example on how to
|
||||
use this method.
|
||||
|
||||
@param mode Correction mode, either `PCF8523_TwoHours` or
|
||||
`PCF8523_OneMinute`.
|
||||
@param offset Correction amount, from -64 to +63. A positive offset
|
||||
makes the clock slower.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_PCF8523::calibrate(Pcf8523OffsetMode mode, int8_t offset) {
|
||||
write_register(PCF8523_OFFSET, ((uint8_t)offset & 0x7F) | mode);
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
#include "RTClib.h"
|
||||
|
||||
#define PCF8563_ADDRESS 0x51 ///< I2C address for PCF8563
|
||||
#define PCF8563_CLKOUTCONTROL 0x0D ///< CLKOUT control register
|
||||
#define PCF8563_CONTROL_1 0x00 ///< Control and status register 1
|
||||
#define PCF8563_CONTROL_2 0x01 ///< Control and status register 2
|
||||
#define PCF8563_VL_SECONDS 0x02 ///< register address for VL_SECONDS
|
||||
#define PCF8563_CLKOUT_MASK 0x83 ///< bitmask for SqwPinMode on CLKOUT pin
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Start I2C for the PCF8563 and test succesful connection
|
||||
@param wireInstance pointer to the I2C bus
|
||||
@return True if Wire can find PCF8563 or false otherwise.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
boolean RTC_PCF8563::begin(TwoWire *wireInstance) {
|
||||
if (i2c_dev)
|
||||
delete i2c_dev;
|
||||
i2c_dev = new Adafruit_I2CDevice(PCF8563_ADDRESS, wireInstance);
|
||||
if (!i2c_dev->begin())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Check the status of the VL bit in the VL_SECONDS register.
|
||||
@details The PCF8563 has an on-chip voltage-low detector. When VDD drops
|
||||
below Vlow, bit VL in the VL_seconds register is set to indicate that
|
||||
the integrity of the clock information is no longer guaranteed.
|
||||
@return True if the bit is set (VDD droped below Vlow) indicating that
|
||||
the clock integrity is not guaranteed and false only after the bit is
|
||||
cleared using adjust()
|
||||
*/
|
||||
/**************************************************************************/
|
||||
boolean RTC_PCF8563::lostPower(void) {
|
||||
return read_register(PCF8563_VL_SECONDS) >> 7;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Set the date and time
|
||||
@param dt DateTime to set
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_PCF8563::adjust(const DateTime &dt) {
|
||||
uint8_t buffer[8] = {PCF8563_VL_SECONDS, // start at location 2, VL_SECONDS
|
||||
bin2bcd(dt.second()), bin2bcd(dt.minute()),
|
||||
bin2bcd(dt.hour()), bin2bcd(dt.day()),
|
||||
bin2bcd(0), // skip weekdays
|
||||
bin2bcd(dt.month()), bin2bcd(dt.year() - 2000U)};
|
||||
i2c_dev->write(buffer, 8);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Get the current date/time
|
||||
@return DateTime object containing the current date/time
|
||||
*/
|
||||
/**************************************************************************/
|
||||
DateTime RTC_PCF8563::now() {
|
||||
uint8_t buffer[7];
|
||||
buffer[0] = 3;
|
||||
i2c_dev->write_then_read(buffer, 1, buffer, 7);
|
||||
|
||||
return DateTime(bcd2bin(buffer[6]) + 2000U, bcd2bin(buffer[5] & 0x1F),
|
||||
bcd2bin(buffer[3] & 0x3F), bcd2bin(buffer[2] & 0x3F),
|
||||
bcd2bin(buffer[1] & 0x7F), bcd2bin(buffer[0] & 0x7F));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Resets the STOP bit in register Control_1
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_PCF8563::start(void) {
|
||||
uint8_t ctlreg = read_register(PCF8563_CONTROL_1);
|
||||
if (ctlreg & (1 << 5))
|
||||
write_register(PCF8563_CONTROL_1, ctlreg & ~(1 << 5));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Sets the STOP bit in register Control_1
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_PCF8563::stop(void) {
|
||||
uint8_t ctlreg = read_register(PCF8563_CONTROL_1);
|
||||
if (!(ctlreg & (1 << 5)))
|
||||
write_register(PCF8563_CONTROL_1, ctlreg | (1 << 5));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Is the PCF8563 running? Check the STOP bit in register Control_1
|
||||
@return 1 if the RTC is running, 0 if not
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint8_t RTC_PCF8563::isrunning() {
|
||||
return !((read_register(PCF8563_CONTROL_1) >> 5) & 1);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Read the mode of the CLKOUT pin on the PCF8563
|
||||
@return CLKOUT pin mode as a #Pcf8563SqwPinMode enum
|
||||
*/
|
||||
/**************************************************************************/
|
||||
Pcf8563SqwPinMode RTC_PCF8563::readSqwPinMode() {
|
||||
int mode = read_register(PCF8563_CLKOUTCONTROL);
|
||||
return static_cast<Pcf8563SqwPinMode>(mode & PCF8563_CLKOUT_MASK);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Set the CLKOUT pin mode on the PCF8563
|
||||
@param mode The mode to set, see the #Pcf8563SqwPinMode enum for options
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void RTC_PCF8563::writeSqwPinMode(Pcf8563SqwPinMode mode) {
|
||||
write_register(PCF8563_CLKOUTCONTROL, mode);
|
||||
}
|
||||
+14
-1092
File diff suppressed because it is too large
Load Diff
+129
-142
@@ -22,47 +22,108 @@
|
||||
#ifndef _RTCLIB_H_
|
||||
#define _RTCLIB_H_
|
||||
|
||||
#include <Adafruit_I2CDevice.h>
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
|
||||
class TimeSpan;
|
||||
|
||||
/** Registers */
|
||||
#define PCF8523_ADDRESS 0x68 ///< I2C address for PCF8523
|
||||
#define PCF8523_CLKOUTCONTROL 0x0F ///< Timer and CLKOUT control register
|
||||
#define PCF8523_CONTROL_1 0x00 ///< Control and status register 1
|
||||
#define PCF8523_CONTROL_2 0x01 ///< Control and status register 2
|
||||
#define PCF8523_CONTROL_3 0x02 ///< Control and status register 3
|
||||
#define PCF8523_TIMER_B_FRCTL 0x12 ///< Timer B source clock frequency control
|
||||
#define PCF8523_TIMER_B_VALUE 0x13 ///< Timer B value (number clock periods)
|
||||
#define PCF8523_OFFSET 0x0E ///< Offset register
|
||||
#define PCF8523_STATUSREG 0x03 ///< Status register
|
||||
|
||||
#define PCF8563_ADDRESS 0x51 ///< I2C address for PCF8563
|
||||
#define PCF8563_CLKOUTCONTROL 0x0D ///< CLKOUT control register
|
||||
#define PCF8563_CONTROL_1 0x00 ///< Control and status register 1
|
||||
#define PCF8563_CONTROL_2 0x01 ///< Control and status register 2
|
||||
#define PCF8563_VL_SECONDS 0x02 ///< register address for VL_SECONDS
|
||||
#define PCF8563_CLKOUT_MASK 0x83 ///< bitmask for SqwPinMode on CLKOUT pin
|
||||
|
||||
#define DS1307_ADDRESS 0x68 ///< I2C address for DS1307
|
||||
#define DS1307_CONTROL 0x07 ///< Control register
|
||||
#define DS1307_NVRAM 0x08 ///< Start of RAM registers - 56 bytes, 0x08 to 0x3f
|
||||
|
||||
#define DS3231_ADDRESS 0x68 ///< I2C address for DS3231
|
||||
#define DS3231_TIME 0x00 ///< Time register
|
||||
#define DS3231_ALARM1 0x07 ///< Alarm 1 register
|
||||
#define DS3231_ALARM2 0x0B ///< Alarm 2 register
|
||||
#define DS3231_CONTROL 0x0E ///< Control register
|
||||
#define DS3231_STATUSREG 0x0F ///< Status register
|
||||
#define DS3231_TEMPERATUREREG \
|
||||
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
|
||||
|
||||
/** DS1307 SQW pin mode settings */
|
||||
enum Ds1307SqwPinMode {
|
||||
DS1307_OFF = 0x00, // Low
|
||||
DS1307_ON = 0x80, // High
|
||||
DS1307_SquareWave1HZ = 0x10, // 1Hz square wave
|
||||
DS1307_SquareWave4kHz = 0x11, // 4kHz square wave
|
||||
DS1307_SquareWave8kHz = 0x12, // 8kHz square wave
|
||||
DS1307_SquareWave32kHz = 0x13 // 32kHz square wave
|
||||
};
|
||||
|
||||
/** DS3231 SQW pin mode settings */
|
||||
enum Ds3231SqwPinMode {
|
||||
DS3231_OFF = 0x1C, /**< Off */
|
||||
DS3231_SquareWave1Hz = 0x00, /**< 1Hz square wave */
|
||||
DS3231_SquareWave1kHz = 0x08, /**< 1kHz square wave */
|
||||
DS3231_SquareWave4kHz = 0x10, /**< 4kHz square wave */
|
||||
DS3231_SquareWave8kHz = 0x18 /**< 8kHz square wave */
|
||||
};
|
||||
|
||||
/** DS3231 Alarm modes for alarm 1 */
|
||||
enum Ds3231Alarm1Mode {
|
||||
DS3231_A1_PerSecond = 0x0F, /**< Alarm once per second */
|
||||
DS3231_A1_Second = 0x0E, /**< Alarm when seconds match */
|
||||
DS3231_A1_Minute = 0x0C, /**< Alarm when minutes and seconds match */
|
||||
DS3231_A1_Hour = 0x08, /**< Alarm when hours, minutes
|
||||
and seconds match */
|
||||
DS3231_A1_Date = 0x00, /**< Alarm when date (day of month), hours,
|
||||
minutes and seconds match */
|
||||
DS3231_A1_Day = 0x10 /**< Alarm when day (day of week), hours,
|
||||
minutes and seconds match */
|
||||
};
|
||||
/** DS3231 Alarm modes for alarm 2 */
|
||||
enum Ds3231Alarm2Mode {
|
||||
DS3231_A2_PerMinute = 0x7, /**< Alarm once per minute
|
||||
(whenever seconds are 0) */
|
||||
DS3231_A2_Minute = 0x6, /**< Alarm when minutes match */
|
||||
DS3231_A2_Hour = 0x4, /**< Alarm when hours and minutes match */
|
||||
DS3231_A2_Date = 0x0, /**< Alarm when date (day of month), hours
|
||||
and minutes match */
|
||||
DS3231_A2_Day = 0x8 /**< Alarm when day (day of week), hours
|
||||
and minutes match */
|
||||
};
|
||||
/** PCF8523 INT/SQW pin mode settings */
|
||||
enum Pcf8523SqwPinMode {
|
||||
PCF8523_OFF = 7, /**< Off */
|
||||
PCF8523_SquareWave1HZ = 6, /**< 1Hz square wave */
|
||||
PCF8523_SquareWave32HZ = 5, /**< 32Hz square wave */
|
||||
PCF8523_SquareWave1kHz = 4, /**< 1kHz square wave */
|
||||
PCF8523_SquareWave4kHz = 3, /**< 4kHz square wave */
|
||||
PCF8523_SquareWave8kHz = 2, /**< 8kHz square wave */
|
||||
PCF8523_SquareWave16kHz = 1, /**< 16kHz square wave */
|
||||
PCF8523_SquareWave32kHz = 0 /**< 32kHz square wave */
|
||||
};
|
||||
|
||||
/** PCF8523 Timer Source Clock Frequencies for Timers A and B */
|
||||
enum PCF8523TimerClockFreq {
|
||||
PCF8523_Frequency4kHz = 0, /**< 1/4096th second = 244 microseconds,
|
||||
max 62.256 milliseconds */
|
||||
PCF8523_Frequency64Hz = 1, /**< 1/64th second = 15.625 milliseconds,
|
||||
max 3.984375 seconds */
|
||||
PCF8523_FrequencySecond = 2, /**< 1 second, max 255 seconds = 4.25 minutes */
|
||||
PCF8523_FrequencyMinute = 3, /**< 1 minute, max 255 minutes = 4.25 hours */
|
||||
PCF8523_FrequencyHour = 4, /**< 1 hour, max 255 hours = 10.625 days */
|
||||
};
|
||||
|
||||
/** PCF8523 Timer Interrupt Low Pulse Width options for Timer B only */
|
||||
enum PCF8523TimerIntPulse {
|
||||
PCF8523_LowPulse3x64Hz = 0, /**< 46.875 ms 3/64ths second */
|
||||
PCF8523_LowPulse4x64Hz = 1, /**< 62.500 ms 4/64ths second */
|
||||
PCF8523_LowPulse5x64Hz = 2, /**< 78.125 ms 5/64ths second */
|
||||
PCF8523_LowPulse6x64Hz = 3, /**< 93.750 ms 6/64ths second */
|
||||
PCF8523_LowPulse8x64Hz = 4, /**< 125.000 ms 8/64ths second */
|
||||
PCF8523_LowPulse10x64Hz = 5, /**< 156.250 ms 10/64ths second */
|
||||
PCF8523_LowPulse12x64Hz = 6, /**< 187.500 ms 12/64ths second */
|
||||
PCF8523_LowPulse14x64Hz = 7 /**< 218.750 ms 14/64ths second */
|
||||
};
|
||||
|
||||
/** PCF8523 Offset modes for making temperature/aging/accuracy adjustments */
|
||||
enum Pcf8523OffsetMode {
|
||||
PCF8523_TwoHours = 0x00, /**< Offset made every two hours */
|
||||
PCF8523_OneMinute = 0x80 /**< Offset made every minute */
|
||||
};
|
||||
|
||||
/** PCF8563 CLKOUT pin mode settings */
|
||||
enum Pcf8563SqwPinMode {
|
||||
PCF8563_SquareWaveOFF = 0x00, /**< Off */
|
||||
PCF8563_SquareWave1Hz = 0x83, /**< 1Hz square wave */
|
||||
PCF8563_SquareWave32Hz = 0x82, /**< 32Hz square wave */
|
||||
PCF8563_SquareWave1kHz = 0x81, /**< 1kHz square wave */
|
||||
PCF8563_SquareWave32kHz = 0x80 /**< 32kHz square wave */
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Simple general-purpose date/time class (no TZ / DST / leap
|
||||
@@ -79,7 +140,6 @@ class TimeSpan;
|
||||
inclusive.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
class DateTime {
|
||||
public:
|
||||
DateTime(uint32_t t = SECONDS_FROM_1970_TO_2000);
|
||||
@@ -258,14 +318,29 @@ protected:
|
||||
int32_t _seconds; ///< Actual TimeSpan value is stored as seconds
|
||||
};
|
||||
|
||||
/** DS1307 SQW pin mode settings */
|
||||
enum Ds1307SqwPinMode {
|
||||
DS1307_OFF = 0x00, // Low
|
||||
DS1307_ON = 0x80, // High
|
||||
DS1307_SquareWave1HZ = 0x10, // 1Hz square wave
|
||||
DS1307_SquareWave4kHz = 0x11, // 4kHz square wave
|
||||
DS1307_SquareWave8kHz = 0x12, // 8kHz square wave
|
||||
DS1307_SquareWave32kHz = 0x13 // 32kHz square wave
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief A generic I2C RTC base class. DO NOT USE DIRECTLY
|
||||
*/
|
||||
/**************************************************************************/
|
||||
class RTC_I2C {
|
||||
protected:
|
||||
/*!
|
||||
@brief Convert a binary coded decimal value to binary. RTC stores
|
||||
time/date values as BCD.
|
||||
@param val BCD value
|
||||
@return Binary value
|
||||
*/
|
||||
static uint8_t bcd2bin(uint8_t val) { return val - 6 * (val >> 4); }
|
||||
/*!
|
||||
@brief Convert a binary value to BCD format for the RTC registers
|
||||
@param val Binary value
|
||||
@return BCD value
|
||||
*/
|
||||
static uint8_t bin2bcd(uint8_t val) { return val + 6 * (val / 10); }
|
||||
Adafruit_I2CDevice *i2c_dev = NULL; ///< Pointer to I2C bus interface
|
||||
uint8_t read_register(uint8_t reg);
|
||||
void write_register(uint8_t reg, uint8_t val);
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
@@ -273,7 +348,7 @@ enum Ds1307SqwPinMode {
|
||||
@brief RTC based on the DS1307 chip connected via I2C and the Wire library
|
||||
*/
|
||||
/**************************************************************************/
|
||||
class RTC_DS1307 {
|
||||
class RTC_DS1307 : RTC_I2C {
|
||||
public:
|
||||
boolean begin(TwoWire *wireInstance = &Wire);
|
||||
void adjust(const DateTime &dt);
|
||||
@@ -285,42 +360,6 @@ public:
|
||||
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:
|
||||
TwoWire *RTCWireBus; ///< I2C bus connected to the RTC
|
||||
};
|
||||
|
||||
/** DS3231 SQW pin mode settings */
|
||||
enum Ds3231SqwPinMode {
|
||||
DS3231_OFF = 0x1C, /**< Off */
|
||||
DS3231_SquareWave1Hz = 0x00, /**< 1Hz square wave */
|
||||
DS3231_SquareWave1kHz = 0x08, /**< 1kHz square wave */
|
||||
DS3231_SquareWave4kHz = 0x10, /**< 4kHz square wave */
|
||||
DS3231_SquareWave8kHz = 0x18 /**< 8kHz square wave */
|
||||
};
|
||||
|
||||
/** DS3231 Alarm modes for alarm 1 */
|
||||
enum Ds3231Alarm1Mode {
|
||||
DS3231_A1_PerSecond = 0x0F, /**< Alarm once per second */
|
||||
DS3231_A1_Second = 0x0E, /**< Alarm when seconds match */
|
||||
DS3231_A1_Minute = 0x0C, /**< Alarm when minutes and seconds match */
|
||||
DS3231_A1_Hour = 0x08, /**< Alarm when hours, minutes
|
||||
and seconds match */
|
||||
DS3231_A1_Date = 0x00, /**< Alarm when date (day of month), hours,
|
||||
minutes and seconds match */
|
||||
DS3231_A1_Day = 0x10 /**< Alarm when day (day of week), hours,
|
||||
minutes and seconds match */
|
||||
};
|
||||
/** DS3231 Alarm modes for alarm 2 */
|
||||
enum Ds3231Alarm2Mode {
|
||||
DS3231_A2_PerMinute = 0x7, /**< Alarm once per minute
|
||||
(whenever seconds are 0) */
|
||||
DS3231_A2_Minute = 0x6, /**< Alarm when minutes match */
|
||||
DS3231_A2_Hour = 0x4, /**< Alarm when hours and minutes match */
|
||||
DS3231_A2_Date = 0x0, /**< Alarm when date (day of month), hours
|
||||
and minutes match */
|
||||
DS3231_A2_Day = 0x8 /**< Alarm when day (day of week), hours
|
||||
and minutes match */
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
@@ -328,7 +367,7 @@ enum Ds3231Alarm2Mode {
|
||||
@brief RTC based on the DS3231 chip connected via I2C and the Wire library
|
||||
*/
|
||||
/**************************************************************************/
|
||||
class RTC_DS3231 {
|
||||
class RTC_DS3231 : RTC_I2C {
|
||||
public:
|
||||
boolean begin(TwoWire *wireInstance = &Wire);
|
||||
void adjust(const DateTime &dt);
|
||||
@@ -345,50 +384,14 @@ public:
|
||||
void disable32K(void);
|
||||
bool isEnabled32K(void);
|
||||
float getTemperature(); // in Celsius degree
|
||||
|
||||
protected:
|
||||
TwoWire *RTCWireBus; ///< I2C bus connected to the RTC
|
||||
};
|
||||
|
||||
/** PCF8523 INT/SQW pin mode settings */
|
||||
enum Pcf8523SqwPinMode {
|
||||
PCF8523_OFF = 7, /**< Off */
|
||||
PCF8523_SquareWave1HZ = 6, /**< 1Hz square wave */
|
||||
PCF8523_SquareWave32HZ = 5, /**< 32Hz square wave */
|
||||
PCF8523_SquareWave1kHz = 4, /**< 1kHz square wave */
|
||||
PCF8523_SquareWave4kHz = 3, /**< 4kHz square wave */
|
||||
PCF8523_SquareWave8kHz = 2, /**< 8kHz square wave */
|
||||
PCF8523_SquareWave16kHz = 1, /**< 16kHz square wave */
|
||||
PCF8523_SquareWave32kHz = 0 /**< 32kHz square wave */
|
||||
};
|
||||
|
||||
/** PCF8523 Timer Source Clock Frequencies for Timers A and B */
|
||||
enum PCF8523TimerClockFreq {
|
||||
PCF8523_Frequency4kHz = 0, /**< 1/4096th second = 244 microseconds,
|
||||
max 62.256 milliseconds */
|
||||
PCF8523_Frequency64Hz = 1, /**< 1/64th second = 15.625 milliseconds,
|
||||
max 3.984375 seconds */
|
||||
PCF8523_FrequencySecond = 2, /**< 1 second, max 255 seconds = 4.25 minutes */
|
||||
PCF8523_FrequencyMinute = 3, /**< 1 minute, max 255 minutes = 4.25 hours */
|
||||
PCF8523_FrequencyHour = 4, /**< 1 hour, max 255 hours = 10.625 days */
|
||||
};
|
||||
|
||||
/** PCF8523 Timer Interrupt Low Pulse Width options for Timer B only */
|
||||
enum PCF8523TimerIntPulse {
|
||||
PCF8523_LowPulse3x64Hz = 0, /**< 46.875 ms 3/64ths second */
|
||||
PCF8523_LowPulse4x64Hz = 1, /**< 62.500 ms 4/64ths second */
|
||||
PCF8523_LowPulse5x64Hz = 2, /**< 78.125 ms 5/64ths second */
|
||||
PCF8523_LowPulse6x64Hz = 3, /**< 93.750 ms 6/64ths second */
|
||||
PCF8523_LowPulse8x64Hz = 4, /**< 125.000 ms 8/64ths second */
|
||||
PCF8523_LowPulse10x64Hz = 5, /**< 156.250 ms 10/64ths second */
|
||||
PCF8523_LowPulse12x64Hz = 6, /**< 187.500 ms 12/64ths second */
|
||||
PCF8523_LowPulse14x64Hz = 7 /**< 218.750 ms 14/64ths second */
|
||||
};
|
||||
|
||||
/** PCF8523 Offset modes for making temperature/aging/accuracy adjustments */
|
||||
enum Pcf8523OffsetMode {
|
||||
PCF8523_TwoHours = 0x00, /**< Offset made every two hours */
|
||||
PCF8523_OneMinute = 0x80 /**< Offset made every minute */
|
||||
/*!
|
||||
@brief Convert the day of the week to a representation suitable for
|
||||
storing in the DS3231: from 1 (Monday) to 7 (Sunday).
|
||||
@param d Day of the week as represented by the library:
|
||||
from 0 (Sunday) to 6 (Saturday).
|
||||
@return the converted value
|
||||
*/
|
||||
static uint8_t dowToDS3231(uint8_t d) { return d == 0 ? 7 : d; }
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
@@ -396,7 +399,7 @@ enum Pcf8523OffsetMode {
|
||||
@brief RTC based on the PCF8523 chip connected via I2C and the Wire library
|
||||
*/
|
||||
/**************************************************************************/
|
||||
class RTC_PCF8523 {
|
||||
class RTC_PCF8523 : RTC_I2C {
|
||||
public:
|
||||
boolean begin(TwoWire *wireInstance = &Wire);
|
||||
void adjust(const DateTime &dt);
|
||||
@@ -416,18 +419,6 @@ public:
|
||||
void disableCountdownTimer(void);
|
||||
void deconfigureAllTimers(void);
|
||||
void calibrate(Pcf8523OffsetMode mode, int8_t offset);
|
||||
|
||||
protected:
|
||||
TwoWire *RTCWireBus; ///< I2C bus connected to the RTC
|
||||
};
|
||||
|
||||
/** PCF8563 CLKOUT pin mode settings */
|
||||
enum Pcf8563SqwPinMode {
|
||||
PCF8563_SquareWaveOFF = 0x00, /**< Off */
|
||||
PCF8563_SquareWave1Hz = 0x83, /**< 1Hz square wave */
|
||||
PCF8563_SquareWave32Hz = 0x82, /**< 32Hz square wave */
|
||||
PCF8563_SquareWave1kHz = 0x81, /**< 1kHz square wave */
|
||||
PCF8563_SquareWave32kHz = 0x80 /**< 32kHz square wave */
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
@@ -435,8 +426,7 @@ enum Pcf8563SqwPinMode {
|
||||
@brief RTC based on the PCF8563 chip connected via I2C and the Wire library
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
class RTC_PCF8563 {
|
||||
class RTC_PCF8563 : RTC_I2C {
|
||||
public:
|
||||
boolean begin(TwoWire *wireInstance = &Wire);
|
||||
boolean lostPower(void);
|
||||
@@ -447,9 +437,6 @@ public:
|
||||
uint8_t isrunning();
|
||||
Pcf8563SqwPinMode readSqwPinMode();
|
||||
void writeSqwPinMode(Pcf8563SqwPinMode mode);
|
||||
|
||||
protected:
|
||||
TwoWire *RTCWireBus; ///< I2C bus connected to the RTC
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
Reference in New Issue
Block a user