diff --git a/applications/dolphin/helpers/dolphin_state.c b/applications/dolphin/helpers/dolphin_state.c index 86287a2a6..8a569392a 100644 --- a/applications/dolphin/helpers/dolphin_state.c +++ b/applications/dolphin/helpers/dolphin_state.c @@ -72,19 +72,8 @@ bool dolphin_state_load(DolphinState* dolphin_state) { uint64_t dolphin_state_timestamp() { FuriHalRtcDateTime datetime; - struct tm current; - furi_hal_rtc_get_datetime(&datetime); - - current.tm_year = datetime.year - 1900; - current.tm_mday = datetime.day; - current.tm_mon = datetime.month - 1; - - current.tm_hour = datetime.hour; - current.tm_min = datetime.minute; - current.tm_sec = datetime.second; - - return mktime(¤t); + return furi_hal_rtc_datetime_to_timestamp(&datetime); } bool dolphin_state_is_levelup(uint32_t icounter) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_rtc.c b/firmware/targets/f7/furi_hal/furi_hal_rtc.c index b580a04b7..df410a9f4 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_rtc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_rtc.c @@ -33,6 +33,20 @@ typedef struct { _Static_assert(sizeof(DeveloperReg) == 4, "DeveloperReg size mismatch"); +#define FURI_HAL_RTC_SECONDS_PER_MINUTE 60 +#define FURI_HAL_RTC_SECONDS_PER_HOUR (FURI_HAL_RTC_SECONDS_PER_MINUTE * 60) +#define FURI_HAL_RTC_SECONDS_PER_DAY (FURI_HAL_RTC_SECONDS_PER_HOUR * 24) +#define FURI_HAL_RTC_MONTHS_COUNT 12 +#define FURI_HAL_RTC_EPOCH_START_YEAR 1970 +#define FURI_HAL_RTC_IS_LEAP_YEAR(year) \ + ((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0)) + +static const uint8_t furi_hal_rtc_days_per_month[][FURI_HAL_RTC_MONTHS_COUNT] = { + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; + +static const uint16_t furi_hal_rtc_days_per_year[] = {365, 366}; + void furi_hal_rtc_init_early() { // LSE and RTC LL_PWR_EnableBkUpAccess(); @@ -259,3 +273,34 @@ void furi_hal_rtc_set_pin_fails(uint32_t value) { uint32_t furi_hal_rtc_get_pin_fails() { return furi_hal_rtc_get_register(FuriHalRtcRegisterPinFails); } + +uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime) { + uint32_t timestamp = 0; + uint8_t years = 0; + uint8_t leap_years = 0; + + for(uint16_t y = FURI_HAL_RTC_EPOCH_START_YEAR; y < datetime->year; y++) { + if(FURI_HAL_RTC_IS_LEAP_YEAR(y)) { + leap_years++; + } else { + years++; + } + } + + timestamp += + ((years * furi_hal_rtc_days_per_year[0]) + (leap_years * furi_hal_rtc_days_per_year[1])) * + FURI_HAL_RTC_SECONDS_PER_DAY; + + uint8_t year_index = (FURI_HAL_RTC_IS_LEAP_YEAR(datetime->year)) ? 1 : 0; + + for(uint8_t m = 0; m < (datetime->month - 1); m++) { + timestamp += furi_hal_rtc_days_per_month[year_index][m] * FURI_HAL_RTC_SECONDS_PER_DAY; + } + + timestamp += (datetime->day - 1) * FURI_HAL_RTC_SECONDS_PER_DAY; + timestamp += datetime->hour * FURI_HAL_RTC_SECONDS_PER_HOUR; + timestamp += datetime->minute * FURI_HAL_RTC_SECONDS_PER_MINUTE; + timestamp += datetime->second; + + return timestamp; +} diff --git a/firmware/targets/furi_hal_include/furi_hal_rtc.h b/firmware/targets/furi_hal_include/furi_hal_rtc.h index 21c69b241..bdae3b931 100644 --- a/firmware/targets/furi_hal_include/furi_hal_rtc.h +++ b/firmware/targets/furi_hal_include/furi_hal_rtc.h @@ -93,6 +93,8 @@ void furi_hal_rtc_set_pin_fails(uint32_t value); uint32_t furi_hal_rtc_get_pin_fails(); +uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime); + #ifdef __cplusplus } #endif