+/* -------- INTERNAL FUNCTIONS -------- */
+
+static uint32_t getCount(uint8_t id) {
+ DINT();
+ uint32_t count = gpioCount[id];
+ gpioCount[id] = 0;
+ EINT();
+ return count;
+}
+
+static void setTimer(uint8_t id, uint16_t delay) {
+ uint8_t i;
+ uint16_t now, left;
+
+ timerActive[id] = true;
+ // enable clock if it was disabled to save power?
+ now = TA1R;
+ timerPoint[id] = now + delay;
+ left = ACLK_TICKS_PER_SECOND;
+ for (i = 0; i < 3; i++)
+ if (timerActive[i] && (timerPoint[i] - now) < left) {
+ left = timerPoint[i] - now;
+ }
+ TA1CCR0 = now + left;
+ TA1CCTL0 = CCIE;
+}
+
+static void clearTimer(uint8_t id) {
+ uint8_t i;
+ bool keep = false;
+
+ timerActive[id] = false;
+ for (i = 0; i < 3; i++)
+ if (timerActive[i]) keep = true;
+ if (!keep) {
+ TA1CCTL0 = 0;
+ // disable clock to save power?
+ }
+}
+
+static void gpioHandler(uint8_t id) {
+ if (timerActive[id])
+ return;
+ setTimer(id, ACLK_TICKS_PER_SECOND); // One second ahead
+}
+
+static void tickHandler(uint16_t clock) {
+ uint8_t i;
+
+ for (i = 0; i < 3; i++)
+ if (timerActive[i] && timerPoint[i] == clock) {
+ uint32_t count = getCount(i);
+ uint16_t mask = BIT3 << i;
+
+ if (count) {
+ setTimer(i, ACLK_TICKS_PER_SECOND); // One second ahead
+ if (appJitterHandler) (*appJitterHandler)(i, count);
+ } else {
+ clearTimer(i);
+ if (GPIO_LOW(mask) && appGpioHandler) (*appGpioHandler)(i);
+ }
+ }
+ // if all timers are unset, disable ticker.
+}
+
+static void postEvent(uint8_t handlerId) {
+ uint8_t key = Em_Hal_lock();
+ handlerEvents |= 1 << handlerId;
+ Em_Hal_unlock(key);
+}