2 * Copyright © 2013 Keith Packard <keithp@keithp.com>
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; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 #include <ao_debounce.h>
21 #include <ao_fast_timer.h>
23 static uint8_t ao_debounce_initialized;
24 static uint8_t ao_debounce_running;
25 static struct ao_debounce *ao_debounce;
27 static uint8_t values[64];
30 #define d_step(n) (((n) + 1) & 63)
33 _ao_debounce_set(struct ao_debounce *debounce, uint8_t value)
35 if (value != debounce->value) {
38 debounce->value = value;
39 debounce->_set(debounce, value);
41 _ao_debounce_stop(debounce);
45 ao_debounce_dump(void)
49 for (s = 0; s < n; s++) {
57 * Get the current value, set the result when we've
58 * reached the debounce count limit
61 _ao_debounce_check(struct ao_debounce *debounce)
63 uint8_t next = debounce->_get(debounce);
65 if (next == debounce->current) {
66 if (debounce->count < debounce->hold) {
67 if (++debounce->count == debounce->hold)
68 _ao_debounce_set(debounce, debounce->current);
72 debounce->current = next;
77 _ao_debounce_isr(void)
79 struct ao_debounce *debounce, *next;
81 for (debounce = ao_debounce; debounce; debounce = next) {
82 next = debounce->next;
83 _ao_debounce_check(debounce);
90 ao_fast_timer_on(_ao_debounce_isr);
96 ao_fast_timer_off(_ao_debounce_isr);
100 * Start monitoring one pin
103 _ao_debounce_start(struct ao_debounce *debounce)
107 m = ao_arch_irqsave();
108 if (!debounce->running) {
109 debounce->running = 1;
111 /* Reset the counter */
115 debounce->next = ao_debounce;
116 ao_debounce = debounce;
118 /* Make sure the timer is running */
119 if (!ao_debounce_running++)
122 /* And go check the current value */
123 _ao_debounce_check(debounce);
125 ao_arch_irqrestore(m);
129 * Stop monitoring one pin
132 _ao_debounce_stop(struct ao_debounce *debounce)
134 struct ao_debounce **prev;
137 m = ao_arch_irqsave();
138 if (debounce->running) {
139 debounce->running = 0;
142 for (prev = &ao_debounce; (*prev); prev = &((*prev)->next)) {
143 if (*prev == debounce) {
144 *prev = debounce->next;
148 debounce->next = NULL;
150 /* Turn off the timer if possible */
151 if (!--ao_debounce_running)
154 ao_arch_irqrestore(m);
158 ao_debounce_init(void)
160 if (ao_debounce_initialized)
162 ao_debounce_initialized = 1;
163 ao_fast_timer_init();