@@ -13,6 +13,7 @@ static aon_timer_alarm_handler_t aon_timer_alarm_handler;
13
13
#if HAS_RP2040_RTC
14
14
#include "hardware/rtc.h"
15
15
#include "pico/util/datetime.h"
16
+
16
17
#elif HAS_POWMAN_TIMER
17
18
#include "hardware/powman.h"
18
19
@@ -23,56 +24,92 @@ static void powman_timer_irq_handler(void) {
23
24
irq_remove_handler (irq_num , powman_timer_irq_handler );
24
25
if (aon_timer_alarm_handler ) aon_timer_alarm_handler ();
25
26
}
27
+
28
+ static bool ts_to_tm (const struct timespec * ts , struct tm * tm ) {
29
+ return pico_localtime_r (& ts -> tv_sec , tm ) != NULL ;
30
+ }
26
31
#endif
27
32
28
- void aon_timer_set_time (const struct timespec * ts ) {
33
+ static bool tm_to_ts (const struct tm * tm , struct timespec * ts ) {
34
+ struct tm tm_clone = * tm ;
35
+ ts -> tv_sec = pico_mktime (& tm_clone );
36
+ ts -> tv_nsec = 0 ;
37
+ return ts -> tv_sec != -1 ;
38
+ }
39
+
40
+ bool aon_timer_set_time (const struct timespec * ts ) {
29
41
#if HAS_RP2040_RTC
30
- datetime_t dt ;
31
- bool ok = time_to_datetime ( ts -> tv_sec , & dt );
32
- assert (ok );
33
- if ( ok ) rtc_set_datetime ( & dt ) ;
42
+ struct tm tm ;
43
+ bool ok = pico_localtime_r ( & ts -> tv_sec , & tm );
44
+ if (ok ) aon_timer_set_time_calendar ( & tm );
45
+ return ok ;
34
46
#elif HAS_POWMAN_TIMER
35
47
powman_timer_set_ms (timespec_to_ms (ts ));
48
+ return true;
36
49
#else
37
50
panic_unsupported ();
38
51
#endif
39
52
}
40
53
41
- void aon_timer_get_time ( struct timespec * ts ) {
54
+ bool aon_timer_set_time_calendar ( const struct tm * tm ) {
42
55
#if HAS_RP2040_RTC
43
56
datetime_t dt ;
44
- rtc_get_datetime (& dt );
45
- time_t t ;
46
- bool ok = datetime_to_time (& dt , & t );
47
- assert (ok );
48
- ts -> tv_nsec = 0 ;
49
- if (ok ) {
50
- ts -> tv_sec = t ;
51
- } else {
52
- ts -> tv_sec = -1 ;
57
+ tm_to_datetime (tm , & dt );
58
+ rtc_set_datetime (& dt );
59
+ return true;
60
+ #elif HAS_POWMAN_TIMER
61
+ struct timespec ts ;
62
+ if (tm_to_ts (tm , & ts )) {
63
+ return aon_timer_set_time (& ts );
53
64
}
65
+ return false;
66
+ #else
67
+ panic_unsupported ();
68
+ #endif
69
+ }
70
+
71
+ bool aon_timer_get_time (struct timespec * ts ) {
72
+ #if HAS_RP2040_RTC
73
+ struct tm tm ;
74
+ bool ok = aon_timer_get_time_calendar (& tm );
75
+ return ok && tm_to_ts (& tm , ts );
54
76
#elif HAS_POWMAN_TIMER
55
77
ms_to_timespec (powman_timer_get_ms (), ts );
78
+ return true;
56
79
#else
57
80
panic_unsupported ();
58
81
#endif
59
82
}
60
83
61
- aon_timer_alarm_handler_t aon_timer_enable_alarm (const struct timespec * ts , aon_timer_alarm_handler_t handler , bool wakeup_from_low_power ) {
62
- uint32_t save = save_and_disable_interrupts ();
63
- aon_timer_alarm_handler_t old_handler = aon_timer_alarm_handler ;
64
- struct timespec ts_adjusted = * ts ;
84
+ bool aon_timer_get_time_calendar (struct tm * tm ) {
65
85
#if HAS_RP2040_RTC
66
- ((void )wakeup_from_low_power ); // don't have a choice
67
86
datetime_t dt ;
87
+ rtc_get_datetime (& dt );
88
+ datetime_to_tm (& dt , tm );
89
+ return true;
90
+ #elif HAS_POWMAN_TIMER
91
+ struct timespec ts ;
92
+ aon_timer_get_time (& ts );
93
+ return ts_to_tm (& ts , tm );
94
+ #else
95
+ panic_unsupported ();
96
+ #endif
97
+ }
98
+
99
+ aon_timer_alarm_handler_t aon_timer_enable_alarm (const struct timespec * ts , aon_timer_alarm_handler_t handler , bool wakeup_from_low_power ) {
100
+ #if HAS_RP2040_RTC
101
+ struct tm tm ;
68
102
// adjust to after the target time
103
+ struct timespec ts_adjusted = * ts ;
69
104
if (ts_adjusted .tv_nsec ) ts_adjusted .tv_sec ++ ;
70
- bool ok = time_to_datetime (ts_adjusted .tv_sec , & dt );
71
- assert (ok );
72
- if (ok ) {
73
- rtc_set_alarm (& dt , handler );
105
+ if (!pico_localtime_r (& ts_adjusted .tv_sec , & tm )) {
106
+ return (aon_timer_alarm_handler_t )PICO_ERROR_INVALID_ARG ;
74
107
}
108
+ return aon_timer_enable_alarm_calendar (& tm , handler , wakeup_from_low_power );
75
109
#elif HAS_POWMAN_TIMER
110
+ uint32_t save = save_and_disable_interrupts ();
111
+ aon_timer_alarm_handler_t old_handler = aon_timer_alarm_handler ;
112
+ struct timespec ts_adjusted = * ts ;
76
113
uint irq_num = aon_timer_get_irq_num ();
77
114
powman_timer_disable_alarm ();
78
115
// adjust to after the target time
@@ -92,12 +129,34 @@ aon_timer_alarm_handler_t aon_timer_enable_alarm(const struct timespec *ts, aon_
92
129
irq_set_exclusive_handler (irq_num , powman_timer_irq_handler );
93
130
irq_set_enabled (irq_num , true);
94
131
}
132
+ aon_timer_alarm_handler = handler ;
133
+ restore_interrupts_from_disabled (save );
134
+ return old_handler ;
95
135
#else
96
136
panic_unsupported ();
97
137
#endif
138
+ }
139
+
140
+ aon_timer_alarm_handler_t aon_timer_enable_alarm_calendar (const struct tm * tm , aon_timer_alarm_handler_t handler , bool wakeup_from_low_power ) {
141
+ #if HAS_RP2040_RTC
142
+ ((void )wakeup_from_low_power ); // don't have a choice
143
+ uint32_t save = save_and_disable_interrupts ();
144
+ aon_timer_alarm_handler_t old_handler = aon_timer_alarm_handler ;
145
+ datetime_t dt ;
146
+ tm_to_datetime (tm , & dt );
147
+ rtc_set_alarm (& dt , handler );
98
148
aon_timer_alarm_handler = handler ;
99
149
restore_interrupts_from_disabled (save );
100
150
return old_handler ;
151
+ #elif HAS_POWMAN_TIMER
152
+ struct timespec ts ;
153
+ if (!tm_to_ts (tm , & ts )) {
154
+ return (aon_timer_alarm_handler_t )PICO_ERROR_INVALID_ARG ;
155
+ }
156
+ return aon_timer_enable_alarm (& ts , handler , wakeup_from_low_power );
157
+ #else
158
+ panic_unsupported ();
159
+ #endif
101
160
}
102
161
103
162
void aon_timer_disable_alarm (void ) {
@@ -120,15 +179,36 @@ void aon_timer_start_with_timeofday(void) {
120
179
aon_timer_start (& ts );
121
180
}
122
181
123
- void aon_timer_start (const struct timespec * ts ) {
182
+ bool aon_timer_start (const struct timespec * ts ) {
124
183
#if HAS_RP2040_RTC
125
184
rtc_init ();
126
- aon_timer_set_time (ts );
185
+ return aon_timer_set_time (ts );
127
186
#elif HAS_POWMAN_TIMER
128
187
// todo how best to allow different configurations; this should just be the default
129
188
powman_timer_set_1khz_tick_source_xosc ();
130
- powman_timer_set_ms (timespec_to_ms (ts ));
131
- powman_timer_start ();
189
+ bool ok = aon_timer_set_time (ts );
190
+ if (ok ) {
191
+ powman_timer_set_ms (timespec_to_ms (ts ));
192
+ powman_timer_start ();
193
+ }
194
+ return ok ;
195
+ #else
196
+ panic_unsupported ();
197
+ #endif
198
+ }
199
+
200
+ bool aon_timer_start_calendar (const struct tm * tm ) {
201
+ #if HAS_RP2040_RTC
202
+ rtc_init ();
203
+ return aon_timer_set_time_calendar (tm );
204
+ #elif HAS_POWMAN_TIMER
205
+ // todo how best to allow different configurations; this should just be the default
206
+ powman_timer_set_1khz_tick_source_xosc ();
207
+ bool ok = aon_timer_set_time_calendar (tm );
208
+ if (ok ) {
209
+ powman_timer_start ();
210
+ }
211
+ return ok ;
132
212
#else
133
213
panic_unsupported ();
134
214
#endif
0 commit comments