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; version 2 of the License.
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.
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.
19 #include <ao_debounce.h>
20 #include <ao_fast_timer.h>
22 static uint8_t ao_debounce_initialized;
23 static uint8_t ao_debounce_running;
24 static struct ao_debounce *ao_debounce;
26 static uint8_t values[64];
29 #define d_step(n) (((n) + 1) & 63)
32 _ao_debounce_set(struct ao_debounce *debounce, uint8_t value)
34 if (value != debounce->value) {
37 debounce->value = value;
38 debounce->_set(debounce, value);
40 _ao_debounce_stop(debounce);
44 ao_debounce_dump(void)
48 for (s = 0; s < n; s++) {
56 * Get the current value, set the result when we've
57 * reached the debounce count limit
60 _ao_debounce_check(struct ao_debounce *debounce)
62 uint8_t next = debounce->_get(debounce);
64 if (next == debounce->current) {
65 if (debounce->count < debounce->hold) {
66 if (++debounce->count == debounce->hold)
67 _ao_debounce_set(debounce, debounce->current);
71 debounce->current = next;
76 _ao_debounce_isr(void)
78 struct ao_debounce *debounce, *next;
80 for (debounce = ao_debounce; debounce; debounce = next) {
81 next = debounce->next;
82 _ao_debounce_check(debounce);
89 ao_fast_timer_on(_ao_debounce_isr);
95 ao_fast_timer_off(_ao_debounce_isr);
99 * Start monitoring one pin
102 _ao_debounce_start(struct ao_debounce *debounce)
106 m = ao_arch_irqsave();
107 if (!debounce->running) {
108 debounce->running = 1;
110 /* Reset the counter */
114 debounce->next = ao_debounce;
115 ao_debounce = debounce;
117 /* Make sure the timer is running */
118 if (!ao_debounce_running++)
121 /* And go check the current value */
122 _ao_debounce_check(debounce);
124 ao_arch_irqrestore(m);
128 * Stop monitoring one pin
131 _ao_debounce_stop(struct ao_debounce *debounce)
133 struct ao_debounce **prev;
136 m = ao_arch_irqsave();
137 if (debounce->running) {
138 debounce->running = 0;
141 for (prev = &ao_debounce; (*prev); prev = &((*prev)->next)) {
142 if (*prev == debounce) {
143 *prev = debounce->next;
147 debounce->next = NULL;
149 /* Turn off the timer if possible */
150 if (!--ao_debounce_running)
153 ao_arch_irqrestore(m);
157 ao_debounce_init(void)
159 if (ao_debounce_initialized)
161 ao_debounce_initialized = 1;
162 ao_fast_timer_init();