diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index fae2f10c39b..1055cb2bfd4 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,27.0,, +Version,+,27.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1313,6 +1313,8 @@ Function,+,furi_hal_rtc_datetime_to_timestamp,uint32_t,FuriHalRtcDateTime* Function,-,furi_hal_rtc_deinit_early,void, Function,+,furi_hal_rtc_get_boot_mode,FuriHalRtcBootMode, Function,+,furi_hal_rtc_get_datetime,void,FuriHalRtcDateTime* +Function,+,furi_hal_rtc_get_days_per_month,uint8_t,"_Bool, uint8_t" +Function,+,furi_hal_rtc_get_days_per_year,uint16_t,uint16_t Function,+,furi_hal_rtc_get_fault_data,uint32_t, Function,+,furi_hal_rtc_get_heap_track_mode,FuriHalRtcHeapTrackMode, Function,+,furi_hal_rtc_get_locale_dateformat,FuriHalRtcLocaleDateFormat, @@ -1325,6 +1327,7 @@ Function,+,furi_hal_rtc_get_timestamp,uint32_t, Function,-,furi_hal_rtc_init,void, Function,-,furi_hal_rtc_init_early,void, Function,+,furi_hal_rtc_is_flag_set,_Bool,FuriHalRtcFlag +Function,+,furi_hal_rtc_is_leap_year,_Bool,uint16_t Function,+,furi_hal_rtc_reset_flag,void,FuriHalRtcFlag Function,+,furi_hal_rtc_set_boot_mode,void,FuriHalRtcBootMode Function,+,furi_hal_rtc_set_datetime,void,FuriHalRtcDateTime* @@ -3085,7 +3088,6 @@ Variable,+,furi_hal_i2c_bus_external,FuriHalI2cBus, Variable,+,furi_hal_i2c_bus_power,FuriHalI2cBus, Variable,+,furi_hal_i2c_handle_external,FuriHalI2cBusHandle, Variable,+,furi_hal_i2c_handle_power,FuriHalI2cBusHandle, -Variable,+,furi_hal_rtc_days_per_month,const uint8_t[2][12], Variable,+,furi_hal_sd_spi_handle,FuriHalSpiBusHandle*, Variable,+,furi_hal_spi_bus_d,FuriHalSpiBus, Variable,+,furi_hal_spi_bus_handle_display,FuriHalSpiBusHandle, diff --git a/firmware/targets/f7/furi_hal/furi_hal_rtc.c b/firmware/targets/f7/furi_hal/furi_hal_rtc.c index abce7de920a..8dfe1a13ec7 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_rtc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_rtc.c @@ -39,7 +39,13 @@ typedef struct { _Static_assert(sizeof(SystemReg) == 4, "SystemReg size mismatch"); -const uint8_t furi_hal_rtc_days_per_month[2][FURI_HAL_RTC_MONTHS_COUNT] = { +#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 + +static const uint8_t furi_hal_rtc_days_per_month[2][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}}; @@ -387,7 +393,7 @@ uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime) { 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)) { + if(furi_hal_rtc_is_leap_year(y)) { leap_years++; } else { years++; @@ -398,10 +404,10 @@ uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime) { ((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; + bool leap_year = furi_hal_rtc_is_leap_year(datetime->year); - 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; + for(uint8_t m = 1; m < datetime->month; m++) { + timestamp += furi_hal_rtc_get_days_per_month(leap_year, m) * FURI_HAL_RTC_SECONDS_PER_DAY; } timestamp += (datetime->day - 1) * FURI_HAL_RTC_SECONDS_PER_DAY; @@ -411,3 +417,15 @@ uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime) { return timestamp; } + +uint16_t furi_hal_rtc_get_days_per_year(uint16_t year) { + return furi_hal_rtc_days_per_year[furi_hal_rtc_is_leap_year(year) ? 1 : 0]; +} + +bool furi_hal_rtc_is_leap_year(uint16_t year) { + return (((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0); +} + +uint8_t furi_hal_rtc_get_days_per_month(bool leap_year, uint8_t month) { + return furi_hal_rtc_days_per_month[leap_year ? 1 : 0][month - 1]; +} diff --git a/firmware/targets/furi_hal_include/furi_hal_rtc.h b/firmware/targets/furi_hal_include/furi_hal_rtc.h index ed7aee228dc..186d22f0798 100644 --- a/firmware/targets/furi_hal_include/furi_hal_rtc.h +++ b/firmware/targets/furi_hal_include/furi_hal_rtc.h @@ -12,17 +12,6 @@ extern "C" { #endif -#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_EPOCH_START_YEAR 1970 -#define FURI_HAL_RTC_IS_LEAP_YEAR(year) \ - ((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0)) - -#define FURI_HAL_RTC_MONTHS_COUNT 12 - -extern const uint8_t furi_hal_rtc_days_per_month[2][FURI_HAL_RTC_MONTHS_COUNT]; - typedef struct { // Time uint8_t hour; /**< Hour in 24H format: 0-23 */ @@ -266,6 +255,30 @@ uint32_t furi_hal_rtc_get_timestamp(); */ uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime); +/** Gets the number of days in the year according to the Gregorian calendar. + * + * @param year Input year. + * + * @return number of days in `year`. + */ +uint16_t furi_hal_rtc_get_days_per_year(uint16_t year); + +/** Check if a year a leap year in the Gregorian calendar. + * + * @param year Input year. + * + * @return true if `year` is a leap year. + */ +bool furi_hal_rtc_is_leap_year(uint16_t year); + +/** Get the number of days in the month. + * + * @param leap_year true to calculate based on leap years + * @param month month to check, where 1 = January + * @return the number of days in the month + */ +uint8_t furi_hal_rtc_get_days_per_month(bool leap_year, uint8_t month); + #ifdef __cplusplus } #endif diff --git a/lib/nfc/parsers/opal.c b/lib/nfc/parsers/opal.c index 05b67fd7ec9..5a54dc82001 100644 --- a/lib/nfc/parsers/opal.c +++ b/lib/nfc/parsers/opal.c @@ -64,7 +64,7 @@ void opal_date_time_to_furi(uint16_t days, uint16_t minutes, FuriHalRtcDateTime* if(!out) return; uint16_t diy; out->year = 1980; - out->month = 0; + out->month = 1; // 1980-01-01 is a Tuesday out->weekday = ((days + 1) % 7) + 1; out->hour = minutes / 60; @@ -73,7 +73,7 @@ void opal_date_time_to_furi(uint16_t days, uint16_t minutes, FuriHalRtcDateTime* // What year is it? for(;;) { - diy = (FURI_HAL_RTC_IS_LEAP_YEAR(out->year) ? 366 : 365); + diy = furi_hal_rtc_get_days_per_year(out->year); if(days < diy) break; days -= diy; out->year++; @@ -82,16 +82,15 @@ void opal_date_time_to_furi(uint16_t days, uint16_t minutes, FuriHalRtcDateTime* // 1-index the day of the year days++; // What month is it? - uint8_t is_leap = diy - 365; + bool is_leap = furi_hal_rtc_is_leap_year(out->year); for(;;) { - uint8_t dim = furi_hal_rtc_days_per_month[is_leap][out->month]; + uint8_t dim = furi_hal_rtc_get_days_per_month(is_leap, out->month); if(days <= dim) break; days -= dim; out->month++; } - out->month++; out->day = days; }