#define AO_PANIC_CRASH 14 /* Processor crashed */
#define AO_PANIC_BUFIO 15 /* Mis-using bufio API */
#define AO_PANIC_EXTI 16 /* Mis-using exti API */
+#define AO_PANIC_FAST_TIMER 17 /* Mis-using fast timer API */
#define AO_PANIC_SELF_TEST_CC1120 0x40 | 1 /* Self test failure */
#define AO_PANIC_SELF_TEST_HMC5883 0x40 | 2 /* Self test failure */
#define AO_PANIC_SELF_TEST_MPU6000 0x40 | 3 /* Self test failure */
--- /dev/null
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_debounce.h>
+#include <ao_fast_timer.h>
+
+static uint8_t ao_debounce_initialized;
+static uint8_t ao_debounce_running;
+static struct ao_debounce *ao_debounce;
+
+static uint8_t values[64];
+static uint8_t n;
+
+#define d_step(n) (((n) + 1) & 63)
+
+static void
+_ao_debounce_set(struct ao_debounce *debounce, uint8_t value)
+{
+ if (value != debounce->value) {
+ values[n] = value;
+ n = (n + 1) & 63;
+ debounce->value = value;
+ debounce->_set(debounce, value);
+ }
+ _ao_debounce_stop(debounce);
+}
+
+void
+ao_debounce_dump(void)
+{
+ uint8_t s;
+
+ for (s = 0; s < n; s++) {
+ printf ("%d: %d\n",
+ s, values[s]);
+ }
+ n = 0;
+}
+
+/*
+ * Get the current value, set the result when we've
+ * reached the debounce count limit
+ */
+static void
+_ao_debounce_check(struct ao_debounce *debounce)
+{
+ uint8_t next = debounce->_get(debounce);
+
+ if (next == debounce->current) {
+ if (debounce->count < debounce->hold) {
+ if (++debounce->count == debounce->hold)
+ _ao_debounce_set(debounce, debounce->current);
+ }
+ } else {
+ debounce->count = 0;
+ debounce->current = next;
+ }
+}
+
+static void
+_ao_debounce_isr(void)
+{
+ struct ao_debounce *debounce, *next;
+
+ for (debounce = ao_debounce; debounce; debounce = next) {
+ next = debounce->next;
+ _ao_debounce_check(debounce);
+ }
+}
+
+static void
+ao_debounce_on(void)
+{
+ ao_fast_timer_on(_ao_debounce_isr);
+}
+
+static void
+ao_debounce_off(void)
+{
+ ao_fast_timer_off(_ao_debounce_isr);
+}
+
+/*
+ * Start monitoring one pin
+ */
+void
+_ao_debounce_start(struct ao_debounce *debounce)
+{
+ uint32_t m;
+
+ m = ao_arch_irqsave();
+ if (!debounce->running) {
+ debounce->running = 1;
+
+ /* Reset the counter */
+ debounce->count = 0;
+
+ /* Link into list */
+ debounce->next = ao_debounce;
+ ao_debounce = debounce;
+
+ /* Make sure the timer is running */
+ if (!ao_debounce_running++)
+ ao_debounce_on();
+
+ /* And go check the current value */
+ _ao_debounce_check(debounce);
+ }
+ ao_arch_irqrestore(m);
+}
+
+/*
+ * Stop monitoring one pin
+ */
+void
+_ao_debounce_stop(struct ao_debounce *debounce)
+{
+ struct ao_debounce **prev;
+ uint32_t m;
+
+ m = ao_arch_irqsave();
+ if (debounce->running) {
+ debounce->running = 0;
+
+ /* Unlink */
+ for (prev = &ao_debounce; (*prev); prev = &((*prev)->next)) {
+ if (*prev == debounce) {
+ *prev = debounce->next;
+ break;
+ }
+ }
+ debounce->next = NULL;
+
+ /* Turn off the timer if possible */
+ if (!--ao_debounce_running)
+ ao_debounce_off();
+ }
+ ao_arch_irqrestore(m);
+}
+
+void
+ao_debounce_init(void)
+{
+ if (ao_debounce_initialized)
+ return;
+ ao_debounce_initialized = 1;
+ ao_fast_timer_init();
+}
struct ao_debounce *next;
/* time that pin value must be stable before accepting */
- int8_t hold;
+ uint8_t hold;
/* last value reported to app; don't report it twice */
uint8_t value;
+ /* current value received from pins */
+ uint8_t current;
+
/* current count of intervals pin value has been stable */
- int8_t count;
+ uint8_t count;
/* This pin is running */
uint8_t running;
void (*_set)(struct ao_debounce *debounce, uint8_t value);
};
+static inline void
+ao_debounce_config(struct ao_debounce *debounce,
+ uint8_t (*_get)(struct ao_debounce *debounce),
+ void (*_set)(struct ao_debounce *debounce, uint8_t value),
+ uint8_t hold)
+{
+ debounce->next = 0;
+ debounce->hold = hold;
+ debounce->value = 0xff;
+ debounce->current = 0xff;
+ debounce->count = 0;
+ debounce->running = 0;
+ debounce->_get = _get;
+ debounce->_set = _set;
+}
+
void
_ao_debounce_start(struct ao_debounce *debounce);
void
ao_debounce_init(void);
+void
+ao_debounce_dump(void);
+
#endif /* _AO_DEBOUNCE_H_ */
static void
ao_button_debounce_init(struct ao_debounce *debounce) {
- debounce->hold = AO_BUTTON_DEBOUNCE_HOLD;
- debounce->_get = _ao_button_get;
- debounce->_set = _ao_button_set;
+ ao_debounce_config(debounce,
+ _ao_button_get,
+ _ao_button_set,
+ AO_BUTTON_DEBOUNCE_HOLD);
}
static void
#include <ao.h>
#include <ao_quadrature.h>
#include <ao_exti.h>
-#include <ao_debounce.h>
+#include <ao_fast_timer.h>
#include <ao_event.h>
-#define AO_QUADRATURE_DEBOUNCE_HOLD 3
-
-static __xdata struct ao_debounce ao_quadrature_debounce[AO_QUADRATURE_COUNT];
-
-#define debounce_id(d) ((d) - ao_quadrature_debounce)
-
__xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT];
-
static uint8_t ao_quadrature_state[AO_QUADRATURE_COUNT];
+static int8_t ao_quadrature_raw[AO_QUADRATURE_COUNT];
#define BIT(a,b) ((a) | ((b) << 1))
#define STATE(old_a, old_b, new_a, new_b) (((BIT(old_a, old_b) << 2) | BIT(new_a, new_b)))
#define bitb(q) AO_QUADRATURE_ ## q ## _B
#define pina(q) AO_QUADRATURE_ ## q ## _A ## _PIN
#define pinb(q) AO_QUADRATURE_ ## q ## _B ## _PIN
+#define isr(q) ao_quadrature_isr_ ## q
-#define q_case(q) case q: v = (!ao_gpio_get(port(q), bita(q), pina(q))) | ((!ao_gpio_get(port(q), bitb(q), pinb(q))) << 1); break
-
-uint8_t quad_raw[64];
-uint8_t quad_r;
-
-static uint8_t
-_ao_quadrature_get(struct ao_debounce *debounce) {
- uint8_t q = debounce_id(debounce);
- uint8_t v = 0;
+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);
- switch (q) {
-#if AO_QUADRATURE_COUNT > 0
- q_case(0);
-#endif
-#if AO_QUADRATURE_COUNT > 1
- q_case(1);
-#endif
- }
- if (q == 0) {
- quad_raw[quad_r] = v;
- quad_r = (quad_r + 1) & 63;
- }
- return v;
+ return ~((((v >> pin_a) & 1) | (((v >> pin_b) & 1) << 1))) & 3;
}
+#define _ao_quadrature_get(q) ao_quadrature_read(port(q), bita(q), bitb(q))
+
static void
_ao_quadrature_queue(uint8_t q, int8_t step)
{
ao_wakeup(&ao_quadrature_count[q]);
}
-uint8_t quad_history[64];
-uint8_t quad_h;
+static const int8_t step[16] = {
+ [STATE(0,0,0,0)] = 0,
+ [STATE(0,0,0,1)] = -1,
+ [STATE(0,0,1,0)] = 1,
+ [STATE(0,0,1,1)] = 0,
+ [STATE(0,1,0,0)] = 1,
+ [STATE(0,1,1,0)] = 0,
+ [STATE(0,1,1,1)] = -1,
+ [STATE(1,0,0,0)] = -1,
+ [STATE(1,0,0,1)] = 0,
+ [STATE(1,0,1,0)] = 0,
+ [STATE(1,0,1,1)] = 1,
+ [STATE(1,1,0,0)] = 0,
+ [STATE(1,1,0,1)] = 1,
+ [STATE(1,1,1,0)] = -1,
+ [STATE(1,1,1,1)] = 0
+};
static void
-_ao_quadrature_set(struct ao_debounce *debounce, uint8_t value) {
- uint8_t q = debounce_id(debounce);
+_ao_quadrature_set(uint8_t q, uint8_t value) {
+ uint8_t v;
- ao_quadrature_state[q] = ((ao_quadrature_state[q] & 3) << 2);
- ao_quadrature_state[q] |= value;
-
- if (q == 0) {
- quad_history[quad_h] = ao_quadrature_state[0];
- quad_h = (quad_h + 1) & 63;
- }
+ v = ao_quadrature_state[q] & 3;
+ value = value & 3;
- switch (ao_quadrature_state[q]) {
- case STATE(0, 1, 0, 0):
- _ao_quadrature_queue(q, 1);
- break;
- case STATE(1, 0, 0, 0):
- _ao_quadrature_queue(q, -1);
- break;
+ if (v == value)
+ return;
+
+ ao_quadrature_state[q] = (v << 2) | value;
+
+ ao_quadrature_raw[q] += step[ao_quadrature_state[q]];
+ if (value == 0) {
+ if (ao_quadrature_raw[q] == 4)
+ _ao_quadrature_queue(q, 1);
+ else if (ao_quadrature_raw[q] == -4)
+ _ao_quadrature_queue(q, -1);
+ ao_quadrature_raw[q] = 0;
}
}
static void
ao_quadrature_isr(void)
{
- uint8_t q;
- for (q = 0; q < AO_QUADRATURE_COUNT; q++)
- _ao_debounce_start(&ao_quadrature_debounce[q]);
+ _ao_quadrature_set(0, _ao_quadrature_get(0));
+ _ao_quadrature_set(1, _ao_quadrature_get(1));
}
int32_t
ao_cmd_decimal();
q = ao_cmd_lex_i;
+ if (q >= AO_QUADRATURE_COUNT) {
+ ao_cmd_status = ao_cmd_syntax_error;
+ return;
+ }
+ printf ("count %d state %x raw %d\n",
+ ao_quadrature_count[q],
+ ao_quadrature_state[q],
+ ao_quadrature_raw[q]);
+#if 0
for (;;) {
int32_t c;
flush();
if (c == 100)
break;
}
+#endif
}
static const struct ao_cmds ao_quadrature_cmds[] = {
{ 0, NULL }
};
-static void
-ao_quadrature_debounce_init(struct ao_debounce *debounce) {
- debounce->hold = AO_QUADRATURE_DEBOUNCE_HOLD;
- debounce->_get = _ao_quadrature_get;
- debounce->_set = _ao_quadrature_set;
-}
-
-#define init(q) do { \
- ao_enable_port(port(q)); \
- ao_quadrature_debounce_init(&ao_quadrature_debounce[q]); \
- ao_exti_setup(port(q), bita(q), \
- AO_QUADRATURE_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \
- ao_quadrature_isr); \
- ao_exti_enable(port(q), bita(q)); \
- \
- ao_exti_setup(port(q), bitb(q), \
- AO_QUADRATURE_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \
- ao_quadrature_isr); \
- ao_exti_enable(port(q), bitb(q)); \
+#define init(q) do { \
+ ao_enable_input(port(q), bita(q), 0); \
+ ao_enable_input(port(q), bitb(q), 0); \
} while (0)
void
ao_quadrature_init(void)
{
- ao_debounce_init();
#if AO_QUADRATURE_COUNT > 0
init(0);
#endif
#if AO_QUADRATURE_COUNT > 1
init(1);
#endif
+ ao_fast_timer_init();
+ ao_fast_timer_on(ao_quadrature_isr);
ao_cmd_register(&ao_quadrature_cmds[0]);
}
+++ /dev/null
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <ao.h>
-#include <ao_debounce.h>
-
-static uint8_t ao_debounce_initialized;
-static uint8_t ao_debounce_running;
-static struct ao_debounce *ao_debounce;
-
-static void
-ao_debounce_on(void)
-{
- stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) |
- (0 << STM_TIM67_CR1_OPM) |
- (1 << STM_TIM67_CR1_URS) |
- (0 << STM_TIM67_CR1_UDIS) |
- (1 << STM_TIM67_CR1_CEN));
-}
-
-static void
-ao_debounce_off(void)
-{
- stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) |
- (0 << STM_TIM67_CR1_OPM) |
- (1 << STM_TIM67_CR1_URS) |
- (0 << STM_TIM67_CR1_UDIS) |
- (0 << STM_TIM67_CR1_CEN));
-}
-
-static void
-_ao_debounce_set(struct ao_debounce *debounce, uint8_t value)
-{
- if (value != debounce->value) {
- debounce->value = value;
- debounce->_set(debounce, value);
- }
- _ao_debounce_stop(debounce);
-}
-
-/*
- * Get the current value, set the result when we've
- * reached the debounce count limit
- */
-static void
-_ao_debounce_check(struct ao_debounce *debounce)
-{
- if (debounce->_get(debounce)) {
- if (debounce->count < 0)
- debounce->count = 0;
- if (debounce->count < debounce->hold) {
- if (++debounce->count == debounce->hold)
- _ao_debounce_set(debounce, 1);
- }
- } else {
- if (debounce->count > 0)
- debounce->count = 0;
- if (debounce->count > -debounce->hold) {
- if (--debounce->count == -debounce->hold)
- _ao_debounce_set(debounce, 0);
- }
- }
-}
-
-/*
- * Start monitoring one pin
- */
-void
-_ao_debounce_start(struct ao_debounce *debounce)
-{
- if (debounce->running)
- return;
- debounce->running = 1;
-
- /* Reset the counter */
- debounce->count = 0;
-
- /* Link into list */
- debounce->next = ao_debounce;
- ao_debounce = debounce;
-
- /* Make sure the timer is running */
- if (!ao_debounce_running++)
- ao_debounce_on();
-
- /* And go check the current value */
- _ao_debounce_check(debounce);
-}
-
-/*
- * Stop monitoring one pin
- */
-void
-_ao_debounce_stop(struct ao_debounce *debounce)
-{
- struct ao_debounce **prev;
- if (!debounce->running)
- return;
-
- debounce->running = 0;
-
- /* Unlink */
- for (prev = &ao_debounce; (*prev); prev = &((*prev)->next)) {
- if (*prev == debounce) {
- *prev = debounce->next;
- break;
- }
- }
- debounce->next = NULL;
-
- /* Turn off the timer if possible */
- if (!--ao_debounce_running)
- ao_debounce_off();
-}
-
-void stm_tim6_isr(void)
-{
- struct ao_debounce *debounce, *next;
- if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) {
- stm_tim6.sr = 0;
-
- /* Walk the current list, allowing the current
- * object to be removed from the list
- */
- for (debounce = ao_debounce; debounce; debounce = next) {
- next = debounce->next;
- _ao_debounce_check(debounce);
- }
- }
-}
-
-/*
- * According to the STM clock-configuration, timers run
- * twice as fast as the APB1 clock *if* the APB1 prescaler
- * is greater than 1.
- */
-
-#if AO_APB1_PRESCALER > 1
-#define TIMER_23467_SCALER 2
-#else
-#define TIMER_23467_SCALER 1
-#endif
-
-#define TIMER_100kHz ((AO_PCLK1 * TIMER_23467_SCALER) / 100000)
-
-void
-ao_debounce_init(void)
-{
- if (ao_debounce_initialized)
- return;
- ao_debounce_initialized = 1;
-
- stm_nvic_set_enable(STM_ISR_TIM6_POS);
- stm_nvic_set_priority(STM_ISR_TIM6_POS, AO_STM_NVIC_CLOCK_PRIORITY);
-
- /* Turn on timer 6 */
- stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN);
-
- stm_tim6.psc = TIMER_100kHz;
- stm_tim6.arr = 9;
- stm_tim6.cnt = 0;
-
- /* Enable update interrupt */
- stm_tim6.dier = (1 << STM_TIM67_DIER_UIE);
-
- /* Poke timer to reload values */
- stm_tim6.egr |= (1 << STM_TIM67_EGR_UG);
-
- stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS);
-
- /* And turn it off (for now) */
- ao_debounce_off();
-}
--- /dev/null
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include <ao.h>
+#include <ao_fast_timer.h>
+
+static void (*ao_fast_timer_callback[AO_FAST_TIMER_MAX])(void);
+static uint8_t ao_fast_timer_count;
+static uint8_t ao_fast_timer_users;
+
+static void
+ao_fast_timer_enable(void)
+{
+ stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) |
+ (0 << STM_TIM67_CR1_OPM) |
+ (1 << STM_TIM67_CR1_URS) |
+ (0 << STM_TIM67_CR1_UDIS) |
+ (1 << STM_TIM67_CR1_CEN));
+}
+
+static void
+ao_fast_timer_disable(void)
+{
+ stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) |
+ (0 << STM_TIM67_CR1_OPM) |
+ (1 << STM_TIM67_CR1_URS) |
+ (0 << STM_TIM67_CR1_UDIS) |
+ (0 << STM_TIM67_CR1_CEN));
+}
+
+void
+ao_fast_timer_on(void (*callback)(void))
+{
+ ao_fast_timer_callback[ao_fast_timer_count] = callback;
+ if (!ao_fast_timer_count++)
+ ao_fast_timer_enable();
+}
+
+void
+ao_fast_timer_off(void (*callback)(void))
+{
+ uint8_t n;
+
+ for (n = 0; n < ao_fast_timer_count; n++)
+ if (ao_fast_timer_callback[n] == callback) {
+ for (; n < ao_fast_timer_count-1; n++) {
+ ao_fast_timer_callback[n] = ao_fast_timer_callback[n+1];
+ }
+ if (!--ao_fast_timer_count)
+ ao_fast_timer_disable();
+ break;
+ }
+}
+
+void stm_tim6_isr(void)
+{
+ uint8_t i;
+ if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) {
+ stm_tim6.sr = 0;
+
+ for (i = 0; i < ao_fast_timer_count; i++)
+ (*ao_fast_timer_callback[i])();
+ }
+}
+
+/*
+ * According to the STM clock-configuration, timers run
+ * twice as fast as the APB1 clock *if* the APB1 prescaler
+ * is greater than 1.
+ */
+
+#if AO_APB1_PRESCALER > 1
+#define TIMER_23467_SCALER 2
+#else
+#define TIMER_23467_SCALER 1
+#endif
+
+#define TIMER_10kHz ((AO_PCLK1 * TIMER_23467_SCALER) / 10000)
+
+void
+ao_fast_timer_init(void)
+{
+ if (!ao_fast_timer_users) {
+ stm_nvic_set_enable(STM_ISR_TIM6_POS);
+ stm_nvic_set_priority(STM_ISR_TIM6_POS, AO_STM_NVIC_CLOCK_PRIORITY);
+
+ /* Turn on timer 6 */
+ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN);
+
+ stm_tim6.psc = TIMER_10kHz;
+ stm_tim6.arr = 9;
+ stm_tim6.cnt = 0;
+
+ /* Enable update interrupt */
+ stm_tim6.dier = (1 << STM_TIM67_DIER_UIE);
+
+ /* Poke timer to reload values */
+ stm_tim6.egr |= (1 << STM_TIM67_EGR_UG);
+
+ stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS);
+ ao_fast_timer_disable();
+ }
+ if (ao_fast_timer_users == AO_FAST_TIMER_MAX)
+ ao_panic(AO_PANIC_FAST_TIMER);
+ ao_fast_timer_users++;
+}
+
--- /dev/null
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_FAST_TIMER_H_
+#define _AO_FAST_TIMER_H_
+
+void
+ao_fast_timer_init(void);
+
+#ifndef AO_FAST_TIMER_MAX
+#define AO_FAST_TIMER_MAX 2
+#endif
+
+void
+ao_fast_timer_on(void (*callback)(void));
+
+void
+ao_fast_timer_off(void (*callback)(void));
+
+#endif /* _AO_FAST_TIMER_H_ */
return (gpio->idr >> pin) & 1;
}
+static inline uint16_t
+stm_gpio_get_all(struct stm_gpio *gpio) {
+ return gpio->idr;
+}
+
extern struct stm_gpio stm_gpioa;
extern struct stm_gpio stm_gpiob;
extern struct stm_gpio stm_gpioc;
ao_beep_stm.c \
ao_storage.c \
ao_eeprom_stm.c \
+ ao_fast_timer.c \
ao_lcd_stm.c \
ao_usb_stm.c \
ao_exti_stm.c \
*/
#define AO_QUADRATURE_COUNT 2
-#define AO_QUADRATURE_MODE 0
#define AO_QUADRATURE_0_PORT &stm_gpioe
#define AO_QUADRATURE_0_A 3