Skip to content

Commit 65d3071

Browse files
authored
Merge pull request #6 from mdaskalov/use-locale
Use Locale to format Date and Time
2 parents 660872a + 9f85e85 commit 65d3071

File tree

1 file changed

+74
-61
lines changed

1 file changed

+74
-61
lines changed

dcf77_clock_sync.c

+74-61
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <notification/notification_messages.h>
66

77
#include <datetime/datetime.h>
8+
#include <locale/locale.h>
89

910
#include "dcf77.h"
1011

@@ -13,51 +14,59 @@
1314
#define DCF77_FREQ 77500
1415
#define DCF77_OFFSET 60
1516
#define SYNC_DELAY 50
16-
#define UPDATES 8
17-
18-
#define SECONDS_PER_DAY 60 * 60 * 24
1917

2018
char* WEEKDAYS[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
2119

2220
typedef struct {
2321
DateTime dt;
2422
bool is_dst;
23+
FuriString* str;
24+
LocaleTimeFormat tim_fmt;
25+
LocaleDateFormat dat_fmt;
2526
} AppData;
2627

2728
static void app_draw_callback(Canvas* canvas, void* context) {
28-
AppData* app_data = (AppData*)context;
29-
30-
char buffer[64];
29+
AppData* app = (AppData*)context;
30+
furi_assert(app->str);
31+
32+
uint8_t hour = app->dt.hour;
33+
bool fmt_12h = false;
34+
if(app->tim_fmt == LocaleTimeFormat12h) {
35+
hour = hour == 0 ? 12 : hour % 12;
36+
fmt_12h = true;
37+
}
3138

32-
snprintf(
33-
buffer,
34-
sizeof(buffer),
35-
"%02u:%02u:%02u",
36-
app_data->dt.hour,
37-
app_data->dt.minute,
38-
app_data->dt.second);
39+
furi_string_printf(app->str, "%2u:%02u:%02u", hour, app->dt.minute, app->dt.second);
40+
const char* tim_cstr = furi_string_get_cstr(app->str);
3941

4042
canvas_set_font(canvas, FontBigNumbers);
4143
canvas_draw_str_aligned(
42-
canvas, SCREEN_SIZE_X / 2, SCREEN_SIZE_Y / 2, AlignCenter, AlignCenter, buffer);
43-
44-
const char* dow_str = WEEKDAYS[(app_data->dt.weekday - 1) % 7];
45-
const char* dst_str = app_data->is_dst ? "CEST" : "CET";
46-
snprintf(
47-
buffer,
48-
sizeof(buffer),
49-
"%s %02u-%02u-%04u %s",
50-
dow_str,
51-
app_data->dt.day,
52-
app_data->dt.month,
53-
app_data->dt.year,
54-
dst_str);
44+
canvas, SCREEN_SIZE_X / 2, SCREEN_SIZE_Y / 2, AlignCenter, AlignCenter, tim_cstr);
45+
46+
if(fmt_12h) {
47+
canvas_set_font(canvas, FontSecondary);
48+
canvas_draw_str_aligned(
49+
canvas,
50+
0,
51+
(SCREEN_SIZE_Y / 2) - 7,
52+
AlignLeft,
53+
AlignTop,
54+
(app->dt.hour >= 12 ? "PM" : "AM"));
55+
}
56+
57+
FuriString* dat = furi_string_alloc();
58+
locale_format_date(dat, &app->dt, app->dat_fmt, "-");
59+
const char* dow_str = WEEKDAYS[(app->dt.weekday - 1) % 7];
60+
const char* dst_str = app->is_dst ? "CEST" : "CET";
61+
furi_string_printf(app->str, "%s %s %s", dow_str, furi_string_get_cstr(dat), dst_str);
62+
furi_string_free(dat);
5563

5664
canvas_set_font(canvas, FontSecondary);
57-
canvas_draw_str_aligned(canvas, SCREEN_SIZE_X / 2, 0, AlignCenter, AlignTop, buffer);
65+
canvas_draw_str_aligned(
66+
canvas, SCREEN_SIZE_X / 2, 0, AlignCenter, AlignTop, furi_string_get_cstr(app->str));
5867

59-
if(app_data->dt.second < 59) {
60-
char* data = get_dcf77_data(app_data->dt.second);
68+
if(app->dt.second < 59) {
69+
char* data = get_dcf77_data(app->dt.second);
6170
canvas_draw_str_aligned(
6271
canvas, SCREEN_SIZE_X, SCREEN_SIZE_Y, AlignRight, AlignBottom, data);
6372
}
@@ -69,27 +78,30 @@ static void app_input_callback(InputEvent* input_event, void* ctx) {
6978
furi_message_queue_put(event_queue, input_event, FuriWaitForever);
7079
}
7180

72-
void set_time(AppData* app_data, int offset) {
81+
void set_time(AppData* app, int offset) {
7382
DateTime dcf_dt;
74-
uint32_t timestamp = datetime_datetime_to_timestamp(&app_data->dt) + offset;
83+
uint32_t timestamp = datetime_datetime_to_timestamp(&app->dt) + offset;
7584
datetime_timestamp_to_datetime(timestamp, &dcf_dt);
85+
set_dcf77_time(&dcf_dt, app->is_dst);
7686
set_dcf77_time(&dcf_dt, app_data->is_dst);
7787
}
7888

7989
int dcf77_clock_sync_app_main(void* p) {
8090
UNUSED(p);
8191

82-
AppData app_data;
83-
InputEvent event;
92+
AppData* app = malloc(sizeof(AppData));
93+
furi_hal_rtc_get_datetime(&app->dt);
94+
app->is_dst = false;
95+
app->str = furi_string_alloc();
96+
app->tim_fmt = locale_get_time_format();
97+
app->dat_fmt = locale_get_date_format();
8498

85-
app_data.is_dst = false;
86-
furi_hal_rtc_get_datetime(&app_data.dt);
87-
set_time(&app_data, DCF77_OFFSET);
99+
set_time(app, DCF77_OFFSET);
88100

89101
ViewPort* view_port = view_port_alloc();
90102
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
91103

92-
view_port_draw_callback_set(view_port, app_draw_callback, &app_data);
104+
view_port_draw_callback_set(view_port, app_draw_callback, app);
93105
view_port_input_callback_set(view_port, app_input_callback, event_queue);
94106

95107
Gui* gui = furi_record_open(RECORD_GUI);
@@ -98,50 +110,48 @@ int dcf77_clock_sync_app_main(void* p) {
98110
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
99111
notification_message_block(notification, &sequence_display_backlight_enforce_on);
100112

113+
InputEvent event;
101114
bool running = false;
102115
bool exit = false;
103-
int sec = app_data.dt.second;
116+
int sec = app->dt.second;
104117
while(!exit) {
105118
int silence_ms = 0;
106119
// wait next second
107-
while(app_data.dt.second == sec) furi_hal_rtc_get_datetime(&app_data.dt);
120+
while(app->dt.second == sec) furi_hal_rtc_get_datetime(&app->dt);
108121

109-
if(app_data.dt.second < 59) {
110-
furi_hal_light_set(LightRed | LightGreen | LightBlue, 0);
122+
if(app->dt.second < 59) {
111123
if(running) {
124+
furi_hal_light_set(LightRed | LightGreen | LightBlue, 0);
112125
furi_hal_rfid_tim_read_stop();
113126
furi_hal_pwm_stop(FuriHalPwmOutputIdLptim2PA4);
114127
furi_hal_gpio_init(
115128
&gpio_ext_pa4, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
116129
}
117-
silence_ms = get_dcf77_bit(app_data.dt.second) ? 200 : 100;
130+
silence_ms = get_dcf77_bit(app->dt.second) ? 200 : 100;
118131
furi_delay_ms(silence_ms);
119132
furi_hal_rfid_tim_read_start(DCF77_FREQ, 0.5);
120133
furi_hal_pwm_start(FuriHalPwmOutputIdLptim2PA4, DCF77_FREQ, 50);
121-
running = true;
122134
furi_hal_light_set(LightBlue, 0xFF);
135+
running = true;
123136
} else
124-
set_time(&app_data, DCF77_OFFSET + 1);
125-
126-
sec = app_data.dt.second;
127-
int wait_ms = (1000 - silence_ms - SYNC_DELAY) / UPDATES;
128-
for(int i = 0; i < UPDATES; i++) {
129-
if(furi_message_queue_get(event_queue, &event, wait_ms) == FuriStatusOk) {
130-
if((event.type == InputTypePress) || (event.type == InputTypeRepeat)) {
131-
switch(event.key) {
132-
case InputKeyOk:
133-
app_data.is_dst = !app_data.is_dst;
134-
break;
135-
case InputKeyBack:
136-
exit = true;
137-
break;
138-
default:
139-
break;
140-
}
137+
set_time(app, DCF77_OFFSET + 1);
138+
139+
sec = app->dt.second;
140+
int wait_ms = 1000 - silence_ms - SYNC_DELAY;
141+
uint32_t tick_start = furi_get_tick();
142+
while(wait_ms > 0) {
143+
FuriStatus status = furi_message_queue_get(event_queue, &event, wait_ms);
144+
if((status == FuriStatusOk) && (event.type == InputTypePress)) {
145+
if(event.key == InputKeyOk)
146+
app->is_dst = !app->is_dst;
147+
else if(event.key == InputKeyBack) {
148+
exit = true;
149+
break;
141150
}
142151
}
143152
view_port_update(view_port);
144-
if(exit) break;
153+
if(status == FuriStatusErrorTimeout) break;
154+
wait_ms -= furi_get_tick() - tick_start;
145155
}
146156
}
147157

@@ -160,5 +170,8 @@ int dcf77_clock_sync_app_main(void* p) {
160170
furi_message_queue_free(event_queue);
161171
view_port_free(view_port);
162172

173+
furi_string_free(app->str);
174+
free(app);
175+
163176
return 0;
164177
}

0 commit comments

Comments
 (0)