X-Git-Url: http://average.org/gitweb/?a=blobdiff_plain;f=msp430%2FHal%2FHal.c;h=dda8c690e6c28bf8d9d22805426c77b55478b0d7;hb=refs%2Fheads%2Fcountjitter;hp=0cdcc297a85b19169fad377c4cf5a2cb2575ed75;hpb=02d2dc9e46149beb63a3dac83a9346232e2626da;p=pulsecounter.git diff --git a/msp430/Hal/Hal.c b/msp430/Hal/Hal.c index 0cdcc29..dda8c69 100644 --- a/msp430/Hal/Hal.c +++ b/msp430/Hal/Hal.c @@ -26,17 +26,10 @@ #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 @@ -97,62 +90,106 @@ 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(); }