From b0b52ca73bc836336ecc70247a9ed1dd633920d9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 6 Aug 2012 19:34:34 -0700 Subject: altos: Add quadrature driver Signed-off-by: Keith Packard --- src/drivers/ao_quadrature.c | 108 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 src/drivers/ao_quadrature.c (limited to 'src/drivers/ao_quadrature.c') diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c new file mode 100644 index 00000000..1cde32e7 --- /dev/null +++ b/src/drivers/ao_quadrature.c @@ -0,0 +1,108 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include +#include + +__xdata int32_t ao_quadrature_count; + +static uint8_t wait_clear; + +static void +ao_quadrature_isr(void) +{ + if (wait_clear) { + wait_clear = 0; + ao_exti_set_mode(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_EXTI_MODE_RISING); + } else { + wait_clear = 1; + ao_exti_set_mode(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_EXTI_MODE_FALLING); + if (ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_QUADRATURE_B_PIN)) + ao_quadrature_count++; + else + ao_quadrature_count--; + ao_wakeup(&ao_quadrature_count); + } +} + +int32_t +ao_quadrature_poll(void) +{ + int32_t ret; + ao_arch_critical(ret = ao_quadrature_count;); + return ret; +} + +int32_t +ao_quadrature_wait(void) +{ + ao_sleep(&ao_quadrature_count); + return ao_quadrature_poll(); +} + +static void +ao_quadrature_test(void) +{ +#if 0 + for (;;) { + int32_t c; + printf ("waiting...\n"); + flush(); + c = ao_quadrature_wait(); + printf ("new count %d\n", c); + if (ao_stdin_ready) + break; + } +#endif + uint8_t a, old_a, b, old_b; + + old_a = 2; old_b = 2; + for (;;) { + a = ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_QUADRATURE_A_PIN); + b = ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_QUADRATURE_B_PIN); + if (a != old_a || b != old_b) { + printf ("A %d B %d\n", a, b); + flush(); + ao_yield(); + old_a = a; + old_b = b; + } + if (ao_stdin_ready) + break; + } + +} + +static const struct ao_cmds ao_quadrature_cmds[] = { + { ao_quadrature_test, "q\0Test quadrature" }, + { 0, NULL } +}; + +void +ao_quadrature_init(void) +{ + ao_quadrature_count = 0; + + ao_enable_port(AO_QUADRATURE_PORT); + ao_exti_setup(AO_QUADRATURE_PORT, AO_QUADRATURE_A, + AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, + ao_quadrature_isr); + ao_exti_enable(AO_QUADRATURE_PORT, AO_QUADRATURE_A); + ao_enable_input(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_EXTI_MODE_PULL_UP); + ao_cmd_register(&ao_quadrature_cmds[0]); +} -- cgit v1.2.3 From 5f7e61c749b02ed16e368502062e39b0471e9257 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 6 Aug 2012 20:20:32 -0700 Subject: altos: Fix up quadrature driver Mostly works now, should work reliably with a bit of input filtering. Signed-off-by: Keith Packard --- src/drivers/ao_quadrature.c | 49 +++++++++++++++++++++++++++------------------ src/stm-demo/ao_pins.h | 4 ++-- 2 files changed, 31 insertions(+), 22 deletions(-) (limited to 'src/drivers/ao_quadrature.c') diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index 1cde32e7..1f94aa44 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -21,23 +21,29 @@ __xdata int32_t ao_quadrature_count; -static uint8_t wait_clear; +static uint8_t ao_quadrature_state; + +#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))) static void ao_quadrature_isr(void) { - if (wait_clear) { - wait_clear = 0; - ao_exti_set_mode(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_EXTI_MODE_RISING); - } else { - wait_clear = 1; - ao_exti_set_mode(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_EXTI_MODE_FALLING); - if (ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_QUADRATURE_B_PIN)) - ao_quadrature_count++; - else - ao_quadrature_count--; - ao_wakeup(&ao_quadrature_count); + ao_quadrature_state = ((ao_quadrature_state & 3) << 2); + ao_quadrature_state |= ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_QUADRATURE_A_PIN); + ao_quadrature_state |= ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_QUADRATURE_B_PIN) << 1; + + switch (ao_quadrature_state) { + case STATE(0, 1, 0, 0): + ao_quadrature_count++; + break; + case STATE(1, 0, 0, 0): + ao_quadrature_count--; + break; + default: + return; } + ao_wakeup(&ao_quadrature_count); } int32_t @@ -58,17 +64,17 @@ ao_quadrature_wait(void) static void ao_quadrature_test(void) { -#if 0 +#if 1 for (;;) { int32_t c; - printf ("waiting...\n"); flush(); c = ao_quadrature_wait(); - printf ("new count %d\n", c); - if (ao_stdin_ready) + printf ("new count %6d\n", c); + if (c == 100) break; } #endif +#if 0 uint8_t a, old_a, b, old_b; old_a = 2; old_b = 2; @@ -76,7 +82,7 @@ ao_quadrature_test(void) a = ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_QUADRATURE_A_PIN); b = ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_QUADRATURE_B_PIN); if (a != old_a || b != old_b) { - printf ("A %d B %d\n", a, b); + printf ("A %d B %d count %ld\n", a, b, ao_quadrature_count); flush(); ao_yield(); old_a = a; @@ -85,7 +91,7 @@ ao_quadrature_test(void) if (ao_stdin_ready) break; } - +#endif } static const struct ao_cmds ao_quadrature_cmds[] = { @@ -100,9 +106,12 @@ ao_quadrature_init(void) ao_enable_port(AO_QUADRATURE_PORT); ao_exti_setup(AO_QUADRATURE_PORT, AO_QUADRATURE_A, - AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, + AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, ao_quadrature_isr); ao_exti_enable(AO_QUADRATURE_PORT, AO_QUADRATURE_A); - ao_enable_input(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_EXTI_MODE_PULL_UP); + ao_exti_setup(AO_QUADRATURE_PORT, AO_QUADRATURE_B, + AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, + ao_quadrature_isr); + ao_exti_enable(AO_QUADRATURE_PORT, AO_QUADRATURE_B); ao_cmd_register(&ao_quadrature_cmds[0]); } diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 17a76bd0..1f5ef4ff 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -171,7 +171,7 @@ struct ao_adc { #define I2C_2_PB10_PB11 0 #define AO_QUADRATURE_PORT &stm_gpioc -#define AO_QUADRATURE_A 0 -#define AO_QUADRATURE_B 1 +#define AO_QUADRATURE_A 1 +#define AO_QUADRATURE_B 0 #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 11046bc89b3ce6386f1005fc8476b08f54d6f5fb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 6 Aug 2012 21:54:58 -0700 Subject: altos: Support multiple quadrature encoders. Signed-off-by: Keith Packard --- src/drivers/ao_quadrature.c | 90 +++++++++++++++++++++++++++++---------------- src/drivers/ao_quadrature.h | 4 +- src/stm-demo/ao_pins.h | 13 +++++-- 3 files changed, 70 insertions(+), 37 deletions(-) (limited to 'src/drivers/ao_quadrature.c') diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index 1f94aa44..aed4999e 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -19,46 +19,63 @@ #include #include -__xdata int32_t ao_quadrature_count; +__xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT]; -static uint8_t ao_quadrature_state; +static uint8_t ao_quadrature_state[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 port(q) AO_QUADRATURE_ ## q ## _PORT +#define bita(q) AO_QUADRATURE_ ## q ## _A +#define bitb(q) AO_QUADRATURE_ ## q ## _B + +#define ao_quadrature_update(q) do { \ + ao_quadrature_state[q] = ((ao_quadrature_state[q] & 3) << 2); \ + ao_quadrature_state[q] |= ao_gpio_get(port(q), bita(q), 0); \ + ao_quadrature_state[q] |= ao_gpio_get(port(q), bitb(q), 0) << 1; \ + } while (0) + + static void ao_quadrature_isr(void) { - ao_quadrature_state = ((ao_quadrature_state & 3) << 2); - ao_quadrature_state |= ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_QUADRATURE_A_PIN); - ao_quadrature_state |= ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_QUADRATURE_B_PIN) << 1; + uint8_t q; +#if AO_QUADRATURE_COUNT > 0 + ao_quadrature_update(0); +#endif +#if AO_QUADRATURE_COUNT > 1 + ao_quadrature_update(1); +#endif - switch (ao_quadrature_state) { - case STATE(0, 1, 0, 0): - ao_quadrature_count++; - break; - case STATE(1, 0, 0, 0): - ao_quadrature_count--; - break; - default: - return; + for (q = 0; q < AO_QUADRATURE_COUNT; q++) { + switch (ao_quadrature_state[q]) { + case STATE(0, 1, 0, 0): + ao_quadrature_count[q]++; + break; + case STATE(1, 0, 0, 0): + ao_quadrature_count[q]--; + break; + default: + continue; + } + ao_wakeup(&ao_quadrature_count[q]); } - ao_wakeup(&ao_quadrature_count); } int32_t -ao_quadrature_poll(void) +ao_quadrature_poll(uint8_t q) { int32_t ret; - ao_arch_critical(ret = ao_quadrature_count;); + ao_arch_critical(ret = ao_quadrature_count[q];); return ret; } int32_t -ao_quadrature_wait(void) +ao_quadrature_wait(uint8_t q) { - ao_sleep(&ao_quadrature_count); - return ao_quadrature_poll(); + ao_sleep(&ao_quadrature_count[q]); + return ao_quadrature_poll(q); } static void @@ -68,7 +85,7 @@ ao_quadrature_test(void) for (;;) { int32_t c; flush(); - c = ao_quadrature_wait(); + c = ao_quadrature_wait(0); printf ("new count %6d\n", c); if (c == 100) break; @@ -99,19 +116,28 @@ static const struct ao_cmds ao_quadrature_cmds[] = { { 0, NULL } }; +#define init(q) do { \ + ao_enable_port(port(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)); \ + } while (0) + void ao_quadrature_init(void) { - ao_quadrature_count = 0; - - ao_enable_port(AO_QUADRATURE_PORT); - ao_exti_setup(AO_QUADRATURE_PORT, AO_QUADRATURE_A, - AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, - ao_quadrature_isr); - ao_exti_enable(AO_QUADRATURE_PORT, AO_QUADRATURE_A); - ao_exti_setup(AO_QUADRATURE_PORT, AO_QUADRATURE_B, - AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, - ao_quadrature_isr); - ao_exti_enable(AO_QUADRATURE_PORT, AO_QUADRATURE_B); +#if AO_QUADRATURE_COUNT > 0 + init(0); +#endif +#if AO_QUADRATURE_COUNT > 1 + init(1); +#endif ao_cmd_register(&ao_quadrature_cmds[0]); } diff --git a/src/drivers/ao_quadrature.h b/src/drivers/ao_quadrature.h index 7e1048bc..f0b73b68 100644 --- a/src/drivers/ao_quadrature.h +++ b/src/drivers/ao_quadrature.h @@ -19,10 +19,10 @@ #define _AO_QUADRATURE_H_ int32_t -ao_quadrature_wait(void); +ao_quadrature_wait(uint8_t q); int32_t -ao_quadrature_poll(void); +ao_quadrature_poll(uint8_t q); void ao_quadrature_init(void); diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 1f5ef4ff..0c1ed8fc 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -170,8 +170,15 @@ struct ao_adc { #define HAS_I2C_2 0 #define I2C_2_PB10_PB11 0 -#define AO_QUADRATURE_PORT &stm_gpioc -#define AO_QUADRATURE_A 1 -#define AO_QUADRATURE_B 0 +#define AO_QUADRATURE_COUNT 2 +#define AO_QUADRATURE_MODE AO_EXTI_MODE_PULL_UP + +#define AO_QUADRATURE_0_PORT &stm_gpioc +#define AO_QUADRATURE_0_A 1 +#define AO_QUADRATURE_0_B 0 + +#define AO_QUADRATURE_1_PORT &stm_gpioc +#define AO_QUADRATURE_1_A 3 +#define AO_QUADRATURE_1_B 2 #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 46f87373bc8c28442273ee4f8da3a352223150f5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 6 Aug 2012 22:53:52 -0700 Subject: altos: Add button driver and event queue With this, a single task can wait for any button or quadrature input device. Signed-off-by: Keith Packard --- src/core/ao.h | 7 ++++++- src/drivers/ao_quadrature.c | 7 +++++++ src/stm-demo/Makefile | 4 +++- src/stm-demo/ao_demo.c | 20 ++++++++++++++++++++ src/stm-demo/ao_pins.h | 14 ++++++++++++++ src/stm/ao_timer.c | 2 +- 6 files changed, 51 insertions(+), 3 deletions(-) (limited to 'src/drivers/ao_quadrature.c') diff --git a/src/core/ao.h b/src/core/ao.h index 1032dd33..5e1fbb9d 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -125,7 +125,12 @@ ao_panic(uint8_t reason); * ao_timer.c */ -extern volatile __data uint16_t ao_tick_count; +#ifndef AO_TICK_TYPE +#define AO_TICK_TYPE uint16_t +#define AO_TICK_SIGNED int16_t +#endif + +extern volatile __data AO_TICK_TYPE ao_tick_count; /* Our timer runs at 100Hz */ #define AO_HERTZ 100 diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index aed4999e..6a2c1bba 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -18,6 +18,12 @@ #include #include #include +#if AO_EVENT +#include +#define ao_quadrature_queue(q) ao_event_put_isr(AO_EVENT_QUADRATURE, q, ao_quadrature_count[q]) +#else +#define ao_quadrature_queue(q) +#endif __xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT]; @@ -59,6 +65,7 @@ ao_quadrature_isr(void) default: continue; } + ao_quadrature_queue(q); ao_wakeup(&ao_quadrature_count[q]); } } diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 52bb7b51..340967fc 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -35,7 +35,9 @@ ALTOS_SRC = \ ao_i2c_stm.c \ ao_usb_stm.c \ ao_exti_stm.c \ - ao_quadrature.c + ao_event.c \ + ao_quadrature.c \ + ao_button.c PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 1b9813fe..fe7c69f2 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -17,7 +17,9 @@ #include "ao.h" #include +#include #include +#include struct ao_task demo_task; @@ -150,12 +152,29 @@ ao_temp (void) printf ("temp: %d\n", temp); } +static void +ao_event(void) +{ + struct ao_event event; + + for (;;) { + flush(); + ao_event_get(&event); + printf ("type %1d unit %1d tick %5u value %ld\n", + event.type, event.unit, event.tick, event.value); + if (event.value == 100) + break; + } + +} + __code struct ao_cmds ao_demo_cmds[] = { { ao_dma_test, "D\0DMA test" }, { ao_spi_write, "W\0SPI write" }, { ao_spi_read, "R\0SPI read" }, { ao_i2c_write, "i\0I2C write" }, { ao_temp, "t\0Show temp" }, + { ao_event, "e\0Monitor event queue" }, { 0, NULL } }; @@ -174,6 +193,7 @@ main(void) ao_i2c_init(); ao_exti_init(); ao_quadrature_init(); + ao_button_init(); ao_timer_set_adc_interval(100); diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 0c1ed8fc..77e42a28 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -170,6 +170,8 @@ struct ao_adc { #define HAS_I2C_2 0 #define I2C_2_PB10_PB11 0 +#define AO_EVENT 1 + #define AO_QUADRATURE_COUNT 2 #define AO_QUADRATURE_MODE AO_EXTI_MODE_PULL_UP @@ -181,4 +183,16 @@ struct ao_adc { #define AO_QUADRATURE_1_A 3 #define AO_QUADRATURE_1_B 2 +#define AO_BUTTON_COUNT 2 +#define AO_BUTTON_MODE AO_EXTI_MODE_PULL_UP + +#define AO_BUTTON_0_PORT &stm_gpioc +#define AO_BUTTON_0 6 + +#define AO_BUTTON_1_PORT &stm_gpioc +#define AO_BUTTON_1 7 + +#define AO_TICK_TYPE uint32_t +#define AO_TICK_SIGNED int32_t + #endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index ebe75366..adec7aad 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -17,7 +17,7 @@ #include "ao.h" -volatile __data uint16_t ao_tick_count; +volatile __data AO_TICK_TYPE ao_tick_count; uint16_t ao_time(void) { -- cgit v1.2.3