altosdroid: initial implementation of telemetry logging.
[fw/altos] / src / cc1111 / ao_button.c
index 3516d55960ebcc7b6c038ff3e779550f23d1873a..69f3475fe660d43125073a40b19118f3f545c07d 100644 (file)
 
 volatile __xdata struct ao_fifo ao_button_fifo;
 
-#define BUTTON_1_PIN   (P0_4)
-#define BUTTON_1_MASK  (1 << 4)        /* P0_4 */
+static __code struct {
+       uint8_t mask;
+       uint8_t reg;
+} ao_buttons[] = {
+#ifdef BUTTON_1_MASK
+       { BUTTON_1_MASK, BUTTON_1_REG },
+#endif
+#ifdef BUTTON_2_MASK
+       { BUTTON_2_MASK, BUTTON_2_REG },
+#endif
+#ifdef BUTTON_3_MASK
+       { BUTTON_3_MASK, BUTTON_3_REG },
+#endif
+};
 
-#define BUTTON_2_PIN   (P2_3)
-#define BUTTON_2_MASK  (1 << 3)        /* P2_3 */
+#define NUM_BUTTONS    ((sizeof ao_buttons) / sizeof (ao_buttons[0]))
 
-#define BUTTON_3_PIN   (P2_4)
-#define BUTTON_3_MASK  (1 << 4)        /* P2_4 */
+static __xdata uint16_t ao_button_tick[NUM_BUTTONS];
 
 static void
 ao_button_insert(char n)
 {
-       ao_fifo_insert(ao_button_fifo, n);
-       ao_wakeup(&ao_button_fifo);
+       uint16_t        now = ao_time();
+       if ((now - ao_button_tick[n]) > 20) {
+               ao_button_tick[n] = now;
+               ao_fifo_insert(ao_button_fifo, n);
+               ao_wakeup(&ao_button_fifo);
+       }
+}
+
+static void
+ao_button_isr(uint8_t flag, uint8_t reg)
+{
+       uint8_t b;
+
+       for (b = 0; b < NUM_BUTTONS; b++)
+               if (ao_buttons[b].reg == reg && (ao_buttons[b].mask & flag))
+                       ao_button_insert(b + 1);
+}
+
+static uint8_t
+ao_button_mask(uint8_t reg)
+{
+       uint8_t b;
+       uint8_t mask = 0;
+
+       for (b = 0; b < NUM_BUTTONS; b++)
+               if (ao_buttons[b].reg == reg)
+                       mask |= ao_buttons[b].mask;
+       return mask;
 }
 
 char
@@ -41,46 +77,82 @@ ao_button_get(void) __critical
        char    b;
 
        while (ao_fifo_empty(ao_button_fifo))
-               ao_sleep(&ao_button_fifo);
+               if (ao_sleep(&ao_button_fifo))
+                       return 0;
        ao_fifo_remove(ao_button_fifo, b);
        return b;
 }
 
 void
-ao_p2_isr(void)
+ao_button_clear(void) __critical
 {
-       if (P2IFG & BUTTON_2_MASK)
-               ao_button_insert(2);
-       if (P2IFG & BUTTON_3_MASK)
-               ao_button_insert(3);
-       P2IFG = 0;
+       char b;
+
+       while (!ao_fifo_empty(ao_button_fifo))
+               ao_fifo_remove(ao_button_fifo, b);
 }
 
 void
 ao_p0_isr(void) ao_arch_interrupt(13)
 {
        P0IF = 0;
-       if (P0IFG & BUTTON_1_MASK)
-               ao_button_insert(1);
+       ao_button_isr(P0IFG, 0);
        P0IFG = 0;
 }
 
+void
+ao_p1_isr(void) ao_arch_interrupt(15)
+{
+       P1IF = 0;
+       ao_button_isr(P1IFG, 1);
+       P1IFG = 0;
+}
+
+/* Shared with USB */
+void
+ao_p2_isr(void)
+{
+       ao_button_isr(P2IFG, 2);
+       P2IFG = 0;
+}
+
 void
 ao_button_init(void)
 {
+       uint8_t mask;
+
        /* Pins are configured as inputs with pull-up by default */
 
-       /* Enable interrupts for P2_0 - P2_4
-        * Enable interrupts for P0_4 - P0_7
-        * Set P2 interrupts to falling edge
-        * Set P0 interrupts to falling edge
-        */
-       
        /* Enable interrupts for P0 inputs */
-       IEN1 |= IEN1_P0IE;
+       mask = ao_button_mask(0);
+       if (mask) {
+               if (mask & 0x0f)
+                       PICTL |= PICTL_P0IENL;
+               if (mask & 0xf0)
+                       PICTL |= PICTL_P0IENH;
+               P0IFG = 0;
+               P0IF = 0;
+               IEN1 |= IEN1_P0IE;
+               PICTL |= PICTL_P0ICON;
+       }
 
-       /* Enable interrupts for P2 inputs */
-       IEN2 |= IEN2_P2IE;
+       /* Enable interrupts for P1 inputs */
+       mask = ao_button_mask(1);
+       if (mask) {
+               P1IEN |= mask;
+               P1IFG = 0;
+               P1IF = 0;
+               IEN2 |= IEN2_P1IE;
+               PICTL |= PICTL_P1ICON;
+       }
 
-       PICTL |= PICTL_P2IEN | PICTL_P0IENH | PICTL_P2ICON | PICTL_P0ICON;
+       /* Enable interrupts for P2 inputs */
+       mask = ao_button_mask(2);
+       if (mask) {
+               PICTL |= PICTL_P2IEN;
+               P2IFG = 0;
+               P2IF = 0;
+               IEN2 |= IEN2_P2IE;
+               PICTL |= PICTL_P2ICON;
+       }
 }