X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fdrivers%2Fao_button.c;h=07e92c670f3a1c590aed332b875d3f8fc66e46b3;hb=97cf9df882291b9e494b2f64f84eb37357a6ab31;hp=a507c909ea0248d80032a0739a67f0e4a8b05819;hpb=b635cb26ba54c8f5c6a958e0ab0bc4d34d33b635;p=fw%2Faltos diff --git a/src/drivers/ao_button.c b/src/drivers/ao_button.c index a507c909..07e92c67 100644 --- a/src/drivers/ao_button.c +++ b/src/drivers/ao_button.c @@ -3,7 +3,8 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,52 +26,94 @@ #define ao_button_queue(b,v) #endif -static uint8_t ao_button[AO_BUTTON_COUNT]; -static AO_TICK_TYPE ao_button_time[AO_BUTTON_COUNT]; +#define AO_BUTTON_DEBOUNCE_INTERVAL AO_MS_TO_TICKS(50) -#define AO_DEBOUNCE AO_MS_TO_TICKS(20) +struct ao_button_state { + AO_TICK_TYPE time; + uint8_t value; +}; + +static struct ao_button_state ao_button_state[AO_BUTTON_COUNT]; #define port(q) AO_BUTTON_ ## q ## _PORT #define bit(q) AO_BUTTON_ ## q #define pin(q) AO_BUTTON_ ## q ## _PIN -static void -ao_button_do(uint8_t b, uint8_t v) -{ - /* Debounce */ - if ((AO_TICK_SIGNED) (ao_tick_count - ao_button_time[b]) < AO_DEBOUNCE) - return; - - /* pins are inverted */ - v = !v; - if (ao_button[b] != v) { - ao_button[b] = v; - ao_button_time[b] = ao_tick_count; - ao_button_queue(b, v); - ao_wakeup(&ao_button[b]); - } -} +#ifndef AO_BUTTON_INVERTED +#define AO_BUTTON_INVERTED 1 +#endif -#define ao_button_update(b) ao_button_do(b, ao_gpio_get(port(b), bit(b), pin(b))) +#if AO_BUTTON_INVERTED +/* pins are inverted */ +#define ao_button_value(b) !ao_gpio_get(port(b), bit(b), pin(b)) +#else +#define ao_button_value(b) ao_gpio_get(port(b), bit(b), pin(b)) +#endif -static void -ao_button_isr(void) +static uint8_t +_ao_button_get(uint8_t b) { + switch (b) { #if AO_BUTTON_COUNT > 0 - ao_button_update(0); + case 0: return ao_button_value(0); #endif #if AO_BUTTON_COUNT > 1 - ao_button_update(1); + case 1: return ao_button_value(1); #endif #if AO_BUTTON_COUNT > 2 - ao_button_update(2); + case 2: return ao_button_value(2); #endif #if AO_BUTTON_COUNT > 3 - ao_button_update(3); + case 3: return ao_button_value(3); #endif #if AO_BUTTON_COUNT > 4 - ao_button_update(4); + case 4: return ao_button_value(4); #endif + } + return 0; +} + +static void +_ao_button_check(uint8_t b) +{ + uint8_t value = _ao_button_get(b); + + if (value != ao_button_state[b].value) { + AO_TICK_TYPE now = ao_time(); + + if ((now - ao_button_state[b].time) >= AO_BUTTON_DEBOUNCE_INTERVAL) { + ao_button_state[b].value = value; + ao_button_queue(b, value); + } + ao_button_state[b].time = now; + } +} + +static void +_ao_button_init(uint8_t b) +{ + uint8_t m = ao_arch_irqsave(); + uint8_t value = _ao_button_get(b); + ao_button_state[b].value = value; + ao_button_state[b].time = ao_time(); + ao_button_queue(b, value); + ao_arch_irqrestore(m); + +} + +uint8_t +ao_button_get(uint8_t b) +{ + return ao_button_state[b].value; +} + +static void +ao_button_isr(void) +{ + uint8_t b; + + for (b = 0; b < AO_BUTTON_COUNT; b++) + _ao_button_check(b); } #define init(b) do { \ @@ -78,8 +121,9 @@ ao_button_isr(void) \ ao_exti_setup(port(b), bit(b), \ AO_BUTTON_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \ - ao_button_isr); \ + ao_button_isr); \ ao_exti_enable(port(b), bit(b)); \ + _ao_button_init(b); \ } while (0) void @@ -91,4 +135,13 @@ ao_button_init(void) #if AO_BUTTON_COUNT > 1 init(1); #endif +#if AO_BUTTON_COUNT > 2 + init(2); +#endif +#if AO_BUTTON_COUNT > 3 + init(3); +#endif +#if AO_BUTTON_COUNT > 4 + init(4); +#endif }