@@ -13,6 +13,7 @@ static aon_timer_alarm_handler_t aon_timer_alarm_handler;
1313#if HAS_RP2040_RTC
1414#include "hardware/rtc.h"
1515#include "pico/util/datetime.h"
16+
1617#elif HAS_POWMAN_TIMER
1718#include "hardware/powman.h"
1819
@@ -23,56 +24,92 @@ static void powman_timer_irq_handler(void) {
2324 irq_remove_handler (irq_num , powman_timer_irq_handler );
2425 if (aon_timer_alarm_handler ) aon_timer_alarm_handler ();
2526}
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+ }
2631#endif
2732
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 ) {
2941#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 ;
3446#elif HAS_POWMAN_TIMER
3547 powman_timer_set_ms (timespec_to_ms (ts ));
48+ return true;
3649#else
3750 panic_unsupported ();
3851#endif
3952}
4053
41- void aon_timer_get_time ( struct timespec * ts ) {
54+ bool aon_timer_set_time_calendar ( const struct tm * tm ) {
4255#if HAS_RP2040_RTC
4356 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 );
5364 }
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 );
5476#elif HAS_POWMAN_TIMER
5577 ms_to_timespec (powman_timer_get_ms (), ts );
78+ return true;
5679#else
5780 panic_unsupported ();
5881#endif
5982}
6083
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 ) {
6585#if HAS_RP2040_RTC
66- ((void )wakeup_from_low_power ); // don't have a choice
6786 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 ;
68102 // adjust to after the target time
103+ struct timespec ts_adjusted = * ts ;
69104 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 ;
74107 }
108+ return aon_timer_enable_alarm_calendar (& tm , handler , wakeup_from_low_power );
75109#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 ;
76113 uint irq_num = aon_timer_get_irq_num ();
77114 powman_timer_disable_alarm ();
78115 // adjust to after the target time
@@ -92,12 +129,34 @@ aon_timer_alarm_handler_t aon_timer_enable_alarm(const struct timespec *ts, aon_
92129 irq_set_exclusive_handler (irq_num , powman_timer_irq_handler );
93130 irq_set_enabled (irq_num , true);
94131 }
132+ aon_timer_alarm_handler = handler ;
133+ restore_interrupts_from_disabled (save );
134+ return old_handler ;
95135#else
96136 panic_unsupported ();
97137#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 );
98148 aon_timer_alarm_handler = handler ;
99149 restore_interrupts_from_disabled (save );
100150 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
101160}
102161
103162void aon_timer_disable_alarm (void ) {
@@ -120,15 +179,36 @@ void aon_timer_start_with_timeofday(void) {
120179 aon_timer_start (& ts );
121180}
122181
123- void aon_timer_start (const struct timespec * ts ) {
182+ bool aon_timer_start (const struct timespec * ts ) {
124183#if HAS_RP2040_RTC
125184 rtc_init ();
126- aon_timer_set_time (ts );
185+ return aon_timer_set_time (ts );
127186#elif HAS_POWMAN_TIMER
128187 // todo how best to allow different configurations; this should just be the default
129188 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 ;
132212#else
133213 panic_unsupported ();
134214#endif
0 commit comments