From cf147c300e630f6c128e178ceec3533c2c37c9a7 Mon Sep 17 00:00:00 2001 From: Aurelien BOUIN Date: Sat, 23 Sep 2023 09:33:22 +0200 Subject: [PATCH 1/7] Add some functions to PCF8523 (Alarm) --- src/RTC_PCF8523.cpp | 158 +++++++++++++++++++++++++++++++++++++++++++- src/RTClib.cpp | 6 ++ src/RTClib.h | 18 +++++ 3 files changed, 181 insertions(+), 1 deletion(-) diff --git a/src/RTC_PCF8523.cpp b/src/RTC_PCF8523.cpp index 17debef7..41e9e925 100644 --- a/src/RTC_PCF8523.cpp +++ b/src/RTC_PCF8523.cpp @@ -52,6 +52,143 @@ bool RTC_PCF8523::initialized(void) { return (read_register(PCF8523_CONTROL_3) & 0xE0) != 0xE0; } +/**************************************************************************/ +/*! + @brief Set RTC alarm value for a specific register +*/ +/**************************************************************************/ + +void RTC_PCF8523::set_alarm_value_for_register(Pcf8563AlarmRegister the_register,uint8_t the_value) { + //set the value and enable the AEN_X (enabled with 0 value) + switch(the_register){ + case PCF8523_ALARM_MINUTE: + write_register(the_register,bin2bcd((the_value%60) & 0x7F)); + break; + case PCF8523_ALARM_HOUR: + write_register(the_register,bin2bcd((the_value%24) & 0x7F)); + break; + case PCF8523_ALARM_DAY: + write_register(the_register,bin2bcd((the_value%32) & 0x7F)); + break; + case PCF8523_ALARM_WEEKDAY: + write_register(the_register,bin2bcd((the_value%8) & 0x7F)); + break; + default: + break; + } +} + +/**************************************************************************/ +/*! + @brief Get RTC alarm value for a specific register +*/ +/**************************************************************************/ + +uint8_t RTC_PCF8523::get_alarm_value_for_register(Pcf8563AlarmRegister the_register) { + //set the value and enable the AEN_X (enabled with 0 value) + switch(the_register){ + case PCF8523_ALARM_MINUTE: + return bcd2bin(read_register(the_register)); + break; + case PCF8523_ALARM_HOUR: + return bcd2bin(read_register(the_register)); + break; + case PCF8523_ALARM_DAY: + return bcd2bin(read_register(the_register)); + break; + case PCF8523_ALARM_WEEKDAY: + return bcd2bin(read_register(the_register)); + break; + default: + break; + } + return 0xFF; +} + +/**************************************************************************/ +/*! + @brief RTC Upgrade oscillator capacitor From 7pF to 12.5pF +*/ +/**************************************************************************/ + +void RTC_PCF8523::upgrade_osci_capa_to_12pf5() { + write_register(PCF8523_CONTROL_1, + read_register(PCF8523_CONTROL_1) | (1 << 7));//Enable CAP_SEL + +} + +/**************************************************************************/ +/*! + @brief Enable Alarm based on previous set_alarm_value_for_register call +*/ +/**************************************************************************/ + +void RTC_PCF8523::enable_alarm() { + write_register(PCF8523_CONTROL_1, + read_register(PCF8523_CONTROL_1) | (1 << 1));//Enable AIE + +} + +/**************************************************************************/ +/*! + @brief Check Alarm fired +*/ +/**************************************************************************/ + +bool RTC_PCF8523::is_alarm_fired(void) { + return (read_register(PCF8523_CONTROL_2) && (1 << 3));//Check AF +} + +/**************************************************************************/ +/*! + @brief Clear Alarm +*/ +/**************************************************************************/ + +void RTC_PCF8523::clear_alarm() { + write_register(PCF8523_CONTROL_2, + read_register(PCF8523_CONTROL_2) & ~(1 << 3));//Clear AF +} + +/**************************************************************************/ +/*! + @brief Disable Alarm +*/ +/**************************************************************************/ + +void RTC_PCF8523::disable_alarm() { + //write_register(PCF8523_CONTROL_1, + // read_register(PCF8523_CONTROL_1) & 0xFD);//Disable AIE + write_register(PCF8523_CONTROL_1, + read_register(PCF8523_CONTROL_1) & ~(1 << 1));//Disable AIE + write_register(PCF8523_ALARM_MINUTE,0x80); + write_register(PCF8523_ALARM_HOUR,0x80); + write_register(PCF8523_ALARM_DAY,0x80); + write_register(PCF8523_ALARM_WEEKDAY,0x80); +} + +/**************************************************************************/ +/*! + @brief Ask if any Alarm is setup +*/ +/**************************************************************************/ + +bool RTC_PCF8523::is_any_alarm_setup(void) { + if(read_register(PCF8523_CONTROL_1) && (1<<1)){ + return true; + } + return false; +} + +/**************************************************************************/ +/*! + @brief Set RTC battery switch-over mode in register Control_3 +*/ +/**************************************************************************/ +void RTC_PCF8523::set_battery_switch_over(uint8_t battery_switch_over_value) { + write_register(PCF8523_CONTROL_3,battery_switch_over_value); +} + /**************************************************************************/ /*! @brief Set the date and time, set battery switchover mode @@ -67,10 +204,20 @@ void RTC_PCF8523::adjust(const DateTime &dt) { bin2bcd(0), // skip weekdays bin2bcd(dt.month()), bin2bcd(dt.year() - 2000U)}; + +#ifdef DEBUG_RTCLIB + DEBUG_RTCLIB.printf("I2C_W(0x%02X,0x%02X)\n",3,buffer[1]); + DEBUG_RTCLIB.printf("I2C_W(0x%02X,0x%02X)\n",4,buffer[2]); + DEBUG_RTCLIB.printf("I2C_W(0x%02X,0x%02X)\n",5,buffer[3]); + DEBUG_RTCLIB.printf("I2C_W(0x%02X,0x%02X)\n",6,buffer[4]); + DEBUG_RTCLIB.printf("I2C_W(0x%02X,0x%02X)\n",7,buffer[5]); + DEBUG_RTCLIB.printf("I2C_W(0x%02X,0x%02X)\n",8,buffer[6]); + DEBUG_RTCLIB.printf("I2C_W(0x%02X,0x%02X)\n",9,buffer[7]); +#endif /* DEBUG_RTCLIB */ i2c_dev->write(buffer, 8); // set to battery switchover mode - write_register(PCF8523_CONTROL_3, 0x00); + set_battery_switch_over(0x00); } /**************************************************************************/ @@ -110,6 +257,15 @@ void RTC_PCF8523::stop(void) { read_register(PCF8523_CONTROL_1) | (1 << 5)); } +/**************************************************************************/ +/*! + @brief Reset RTC sending 0x58 in register Control_1 +*/ +/**************************************************************************/ +void RTC_PCF8523::reset(void) { + write_register(PCF8523_CONTROL_1,0x58); +} + /**************************************************************************/ /*! @brief Is the PCF8523 running? Check the STOP bit in register Control_1 diff --git a/src/RTClib.cpp b/src/RTClib.cpp index 8f1f4ea5..99c690f4 100644 --- a/src/RTClib.cpp +++ b/src/RTClib.cpp @@ -65,6 +65,9 @@ /**************************************************************************/ void RTC_I2C::write_register(uint8_t reg, uint8_t val) { uint8_t buffer[2] = {reg, val}; +#ifdef DEBUG_RTCLIB + Serial.printf("I2C_W(0x%02X,0x%02X)\n",reg,val); +#endif /* DEBUG_RTCLIB */ i2c_dev->write(buffer, 2); } @@ -79,6 +82,9 @@ uint8_t RTC_I2C::read_register(uint8_t reg) { uint8_t buffer[1]; i2c_dev->write(®, 1); i2c_dev->read(buffer, 1); +#ifdef DEBUG_RTCLIB + DEBUG_RTCLIB.printf("I2C_R(0x%02X)=0x%02X\n",reg,buffer[0]); +#endif /* DEBUG_RTCLIB */ return buffer[0]; } diff --git a/src/RTClib.h b/src/RTClib.h index 879bb3fa..fd43dfc5 100644 --- a/src/RTClib.h +++ b/src/RTClib.h @@ -124,6 +124,14 @@ enum Pcf8563SqwPinMode { PCF8563_SquareWave32kHz = 0x80 /**< 32kHz square wave */ }; +/** PCF8563 CLKOUT pin mode settings */ +enum Pcf8563AlarmRegister { + PCF8523_ALARM_MINUTE = 0x0A, ///< Minute Alarm register + PCF8523_ALARM_HOUR = 0x0B, ///< Hour Alarm register + PCF8523_ALARM_DAY = 0x0C, ///< Day Alarm register + PCF8523_ALARM_WEEKDAY = 0x0D, ///< WeekDay Alarm register +}; + /**************************************************************************/ /*! @brief Simple general-purpose date/time class (no TZ / DST / leap @@ -409,9 +417,19 @@ class RTC_PCF8523 : RTC_I2C { void adjust(const DateTime &dt); bool lostPower(void); bool initialized(void); + bool is_alarm_fired(void); + bool is_any_alarm_setup(void); DateTime now(); + void upgrade_osci_capa_to_12pf5(); void start(void); void stop(void); + void reset(void); + void set_battery_switch_over(uint8_t battery_switch_over_value); + void set_alarm_value_for_register(Pcf8563AlarmRegister the_register,uint8_t the_value); + uint8_t get_alarm_value_for_register(Pcf8563AlarmRegister the_register); + void enable_alarm(); + void clear_alarm(); + void disable_alarm(); uint8_t isrunning(); Pcf8523SqwPinMode readSqwPinMode(); void writeSqwPinMode(Pcf8523SqwPinMode mode); From 92db4823c7a177db116e584ba8e924f24c2c349b Mon Sep 17 00:00:00 2001 From: Aurelien BOUIN Date: Sun, 24 Sep 2023 13:13:55 +0200 Subject: [PATCH 2/7] Update function name to respect initial camelCase style --- src/RTC_PCF8523.cpp | 28 +++++++++++++--------------- src/RTClib.cpp | 2 +- src/RTClib.h | 18 +++++++++--------- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/RTC_PCF8523.cpp b/src/RTC_PCF8523.cpp index 41e9e925..c734a550 100644 --- a/src/RTC_PCF8523.cpp +++ b/src/RTC_PCF8523.cpp @@ -58,7 +58,7 @@ bool RTC_PCF8523::initialized(void) { */ /**************************************************************************/ -void RTC_PCF8523::set_alarm_value_for_register(Pcf8563AlarmRegister the_register,uint8_t the_value) { +void RTC_PCF8523::setAlarmValueForRegister(Pcf8563AlarmRegister the_register,uint8_t the_value) { //set the value and enable the AEN_X (enabled with 0 value) switch(the_register){ case PCF8523_ALARM_MINUTE: @@ -84,7 +84,7 @@ void RTC_PCF8523::set_alarm_value_for_register(Pcf8563AlarmRegister the_register */ /**************************************************************************/ -uint8_t RTC_PCF8523::get_alarm_value_for_register(Pcf8563AlarmRegister the_register) { +uint8_t RTC_PCF8523::getAlarmValueForRegister(Pcf8563AlarmRegister the_register) { //set the value and enable the AEN_X (enabled with 0 value) switch(the_register){ case PCF8523_ALARM_MINUTE: @@ -111,7 +111,7 @@ uint8_t RTC_PCF8523::get_alarm_value_for_register(Pcf8563AlarmRegister the_regis */ /**************************************************************************/ -void RTC_PCF8523::upgrade_osci_capa_to_12pf5() { +void RTC_PCF8523::upgradeOsciCapaTo12pf5() { write_register(PCF8523_CONTROL_1, read_register(PCF8523_CONTROL_1) | (1 << 7));//Enable CAP_SEL @@ -119,11 +119,11 @@ void RTC_PCF8523::upgrade_osci_capa_to_12pf5() { /**************************************************************************/ /*! - @brief Enable Alarm based on previous set_alarm_value_for_register call + @brief Enable Alarm based on previous setAlarmValueForRegister call */ /**************************************************************************/ -void RTC_PCF8523::enable_alarm() { +void RTC_PCF8523::enableAlarm() { write_register(PCF8523_CONTROL_1, read_register(PCF8523_CONTROL_1) | (1 << 1));//Enable AIE @@ -135,8 +135,8 @@ void RTC_PCF8523::enable_alarm() { */ /**************************************************************************/ -bool RTC_PCF8523::is_alarm_fired(void) { - return (read_register(PCF8523_CONTROL_2) && (1 << 3));//Check AF +bool RTC_PCF8523::isAlarmFired(void) { + return (read_register(PCF8523_CONTROL_2) & (1 << 3));//Check AF } /**************************************************************************/ @@ -145,7 +145,7 @@ bool RTC_PCF8523::is_alarm_fired(void) { */ /**************************************************************************/ -void RTC_PCF8523::clear_alarm() { +void RTC_PCF8523::clearAlarm() { write_register(PCF8523_CONTROL_2, read_register(PCF8523_CONTROL_2) & ~(1 << 3));//Clear AF } @@ -156,9 +156,7 @@ void RTC_PCF8523::clear_alarm() { */ /**************************************************************************/ -void RTC_PCF8523::disable_alarm() { - //write_register(PCF8523_CONTROL_1, - // read_register(PCF8523_CONTROL_1) & 0xFD);//Disable AIE +void RTC_PCF8523::disableAlarm() { write_register(PCF8523_CONTROL_1, read_register(PCF8523_CONTROL_1) & ~(1 << 1));//Disable AIE write_register(PCF8523_ALARM_MINUTE,0x80); @@ -173,8 +171,8 @@ void RTC_PCF8523::disable_alarm() { */ /**************************************************************************/ -bool RTC_PCF8523::is_any_alarm_setup(void) { - if(read_register(PCF8523_CONTROL_1) && (1<<1)){ +bool RTC_PCF8523::isAnyAlarmSetup(void) { + if(read_register(PCF8523_CONTROL_1) & (1<<1)){ return true; } return false; @@ -185,7 +183,7 @@ bool RTC_PCF8523::is_any_alarm_setup(void) { @brief Set RTC battery switch-over mode in register Control_3 */ /**************************************************************************/ -void RTC_PCF8523::set_battery_switch_over(uint8_t battery_switch_over_value) { +void RTC_PCF8523::setBatterySwitchOver(uint8_t battery_switch_over_value) { write_register(PCF8523_CONTROL_3,battery_switch_over_value); } @@ -217,7 +215,7 @@ void RTC_PCF8523::adjust(const DateTime &dt) { i2c_dev->write(buffer, 8); // set to battery switchover mode - set_battery_switch_over(0x00); + setBatterySwitchOver(0x00); } /**************************************************************************/ diff --git a/src/RTClib.cpp b/src/RTClib.cpp index 99c690f4..0c5f2b1d 100644 --- a/src/RTClib.cpp +++ b/src/RTClib.cpp @@ -66,7 +66,7 @@ void RTC_I2C::write_register(uint8_t reg, uint8_t val) { uint8_t buffer[2] = {reg, val}; #ifdef DEBUG_RTCLIB - Serial.printf("I2C_W(0x%02X,0x%02X)\n",reg,val); + DEBUG_RTCLIB.printf("I2C_W(0x%02X,0x%02X)\n",reg,val); #endif /* DEBUG_RTCLIB */ i2c_dev->write(buffer, 2); } diff --git a/src/RTClib.h b/src/RTClib.h index fd43dfc5..cb5b80c3 100644 --- a/src/RTClib.h +++ b/src/RTClib.h @@ -417,19 +417,19 @@ class RTC_PCF8523 : RTC_I2C { void adjust(const DateTime &dt); bool lostPower(void); bool initialized(void); - bool is_alarm_fired(void); - bool is_any_alarm_setup(void); + bool isAlarmFired(void); + bool isAnyAlarmSetup(void); DateTime now(); - void upgrade_osci_capa_to_12pf5(); + void upgradeOsciCapaTo12pf5(); void start(void); void stop(void); void reset(void); - void set_battery_switch_over(uint8_t battery_switch_over_value); - void set_alarm_value_for_register(Pcf8563AlarmRegister the_register,uint8_t the_value); - uint8_t get_alarm_value_for_register(Pcf8563AlarmRegister the_register); - void enable_alarm(); - void clear_alarm(); - void disable_alarm(); + void setBatterySwitchOver(uint8_t battery_switch_over_value); + void setAlarmValueForRegister(Pcf8563AlarmRegister the_register,uint8_t the_value); + uint8_t getAlarmValueForRegister(Pcf8563AlarmRegister the_register); + void enableAlarm(); + void clearAlarm(); + void disableAlarm(); uint8_t isrunning(); Pcf8523SqwPinMode readSqwPinMode(); void writeSqwPinMode(Pcf8523SqwPinMode mode); From a0a206c93dad0107661a2e82fc6df55645937d69 Mon Sep 17 00:00:00 2001 From: Aurelien BOUIN Date: Sun, 24 Sep 2023 13:14:39 +0200 Subject: [PATCH 3/7] Remove DEBUG_RTCLIB --- src/RTC_PCF8523.cpp | 10 ---------- src/RTClib.cpp | 6 ------ 2 files changed, 16 deletions(-) diff --git a/src/RTC_PCF8523.cpp b/src/RTC_PCF8523.cpp index c734a550..b88df1bc 100644 --- a/src/RTC_PCF8523.cpp +++ b/src/RTC_PCF8523.cpp @@ -202,16 +202,6 @@ void RTC_PCF8523::adjust(const DateTime &dt) { bin2bcd(0), // skip weekdays bin2bcd(dt.month()), bin2bcd(dt.year() - 2000U)}; - -#ifdef DEBUG_RTCLIB - DEBUG_RTCLIB.printf("I2C_W(0x%02X,0x%02X)\n",3,buffer[1]); - DEBUG_RTCLIB.printf("I2C_W(0x%02X,0x%02X)\n",4,buffer[2]); - DEBUG_RTCLIB.printf("I2C_W(0x%02X,0x%02X)\n",5,buffer[3]); - DEBUG_RTCLIB.printf("I2C_W(0x%02X,0x%02X)\n",6,buffer[4]); - DEBUG_RTCLIB.printf("I2C_W(0x%02X,0x%02X)\n",7,buffer[5]); - DEBUG_RTCLIB.printf("I2C_W(0x%02X,0x%02X)\n",8,buffer[6]); - DEBUG_RTCLIB.printf("I2C_W(0x%02X,0x%02X)\n",9,buffer[7]); -#endif /* DEBUG_RTCLIB */ i2c_dev->write(buffer, 8); // set to battery switchover mode diff --git a/src/RTClib.cpp b/src/RTClib.cpp index 0c5f2b1d..8f1f4ea5 100644 --- a/src/RTClib.cpp +++ b/src/RTClib.cpp @@ -65,9 +65,6 @@ /**************************************************************************/ void RTC_I2C::write_register(uint8_t reg, uint8_t val) { uint8_t buffer[2] = {reg, val}; -#ifdef DEBUG_RTCLIB - DEBUG_RTCLIB.printf("I2C_W(0x%02X,0x%02X)\n",reg,val); -#endif /* DEBUG_RTCLIB */ i2c_dev->write(buffer, 2); } @@ -82,9 +79,6 @@ uint8_t RTC_I2C::read_register(uint8_t reg) { uint8_t buffer[1]; i2c_dev->write(®, 1); i2c_dev->read(buffer, 1); -#ifdef DEBUG_RTCLIB - DEBUG_RTCLIB.printf("I2C_R(0x%02X)=0x%02X\n",reg,buffer[0]); -#endif /* DEBUG_RTCLIB */ return buffer[0]; } From 43065c065f08f8427d8486b5530bd18d36a95c3e Mon Sep 17 00:00:00 2001 From: Aurelien BOUIN Date: Sun, 24 Sep 2023 16:38:39 +0200 Subject: [PATCH 4/7] Apply clang-format -i src/* --- src/RTC_PCF8523.cpp | 98 ++++++++++++++++++++++----------------------- src/RTClib.h | 11 ++--- 2 files changed, 54 insertions(+), 55 deletions(-) diff --git a/src/RTC_PCF8523.cpp b/src/RTC_PCF8523.cpp index b88df1bc..4edde21b 100644 --- a/src/RTC_PCF8523.cpp +++ b/src/RTC_PCF8523.cpp @@ -58,23 +58,24 @@ bool RTC_PCF8523::initialized(void) { */ /**************************************************************************/ -void RTC_PCF8523::setAlarmValueForRegister(Pcf8563AlarmRegister the_register,uint8_t the_value) { - //set the value and enable the AEN_X (enabled with 0 value) - switch(the_register){ - case PCF8523_ALARM_MINUTE: - write_register(the_register,bin2bcd((the_value%60) & 0x7F)); - break; - case PCF8523_ALARM_HOUR: - write_register(the_register,bin2bcd((the_value%24) & 0x7F)); - break; - case PCF8523_ALARM_DAY: - write_register(the_register,bin2bcd((the_value%32) & 0x7F)); - break; - case PCF8523_ALARM_WEEKDAY: - write_register(the_register,bin2bcd((the_value%8) & 0x7F)); - break; - default: - break; +void RTC_PCF8523::setAlarmValueForRegister(Pcf8563AlarmRegister the_register, + uint8_t the_value) { + // set the value and enable the AEN_X (enabled with 0 value) + switch (the_register) { + case PCF8523_ALARM_MINUTE: + write_register(the_register, bin2bcd((the_value % 60) & 0x7F)); + break; + case PCF8523_ALARM_HOUR: + write_register(the_register, bin2bcd((the_value % 24) & 0x7F)); + break; + case PCF8523_ALARM_DAY: + write_register(the_register, bin2bcd((the_value % 32) & 0x7F)); + break; + case PCF8523_ALARM_WEEKDAY: + write_register(the_register, bin2bcd((the_value % 8) & 0x7F)); + break; + default: + break; } } @@ -84,23 +85,24 @@ void RTC_PCF8523::setAlarmValueForRegister(Pcf8563AlarmRegister the_register,uin */ /**************************************************************************/ -uint8_t RTC_PCF8523::getAlarmValueForRegister(Pcf8563AlarmRegister the_register) { - //set the value and enable the AEN_X (enabled with 0 value) - switch(the_register){ - case PCF8523_ALARM_MINUTE: - return bcd2bin(read_register(the_register)); - break; - case PCF8523_ALARM_HOUR: - return bcd2bin(read_register(the_register)); - break; - case PCF8523_ALARM_DAY: - return bcd2bin(read_register(the_register)); - break; - case PCF8523_ALARM_WEEKDAY: - return bcd2bin(read_register(the_register)); - break; - default: - break; +uint8_t +RTC_PCF8523::getAlarmValueForRegister(Pcf8563AlarmRegister the_register) { + // set the value and enable the AEN_X (enabled with 0 value) + switch (the_register) { + case PCF8523_ALARM_MINUTE: + return bcd2bin(read_register(the_register)); + break; + case PCF8523_ALARM_HOUR: + return bcd2bin(read_register(the_register)); + break; + case PCF8523_ALARM_DAY: + return bcd2bin(read_register(the_register)); + break; + case PCF8523_ALARM_WEEKDAY: + return bcd2bin(read_register(the_register)); + break; + default: + break; } return 0xFF; } @@ -113,8 +115,7 @@ uint8_t RTC_PCF8523::getAlarmValueForRegister(Pcf8563AlarmRegister the_register) void RTC_PCF8523::upgradeOsciCapaTo12pf5() { write_register(PCF8523_CONTROL_1, - read_register(PCF8523_CONTROL_1) | (1 << 7));//Enable CAP_SEL - + read_register(PCF8523_CONTROL_1) | (1 << 7)); // Enable CAP_SEL } /**************************************************************************/ @@ -125,8 +126,7 @@ void RTC_PCF8523::upgradeOsciCapaTo12pf5() { void RTC_PCF8523::enableAlarm() { write_register(PCF8523_CONTROL_1, - read_register(PCF8523_CONTROL_1) | (1 << 1));//Enable AIE - + read_register(PCF8523_CONTROL_1) | (1 << 1)); // Enable AIE } /**************************************************************************/ @@ -136,7 +136,7 @@ void RTC_PCF8523::enableAlarm() { /**************************************************************************/ bool RTC_PCF8523::isAlarmFired(void) { - return (read_register(PCF8523_CONTROL_2) & (1 << 3));//Check AF + return (read_register(PCF8523_CONTROL_2) & (1 << 3)); // Check AF } /**************************************************************************/ @@ -147,7 +147,7 @@ bool RTC_PCF8523::isAlarmFired(void) { void RTC_PCF8523::clearAlarm() { write_register(PCF8523_CONTROL_2, - read_register(PCF8523_CONTROL_2) & ~(1 << 3));//Clear AF + read_register(PCF8523_CONTROL_2) & ~(1 << 3)); // Clear AF } /**************************************************************************/ @@ -158,11 +158,11 @@ void RTC_PCF8523::clearAlarm() { void RTC_PCF8523::disableAlarm() { write_register(PCF8523_CONTROL_1, - read_register(PCF8523_CONTROL_1) & ~(1 << 1));//Disable AIE - write_register(PCF8523_ALARM_MINUTE,0x80); - write_register(PCF8523_ALARM_HOUR,0x80); - write_register(PCF8523_ALARM_DAY,0x80); - write_register(PCF8523_ALARM_WEEKDAY,0x80); + read_register(PCF8523_CONTROL_1) & ~(1 << 1)); // Disable AIE + write_register(PCF8523_ALARM_MINUTE, 0x80); + write_register(PCF8523_ALARM_HOUR, 0x80); + write_register(PCF8523_ALARM_DAY, 0x80); + write_register(PCF8523_ALARM_WEEKDAY, 0x80); } /**************************************************************************/ @@ -172,7 +172,7 @@ void RTC_PCF8523::disableAlarm() { /**************************************************************************/ bool RTC_PCF8523::isAnyAlarmSetup(void) { - if(read_register(PCF8523_CONTROL_1) & (1<<1)){ + if (read_register(PCF8523_CONTROL_1) & (1 << 1)) { return true; } return false; @@ -184,7 +184,7 @@ bool RTC_PCF8523::isAnyAlarmSetup(void) { */ /**************************************************************************/ void RTC_PCF8523::setBatterySwitchOver(uint8_t battery_switch_over_value) { - write_register(PCF8523_CONTROL_3,battery_switch_over_value); + write_register(PCF8523_CONTROL_3, battery_switch_over_value); } /**************************************************************************/ @@ -250,9 +250,7 @@ void RTC_PCF8523::stop(void) { @brief Reset RTC sending 0x58 in register Control_1 */ /**************************************************************************/ -void RTC_PCF8523::reset(void) { - write_register(PCF8523_CONTROL_1,0x58); -} +void RTC_PCF8523::reset(void) { write_register(PCF8523_CONTROL_1, 0x58); } /**************************************************************************/ /*! diff --git a/src/RTClib.h b/src/RTClib.h index cb5b80c3..8d8dbdd0 100644 --- a/src/RTClib.h +++ b/src/RTClib.h @@ -126,10 +126,10 @@ enum Pcf8563SqwPinMode { /** PCF8563 CLKOUT pin mode settings */ enum Pcf8563AlarmRegister { - PCF8523_ALARM_MINUTE = 0x0A, ///< Minute Alarm register - PCF8523_ALARM_HOUR = 0x0B, ///< Hour Alarm register - PCF8523_ALARM_DAY = 0x0C, ///< Day Alarm register - PCF8523_ALARM_WEEKDAY = 0x0D, ///< WeekDay Alarm register + PCF8523_ALARM_MINUTE = 0x0A, ///< Minute Alarm register + PCF8523_ALARM_HOUR = 0x0B, ///< Hour Alarm register + PCF8523_ALARM_DAY = 0x0C, ///< Day Alarm register + PCF8523_ALARM_WEEKDAY = 0x0D, ///< WeekDay Alarm register }; /**************************************************************************/ @@ -425,7 +425,8 @@ class RTC_PCF8523 : RTC_I2C { void stop(void); void reset(void); void setBatterySwitchOver(uint8_t battery_switch_over_value); - void setAlarmValueForRegister(Pcf8563AlarmRegister the_register,uint8_t the_value); + void setAlarmValueForRegister(Pcf8563AlarmRegister the_register, + uint8_t the_value); uint8_t getAlarmValueForRegister(Pcf8563AlarmRegister the_register); void enableAlarm(); void clearAlarm(); From ed356607c5fd4c7279464262dee9ab9c0bd2e6ef Mon Sep 17 00:00:00 2001 From: Aurelien BOUIN Date: Sun, 24 Sep 2023 18:50:51 +0200 Subject: [PATCH 5/7] Fix Doxygen code documentation --- src/RTC_PCF8523.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/RTC_PCF8523.cpp b/src/RTC_PCF8523.cpp index 4edde21b..96212dc4 100644 --- a/src/RTC_PCF8523.cpp +++ b/src/RTC_PCF8523.cpp @@ -45,7 +45,7 @@ bool RTC_PCF8523::lostPower(void) { /*! @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 + @return 1 if the PCF8523 has been set up, false if not */ /**************************************************************************/ bool RTC_PCF8523::initialized(void) { @@ -55,6 +55,8 @@ bool RTC_PCF8523::initialized(void) { /**************************************************************************/ /*! @brief Set RTC alarm value for a specific register + @param the_register The Alarm register concerned + @param the_value The Alarm register value */ /**************************************************************************/ @@ -82,6 +84,8 @@ void RTC_PCF8523::setAlarmValueForRegister(Pcf8563AlarmRegister the_register, /**************************************************************************/ /*! @brief Get RTC alarm value for a specific register + @param the_register The Alarm register concerned + @return The value for the requested Alarm register */ /**************************************************************************/ @@ -132,6 +136,7 @@ void RTC_PCF8523::enableAlarm() { /**************************************************************************/ /*! @brief Check Alarm fired + @return 1 if an alarm fired */ /**************************************************************************/ @@ -168,6 +173,7 @@ void RTC_PCF8523::disableAlarm() { /**************************************************************************/ /*! @brief Ask if any Alarm is setup + @return true if an alarm is setup */ /**************************************************************************/ @@ -181,6 +187,7 @@ bool RTC_PCF8523::isAnyAlarmSetup(void) { /**************************************************************************/ /*! @brief Set RTC battery switch-over mode in register Control_3 + @param battery_switch_over_value The value for battery switch over register */ /**************************************************************************/ void RTC_PCF8523::setBatterySwitchOver(uint8_t battery_switch_over_value) { From 5c40554fa2fcd79038b36126de2e52cc02089239 Mon Sep 17 00:00:00 2001 From: Aurelien BOUIN Date: Fri, 7 Jun 2024 18:28:55 +0200 Subject: [PATCH 6/7] Add Watchdog TimerA support for PCF8523 --- src/RTC_PCF8523.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++++- src/RTClib.h | 14 ++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/src/RTC_PCF8523.cpp b/src/RTC_PCF8523.cpp index 96212dc4..684f5c49 100644 --- a/src/RTC_PCF8523.cpp +++ b/src/RTC_PCF8523.cpp @@ -5,6 +5,8 @@ #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_A_FRCTL 0x10 ///< Timer A source clock frequency control +#define PCF8523_TIMER_A_VALUE 0x11 ///< Timer A value (number clock periods) #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 @@ -18,6 +20,8 @@ */ /**************************************************************************/ bool RTC_PCF8523::begin(TwoWire *wireInstance) { + wdgTimeoutUnitySet = PCF8523_WDG_DISABLED; + wdgTimeoutValueSet = 0; if (i2c_dev) delete i2c_dev; i2c_dev = new Adafruit_I2CDevice(PCF8523_ADDRESS, wireInstance); @@ -257,7 +261,11 @@ void RTC_PCF8523::stop(void) { @brief Reset RTC sending 0x58 in register Control_1 */ /**************************************************************************/ -void RTC_PCF8523::reset(void) { write_register(PCF8523_CONTROL_1, 0x58); } +void RTC_PCF8523::reset(void) { + wdgTimeoutUnitySet = PCF8523_WDG_DISABLED; + wdgTimeoutValueSet = 0; + write_register(PCF8523_CONTROL_1, 0x58); + } /**************************************************************************/ /*! @@ -317,6 +325,84 @@ void RTC_PCF8523::disableSecondTimer() { read_register(PCF8523_CONTROL_1) & ~(1 << 2)); } +/**************************************************************************/ +/*! + @brief Enable Timer A as Watchdog permanent Interrupt on the PCF8523. + How : + TAC[2:1] = 10 : {Tmr_CLKOUT_ctrl(0x0F)} : set as watchdog timer + TAQ[2:0] : {Tmr_A_freq_ctrl(0x10)} : determine source clock frequency + WTAIE(2) : {Control_2(0x01)} : watchdog timer A interrupt enabled + + TAM(7) : {Tmr_CLKOUT_ctrl(0x0F)} : control the interrupt generation mode(permanent) force to 0 + + T_A : {Tmr_A_reg(0x11)} : determines the watchdog timer-period + + The watchdog timer counts down from value T_A in register Tmr_A_reg (11h). When the + counter reaches 1, the watchdog timer flag WTAF (register Control_2) is set logic 1 on the + next rising edge of the timer clock + + The counter does not automatically reload + + When loading the counter with any valid value of T_A except 0, (interrupt is cleared, and watchdog timer starts) + When loading the counter with 0, The watchdog timer stops + + A read of the register Control_2 (01h) automatically resets WTAF (WTAF = 0) and clears the interrupt +*/ +/**************************************************************************/ +void RTC_PCF8523::enableWatchdog(PCF8523WatchdogTimeoutUnity wdgTimeoutUnity, uint8_t wdgTimeoutValue) { + uint8_t ctlreg = read_register(PCF8523_CONTROL_2); + if(wdgTimeoutUnitySet || wdgTimeoutValueSet){ + disableWatchdog(); + } + if((!wdgTimeoutUnity)||(!wdgTimeoutValue)){ + return; + } + wdgTimeoutUnitySet = wdgTimeoutUnity; + wdgTimeoutValueSet = wdgTimeoutValue; + write_register(PCF8523_TIMER_A_VALUE,0);//Stop the watchdog timer + //TAC[2:1] = 10 : {Tmr_CLKOUT_ctrl(0x0F)} : set as watchdog timer + write_register(PCF8523_CLKOUTCONTROL, + (read_register(PCF8523_CLKOUTCONTROL) & 0xFC) | (0x02 << 1)); + //TAQ[2:0] : {Tmr_A_freq_ctrl(0x10)} : determine source clock frequency + write_register(PCF8523_TIMER_A_FRCTL, + (read_register(PCF8523_TIMER_A_FRCTL) & 0xF8) | wdgTimeoutUnitySet); + //WTAIE(2) : {Control_2(0x01)} : watchdog timer A interrupt enabled + write_register(PCF8523_CONTROL_2, ctlreg | (1 << 2)); + //TAM(7) : {Tmr_CLKOUT_ctrl(0x0F)} : control the interrupt generation mode(permanent) force to 0 + write_register(PCF8523_CLKOUTCONTROL, + read_register(PCF8523_CLKOUTCONTROL) & ~(1<<7)); + + //Start the watchdog timer + write_register(PCF8523_TIMER_A_VALUE, wdgTimeoutValueSet); +} + +/**************************************************************************/ +/*! + @brief Reset Timer A Watchdog on the PCF8523. +*/ +/**************************************************************************/ + +void RTC_PCF8523::resetWatchdog(void) { + if((!wdgTimeoutUnitySet)||(!wdgTimeoutValueSet)){ + return; + } + write_register(PCF8523_TIMER_A_VALUE, wdgTimeoutValueSet); +} + +/**************************************************************************/ +/*! + @brief Disable Timer A Watchdog on the PCF8523. +*/ +/**************************************************************************/ + +void RTC_PCF8523::disableWatchdog(void) { + uint8_t ctlreg = read_register(PCF8523_CONTROL_2); + // WTAIE set to 0 + write_register(PCF8523_CONTROL_2, ctlreg & ~(1 << 2)); + wdgTimeoutUnitySet = PCF8523_WDG_DISABLED; + wdgTimeoutValueSet = 0; +} + /**************************************************************************/ /*! @brief Enable the Countdown Timer Interrupt on the PCF8523. diff --git a/src/RTClib.h b/src/RTClib.h index 8d8dbdd0..ae5b4f29 100644 --- a/src/RTClib.h +++ b/src/RTClib.h @@ -97,6 +97,14 @@ enum PCF8523TimerClockFreq { PCF8523_FrequencyHour = 4, /**< 1 hour, max 255 hours = 10.625 days */ }; +/** PCF8523 Watchdog Timeout */ +enum PCF8523WatchdogTimeoutUnity { + PCF8523_WDG_DISABLED = 0, /** Watchog Timer disabled*/ + PCF8523_WDG_SEC = 2, /** Watchog Timer unity will be seconds*/ + PCF8523_WDG_MIN = 3, /** Watchog Timer unity will be minutes*/ + PCF8523_WDG_HOUR = 4, /** Watchog Timer unity will be hours*/ +}; + /** PCF8523 Timer Interrupt Low Pulse Width options for Timer B only */ enum PCF8523TimerIntPulse { PCF8523_LowPulse3x64Hz = 0, /**< 46.875 ms 3/64ths second */ @@ -442,6 +450,12 @@ class RTC_PCF8523 : RTC_I2C { void disableCountdownTimer(void); void deconfigureAllTimers(void); void calibrate(Pcf8523OffsetMode mode, int8_t offset); + void enableWatchdog(PCF8523WatchdogTimeoutUnity wdgTimeoutUnity, uint8_t wdgTimeoutValue); + void resetWatchdog(void); + void disableWatchdog(void); +private: + PCF8523WatchdogTimeoutUnity wdgTimeoutUnitySet; + uint8_t wdgTimeoutValueSet; }; /**************************************************************************/ From 001f729d6f43d4389fd159dcc7bcfb16e55f50e1 Mon Sep 17 00:00:00 2001 From: Aurelien BOUIN Date: Sat, 8 Jun 2024 09:16:16 +0200 Subject: [PATCH 7/7] Add isWatchdogFired for Watchdog TimerA on PCF8523 --- src/RTC_PCF8523.cpp | 13 +++++++++++++ src/RTClib.h | 1 + 2 files changed, 14 insertions(+) diff --git a/src/RTC_PCF8523.cpp b/src/RTC_PCF8523.cpp index 684f5c49..7f336560 100644 --- a/src/RTC_PCF8523.cpp +++ b/src/RTC_PCF8523.cpp @@ -137,6 +137,19 @@ void RTC_PCF8523::enableAlarm() { read_register(PCF8523_CONTROL_1) | (1 << 1)); // Enable AIE } +/**************************************************************************/ +/*! + @brief Check Watchdog TimerA fired, isWatchdogFired must be read at the + very beginning, because flag is read-only and cleared by reading + register Control_2 + @return 1 if a Watchdog TimerA fired +*/ +/**************************************************************************/ + +bool RTC_PCF8523::isWatchdogFired(void) { + return (read_register(PCF8523_CONTROL_2) & (1 << 7)); // Check WTAF +} + /**************************************************************************/ /*! @brief Check Alarm fired diff --git a/src/RTClib.h b/src/RTClib.h index ae5b4f29..e31ac233 100644 --- a/src/RTClib.h +++ b/src/RTClib.h @@ -425,6 +425,7 @@ class RTC_PCF8523 : RTC_I2C { void adjust(const DateTime &dt); bool lostPower(void); bool initialized(void); + bool isWatchdogFired(void); bool isAlarmFired(void); bool isAnyAlarmSetup(void); DateTime now();