*
* 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
__xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT];
static uint8_t ao_quadrature_state[AO_QUADRATURE_COUNT];
+struct ao_debounce {
+ uint8_t state;
+ uint8_t count;
+};
+
+static struct ao_debounce ao_debounce_state[AO_QUADRATURE_COUNT][2];
+
#define port(q) AO_QUADRATURE_ ## q ## _PORT
#define bita(q) AO_QUADRATURE_ ## q ## _A
#define bitb(q) AO_QUADRATURE_ ## q ## _B
#define pinb(q) AO_QUADRATURE_ ## q ## _B ## _PIN
#define isr(q) ao_quadrature_isr_ ## q
-static inline uint16_t
-ao_quadrature_read(struct stm_gpio *gpio, uint8_t pin_a, uint8_t pin_b) {
- uint16_t v = stm_gpio_get_all(gpio);
+#ifndef AO_QUADRATURE_DEBOUNCE
+#define AO_QUADRATURE_DEBOUNCE 30
+#endif
- return ~((((v >> pin_a) & 1) | (((v >> pin_b) & 1) << 1))) & 3;
+static uint8_t
+ao_debounce(uint8_t cur, struct ao_debounce *debounce)
+{
+#if AO_QUADRATURE_DEBOUNCE > 0
+ if (debounce->count > 0) {
+ debounce->count--;
+ } else if (cur != debounce->state) {
+ debounce->state = cur;
+ debounce->count = AO_QUADRATURE_DEBOUNCE;
+ }
+ return debounce->state;
+#else
+ (void) debounce;
+ return cur;
+#endif
}
-#define _ao_quadrature_get(q) ao_quadrature_read(port(q), bita(q), bitb(q))
+static uint16_t
+ao_quadrature_read(struct stm_gpio *gpio, uint8_t pin_a, uint8_t pin_b, struct ao_debounce debounce_state[2]) {
+ uint16_t v = ~stm_gpio_get_all(gpio);
+ uint8_t a = (v >> pin_a) & 1;
+ uint8_t b = (v >> pin_b) & 1;
+
+ a = ao_debounce(a, &debounce_state[0]);
+ b = ao_debounce(b, &debounce_state[1]);
+
+ return a | (b << 1);
+}
+
+#define _ao_quadrature_get(q) ao_quadrature_read(port(q), bita(q), bitb(q), ao_debounce_state[q])
static void
_ao_quadrature_queue(uint8_t q, int8_t step)
ao_wakeup(&ao_quadrature_count[q]);
}
+#if AO_QUADRATURE_SINGLE_CODE
+struct ao_quadrature_step {
+ uint8_t inc;
+ uint8_t dec;
+};
+
+static struct ao_quadrature_step ao_quadrature_steps[4] = {
+ [0] = { .inc = 1, .dec = 2 },
+ [1] = { .inc = 3, .dec = 0 },
+ [3] = { .inc = 2, .dec = 1 },
+ [2] = { .inc = 0, .dec = 3 },
+};
+#endif
static void
_ao_quadrature_set(uint8_t q, uint8_t new) {
uint8_t old = ao_quadrature_state[q];
+#ifdef AO_QUADRATURE_SINGLE_CODE
+ if (new == ao_quadrature_steps[old].inc) {
+ _ao_quadrature_queue(q, 1);
+ } else if (new == ao_quadrature_steps[old].dec) {
+ _ao_quadrature_queue(q, -1);
+ }
+#else
if (old != new && new == 0) {
- if (old & 2)
+ if (old == 2)
_ao_quadrature_queue(q, 1);
- else if (old & 1)
+ else if (old == 1)
_ao_quadrature_queue(q, -1);
}
+#endif
ao_quadrature_state[q] = new;
}