5
5
#include <notification/notification_messages.h>
6
6
7
7
#include <datetime/datetime.h>
8
+ #include <locale/locale.h>
8
9
9
10
#include "dcf77.h"
10
11
13
14
#define DCF77_FREQ 77500
14
15
#define DCF77_OFFSET 60
15
16
#define SYNC_DELAY 50
16
- #define UPDATES 8
17
-
18
- #define SECONDS_PER_DAY 60 * 60 * 24
19
17
20
18
char * WEEKDAYS [] = {"Mon" , "Tue" , "Wed" , "Thu" , "Fri" , "Sat" , "Sun" };
21
19
22
20
typedef struct {
23
21
DateTime dt ;
24
22
bool is_dst ;
23
+ FuriString * str ;
24
+ LocaleTimeFormat tim_fmt ;
25
+ LocaleDateFormat dat_fmt ;
25
26
} AppData ;
26
27
27
28
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
+ }
31
38
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 );
39
41
40
42
canvas_set_font (canvas , FontBigNumbers );
41
43
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 );
55
63
56
64
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 ));
58
67
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 );
61
70
canvas_draw_str_aligned (
62
71
canvas , SCREEN_SIZE_X , SCREEN_SIZE_Y , AlignRight , AlignBottom , data );
63
72
}
@@ -69,27 +78,30 @@ static void app_input_callback(InputEvent* input_event, void* ctx) {
69
78
furi_message_queue_put (event_queue , input_event , FuriWaitForever );
70
79
}
71
80
72
- void set_time (AppData * app_data , int offset ) {
81
+ void set_time (AppData * app , int offset ) {
73
82
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 ;
75
84
datetime_timestamp_to_datetime (timestamp , & dcf_dt );
85
+ set_dcf77_time (& dcf_dt , app -> is_dst );
76
86
set_dcf77_time (& dcf_dt , app_data -> is_dst );
77
87
}
78
88
79
89
int dcf77_clock_sync_app_main (void * p ) {
80
90
UNUSED (p );
81
91
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 ();
84
98
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 );
88
100
89
101
ViewPort * view_port = view_port_alloc ();
90
102
FuriMessageQueue * event_queue = furi_message_queue_alloc (8 , sizeof (InputEvent ));
91
103
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 );
93
105
view_port_input_callback_set (view_port , app_input_callback , event_queue );
94
106
95
107
Gui * gui = furi_record_open (RECORD_GUI );
@@ -98,50 +110,48 @@ int dcf77_clock_sync_app_main(void* p) {
98
110
NotificationApp * notification = furi_record_open (RECORD_NOTIFICATION );
99
111
notification_message_block (notification , & sequence_display_backlight_enforce_on );
100
112
113
+ InputEvent event ;
101
114
bool running = false;
102
115
bool exit = false;
103
- int sec = app_data . dt .second ;
116
+ int sec = app -> dt .second ;
104
117
while (!exit ) {
105
118
int silence_ms = 0 ;
106
119
// 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 );
108
121
109
- if (app_data .dt .second < 59 ) {
110
- furi_hal_light_set (LightRed | LightGreen | LightBlue , 0 );
122
+ if (app -> dt .second < 59 ) {
111
123
if (running ) {
124
+ furi_hal_light_set (LightRed | LightGreen | LightBlue , 0 );
112
125
furi_hal_rfid_tim_read_stop ();
113
126
furi_hal_pwm_stop (FuriHalPwmOutputIdLptim2PA4 );
114
127
furi_hal_gpio_init (
115
128
& gpio_ext_pa4 , GpioModeOutputPushPull , GpioPullNo , GpioSpeedVeryHigh );
116
129
}
117
- silence_ms = get_dcf77_bit (app_data . dt .second ) ? 200 : 100 ;
130
+ silence_ms = get_dcf77_bit (app -> dt .second ) ? 200 : 100 ;
118
131
furi_delay_ms (silence_ms );
119
132
furi_hal_rfid_tim_read_start (DCF77_FREQ , 0.5 );
120
133
furi_hal_pwm_start (FuriHalPwmOutputIdLptim2PA4 , DCF77_FREQ , 50 );
121
- running = true;
122
134
furi_hal_light_set (LightBlue , 0xFF );
135
+ running = true;
123
136
} 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 ;
141
150
}
142
151
}
143
152
view_port_update (view_port );
144
- if (exit ) break ;
153
+ if (status == FuriStatusErrorTimeout ) break ;
154
+ wait_ms -= furi_get_tick () - tick_start ;
145
155
}
146
156
}
147
157
@@ -160,5 +170,8 @@ int dcf77_clock_sync_app_main(void* p) {
160
170
furi_message_queue_free (event_queue );
161
171
view_port_free (view_port );
162
172
173
+ furi_string_free (app -> str );
174
+ free (app );
175
+
163
176
return 0 ;
164
177
}
0 commit comments