diff options
Diffstat (limited to 'watch-library/watch/watch_rtc.c')
-rw-r--r-- | watch-library/watch/watch_rtc.c | 71 |
1 files changed, 56 insertions, 15 deletions
diff --git a/watch-library/watch/watch_rtc.c b/watch-library/watch/watch_rtc.c index 0974c796..519a1f00 100644 --- a/watch-library/watch/watch_rtc.c +++ b/watch-library/watch/watch_rtc.c @@ -24,7 +24,7 @@ #include "watch_rtc.h" -ext_irq_cb_t tick_callback; +ext_irq_cb_t tick_callbacks[8]; ext_irq_cb_t alarm_callback; ext_irq_cb_t btn_alarm_callback; ext_irq_cb_t a2_callback; @@ -70,15 +70,40 @@ watch_date_time watch_rtc_get_date_time() { return retval; } -void watch_register_tick_callback(ext_irq_cb_t callback) { - tick_callback = callback; +void watch_rtc_register_1Hz_callback(ext_irq_cb_t callback) { + watch_rtc_register_tick_callback(callback, 1); +} + +void watch_rtc_disable_1Hz_callback() { + watch_rtc_disable_tick_callback(1); +} + +void watch_rtc_register_tick_callback(ext_irq_cb_t callback, uint8_t period) { + // we told them, it has to be a power of 2. + if (__builtin_popcount(period) != 1) return; + + // this left-justifies the period in a 32-bit integer. + uint32_t tmp = period << 24; + // now we can count the leading zeroes to get the value we need. + // 0x01 (1 Hz) will have 7 leading zeros for PER7. 0xF0 (128 Hz) will have no leading zeroes for PER0. + uint8_t per_n = __builtin_clz(tmp); + + // this also maps nicely to an index for our list of tick callbacks. + tick_callbacks[per_n] = callback; + NVIC_ClearPendingIRQ(RTC_IRQn); NVIC_EnableIRQ(RTC_IRQn); - RTC->MODE2.INTENSET.reg = RTC_MODE2_INTENSET_PER7; + RTC->MODE2.INTENSET.reg = 1 << per_n; +} + +void watch_rtc_disable_tick_callback(uint8_t period) { + if (__builtin_popcount(period) != 1) return; + uint8_t per_n = __builtin_clz(period << 24); + RTC->MODE2.INTENCLR.reg = 1 << per_n; } -void watch_disable_tick_callback() { - RTC->MODE2.INTENCLR.reg = RTC_MODE2_INTENCLR_PER7; +void watch_rtc_disable_all_tick_callbacks() { + RTC->MODE2.INTENCLR.reg = 0xFF; } void watch_rtc_register_alarm_callback(ext_irq_cb_t callback, watch_date_time alarm_time, watch_rtc_alarm_match mask) { @@ -99,17 +124,20 @@ void RTC_Handler(void) { uint16_t interrupt_status = RTC->MODE2.INTFLAG.reg; uint16_t interrupt_enabled = RTC->MODE2.INTENSET.reg; - if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_ALARM0) { - if (alarm_callback != NULL) { - alarm_callback(); + if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_PER_Msk) { + // handle the tick callback first, it's what we do the most. + // start from PER7, the 1 Hz tick. + for(int8_t i = 7; i >= 0; i--) { + if ((interrupt_status & interrupt_enabled) & (1 << i)) { + if (tick_callbacks[i] != NULL) { + tick_callbacks[i](); + } + RTC->MODE2.INTFLAG.reg = 1 << i; + break; + } } - RTC->MODE2.INTFLAG.reg = RTC_MODE2_INTFLAG_ALARM0; - } else if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_PER7) { - if (tick_callback != NULL) { - tick_callback(); - } - RTC->MODE2.INTFLAG.reg = RTC_MODE2_INTFLAG_PER7; } else if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_TAMPER) { + // handle the extwake interrupts next. uint8_t reason = RTC->MODE2.TAMPID.reg; if (reason & RTC_TAMPID_TAMPID2) { if (btn_alarm_callback != NULL) btn_alarm_callback(); @@ -120,6 +148,12 @@ void RTC_Handler(void) { } RTC->MODE2.TAMPID.reg = reason; RTC->MODE2.INTFLAG.reg = RTC_MODE2_INTFLAG_TAMPER; + } else if ((interrupt_status & interrupt_enabled) & RTC_MODE2_INTFLAG_ALARM0) { + // finally handle the alarm. + if (alarm_callback != NULL) { + alarm_callback(); + } + RTC->MODE2.INTFLAG.reg = RTC_MODE2_INTFLAG_ALARM0; } } @@ -152,3 +186,10 @@ void watch_get_date_time(struct calendar_date_time *date_time) { date_time->date.month = val.bit.MONTH; date_time->date.year = val.bit.YEAR + WATCH_RTC_REFERENCE_YEAR; } + +void watch_register_tick_callback(ext_irq_cb_t callback) { + tick_callbacks[7] = callback; + NVIC_ClearPendingIRQ(RTC_IRQn); + NVIC_EnableIRQ(RTC_IRQn); + RTC->MODE2.INTENSET.reg = RTC_MODE2_INTENSET_PER7; +} |