summaryrefslogtreecommitdiffstats
path: root/watch-library/watch/watch_rtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'watch-library/watch/watch_rtc.c')
-rw-r--r--watch-library/watch/watch_rtc.c71
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;
+}