altos/telefire: Leave siren on all the time. Add siren/strobe debugging.
[fw/altos] / src / drivers / ao_button.c
1 /*
2  * Copyright © 2012 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include <ao.h>
19 #include <ao_button.h>
20 #include <ao_exti.h>
21 #if AO_EVENT
22 #include <ao_event.h>
23 #define ao_button_queue(b,v)    ao_event_put_isr(AO_EVENT_BUTTON, b, v)
24 #else
25 #define ao_button_queue(b,v)
26 #endif
27
28 static uint8_t          ao_button[AO_BUTTON_COUNT];
29 static AO_TICK_TYPE     ao_button_time[AO_BUTTON_COUNT];
30
31 #define AO_DEBOUNCE     AO_MS_TO_TICKS(20)
32
33 #define port(q) AO_BUTTON_ ## q ## _PORT
34 #define bit(q) AO_BUTTON_ ## q
35 #define pin(q) AO_BUTTON_ ## q ## _PIN
36
37 static void
38 ao_button_do(uint8_t b, uint8_t v)
39 {
40         /* Debounce */
41         if ((AO_TICK_SIGNED) (ao_tick_count - ao_button_time[b]) < AO_DEBOUNCE)
42                 return;
43
44         /* pins are inverted */
45         v = !v;
46         if (ao_button[b] != v) {
47                 ao_button[b] = v;
48                 ao_button_time[b] = ao_tick_count;
49                 ao_button_queue(b, v);
50                 ao_wakeup(&ao_button[b]);
51         }
52 }
53
54 #define ao_button_update(b)     ao_button_do(b, ao_gpio_get(port(b), bit(b), pin(b)))
55
56 static void
57 ao_button_isr(void)
58 {
59 #if AO_BUTTON_COUNT > 0
60         ao_button_update(0);
61 #endif
62 #if AO_BUTTON_COUNT > 1
63         ao_button_update(1);
64 #endif
65 #if AO_BUTTON_COUNT > 2
66         ao_button_update(2);
67 #endif
68 #if AO_BUTTON_COUNT > 3
69         ao_button_update(3);
70 #endif
71 #if AO_BUTTON_COUNT > 4
72         ao_button_update(4);
73 #endif
74 }
75
76 #define init(b) do {                                                    \
77                 ao_enable_port(port(b));                                \
78                                                                         \
79                 ao_exti_setup(port(b), bit(b),                          \
80                               AO_BUTTON_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \
81                               ao_button_isr);                   \
82                 ao_exti_enable(port(b), bit(b));                        \
83         } while (0)
84
85 void
86 ao_button_init(void)
87 {
88 #if AO_BUTTON_COUNT > 0
89         init(0);
90 #endif
91 #if AO_BUTTON_COUNT > 1
92         init(1);
93 #endif
94 }