diff --git a/src/rtc.c b/src/rtc.c --- a/src/rtc.c +++ b/src/rtc.c @@ -34,8 +34,8 @@ void rtc_init(void) hrtc.Instance = RTC; hrtc.Init.HourFormat = RTC_HOURFORMAT_24; - hrtc.Init.AsynchPrediv = 124; - hrtc.Init.SynchPrediv = 322; // if this has enough bits should be 1.0018Hz based on 40kHz LSI + hrtc.Init.AsynchPrediv = 127; // Note that both these dividers actually divide by their value + 1 + hrtc.Init.SynchPrediv = 311; // About 1Hz with 40kHz LSI hrtc.Init.OutPut = RTC_OUTPUT_DISABLE; hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; @@ -102,6 +102,58 @@ RTC_TimeTypeDef* rtc_time(void) return &time_last; } +uint16_t __rtc_millis(uint32_t sub_seconds) +{ + // Subsecond counter counts down from SynchPrediv value to zero + return (hrtc.Init.SynchPrediv - sub_seconds) * 999 / hrtc.Init.SynchPrediv; // 0 - 999 mS +} + +#define JULIAN_DATE_BASE 2440588 // Unix epoch time in Julian calendar (UnixTime = 00:00:00 01.01.1970 => JDN = 2440588) + +uint64_t rtc_timestamp(void) +{ + RTC_TimeTypeDef time = {0}; + RTC_DateTypeDef date = {0}; + + HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BCD); + HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BCD); + + // Thanks to LonelyWolf: https://github.com/LonelyWolf/stm32/blob/master/stm32l-dosfs/RTC.c + // Convert Date/Time structures to epoch time + uint8_t a; + uint16_t y; + uint8_t m; + uint64_t JDN; + + // These hardcore math's are taken from http://en.wikipedia.org/wiki/Julian_day + + // Calculate some coefficients + a = (14 - date.Month) / 12; + y = (date.Year + 2000) + 4800 - a; // years since 1 March, 4801 BC + m = date.Month + (12 * a) - 3; // since 1 March, 4801 BC + + // Gregorian calendar date compute + JDN = date.Date; + JDN += (153 * m + 2) / 5; + JDN += 365 * y; + JDN += y / 4; + JDN += -y / 100; + JDN += y / 400; + JDN = JDN - 32045; + JDN = JDN - JULIAN_DATE_BASE; // Calculate from base date + JDN *= 86400; // Days to seconds + JDN += time.Hours * 3600; // ... and today seconds + JDN += time.Minutes * 60; + JDN += time.Seconds; + + JDN *= 1000; // Prepare to add ms + + JDN += __rtc_millis(time.SubSeconds); + + return JDN; + +} + void rtc_cal(void) {