From 0385636e4af83660eddbd6f2efc666998a89b03d Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Fri, 8 Sep 2023 14:25:41 +0200 Subject: [PATCH] feat: add a parameter to set binary mode This is valid when the RTC_BINARY_MIX mode exists in the RTC (bitfield in the RTC ICSR register) Set the RTC mode through a setBinaryMode function to be called before begin. Signed-off-by: Francois Ramu Co-authored-by: Frederic Pillon --- src/STM32RTC.cpp | 21 ++++++++++++++++++++ src/STM32RTC.h | 12 +++++++++++- src/rtc.c | 51 +++++++++++++++++++++++++++++++++++++++++++++--- src/rtc.h | 8 +++++++- 4 files changed, 87 insertions(+), 5 deletions(-) diff --git a/src/STM32RTC.cpp b/src/STM32RTC.cpp index 5a0f4ef..4e8e58d 100644 --- a/src/STM32RTC.cpp +++ b/src/STM32RTC.cpp @@ -63,6 +63,7 @@ void STM32RTC::begin(bool resetTime, Hour_Format format) _format = format; reinit = RTC_init((format == HOUR_12) ? HOUR_FORMAT_12 : HOUR_FORMAT_24, + (_mode == MODE_MIX) ? ::MODE_BINARY_MIX : ((_mode == MODE_BIN) ? ::MODE_BINARY_ONLY : ::MODE_BINARY_NONE), (_clockSource == LSE_CLOCK) ? ::LSE_CLOCK : (_clockSource == HSE_CLOCK) ? ::HSE_CLOCK : ::LSI_CLOCK , resetTime); @@ -136,6 +137,26 @@ void STM32RTC::setClockSource(Source_Clock source, uint32_t predivA, uint32_t pr RTC_setPrediv(predivA, predivS); } +/** + * @brief get the Binary Mode. + * @retval mode: MODE_BCD, MODE_BIN or MODE_MIX + */ +STM32RTC::Binary_Mode STM32RTC::getBinaryMode(void) +{ + return _mode; +} + +/** + * @brief set the Binary Mode. By default MODE_BCD is selected. This + * method must be called before begin(). + * @param mode: the RTC mode: MODE_BCD, MODE_BIN or MODE_MIX + * @retval None + */ +void STM32RTC::setBinaryMode(Binary_Mode mode) +{ + _mode = mode; +} + /** * @brief get user (a)synchronous prescaler values if set else computed * ones for the current clock source. diff --git a/src/STM32RTC.h b/src/STM32RTC.h index 1fd71e4..78b0b51 100644 --- a/src/STM32RTC.h +++ b/src/STM32RTC.h @@ -85,6 +85,12 @@ class STM32RTC { PM = HOUR_PM }; + enum Binary_Mode : uint8_t { + MODE_BCD = MODE_BINARY_NONE, /* not used */ + MODE_BIN = MODE_BINARY_ONLY, + MODE_MIX = MODE_BINARY_MIX + }; + enum Alarm_Match : uint8_t { MATCH_OFF = OFF_MSK, // Never MATCH_SS = SS_MSK, // Every Minute @@ -130,6 +136,9 @@ class STM32RTC { void getPrediv(uint32_t *predivA, uint32_t *predivS); void setPrediv(uint32_t predivA, uint32_t predivS); + Binary_Mode getBinaryMode(void); + void setBinaryMode(Binary_Mode mode); + void enableAlarm(Alarm_Match match, Alarm name = ALARM_A); void disableAlarm(Alarm name = ALARM_A); @@ -227,7 +236,7 @@ class STM32RTC { friend class STM32LowPower; private: - STM32RTC(void): _clockSource(LSI_CLOCK) + STM32RTC(void): _clockSource(LSI_CLOCK), _mode(MODE_BCD) { setClockSource(_clockSource); } @@ -235,6 +244,7 @@ class STM32RTC { static bool _timeSet; Hour_Format _format; + Binary_Mode _mode; AM_PM _hoursPeriod; uint8_t _hours; uint8_t _minutes; diff --git a/src/rtc.c b/src/rtc.c index 3c81495..922b8d2 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -79,12 +79,16 @@ static uint32_t prediv = RTC_AUTO_1_SECOND; #endif /* !STM32F1xx */ static hourFormat_t initFormat = HOUR_FORMAT_12; +static binaryMode_t initMode = MODE_BINARY_NONE; /* Private function prototypes -----------------------------------------------*/ static void RTC_initClock(sourceClock_t source); #if !defined(STM32F1xx) static void RTC_computePrediv(uint32_t *asynch, uint32_t *synch); #endif /* !STM32F1xx */ +#if defined(RTC_BINARY_NONE) +static void RTC_BinaryConf(binaryMode_t mode); +#endif static inline int _log2(int x) { @@ -334,17 +338,49 @@ static void RTC_computePrediv(uint32_t *asynch, uint32_t *synch) } #endif /* !STM32F1xx */ +#if defined(RTC_BINARY_NONE) +static void RTC_BinaryConf(binaryMode_t mode) +{ + RtcHandle.Init.BinMode = (mode == MODE_BINARY_MIX) ? RTC_BINARY_MIX : ((mode == MODE_BINARY_ONLY) ? RTC_BINARY_ONLY : RTC_BINARY_NONE); + if (RtcHandle.Init.BinMode == RTC_BINARY_MIX) { + /* Configure the 1s BCD calendar increment */ + + uint32_t inc = 1 / (1.0 / ((float)clkVal / (float)(predivAsync + 1.0))); + if (inc <= 256) { + RtcHandle.Init.BinMixBcdU = RTC_BINARY_MIX_BCDU_0; + } else if (inc < (256 << 1)) { + RtcHandle.Init.BinMixBcdU = RTC_BINARY_MIX_BCDU_1; + } else if (inc < (256 << 2)) { + RtcHandle.Init.BinMixBcdU = RTC_BINARY_MIX_BCDU_2; + } else if (inc < (256 << 3)) { + RtcHandle.Init.BinMixBcdU = RTC_BINARY_MIX_BCDU_3; + } else if (inc < (256 << 4)) { + RtcHandle.Init.BinMixBcdU = RTC_BINARY_MIX_BCDU_4; + } else if (inc < (256 << 5)) { + RtcHandle.Init.BinMixBcdU = RTC_BINARY_MIX_BCDU_5; + } else if (inc < (256 << 6)) { + RtcHandle.Init.BinMixBcdU = RTC_BINARY_MIX_BCDU_6; + } else if (inc < (256 << 7)) { + RtcHandle.Init.BinMixBcdU = RTC_BINARY_MIX_BCDU_7; + } else { + Error_Handler(); + } + } +} +#endif /* RTC_BINARY_NONE */ + /** * @brief RTC Initialization * This function configures the RTC time and calendar. By default, the * RTC is set to the 1st January 2001 * Note: year 2000 is invalid as it is the hardware reset value and doesn't raise INITS flag * @param format: enable the RTC in 12 or 24 hours mode + * @param mode: enable the RTC in BCD or Mix or Binary mode * @param source: RTC clock source: LSE, LSI or HSE * @param reset: force RTC reset, even if previously configured * @retval True if RTC is reinitialized, else false */ -bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) +bool RTC_init(hourFormat_t format, binaryMode_t mode, sourceClock_t source, bool reset) { bool reinit = false; hourAM_PM_t period = HOUR_AM, alarmPeriod = HOUR_AM; @@ -360,7 +396,7 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) #endif initFormat = format; - + initMode = mode; /* Ensure all RtcHandle properly set */ RtcHandle.Instance = RTC; #if defined(STM32F1xx) @@ -409,7 +445,10 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) // Init RTC clock RTC_initClock(source); RTC_getPrediv(&(RtcHandle.Init.AsynchPrediv), &(RtcHandle.Init.SynchPrediv)); -#endif // STM32F1xx +#if defined(RTC_BINARY_NONE) + RTC_BinaryConf(mode); +#endif /* RTC_BINARY_NONE */ +#endif // STM32F1xx HAL_RTC_Init(&RtcHandle); // Default: saturday 1st of January 2001 @@ -463,6 +502,9 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) // Init RTC clock RTC_initClock(source); RTC_getPrediv(&(RtcHandle.Init.AsynchPrediv), &(RtcHandle.Init.SynchPrediv)); +#if defined(RTC_BINARY_NONE) + RTC_BinaryConf(mode); +#endif /* RTC_BINARY_NONE */ HAL_RTC_Init(&RtcHandle); // Restore config RTC_SetTime(hours, minutes, seconds, subSeconds, period); @@ -481,6 +523,9 @@ bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset) RTC_initClock(source); // This initialize variables: predivAsync, predivSync and predivSync_bits RTC_getPrediv(&(RtcHandle.Init.AsynchPrediv), &(RtcHandle.Init.SynchPrediv)); +#if defined(RTC_BINARY_NONE) + RTC_BinaryConf(mode); +#endif /* RTC_BINARY_NONE */ #if defined(STM32F1xx) memcpy(&RtcHandle.DateToUpdate, &BackupDate, 4); /* Update date automatically by calling HAL_RTC_GetDate */ diff --git a/src/rtc.h b/src/rtc.h index 4e384d3..72070d2 100644 --- a/src/rtc.h +++ b/src/rtc.h @@ -55,6 +55,12 @@ typedef enum { HOUR_FORMAT_24 } hourFormat_t; +typedef enum { + MODE_BINARY_NONE, /* BCD only */ + MODE_BINARY_ONLY, + MODE_BINARY_MIX +} binaryMode_t; + typedef enum { HOUR_AM, HOUR_PM @@ -169,7 +175,7 @@ void RTC_SetClockSource(sourceClock_t source); void RTC_getPrediv(uint32_t *asynch, uint32_t *synch); void RTC_setPrediv(uint32_t asynch, uint32_t synch); -bool RTC_init(hourFormat_t format, sourceClock_t source, bool reset); +bool RTC_init(hourFormat_t format, binaryMode_t mode, sourceClock_t source, bool reset); void RTC_DeInit(bool reset_cb); bool RTC_IsConfigured(void);