]> www.average.org Git - pulsecounter.git/blobdiff - msp430/Hal/Hal.c
mark possible place that is losing events
[pulsecounter.git] / msp430 / Hal / Hal.c
index 0cdcc297a85b19169fad377c4cf5a2cb2575ed75..dda8c690e6c28bf8d9d22805426c77b55478b0d7 100644 (file)
 #define GPIO_ENABLE(mask)           (P1IFG &= ~mask, P1IE |= mask)
 #define GPIO_DISABLE(mask)          (P1IE &= ~mask, P1IFG &= ~mask)
 #define GPIO_FIRED(mask)            (P1IFG & mask)
+#define GPIO_ACK(mask)              (P1IFG &= ~mask)
 #define GPIO_LOW(mask)              (!(P1IN & mask))
 #define GPIO_DEBOUNCE_MSECS         100
 
-#define DEBUG1_CONFIG()             (P2DIR |= BIT3)
-#define DEBUG1_ON()                 (P2OUT |= BIT3)
-#define DEBUG1_OFF()                (P2OUT &= ~BIT3)
-
-#define DEBUG2_CONFIG()             (P2DIR |= BIT4)
-#define DEBUG2_ON()                 (P2OUT |= BIT4)
-#define DEBUG2_OFF()                (P2OUT &= ~BIT4)
-
 #define EAP_RX_BUF                  UCA0RXBUF
 #define EAP_TX_BUF                  UCA0TXBUF
 
 static void gpioHandler(uint8_t id);
 static void postEvent(uint8_t handlerId);
 
-static Hal_Handler appGpioHandler;
+static Hal_Handler appSettleHandler;
+static void (*appJitterHandler)(uint8_t id, uint32_t count);
 static volatile uint16_t handlerEvents = 0;
 static uint16_t clockTick = 0;
 static Hal_Handler handlerTab[NUM_HANDLERS];
+static volatile uint32_t gpioCount[3] = {0};
+static bool timerActive[3] = {false, false, false};
+static uint16_t timerPoint[3];
+
+/* -------- 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) { /* FIXME */
+            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) && appSettleHandler) (*appSettleHandler)(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);
+}
 
 /* -------- APP-HAL INTERFACE -------- */
 
-void Hal_gpioEnable(Hal_Handler handler) {
+void Hal_gpioEnable(Hal_Handler shandler, void (*jhandler)(uint8_t id, uint32_t count)) {
     uint8_t id;
     uint16_t mask;
 
     for (id = 0, mask = BIT3; id < 3; id++, mask <<= 1) {
         handlerTab[id] = gpioHandler;
-        appGpioHandler = handler;
+        appSettleHandler = shandler;
+        appJitterHandler = jhandler;
         (P1DIR &= ~mask, P1REN |= mask, P1OUT |= mask, P1IES |= mask);
         Hal_delay(100);
         (P1IFG &= ~mask, P1IE |= mask);
     }
+    handlerTab[TICK_HANDLER_ID] = tickHandler;
 }
 
 void Hal_connected(void) {
 }
 
-void Hal_debugOn(uint8_t line) {
-    switch (line) {
-    case 1:
-        DEBUG1_ON();
-        break;
-    case 2:
-        DEBUG2_ON();
-    }
-}
-
-void Hal_debugOff(uint8_t line) {
-    switch (line) {
-    case 1:
-        DEBUG1_OFF();
-        break;
-    case 2:
-        DEBUG2_OFF();
-    }
-}
-
-void Hal_debugPulse(uint8_t line) {
-    switch (line) {
-    case 1:
-        DEBUG1_ON();
-        DEBUG1_OFF();
-        break;
-    case 2:
-        DEBUG2_ON();
-        DEBUG2_OFF();
-    }
-}
-
 void Hal_delay(uint16_t msecs) {
     while (msecs--) {
         __delay_cycles(MCLK_TICKS_PER_MS);
@@ -191,13 +228,6 @@ void Hal_init(void) {
     RED_LED_CONFIG();
     RED_LED_OFF();
 
-    /* setup debug pins */
-
-    DEBUG1_CONFIG(); DEBUG1_OFF();
-    DEBUG2_CONFIG(); DEBUG2_OFF();
-
-    DEBUG1_ON(); DEBUG1_OFF();
-
     /* setup TimerA1 */
     TA1CTL = TASSEL_1 + MC_2;           // ACLK, Continuous mode
     UART_WATCH_DISABLE();
@@ -239,14 +269,20 @@ void Hal_idleLoop(void) {
             EINT();
             uint16_t mask;
             uint8_t id;
+
             for (id = 0, mask = 0x1; id < NUM_HANDLERS; id++, mask <<= 1) {
                 if ((events & mask) && handlerTab[id]) {
-                    handlerTab[id](id);
+                    if (id == TICK_HANDLER_ID) {
+                        uint16_t now = TA1R;
+                        handlerTab[id](now);
+                    } else {
+                        handlerTab[id](id);
+                    }
                 }
             }
         }
         else {          // await more events
-            SLEEP();
+            SLEEP();    // this also enables interrupts
         }
     }
 }
@@ -283,11 +319,13 @@ void Hal_redLedToggle(void) {
     RED_LED_TOGGLE();
 }
 
-void Hal_tickStart(uint16_t msecs, Hal_Handler handler) {
+uint16_t Hal_tickStart(uint16_t msecs, void (*handler)(uint16_t clock)) {
     handlerTab[TICK_HANDLER_ID] = handler;
     clockTick = (ACLK_TICKS_PER_SECOND * msecs) / 1000;
-    TA1CCR0 = TA1R + clockTick;                 // Set the CCR0 interrupt for msecs from now.
+    uint16_t then = TA1R + clockTick;
+    TA1CCR0 = then;               // Set the CCR0 interrupt for msecs from now.
     TA1CCTL0 = CCIE;                            // Enable the CCR0 interrupt
+    return then;
 }
 
 void Hal_tickStop(void) {
@@ -338,24 +376,6 @@ void Em_Hal_watchOn(void) {
     UART_WATCH_ENABLE();
 }
 
-
-/* -------- INTERNAL FUNCTIONS -------- */
-
-static void gpioHandler(uint8_t id) {
-    uint16_t mask = BIT3 << id;
-
-    Hal_delay(GPIO_DEBOUNCE_MSECS);
-    if (GPIO_LOW(mask) && appGpioHandler)
-        appGpioHandler(id);
-    GPIO_ENABLE(mask);
-}
-
-static void postEvent(uint8_t handlerId) {
-    uint8_t key = Em_Hal_lock();
-    handlerEvents |= 1 << handlerId;
-    Em_Hal_unlock(key);
-}
-
 /* -------- INTERRUPT SERVICE ROUTINES -------- */
 
 #ifdef __GNUC__
@@ -370,8 +390,9 @@ INTERRUPT void gpioIsr(void) {
 
     for (id = 0, mask = BIT3; id < 3; id++, mask <<= 1)
         if (GPIO_FIRED(mask)) {
+            gpioCount[id]++;
             postEvent(id);
-            GPIO_DISABLE(mask);
+            GPIO_ACK(mask);
         }
     WAKEUP();
 }
@@ -400,7 +421,7 @@ INTERRUPT void rxIsr(void) {
     #pragma vector=TIMER1_A0_VECTOR
 #endif
 INTERRUPT void timerIsr(void) {
-    TA1CCR0 += clockTick;
+    // TA1CCR0 += clockTick;
     postEvent(TICK_HANDLER_ID);
     WAKEUP();
 }