/** ****************************************************************************** * @file STM32RTC.h * @author Frederic Pillon * @brief Provides a RTC interface for Arduino * ****************************************************************************** * @attention * *

© COPYRIGHT(c) 2020 STMicroelectronics

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ #ifndef __STM32_RTC_H #define __STM32_RTC_H #include "Arduino.h" #if defined(STM32_CORE_VERSION) && (STM32_CORE_VERSION < 0x02000000) #error "This library is not compatible with core version used. Please update the core." #endif #include "rtc.h" // Check if RTC HAL enable in variants/board_name/stm32yzxx_hal_conf.h #ifndef HAL_RTC_MODULE_ENABLED #error "RTC configuration is missing. Check flag HAL_RTC_MODULE_ENABLED in variants/board_name/stm32yzxx_hal_conf.h" #endif #include /** * @brief STM32 RTC library version number */ #define STM32_RTC_VERSION_MAJOR (0x01U) /*!< [31:24] major version */ #define STM32_RTC_VERSION_MINOR (0x03U) /*!< [23:16] minor version */ #define STM32_RTC_VERSION_PATCH (0x06U) /*!< [15:8] patch version */ /* * Extra label for development: * 0: official release * [1-9]: release candidate * F[0-9]: development */ #define STM32_RTC_VERSION_EXTRA (0x00U) /*!< [7:0] extra version */ #define STM32_RTC_VERSION ((STM32_RTC_VERSION_MAJOR << 24U)\ |(STM32_RTC_VERSION_MINOR << 16U)\ |(STM32_RTC_VERSION_PATCH << 8U )\ |(STM32_RTC_VERSION_EXTRA)) typedef void(*voidFuncPtr)(void *); #define IS_CLOCK_SOURCE(SRC) (((SRC) == STM32RTC::LSI_CLOCK) || ((SRC) == STM32RTC::LSE_CLOCK) ||\ ((SRC) == STM32RTC::HSE_CLOCK)) #define IS_HOUR_FORMAT(FMT) (((FMT) == STM32RTC::HOUR_12) || ((FMT) == STM32RTC::HOUR_24)) class STM32RTC { public: enum Hour_Format : uint8_t { HOUR_12 = HOUR_FORMAT_12, HOUR_24 = HOUR_FORMAT_24 }; enum AM_PM : uint8_t { AM = HOUR_AM, PM = HOUR_PM }; enum Binary_Mode : uint8_t { MODE_BCD = MODE_BINARY_NONE, MODE_BIN = MODE_BINARY_ONLY, MODE_MIX = MODE_BINARY_MIX }; enum Alarm_Match : uint8_t { MATCH_OFF = OFF_MSK, // Never MATCH_SUBSEC = SUBSEC_MSK, // Every Subsecond MATCH_SS = SS_MSK, // Every Minute MATCH_MMSS = SS_MSK | MM_MSK, // Every Hour MATCH_HHMMSS = SS_MSK | MM_MSK | HH_MSK, // Every Day MATCH_DHHMMSS = SS_MSK | MM_MSK | HH_MSK | D_MSK, // Every Month /* NOTE: STM32 RTC can't assign a month or a year to an alarm. Those enum are kept for compatibility but are ignored inside enableAlarm(). */ MATCH_MMDDHHMMSS = SS_MSK | MM_MSK | HH_MSK | D_MSK | M_MSK, MATCH_YYMMDDHHMMSS = SS_MSK | MM_MSK | HH_MSK | D_MSK | M_MSK | Y_MSK }; enum Source_Clock : uint8_t { LSI_CLOCK = ::LSI_CLOCK, LSE_CLOCK = ::LSE_CLOCK, HSE_CLOCK = ::HSE_CLOCK }; enum Alarm : uint32_t { ALARM_A = ::ALARM_A, #ifdef RTC_ALARM_B ALARM_B = ::ALARM_B #endif }; static STM32RTC &getInstance() { static STM32RTC instance; // Guaranteed to be destroyed. // Instantiated on first use. return instance; } STM32RTC(STM32RTC const &) = delete; void operator=(STM32RTC const &) = delete; void begin(bool resetTime, Hour_Format format = HOUR_24); void begin(Hour_Format format = HOUR_24); void end(void); // Could be used to mix Arduino API and STM32Cube HAL API (ex: DMA). Use at your own risk. RTC_HandleTypeDef *getHandle(void) { return RTC_GetHandle(); } Source_Clock getClockSource(void); void setClockSource(Source_Clock source, uint32_t predivA = (PREDIVA_MAX + 1), uint32_t predivS = (PREDIVS_MAX + 1)); 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); void attachInterrupt(voidFuncPtr callback, Alarm name); void attachInterrupt(voidFuncPtr callback, void *data = nullptr, Alarm name = ALARM_A); void detachInterrupt(Alarm name = ALARM_A); #ifdef ONESECOND_IRQn // Other mcu than stm32F1 will use the WakeUp feature to interrupt each second. void attachSecondsInterrupt(voidFuncPtr callback); void detachSecondsInterrupt(void); #endif /* ONESECOND_IRQn */ // Kept for compatibility: use STM32LowPower library. void standbyMode(); /* Get Functions */ uint32_t getSubSeconds(void); uint8_t getSeconds(void); uint8_t getMinutes(void); uint8_t getHours(AM_PM *period = nullptr); void getTime(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *subSeconds, AM_PM *period = nullptr); uint8_t getWeekDay(void); uint8_t getDay(void); uint8_t getMonth(void); uint8_t getYear(void); void getDate(uint8_t *weekDay, uint8_t *day, uint8_t *month, uint8_t *year); uint32_t getAlarmSubSeconds(Alarm name = ALARM_A); uint8_t getAlarmSeconds(Alarm name = ALARM_A); uint8_t getAlarmMinutes(Alarm name = ALARM_A); uint8_t getAlarmHours(Alarm name); uint8_t getAlarmHours(AM_PM *period = nullptr, Alarm name = ALARM_A); uint8_t getAlarmDay(Alarm name = ALARM_A); // Kept for compatibility with Arduino RTCZero library. uint8_t getAlarmMonth(void); uint8_t getAlarmYear(void); /* Set Functions */ void setSubSeconds(uint32_t subSeconds); void setSeconds(uint8_t seconds); void setMinutes(uint8_t minutes); void setHours(uint8_t hours, AM_PM period = AM); void setTime(uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t subSeconds = 1000, AM_PM period = AM); void setWeekDay(uint8_t weekDay); void setDay(uint8_t day); void setMonth(uint8_t month); void setYear(uint8_t year); void setDate(uint8_t day, uint8_t month, uint8_t year); void setDate(uint8_t weekDay, uint8_t day, uint8_t month, uint8_t year); void setAlarmSubSeconds(uint32_t subSeconds, Alarm name = ALARM_A); void setAlarmSeconds(uint8_t seconds, Alarm name = ALARM_A); void setAlarmMinutes(uint8_t minutes, Alarm name = ALARM_A); void setAlarmHours(uint8_t hours, Alarm name); void setAlarmHours(uint8_t hours, AM_PM period = AM, Alarm name = ALARM_A); void setAlarmTime(uint32_t subSeconds, Alarm name = ALARM_A); void setAlarmTime(uint8_t hours, uint8_t minutes, uint8_t seconds, Alarm name); void setAlarmTime(uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t subSeconds, Alarm name); void setAlarmTime(uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t subSeconds = 0, AM_PM period = AM, Alarm name = ALARM_A); void setAlarmDay(uint8_t day, Alarm name = ALARM_A); // Kept for compatibility with Arduino RTCZero library. void setAlarmMonth(uint8_t month); void setAlarmYear(uint8_t year); void setAlarmDate(uint8_t day, uint8_t month, uint8_t year, Alarm name = ALARM_A); /* Epoch Functions */ time_t getEpoch(uint32_t *subSeconds = nullptr); time_t getY2kEpoch(void); void setEpoch(time_t ts, uint32_t subSeconds = 0); void setY2kEpoch(time_t ts); time_t getAlarmEpoch(Alarm name); time_t getAlarmEpoch(uint32_t *subSeconds = nullptr, Alarm name = ALARM_A); void setAlarmEpoch(time_t ts, Alarm_Match match, Alarm name); void setAlarmEpoch(time_t ts, Alarm_Match match = MATCH_DHHMMSS, uint32_t subSeconds = 0, Alarm name = ALARM_A); bool isConfigured(void) { return RTC_IsConfigured(); } bool isAlarmEnabled(Alarm name = ALARM_A); bool isTimeSet(void) { return _timeSet; } friend class STM32LowPower; private: STM32RTC(void): _mode(MODE_BCD), _clockSource(LSI_CLOCK) { setClockSource(_clockSource); } static bool _timeSet; Hour_Format _format; Binary_Mode _mode; AM_PM _hoursPeriod; uint8_t _hours; uint8_t _minutes; uint8_t _seconds; uint32_t _subSeconds; uint8_t _year; uint8_t _month; uint8_t _day; uint8_t _wday; /* ALARM A */ uint8_t _alarmDay; uint8_t _alarmHours; uint8_t _alarmMinutes; uint8_t _alarmSeconds; uint32_t _alarmSubSeconds; AM_PM _alarmPeriod; Alarm_Match _alarmMatch; #ifdef RTC_ALARM_B /* ALARM B */ uint8_t _alarmBDay; uint8_t _alarmBHours; uint8_t _alarmBMinutes; uint8_t _alarmBSeconds; uint32_t _alarmBSubSeconds; AM_PM _alarmBPeriod; Alarm_Match _alarmBMatch; #endif Source_Clock _clockSource; void configForLowPower(Source_Clock source); void syncTime(void); void syncDate(void); void syncAlarmTime(Alarm name = ALARM_A); }; #endif // __STM32_RTC_H