MX 1 anno fa
parent
commit
ef52585847

+ 5 - 5
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",
+)

+ 1 - 1
non_catalog_apps/dcf77_clock_sync/dcf77.c

@@ -1,4 +1,4 @@
-#include <furi_hal.h>
+#include "dcf77.h"
 
 #define DST_BIT 17
 #define MIN_BIT 21

+ 3 - 2
non_catalog_apps/dcf77_clock_sync/dcf77.h

@@ -1,7 +1,8 @@
 #pragma once
 
-#include <furi_hal.h>
+#include <datetime/datetime.h>
+#include <furi.h>
 
 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);

+ 79 - 93
non_catalog_apps/dcf77_clock_sync/dcf77_clock_sync.c

@@ -4,6 +4,9 @@
 #include <notification/notification.h>
 #include <notification/notification_messages.h>
 
+#include <datetime/datetime.h>
+#include <locale/locale.h>
+
 #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;
 }