From ef525858470d64e6a9de4fc8670cbfc508f4be54 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 20 Mar 2024 18:00:17 +0300 Subject: [PATCH] update dcf77 sync --- .../dcf77_clock_sync/application.fam | 10 +- non_catalog_apps/dcf77_clock_sync/dcf77.c | 2 +- non_catalog_apps/dcf77_clock_sync/dcf77.h | 5 +- .../dcf77_clock_sync/dcf77_clock_sync.c | 172 ++++++++---------- 4 files changed, 88 insertions(+), 101 deletions(-) diff --git a/non_catalog_apps/dcf77_clock_sync/application.fam b/non_catalog_apps/dcf77_clock_sync/application.fam index 2e9b5ac35d6..5eb81ea5760 100644 --- a/non_catalog_apps/dcf77_clock_sync/application.fam +++ b/non_catalog_apps/dcf77_clock_sync/application.fam @@ -8,8 +8,8 @@ App( order=10, fap_icon="icons/app_10x10.png", fap_category="Tools", - fap_author="@mdaskalov", - fap_weburl="https://github.com/mdaskalov/dcf77-clock-sync.git", - fap_version="1.1", - fap_description="Emulate DCF77 time signal on the RFID antena and the A4 GPIO pin", -) + fap_author="mdaskalov", + fap_weburl="https://github.com/mdaskalov/dcf77-clock-sync", + fap_version="1.3", + fap_description="Emulate DCF77 time signal on the RFID antenna and the A4 GPIO pin", +) \ No newline at end of file diff --git a/non_catalog_apps/dcf77_clock_sync/dcf77.c b/non_catalog_apps/dcf77_clock_sync/dcf77.c index a7bac6e910a..b5c5693a59b 100644 --- a/non_catalog_apps/dcf77_clock_sync/dcf77.c +++ b/non_catalog_apps/dcf77_clock_sync/dcf77.c @@ -1,4 +1,4 @@ -#include +#include "dcf77.h" #define DST_BIT 17 #define MIN_BIT 21 diff --git a/non_catalog_apps/dcf77_clock_sync/dcf77.h b/non_catalog_apps/dcf77_clock_sync/dcf77.h index 32436848bb0..cd092f09b44 100644 --- a/non_catalog_apps/dcf77_clock_sync/dcf77.h +++ b/non_catalog_apps/dcf77_clock_sync/dcf77.h @@ -1,7 +1,8 @@ #pragma once -#include +#include +#include void set_dcf77_time(DateTime* dt, bool is_dst); -int get_dcf77_bit(int sec); +bool get_dcf77_bit(int sec); char* get_dcf77_data(int sec); \ No newline at end of file diff --git a/non_catalog_apps/dcf77_clock_sync/dcf77_clock_sync.c b/non_catalog_apps/dcf77_clock_sync/dcf77_clock_sync.c index 948df3de3e8..e242324e176 100644 --- a/non_catalog_apps/dcf77_clock_sync/dcf77_clock_sync.c +++ b/non_catalog_apps/dcf77_clock_sync/dcf77_clock_sync.c @@ -4,6 +4,9 @@ #include #include +#include +#include + #include "dcf77.h" #define SCREEN_SIZE_X 128 @@ -11,56 +14,59 @@ #define DCF77_FREQ 77500 #define DCF77_OFFSET 60 #define SYNC_DELAY 50 -#define UPDATES 8 - -#define SECONDS_PER_MINUTE 60 -#define SECONDS_PER_HOUR (SECONDS_PER_MINUTE * 60) -#define SECONDS_PER_DAY (SECONDS_PER_HOUR * 24) -#define MONTHS_COUNT 12 -#define EPOCH_START_YEAR 1970 char* WEEKDAYS[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; typedef struct { DateTime dt; - DateTime dcf_dt; bool is_dst; + FuriString* str; + LocaleTimeFormat tim_fmt; + LocaleDateFormat dat_fmt; } AppData; static void app_draw_callback(Canvas* canvas, void* context) { - AppData* app_data = (AppData*)context; - - char buffer[64]; + AppData* app = (AppData*)context; + furi_assert(app->str); + + uint8_t hour = app->dt.hour; + bool fmt_12h = false; + if(app->tim_fmt == LocaleTimeFormat12h) { + hour = hour == 0 ? 12 : hour % 12; + fmt_12h = true; + } - snprintf( - buffer, - sizeof(buffer), - "%02u:%02u:%02u", - app_data->dt.hour, - app_data->dt.minute, - app_data->dt.second); + furi_string_printf(app->str, "%2u:%02u:%02u", hour, app->dt.minute, app->dt.second); + const char* tim_cstr = furi_string_get_cstr(app->str); canvas_set_font(canvas, FontBigNumbers); canvas_draw_str_aligned( - canvas, SCREEN_SIZE_X / 2, SCREEN_SIZE_Y / 2, AlignCenter, AlignCenter, buffer); - - const char* dow_str = WEEKDAYS[(app_data->dt.weekday - 1) % 7]; - const char* dst_str = app_data->is_dst ? "CEST" : "CET"; - snprintf( - buffer, - sizeof(buffer), - "%s %02u-%02u-%04u %s", - dow_str, - app_data->dt.day, - app_data->dt.month, - app_data->dt.year, - dst_str); + canvas, SCREEN_SIZE_X / 2, SCREEN_SIZE_Y / 2, AlignCenter, AlignCenter, tim_cstr); + + if(fmt_12h) { + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned( + canvas, + 0, + (SCREEN_SIZE_Y / 2) - 7, + AlignLeft, + AlignTop, + (app->dt.hour >= 12 ? "PM" : "AM")); + } + + FuriString* dat = furi_string_alloc(); + locale_format_date(dat, &app->dt, app->dat_fmt, "-"); + const char* dow_str = WEEKDAYS[(app->dt.weekday - 1) % 7]; + const char* dst_str = app->is_dst ? "CEST" : "CET"; + furi_string_printf(app->str, "%s %s %s", dow_str, furi_string_get_cstr(dat), dst_str); + furi_string_free(dat); canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, SCREEN_SIZE_X / 2, 0, AlignCenter, AlignTop, buffer); + canvas_draw_str_aligned( + canvas, SCREEN_SIZE_X / 2, 0, AlignCenter, AlignTop, furi_string_get_cstr(app->str)); - if(app_data->dt.second < 59) { - char* data = get_dcf77_data(app_data->dt.second); + if(app->dt.second < 59) { + char* data = get_dcf77_data(app->dt.second); canvas_draw_str_aligned( canvas, SCREEN_SIZE_X, SCREEN_SIZE_Y, AlignRight, AlignBottom, data); } @@ -72,48 +78,29 @@ static void app_input_callback(InputEvent* input_event, void* ctx) { furi_message_queue_put(event_queue, input_event, FuriWaitForever); } -void time_add(DateTime* from, DateTime* to, int add) { - uint32_t timestamp = datetime_datetime_to_timestamp(from) + add; - - uint32_t days = timestamp / SECONDS_PER_DAY; - uint32_t seconds_in_day = timestamp % SECONDS_PER_DAY; - - to->year = EPOCH_START_YEAR; - - while(days >= datetime_get_days_per_year(to->year)) { - days -= datetime_get_days_per_year(to->year); - (to->year)++; - } - - to->month = 1; - while(days >= datetime_get_days_per_month(datetime_is_leap_year(to->year), to->month)) { - days -= datetime_get_days_per_month(datetime_is_leap_year(to->year), to->month); - (to->month)++; - } - - to->weekday = ((days + 4) % 7) + 1; - - to->day = days + 1; - to->hour = seconds_in_day / SECONDS_PER_HOUR; - to->minute = (seconds_in_day % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE; - to->second = seconds_in_day % SECONDS_PER_MINUTE; +void set_time(AppData* app, int offset) { + DateTime dcf_dt; + uint32_t timestamp = datetime_datetime_to_timestamp(&app->dt) + offset; + datetime_timestamp_to_datetime(timestamp, &dcf_dt); + set_dcf77_time(&dcf_dt, app->is_dst); } int dcf77_clock_sync_app_main(void* p) { UNUSED(p); - AppData app_data; - InputEvent event; + AppData* app = malloc(sizeof(AppData)); + furi_hal_rtc_get_datetime(&app->dt); + app->is_dst = false; + app->str = furi_string_alloc(); + app->tim_fmt = locale_get_time_format(); + app->dat_fmt = locale_get_date_format(); - app_data.is_dst = false; - furi_hal_rtc_get_datetime(&app_data.dt); - time_add(&app_data.dt, &app_data.dcf_dt, DCF77_OFFSET); - set_dcf77_time(&app_data.dcf_dt, app_data.is_dst); + set_time(app, DCF77_OFFSET); ViewPort* view_port = view_port_alloc(); FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); - view_port_draw_callback_set(view_port, app_draw_callback, &app_data); + view_port_draw_callback_set(view_port, app_draw_callback, app); view_port_input_callback_set(view_port, app_input_callback, event_queue); Gui* gui = furi_record_open(RECORD_GUI); @@ -122,52 +109,48 @@ int dcf77_clock_sync_app_main(void* p) { NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); notification_message_block(notification, &sequence_display_backlight_enforce_on); + InputEvent event; bool running = false; bool exit = false; - int sec = app_data.dt.second; + int sec = app->dt.second; while(!exit) { int silence_ms = 0; // wait next second - while(app_data.dt.second == sec) furi_hal_rtc_get_datetime(&app_data.dt); + while(app->dt.second == sec) furi_hal_rtc_get_datetime(&app->dt); - if(app_data.dt.second < 59) { - furi_hal_light_set(LightRed | LightGreen | LightBlue, 0); + if(app->dt.second < 59) { if(running) { + furi_hal_light_set(LightRed | LightGreen | LightBlue, 0); furi_hal_rfid_tim_read_stop(); furi_hal_pwm_stop(FuriHalPwmOutputIdLptim2PA4); furi_hal_gpio_init( &gpio_ext_pa4, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); } - silence_ms = get_dcf77_bit(app_data.dt.second) ? 200 : 100; + silence_ms = get_dcf77_bit(app->dt.second) ? 200 : 100; furi_delay_ms(silence_ms); furi_hal_rfid_tim_read_start(DCF77_FREQ, 0.5); furi_hal_pwm_start(FuriHalPwmOutputIdLptim2PA4, DCF77_FREQ, 50); - running = true; furi_hal_light_set(LightBlue, 0xFF); - } else { - time_add(&app_data.dt, &app_data.dcf_dt, DCF77_OFFSET + 1); - set_dcf77_time(&app_data.dcf_dt, app_data.is_dst); - } - - sec = app_data.dt.second; - int wait_ms = (1000 - silence_ms - SYNC_DELAY) / UPDATES; - for(int i = 0; i < UPDATES; i++) { - if(furi_message_queue_get(event_queue, &event, wait_ms) == FuriStatusOk) { - if((event.type == InputTypePress) || (event.type == InputTypeRepeat)) { - switch(event.key) { - case InputKeyOk: - app_data.is_dst = !app_data.is_dst; - break; - case InputKeyBack: - exit = true; - break; - default: - break; - } + running = true; + } else + set_time(app, DCF77_OFFSET + 1); + + sec = app->dt.second; + int wait_ms = 1000 - silence_ms - SYNC_DELAY; + uint32_t tick_start = furi_get_tick(); + while(wait_ms > 0) { + FuriStatus status = furi_message_queue_get(event_queue, &event, wait_ms); + if((status == FuriStatusOk) && (event.type == InputTypePress)) { + if(event.key == InputKeyOk) + app->is_dst = !app->is_dst; + else if(event.key == InputKeyBack) { + exit = true; + break; } } view_port_update(view_port); - if(exit) break; + if(status == FuriStatusErrorTimeout) break; + wait_ms -= furi_get_tick() - tick_start; } } @@ -186,5 +169,8 @@ int dcf77_clock_sync_app_main(void* p) { furi_message_queue_free(event_queue); view_port_free(view_port); + furi_string_free(app->str); + free(app); + return 0; } \ No newline at end of file