From 843fcab46d633e5bb6959286adeb68e41a4c30a3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Jul 2012 19:44:56 -0700 Subject: altos: Add telefire-v0.1 Signed-off-by: Keith Packard --- src/drivers/ao_74hc497.c | 40 +++++++++ src/drivers/ao_74hc497.h | 27 ++++++ src/drivers/ao_pad.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_pad.h | 67 ++++++++++++++ src/drivers/ao_pca9922.c | 78 ++++++++++++++++ 5 files changed, 439 insertions(+) create mode 100644 src/drivers/ao_74hc497.c create mode 100644 src/drivers/ao_74hc497.h create mode 100644 src/drivers/ao_pad.c create mode 100644 src/drivers/ao_pad.h create mode 100644 src/drivers/ao_pca9922.c (limited to 'src/drivers') diff --git a/src/drivers/ao_74hc497.c b/src/drivers/ao_74hc497.c new file mode 100644 index 00000000..93c544c3 --- /dev/null +++ b/src/drivers/ao_74hc497.c @@ -0,0 +1,40 @@ +/* + * 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. + */ + +/* + * 74HC597 driver. + * Reads a single byte from the shift register + */ + +#include +#include + +uint8_t +ao_74hc497_read(void) +{ + static __xdata state; + ao_spi_get_bit(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, AO_74HC497_SPI_BUS, AO_SPI_SPEED_FAST); + ao_spi_send(&state, 1, AO_74HC497_SPI_BUS); + ao_spi_put_bit(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, AO_74HC497_SPI_BUS); + return state; +} + +void +ao_74hc497_init(void) +{ + ao_enable_output(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, 1); +} diff --git a/src/drivers/ao_74hc497.h b/src/drivers/ao_74hc497.h new file mode 100644 index 00000000..6df7bcae --- /dev/null +++ b/src/drivers/ao_74hc497.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef _AO_74HC497_H_ +#define _AO_74HC497_H_ + +uint8_t +ao_74hc497_read(void); + +void +ao_74hc497_init(void); + +#endif /* _AO_74HC497_H_ */ diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c new file mode 100644 index 00000000..21aa788d --- /dev/null +++ b/src/drivers/ao_pad.c @@ -0,0 +1,227 @@ +/* + * 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 uint8_t ao_pad_ignite; + +#define ao_pad_igniter_status(c) AO_PAD_IGNITER_STATUS_UNKNOWN +#define ao_pad_arm_status() AO_PAD_ARM_STATUS_UNKNOWN + +#if 0 +#define PRINTD(...) printf(__VA_ARGS__) +#else +#define PRINTD(...) +#endif + +static void +ao_pad_run(void) +{ + for (;;) { + while (!ao_pad_ignite) + ao_sleep(&ao_pad_ignite); + /* + * Actually set the pad bits + */ + AO_PAD_PORT = (AO_PAD_PORT & (~AO_PAD_ALL_PINS)) | ao_pad_ignite; + while (ao_pad_ignite) { + ao_pad_ignite = 0; + ao_delay(AO_PAD_FIRE_TIME); + } + AO_PAD_PORT &= ~(AO_PAD_ALL_PINS); + } +} + +static void +ao_pad_status(void) +{ + for (;;) { + ao_delay(AO_SEC_TO_TICKS(1)); +#if 0 + if (ao_igniter_status(ao_igniter_drogue) == ao_igniter_ready) { + if (ao_igniter_status(ao_igniter_main) == ao_igniter_ready) { + for (i = 0; i < 5; i++) { + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); + ao_delay(AO_MS_TO_TICKS(100)); + } + } else { + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + } + } +#endif + } +} + +static __pdata uint8_t ao_pad_armed; +static __pdata uint16_t ao_pad_arm_time; +static __pdata uint8_t ao_pad_box; + +static void +ao_pad(void) +{ + static __xdata struct ao_pad_command command; + static __xdata struct ao_pad_query query; + int16_t time_difference; + uint8_t c; + + ao_led_off(AO_LED_RED); + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + ao_pad_box = ao_74hc497_read(); + for (;;) { + flush(); + if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) + continue; + + PRINTD ("tick %d serial %d cmd %d channel %d\n", + command.tick, command.serial, command.cmd, command.channel); + + switch (command.cmd) { + case AO_LAUNCH_ARM: + if (command.box != ao_pad_box) { + PRINTD ("box number mismatch\n"); + break; + } + + if (command.channels & ~(AO_PAD_ALL_PINS)) + break; + + time_difference = command.tick - ao_time(); + PRINTD ("arm tick %d local tick %d\n", command.tick, ao_time()); + if (time_difference < 0) + time_difference = -time_difference; + if (time_difference > 10) { + PRINTD ("time difference too large %d\n", time_difference); + break; + } + PRINTD ("armed\n"); + ao_pad_armed = command.channels; + ao_pad_arm_time = ao_time(); + + /* fall through ... */ + + case AO_LAUNCH_QUERY: + if (command.box != ao_pad_box) { + PRINTD ("box number mismatch\n"); + break; + } + + query.tick = ao_time(); + query.box = ao_pad_box; + query.channels = AO_PAD_ALL_PINS; + query.armed = ao_pad_armed; + query.arm_status = ao_pad_arm_status(); + for (c = 0; c < AO_PAD_NUM; c++) + query.igniter_status[c] = ao_pad_igniter_status(c); + PRINTD ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", + query.tick, query.serial, query.channel, query.valid, query.arm_status, + query.igniter_status); + ao_radio_cmac_send(&query, sizeof (query)); + break; + case AO_LAUNCH_FIRE: + if (!ao_pad_armed) { + PRINTD ("not armed\n"); + break; + } + if ((uint16_t) (ao_time() - ao_pad_arm_time) > AO_SEC_TO_TICKS(20)) { + PRINTD ("late pad arm_time %d time %d\n", + ao_pad_arm_time, ao_time()); + break; + } + time_difference = command.tick - ao_time(); + if (time_difference < 0) + time_difference = -time_difference; + if (time_difference > 10) { + PRINTD ("time different too large %d\n", time_difference); + break; + } + PRINTD ("ignite\n"); + ao_pad_ignite = ao_pad_armed; + ao_wakeup(&ao_pad_ignite); + break; + } + } +} + +void +ao_pad_test(void) +{ +#if 0 + switch (ao_igniter_status(ao_igniter_drogue)) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + switch (ao_igniter_status(ao_igniter_main)) { + default: + printf("unknown status\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; + } + break; + default: + printf("Disarmed\n"); + } +#endif +} + +void +ao_pad_manual(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + ao_cmd_white(); + ao_pad_ignite = 1; + ao_wakeup(&ao_pad_ignite); +} + +static __xdata struct ao_task ao_pad_task; +static __xdata struct ao_task ao_pad_ignite_task; +static __xdata struct ao_task ao_pad_status_task; + +__code struct ao_cmds ao_pad_cmds[] = { + { ao_pad_test, "t\0Test pad continuity" }, + { ao_pad_manual, "i \0Fire igniter. is doit with D&I" }, + { 0, NULL } +}; + +void +ao_pad_init(void) +{ +#if AO_PAD_NUM > 0 + ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_0, AO_PAD_0, 0); +#endif +#if AO_PAD_NUM > 1 + ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_1, AO_PAD_1, 0); +#endif +#if AO_PAD_NUM > 2 + ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_2, AO_PAD_2, 0); +#endif +#if AO_PAD_NUM > 3 + ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_3, AO_PAD_3, 0); +#endif + ao_cmd_register(&ao_pad_cmds[0]); + ao_add_task(&ao_pad_task, ao_pad, "pad listener"); + ao_add_task(&ao_pad_ignite_task, ao_pad_run, "pad igniter"); + ao_add_task(&ao_pad_status_task, ao_pad_status, "pad status"); +} diff --git a/src/drivers/ao_pad.h b/src/drivers/ao_pad.h new file mode 100644 index 00000000..9ea016ff --- /dev/null +++ b/src/drivers/ao_pad.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#ifndef _AO_PAD_H_ +#define _AO_PAD_H_ + +#define AO_PAD_MAX_CHANNELS 8 + +struct ao_pad_command { + uint16_t tick; + uint16_t box; + uint8_t cmd; + uint8_t channels; +}; + +/* Report current telefire status. + */ + +#define AO_PAD_QUERY 1 + +struct ao_pad_query { + uint16_t tick; /* telefire tick */ + uint16_t box; /* telefire box number */ + uint8_t channels; /* which chanels are present */ + uint8_t armed; /* which channels are armed */ + uint8_t arm_status; /* status of arming switch */ + uint8_t igniter_status[AO_PAD_MAX_CHANNELS]; /* status for each igniter */ +}; + +/* Set current armed pads, report back status + */ + +#define AO_PAD_ARM 2 + +/* Fire current armed pads for 200ms, no report + */ +#define AO_PAD_FIRE 3 + +#define AO_PAD_FIRE_TIME AO_MS_TO_TICKS(200) + +#define AO_PAD_ARM_STATUS_DISARMED 0 +#define AO_PAD_ARM_STATUS_ARMED 1 +#define AO_PAD_ARM_STATUS_UNKNOWN 2 + +#define AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN 0 +#define AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN 1 +#define AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED 2 +#define AO_PAD_IGNITER_STATUS_UNKNOWN 3 + +void +ao_pad_init(void); + +#endif /* _AO_PAD_H_ */ diff --git a/src/drivers/ao_pca9922.c b/src/drivers/ao_pca9922.c new file mode 100644 index 00000000..dc006f55 --- /dev/null +++ b/src/drivers/ao_pca9922.c @@ -0,0 +1,78 @@ +/* + * 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. + */ + +/* + * PCA9922 LED driver. This uses SPI to send a single byte to the device to + * set the current state of the LEDs using the existing LED interface + */ + +#include + +static __xdata uint8_t ao_led_state; + +static void +ao_led_apply(void) +{ + /* Don't try the SPI bus during initialization */ + if (!ao_cur_task) + return; + ao_spi_get_bit(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, AO_PCA9922_SPI_BUS, AO_SPI_SPEED_FAST); + ao_spi_send(&ao_led_state, 1, AO_PCA9922_SPI_BUS); + ao_spi_put_bit(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, AO_PCA9922_SPI_BUS); +} + +void +ao_led_on(uint8_t colors) +{ + ao_led_state |= colors; + ao_led_apply(); +} + +void +ao_led_off(uint8_t colors) +{ + ao_led_state &= ~colors; + ao_led_apply(); +} + +void +ao_led_set(uint8_t colors) +{ + ao_led_state = colors; + ao_led_apply(); +} + +void +ao_led_toggle(uint8_t colors) +{ + ao_led_state ^= colors; + ao_led_apply(); +} + +void +ao_led_for(uint8_t colors, uint16_t ticks) __reentrant +{ + ao_led_on(colors); + ao_delay(ticks); + ao_led_off(colors); +} + +void +ao_led_init(uint8_t enable) +{ + ao_enable_output(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, 1); +} -- cgit v1.2.3 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 ++++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_quadrature.h | 30 ++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 src/drivers/ao_quadrature.c create mode 100644 src/drivers/ao_quadrature.h (limited to 'src/drivers') 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]); +} diff --git a/src/drivers/ao_quadrature.h b/src/drivers/ao_quadrature.h new file mode 100644 index 00000000..7e1048bc --- /dev/null +++ b/src/drivers/ao_quadrature.h @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#ifndef _AO_QUADRATURE_H_ +#define _AO_QUADRATURE_H_ + +int32_t +ao_quadrature_wait(void); + +int32_t +ao_quadrature_poll(void); + +void +ao_quadrature_init(void); + +#endif /* _AO_QUADRATURE_H_ */ -- 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') 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') 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') 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 From f46d94ca5c969c88dd307d1b684d6fafa2157020 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 Aug 2012 21:24:16 -0700 Subject: altos: Use split SPI bus for MS5607 sensor Leave CS low while releasing the SPI bus when waiting for conversion complete -- other SPI bus users will use another set of pins. Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/drivers') diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 17fe853b..1b55b7fd 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -134,11 +134,18 @@ ao_ms5607_get_sample(uint8_t cmd) { ao_ms5607_start(); ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); ao_exti_enable(AO_MS5607_MISO_GPIO, AO_MS5607_MISO); +#if AO_MS5607_PRIVATE_PINS + ao_spi_put(AO_MS5607_SPI_INDEX); +#endif cli(); while (!ao_ms5607_done) ao_sleep(&ao_ms5607_done); sei(); +#if AO_MS5607_PRIVATE_PINS + stm_gpio_set(AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); +#else ao_ms5607_stop(); +#endif ao_ms5607_start(); read = AO_MS5607_ADC_READ; -- cgit v1.2.3 From 93db8febda03d9a02c5c1ccdc6ad44eaf00a433b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 Aug 2012 21:26:34 -0700 Subject: altos: Add MMA655X driver Just debug code at this point, will complete on real hardware Signed-off-by: Keith Packard --- src/drivers/ao_mma655x.c | 210 ++++++++++++++++++++++++++++++++++++ src/drivers/ao_mma655x.h | 85 +++++++++++++++ src/megametrum-v0.1/Makefile | 2 + src/megametrum-v0.1/ao_megametrum.c | 4 + src/megametrum-v0.1/ao_pins.h | 9 ++ 5 files changed, 310 insertions(+) create mode 100644 src/drivers/ao_mma655x.c create mode 100644 src/drivers/ao_mma655x.h (limited to 'src/drivers') diff --git a/src/drivers/ao_mma655x.c b/src/drivers/ao_mma655x.c new file mode 100644 index 00000000..e4e41627 --- /dev/null +++ b/src/drivers/ao_mma655x.c @@ -0,0 +1,210 @@ +/* + * 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 + +static uint8_t mma655x_configured; +uint8_t ao_mma655x_valid; + +static void +ao_mma655x_start(void) { + ao_spi_get_bit(AO_MMA655X_CS_GPIO, + AO_MMA655X_CS, + AO_MMA655X_CS_PIN, + AO_MMA655X_SPI_INDEX, + AO_SPI_SPEED_FAST); +} + +static void +ao_mma655x_stop(void) { + ao_spi_put_bit(AO_MMA655X_CS_GPIO, + AO_MMA655X_CS, + AO_MMA655X_CS_PIN, + AO_MMA655X_SPI_INDEX); +} + +static uint8_t +ao_parity(uint8_t v) +{ + /* down to four bits */ + v = (v ^ (v >> 4)) & 0xf; + + /* Cute lookup hack -- 0x6996 encodes the sixteen + * even parity values in order. + */ + return (~0x6996 >> v) & 1; +} + +static void +ao_mma655x_cmd(uint8_t d[2]) +{ + ao_mma655x_start(); + ao_spi_send(d, 2, AO_MMA655X_SPI_INDEX); + ao_spi_recv(d, 2, AO_MMA655X_SPI_INDEX); + ao_mma655x_stop(); +} + +static uint8_t +ao_mma655x_reg_write(uint8_t addr, uint8_t value) +{ + uint8_t d[2]; + + addr |= (1 << 6); /* write mode */ + d[0] = addr | (ao_parity(addr^value) << 7); + d[1] = value; + ao_mma655x_cmd(d); + return d[1]; +} + +static uint8_t +ao_mma655x_reg_read(uint8_t addr) +{ + uint8_t d[2]; + + d[0] = addr | (ao_parity(addr) << 7); + d[1] = 0; + ao_mma655x_cmd(d); + return d[1]; +} + +static uint16_t +ao_mma655x_value(void) +{ + uint8_t d[2]; + uint16_t v; + + d[0] = ((0 << 7) | /* Axis selection (X) */ + (1 << 6) | /* Acceleration operation */ + (1 << 5)); /* Raw data */ + d[1] = ((1 << 3) | /* must be one */ + (1 << 2) | /* Unsigned data */ + (0 << 1) | /* Arm disabled */ + (1 << 0)); /* Odd parity */ + ao_mma655x_cmd(d); + v = (uint16_t) d[1] << 2; + v |= d[0] >> 6; + v |= (uint16_t) (d[0] & 3) << 10; + return v; +} + +static void +ao_mma655x_reset(void) { + ao_mma655x_reg_write(AO_MMA655X_DEVCTL, + (0 << AO_MMA655X_DEVCTL_RES_1) | + (0 << AO_MMA655X_DEVCTL_RES_1)); + ao_mma655x_reg_write(AO_MMA655X_DEVCTL, + (1 << AO_MMA655X_DEVCTL_RES_1) | + (1 << AO_MMA655X_DEVCTL_RES_1)); + ao_mma655x_reg_write(AO_MMA655X_DEVCTL, + (0 << AO_MMA655X_DEVCTL_RES_1) | + (1 << AO_MMA655X_DEVCTL_RES_1)); +} + +#define DEVCFG_VALUE (\ + (1 << AO_MMA655X_DEVCFG_OC) | /* Disable offset cancelation */ \ + (1 << AO_MMA655X_DEVCFG_SD) | /* Receive unsigned data */ \ + (0 << AO_MMA655X_DEVCFG_OFMON) | /* Disable offset monitor */ \ + (AO_MMA655X_DEVCFG_A_CFG_DISABLE << AO_MMA655X_DEVCFG_A_CFG)) + +#define AXISCFG_VALUE (\ + (0 << AO_MMA655X_AXISCFG_LPF)) /* 100Hz 4-pole filter */ + + +static void +ao_mma655x_setup(void) +{ + uint8_t v; + uint16_t a, a_st; + uint8_t stdefl; + + if (mma655x_configured) + return; + mma655x_configured = 1; + ao_delay(AO_MS_TO_TICKS(10)); /* Top */ + ao_mma655x_reset(); + ao_delay(AO_MS_TO_TICKS(10)); /* Top */ + (void) ao_mma655x_reg_read(AO_MMA655X_DEVSTAT); + v = ao_mma655x_reg_read(AO_MMA655X_DEVSTAT); + + /* Configure R/W register values. + * Most of them relate to the arming feature, which + * we don't use, so the only registers we need to + * write are DEVCFG and AXISCFG + */ + + ao_mma655x_reg_write(AO_MMA655X_DEVCFG, + DEVCFG_VALUE | (0 << AO_MMA655X_DEVCFG_ENDINIT)); + + /* Test X axis + */ + + ao_mma655x_reg_write(AO_MMA655X_AXISCFG, + AXISCFG_VALUE | + (1 << AO_MMA655X_AXISCFG_ST)); + a_st = ao_mma655x_value(); + + stdefl = ao_mma655x_reg_read(AO_MMA655X_STDEFL); + + ao_mma655x_reg_write(AO_MMA655X_AXISCFG, + AXISCFG_VALUE | + (0 << AO_MMA655X_AXISCFG_ST)); + a = ao_mma655x_value(); + printf ("normal: %u self_test: %u stdefl: %u\n", + a, a_st, stdefl); + + ao_mma655x_reg_write(AO_MMA655X_DEVCFG, + DEVCFG_VALUE | (1 << AO_MMA655X_DEVCFG_ENDINIT)); +} + +static void +ao_mma655x_dump(void) +{ + uint8_t s0, s1, s2, s3; + uint32_t lot; + uint16_t serial; + + ao_mma655x_setup(); + + s0 = ao_mma655x_reg_read(AO_MMA655X_SN0); + s1 = ao_mma655x_reg_read(AO_MMA655X_SN1); + s2 = ao_mma655x_reg_read(AO_MMA655X_SN2); + s3 = ao_mma655x_reg_read(AO_MMA655X_SN3); + lot = ((uint32_t) s3 << 24) | ((uint32_t) s2 << 16) | + ((uint32_t) s1 << 8) | ((uint32_t) s0); + serial = lot & 0x1fff; + lot >>= 12; + printf ("MMA655X lot %d serial %d\n", lot, serial); + mma655x_configured = 0; +} + +__code struct ao_cmds ao_mma655x_cmds[] = { + { ao_mma655x_dump, "A\0Display MMA655X data" }, + { 0, NULL }, +}; + +void +ao_mma655x_init(void) +{ + mma655x_configured = 0; + ao_mma655x_valid = 0; + + ao_cmd_register(&ao_mma655x_cmds[0]); + ao_spi_init_cs(AO_MMA655X_CS_GPIO, (1 << AO_MMA655X_CS)); + +// ao_add_task(&ao_mma655x_task, ao_mma655x, "mma655x"); +} diff --git a/src/drivers/ao_mma655x.h b/src/drivers/ao_mma655x.h new file mode 100644 index 00000000..9c0c59dc --- /dev/null +++ b/src/drivers/ao_mma655x.h @@ -0,0 +1,85 @@ +/* + * 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. + */ + +#ifndef _AO_MMA655X_H_ +#define _AO_MMA655X_H_ + + +#define AO_MMA655X_SN0 0x00 +#define AO_MMA655X_SN1 0x01 +#define AO_MMA655X_SN2 0x02 +#define AO_MMA655X_SN3 0x03 +#define AO_MMA655X_SN3 0x03 +#define AO_MMA655X_STDEFL 0x04 +#define AO_MMA655X_FCTCFG 0x06 +# define AO_MMA655X_FCTCFG_STMAG 7 + +#define AO_MMA655X_PN 0x08 +#define AO_MMA655X_DEVCTL 0x0a +#define AO_MMA655X_DEVCTL_RES_1 7 +#define AO_MMA655X_DEVCTL_RES_0 6 +#define AO_MMA655X_DEVCTL_OCPHASE 4 +#define AO_MMA655X_DEVCTL_OCPHASE_MASK 3 +#define AO_MMA655X_DEVCTL_OFFCFG_EN 3 + +#define AO_MMA655X_DEVCFG 0x0b +#define AO_MMA655X_DEVCFG_OC 7 +#define AO_MMA655X_DEVCFG_ENDINIT 5 +#define AO_MMA655X_DEVCFG_SD 4 +#define AO_MMA655X_DEVCFG_OFMON 3 +#define AO_MMA655X_DEVCFG_A_CFG 0 +#define AO_MMA655X_DEVCFG_A_CFG_DISABLE 0 +#define AO_MMA655X_DEVCFG_A_CFG_PCM 1 +#define AO_MMA655X_DEVCFG_A_CFG_MOVING_AVG_HIGH 2 +#define AO_MMA655X_DEVCFG_A_CFG_MOVING_AVG_LOW 3 +#define AO_MMA655X_DEVCFG_A_CFG_COUNT_HIGH 4 +#define AO_MMA655X_DEVCFG_A_CFG_COUNT_LOW 5 +#define AO_MMA655X_DEVCFG_A_CFG_UNFILTERED_HIGH 6 +#define AO_MMA655X_DEVCFG_A_CFG_UNFILTERED_LOW 7 +#define AO_MMA655X_DEVCFG_A_CFG_MASK 7 + +#define AO_MMA655X_AXISCFG 0x0c +#define AO_MMA655X_AXISCFG_ST 7 +#define AO_MMA655X_AXISCFG_LPF 0 +#define AO_MMA655X_AXISCFG_LPF_MASK 0xf + +#define AO_MMA655X_ARMCFG 0x0e +#define AO_MMA655X_ARMCFG_APS 4 +#define AO_MMA655X_ARMCFG_APS_MASK 3 +#define AO_MMA655X_ARMCFG_AWS_N 2 +#define AO_MMA655X_ARMCFG_AWS_N_MASK 3 +#define AO_MMA655X_ARMCFG_AWS_P 0 +#define AO_MMA655X_ARMCFG_AWS_P_MASK 3 + +#define AO_MMA655X_ARMT_P 0x10 +#define AO_MMA655X_ARMT_N 0x12 + +#define AO_MMA655X_DEVSTAT 0x14 +#define AO_MMA655X_DEVSTAT_IDE 6 +#define AO_MMA655X_DEVSTAT_DEVINIT 4 +#define AO_MMA655X_DEVSTAT_MISOERR 3 +#define AO_MMA655X_DEVSTAT_OFFSET 1 +#define AO_MMA655X_DEVSTAT_DEVRES 0 + +#define AO_MMA655X_COUNT 0x15 +#define AO_MMA655X_OFFCORR 0x16 + + +void +ao_mma655x_init(void); + +#endif /* _AO_MMA655X_H_ */ diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 4a4c983a..1dfebca0 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -19,6 +19,7 @@ INC = \ ao_ms5607.h \ ao_hmc5883.h \ ao_mpu6000.h \ + ao_mma655x.h \ ao_cc1120_CC1120.h \ ao_profile.h \ ao_whiten.h \ @@ -56,6 +57,7 @@ ALTOS_SRC = \ ao_fec_tx.c \ ao_fec_rx.c \ ao_ms5607.c \ + ao_mma655x.c \ ao_adc_stm.c \ ao_beep_stm.c \ ao_storage.c \ diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 55324514..d3ae4690 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,9 @@ main(void) #if HAS_MPU6000 ao_mpu6000_init(); #endif +#if HAS_MMA655X + ao_mma655x_init(); +#endif ao_storage_init(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 42715968..6256d2f6 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -305,6 +305,15 @@ struct ao_adc { #define HAS_HIGHG_ACCEL 0 +/* + * mma655x + */ + +#define HAS_MMA655X 1 +#define AO_MMA655X_SPI_INDEX AO_SPI_1_PA5_PA6_PA7 +#define AO_MMA655X_CS_GPIO (&stm_gpiod) +#define AO_MMA655X_CS 4 + #define NUM_CMDS 16 /* -- cgit v1.2.3 From ab1279cc6a683595631d7ac8bed7b36e0c8a691c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 Aug 2012 22:51:47 -0700 Subject: Here's the button driver and event queue logic These were neglected in the commit which was supposed to include them Signed-off-by: Keith Packard --- src/drivers/ao_button.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_button.h | 24 +++++++++++++ src/drivers/ao_event.c | 77 ++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_event.h | 41 +++++++++++++++++++++ 4 files changed, 236 insertions(+) create mode 100644 src/drivers/ao_button.c create mode 100644 src/drivers/ao_button.h create mode 100644 src/drivers/ao_event.c create mode 100644 src/drivers/ao_event.h (limited to 'src/drivers') diff --git a/src/drivers/ao_button.c b/src/drivers/ao_button.c new file mode 100644 index 00000000..a507c909 --- /dev/null +++ b/src/drivers/ao_button.c @@ -0,0 +1,94 @@ +/* + * 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 +#if AO_EVENT +#include +#define ao_button_queue(b,v) ao_event_put_isr(AO_EVENT_BUTTON, b, v) +#else +#define ao_button_queue(b,v) +#endif + +static uint8_t ao_button[AO_BUTTON_COUNT]; +static AO_TICK_TYPE ao_button_time[AO_BUTTON_COUNT]; + +#define AO_DEBOUNCE AO_MS_TO_TICKS(20) + +#define port(q) AO_BUTTON_ ## q ## _PORT +#define bit(q) AO_BUTTON_ ## q +#define pin(q) AO_BUTTON_ ## q ## _PIN + +static void +ao_button_do(uint8_t b, uint8_t v) +{ + /* Debounce */ + if ((AO_TICK_SIGNED) (ao_tick_count - ao_button_time[b]) < AO_DEBOUNCE) + return; + + /* pins are inverted */ + v = !v; + if (ao_button[b] != v) { + ao_button[b] = v; + ao_button_time[b] = ao_tick_count; + ao_button_queue(b, v); + ao_wakeup(&ao_button[b]); + } +} + +#define ao_button_update(b) ao_button_do(b, ao_gpio_get(port(b), bit(b), pin(b))) + +static void +ao_button_isr(void) +{ +#if AO_BUTTON_COUNT > 0 + ao_button_update(0); +#endif +#if AO_BUTTON_COUNT > 1 + ao_button_update(1); +#endif +#if AO_BUTTON_COUNT > 2 + ao_button_update(2); +#endif +#if AO_BUTTON_COUNT > 3 + ao_button_update(3); +#endif +#if AO_BUTTON_COUNT > 4 + ao_button_update(4); +#endif +} + +#define init(b) do { \ + ao_enable_port(port(b)); \ + \ + ao_exti_setup(port(b), bit(b), \ + AO_BUTTON_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \ + ao_button_isr); \ + ao_exti_enable(port(b), bit(b)); \ + } while (0) + +void +ao_button_init(void) +{ +#if AO_BUTTON_COUNT > 0 + init(0); +#endif +#if AO_BUTTON_COUNT > 1 + init(1); +#endif +} diff --git a/src/drivers/ao_button.h b/src/drivers/ao_button.h new file mode 100644 index 00000000..ce349d65 --- /dev/null +++ b/src/drivers/ao_button.h @@ -0,0 +1,24 @@ +/* + * 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. + */ + +#ifndef _AO_BUTTON_H_ +#define _AO_BUTTON_H_ + +void +ao_button_init(void); + +#endif /* _AO_BUTTON_H_ */ diff --git a/src/drivers/ao_event.c b/src/drivers/ao_event.c new file mode 100644 index 00000000..440ef2de --- /dev/null +++ b/src/drivers/ao_event.c @@ -0,0 +1,77 @@ +/* + * 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 + +#define AO_EVENT_QUEUE 64 + +#define ao_event_queue_next(n) (((n) + 1) & (AO_EVENT_QUEUE - 1)) +#define ao_event_queue_prev(n) (((n) - 1) & (AO_EVENT_QUEUE - 1)) +#define ao_event_queue_empty() (ao_event_queue_insert == ao_event_queue_remove) +#define ao_event_queue_full() (ao_event_queue_next(ao_event_queue_insert) == ao_event_queue_remove) + +/* + * Whether a sequence of events from the same device should be collapsed + */ +#define ao_event_can_collapse(type) ((type) == AO_EVENT_QUADRATURE) + +struct ao_event ao_event_queue[AO_EVENT_QUEUE]; +uint8_t ao_event_queue_insert; +uint8_t ao_event_queue_remove; + + +uint8_t +ao_event_get(struct ao_event *ev) +{ + ao_arch_critical( + while (ao_event_queue_empty()) + ao_sleep(&ao_event_queue); + *ev = ao_event_queue[ao_event_queue_remove]; + ao_event_queue_remove = ao_event_queue_next(ao_event_queue_remove); + ); +} + +/* called with interrupts disabled */ +void +ao_event_put_isr(uint8_t type, uint8_t unit, uint32_t value) +{ + if (!ao_event_queue_full()) { + + if (ao_event_can_collapse(type) && !ao_event_queue_empty()) { + uint8_t prev = ao_event_queue_prev(ao_event_queue_insert); + + if (ao_event_queue[prev].type == type && + ao_event_queue[prev].unit == unit) + ao_event_queue_insert = prev; + } + ao_event_queue[ao_event_queue_insert] = (struct ao_event) { + .type = type, + .unit = unit, + .tick = ao_tick_count, + .value = value + }; + ao_event_queue_insert = ao_event_queue_next(ao_event_queue_insert); + ao_wakeup(&ao_event_queue); + } +} + +void +ao_event_put(uint8_t type, uint8_t unit, uint32_t value) +{ + ao_arch_critical(ao_event_put_isr(type, unit, value);); +} diff --git a/src/drivers/ao_event.h b/src/drivers/ao_event.h new file mode 100644 index 00000000..25c49c35 --- /dev/null +++ b/src/drivers/ao_event.h @@ -0,0 +1,41 @@ +/* + * 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. + */ + +#ifndef _AO_EVENT_H_ +#define _AO_EVENT_H_ + +#define AO_EVENT_NONE 0 +#define AO_EVENT_QUADRATURE 1 +#define AO_EVENT_BUTTON 2 + +struct ao_event { + uint8_t type; + uint8_t unit; + uint16_t tick; + uint32_t value; +}; + +uint8_t +ao_event_get(struct ao_event *ev); + +void +ao_event_put_isr(uint8_t type, uint8_t unit, uint32_t value); + +void +ao_event_put(uint8_t type, uint8_t unit, uint32_t value); + +#endif /* _AO_EVENT_H_ */ -- cgit v1.2.3 From 7a0ed0ff4192060854d69e640de2c30105eb2f62 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Aug 2012 00:27:13 -0700 Subject: altos: Disable telefire 'pad' listener when testing radio Ensures that the radio testing won't block waiting for a firing mode packet to arrive. Signed-off-by: Keith Packard --- src/cc1111/ao_radio.c | 9 +++++++++ src/drivers/ao_pad.c | 19 +++++++++++++++++++ src/drivers/ao_pad.h | 6 ++++++ 3 files changed, 34 insertions(+) (limited to 'src/drivers') diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 2071c47a..46b2362d 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -16,6 +16,9 @@ */ #include "ao.h" +#if HAS_PAD +#include +#endif /* Values from SmartRF® Studio for: * @@ -484,6 +487,9 @@ ao_radio_test(void) #endif #if PACKET_HAS_SLAVE ao_packet_slave_stop(); +#endif +#if HAS_PAD + ao_pad_disable(); #endif ao_radio_get(0xff); RFST = RFST_STX; @@ -500,6 +506,9 @@ ao_radio_test(void) radio_on = 0; #if HAS_MONITOR ao_monitor_enable(); +#endif +#if HAS_PAD + ao_pad_enable(); #endif } } diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 21aa788d..b6dbcefe 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -71,6 +71,23 @@ ao_pad_status(void) static __pdata uint8_t ao_pad_armed; static __pdata uint16_t ao_pad_arm_time; static __pdata uint8_t ao_pad_box; +static __xdata uint8_t ao_pad_disabled; + +void +ao_pad_disable(void) +{ + if (!ao_pad_disabled) { + ao_pad_disabled = 1; + ao_radio_recv_abort(); + } +} + +void +ao_pad_enable(void) +{ + ao_pad_disabled = 0; + ao_wakeup (&ao_pad_disabled); +} static void ao_pad(void) @@ -85,6 +102,8 @@ ao_pad(void) ao_pad_box = ao_74hc497_read(); for (;;) { flush(); + while (ao_pad_disabled) + ao_sleep(&ao_pad_disabled); if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) continue; diff --git a/src/drivers/ao_pad.h b/src/drivers/ao_pad.h index 9ea016ff..d5ca3a88 100644 --- a/src/drivers/ao_pad.h +++ b/src/drivers/ao_pad.h @@ -64,4 +64,10 @@ struct ao_pad_query { void ao_pad_init(void); +void +ao_pad_disable(void); + +void +ao_pad_enable(void); + #endif /* _AO_PAD_H_ */ -- cgit v1.2.3 From a8e9906513227600599da12b268ff5f807ae98c7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Aug 2012 00:34:55 -0700 Subject: altos: Add 'ao_led_set_mask' in the PCA9922 driver This lets a subset of the LEDs be controlled independent of other LED settings. Signed-off-by: Keith Packard --- src/core/ao_led.h | 4 ++++ src/drivers/ao_pca9922.c | 8 ++++++++ 2 files changed, 12 insertions(+) (limited to 'src/drivers') diff --git a/src/core/ao_led.h b/src/core/ao_led.h index edc5fd1f..d9a0914a 100644 --- a/src/core/ao_led.h +++ b/src/core/ao_led.h @@ -40,6 +40,10 @@ ao_led_off(AO_LED_TYPE colors); void ao_led_set(AO_LED_TYPE colors); +/* Set all LEDs in 'mask' to the specified state */ +void +ao_led_set_mask(uint8_t colors, uint8_t mask); + /* Toggle the specified LEDs */ void ao_led_toggle(AO_LED_TYPE colors); diff --git a/src/drivers/ao_pca9922.c b/src/drivers/ao_pca9922.c index dc006f55..6d8d18d8 100644 --- a/src/drivers/ao_pca9922.c +++ b/src/drivers/ao_pca9922.c @@ -56,6 +56,13 @@ ao_led_set(uint8_t colors) ao_led_apply(); } +void +ao_led_set_mask(uint8_t colors, uint8_t mask) +{ + ao_led_state = (ao_led_state & ~mask) | (colors & mask); + ao_led_apply(); +} + void ao_led_toggle(uint8_t colors) { @@ -74,5 +81,6 @@ ao_led_for(uint8_t colors, uint16_t ticks) __reentrant void ao_led_init(uint8_t enable) { + (void) enable; ao_enable_output(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, 1); } -- cgit v1.2.3 From 83e0d4352041b3964ea7a133b0f67da9ebaa1c77 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Aug 2012 00:40:27 -0700 Subject: altos: Split out LCO functions from ao_radio_cmac.c to ao_lco.c These functions are not used in the telelaunch or telefire nodes, so don't force them to be included. Signed-off-by: Keith Packard --- src/core/ao_radio_cmac.c | 173 ------------------------------------------ src/drivers/ao_lco.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_lco.h | 24 ++++++ 3 files changed, 217 insertions(+), 173 deletions(-) create mode 100644 src/drivers/ao_lco.c create mode 100644 src/drivers/ao_lco.h (limited to 'src/drivers') diff --git a/src/core/ao_radio_cmac.c b/src/core/ao_radio_cmac.c index 32ce8793..3e8dce53 100644 --- a/src/core/ao_radio_cmac.c +++ b/src/core/ao_radio_cmac.c @@ -243,176 +243,3 @@ radio_cmac_recv_cmd(void) __reentrant ao_mutex_put(&ao_radio_cmac_mutex); } -static __xdata struct ao_launch_command command; -static __xdata struct ao_launch_query query; -static __pdata uint16_t launch_serial; -static __pdata uint8_t launch_channel; -static __pdata uint16_t tick_offset; - -static void -launch_args(void) __reentrant -{ - ao_cmd_decimal(); - launch_serial = ao_cmd_lex_i; - ao_cmd_decimal(); - launch_channel = ao_cmd_lex_i; -} - -static int8_t -launch_query(void) -{ - uint8_t i; - int8_t r = AO_RADIO_CMAC_OK; - - tick_offset = ao_time(); - for (i = 0; i < 10; i++) { - printf ("."); flush(); - command.tick = ao_time(); - command.serial = launch_serial; - command.cmd = AO_LAUNCH_QUERY; - command.channel = launch_channel; - ao_radio_cmac_send(&command, sizeof (command)); - r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); - if (r == AO_RADIO_CMAC_OK) - break; - } - tick_offset -= query.tick; - printf("\n"); flush(); - return r; -} - -static void -launch_report_cmd(void) __reentrant -{ - int8_t r; - - launch_args(); - if (ao_cmd_status != ao_cmd_success) - return; - r = launch_query(); - switch (r) { - case AO_RADIO_CMAC_OK: - if (query.valid) { - switch (query.arm_status) { - case ao_igniter_ready: - case ao_igniter_active: - printf ("Armed: "); - break; - default: - printf("Disarmed: "); - } - switch (query.igniter_status) { - default: - printf("unknown\n"); - break; - case ao_igniter_ready: - printf("igniter good\n"); - break; - case ao_igniter_open: - printf("igniter bad\n"); - break; - } - } else { - printf("Invalid channel %d\n", launch_channel); - } - printf("Rssi: %d\n", ao_radio_cmac_rssi); - break; - default: - printf("Error %d\n", r); - break; - } -} - -static void -launch_arm(void) __reentrant -{ - command.tick = ao_time() - tick_offset; - command.serial = launch_serial; - command.cmd = AO_LAUNCH_ARM; - command.channel = launch_channel; - ao_radio_cmac_send(&command, sizeof (command)); -} - -static void -launch_ignite(void) __reentrant -{ - command.tick = ao_time() - tick_offset; - command.serial = launch_serial; - command.cmd = AO_LAUNCH_FIRE; - command.channel = 0; - ao_radio_cmac_send(&command, sizeof (command)); -} - -static void -launch_fire_cmd(void) __reentrant -{ - static __xdata struct ao_launch_command command; - uint8_t secs; - uint8_t i; - int8_t r; - - launch_args(); - ao_cmd_decimal(); - secs = ao_cmd_lex_i; - if (ao_cmd_status != ao_cmd_success) - return; - r = launch_query(); - if (r != AO_RADIO_CMAC_OK) { - printf("query failed %d\n", r); - return; - } - - for (i = 0; i < 4; i++) { - printf("arm %d\n", i); flush(); - launch_arm(); - } - - secs = secs * 10 - 5; - if (secs > 100) - secs = 100; - for (i = 0; i < secs; i++) { - printf("fire %d\n", i); flush(); - launch_ignite(); - ao_delay(AO_MS_TO_TICKS(100)); - } -} - -static void -launch_arm_cmd(void) __reentrant -{ - uint8_t i; - int8_t r; - launch_args(); - r = launch_query(); - if (r != AO_RADIO_CMAC_OK) { - printf("query failed %d\n", r); - return; - } - for (i = 0; i < 4; i++) - launch_arm(); -} - -static void -launch_ignite_cmd(void) __reentrant -{ - uint8_t i; - launch_args(); - for (i = 0; i < 4; i++) - launch_ignite(); -} - -static __code struct ao_cmds ao_radio_cmac_cmds[] = { - { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, - { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, - { launch_report_cmd, "l \0Get remote launch status" }, - { launch_fire_cmd, "f \0Fire remote igniter" }, - { launch_arm_cmd, "a \0Arm remote igniter" }, - { launch_ignite_cmd, "i \0Pulse remote igniter" }, - { 0, NULL }, -}; - -void -ao_radio_cmac_init(void) -{ - ao_cmd_register(&ao_radio_cmac_cmds[0]); -} diff --git a/src/drivers/ao_lco.c b/src/drivers/ao_lco.c new file mode 100644 index 00000000..f30f3379 --- /dev/null +++ b/src/drivers/ao_lco.c @@ -0,0 +1,193 @@ +/* + * 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 + +static __xdata struct ao_launch_command command; +static __xdata struct ao_launch_query query; +static __pdata uint16_t launch_serial; +static __pdata uint8_t launch_channel; +static __pdata uint16_t tick_offset; + +static void +launch_args(void) __reentrant +{ + ao_cmd_decimal(); + launch_serial = ao_cmd_lex_i; + ao_cmd_decimal(); + launch_channel = ao_cmd_lex_i; +} + +static int8_t +launch_query(void) +{ + uint8_t i; + int8_t r = AO_RADIO_CMAC_OK; + + tick_offset = ao_time(); + for (i = 0; i < 10; i++) { + printf ("."); flush(); + command.tick = ao_time(); + command.serial = launch_serial; + command.cmd = AO_LAUNCH_QUERY; + command.channel = launch_channel; + ao_radio_cmac_send(&command, sizeof (command)); + r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); + if (r == AO_RADIO_CMAC_OK) + break; + } + tick_offset -= query.tick; + printf("\n"); flush(); + return r; +} + +static void +launch_report_cmd(void) __reentrant +{ + int8_t r; + + launch_args(); + if (ao_cmd_status != ao_cmd_success) + return; + r = launch_query(); + switch (r) { + case AO_RADIO_CMAC_OK: + if (query.valid) { + switch (query.arm_status) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + break; + default: + printf("Disarmed: "); + } + switch (query.igniter_status) { + default: + printf("unknown\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; + } + } else { + printf("Invalid channel %d\n", launch_channel); + } + printf("Rssi: %d\n", ao_radio_cmac_rssi); + break; + default: + printf("Error %d\n", r); + break; + } +} + +static void +launch_arm(void) __reentrant +{ + command.tick = ao_time() - tick_offset; + command.serial = launch_serial; + command.cmd = AO_LAUNCH_ARM; + command.channel = launch_channel; + ao_radio_cmac_send(&command, sizeof (command)); +} + +static void +launch_ignite(void) __reentrant +{ + command.tick = ao_time() - tick_offset; + command.serial = launch_serial; + command.cmd = AO_LAUNCH_FIRE; + command.channel = 0; + ao_radio_cmac_send(&command, sizeof (command)); +} + +static void +launch_fire_cmd(void) __reentrant +{ + static __xdata struct ao_launch_command command; + uint8_t secs; + uint8_t i; + int8_t r; + + launch_args(); + ao_cmd_decimal(); + secs = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + r = launch_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } + + for (i = 0; i < 4; i++) { + printf("arm %d\n", i); flush(); + launch_arm(); + } + + secs = secs * 10 - 5; + if (secs > 100) + secs = 100; + for (i = 0; i < secs; i++) { + printf("fire %d\n", i); flush(); + launch_ignite(); + ao_delay(AO_MS_TO_TICKS(100)); + } +} + +static void +launch_arm_cmd(void) __reentrant +{ + uint8_t i; + int8_t r; + launch_args(); + r = launch_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } + for (i = 0; i < 4; i++) + launch_arm(); +} + +static void +launch_ignite_cmd(void) __reentrant +{ + uint8_t i; + launch_args(); + for (i = 0; i < 4; i++) + launch_ignite(); +} + +static __code struct ao_cmds ao_lco_cmds[] = { + { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, + { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, + { launch_report_cmd, "l \0Get remote launch status" }, + { launch_fire_cmd, "f \0Fire remote igniter" }, + { launch_arm_cmd, "a \0Arm remote igniter" }, + { launch_ignite_cmd, "i \0Pulse remote igniter" }, + { 0, NULL }, +}; + +void +ao_lco_init(void) +{ + ao_cmd_register(&ao_lco_cmds[0]); +} diff --git a/src/drivers/ao_lco.h b/src/drivers/ao_lco.h new file mode 100644 index 00000000..253f9702 --- /dev/null +++ b/src/drivers/ao_lco.h @@ -0,0 +1,24 @@ +/* + * 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. + */ + +#ifndef _AO_LCO_H_ +#define _AO_LCO_H_ + +void +ao_lco_init(void); + +#endif /* _AO_LCO_H_ */ -- cgit v1.2.3 From 6581fa1641882198c870c2f7b1340794b9d47f29 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Aug 2012 00:42:32 -0700 Subject: altos: Get ao_pad.c working on telefire v0.1 Monitor all four channels, allow any channel to be fired. Turn on power LED at startup time. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 61 +++++++++++++++++++++++++++++++++++++++------------- src/drivers/ao_pad.h | 2 +- 2 files changed, 47 insertions(+), 16 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index b6dbcefe..dfa5f9f5 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -51,20 +51,48 @@ ao_pad_run(void) static void ao_pad_status(void) { + uint8_t c; + uint8_t sample; + __pdata uint8_t prev = 0, cur = 0; + __pdata uint8_t beeping = 0; + __xdata struct ao_data *packet; + + sample = ao_data_head; for (;;) { - ao_delay(AO_SEC_TO_TICKS(1)); -#if 0 - if (ao_igniter_status(ao_igniter_drogue) == ao_igniter_ready) { - if (ao_igniter_status(ao_igniter_main) == ao_igniter_ready) { - for (i = 0; i < 5; i++) { - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); - ao_delay(AO_MS_TO_TICKS(100)); - } - } else { - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + __pdata int16_t pyro; + ao_arch_critical( + while (sample == ao_data_head) + ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); + ); + + packet = &ao_data_ring[sample]; + sample = ao_data_ring_next(sample); + + pyro = packet->adc.pyro; + +#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * 27.0 / 127.0 / 3.3 * 32767.0)) + + cur = 0; + if (pyro > VOLTS_TO_PYRO(4)) { + for (c = 0; c < AO_PAD_NUM; c++) { + int16_t sense = packet->adc.sense[c]; + + if (sense >= pyro / 4 * 3) + cur |= AO_LED_CONTINUITY(c); } } -#endif + if (cur != prev) { + ao_led_set_mask(cur, AO_LED_CONTINUITY_MASK); + prev = cur; + } + + if (pyro > VOLTS_TO_PYRO(9) && sample == 0) { + beeping = 1; + ao_beep(AO_BEEP_HIGH); + } else if (beeping) { + beeping = 0; + ao_beep(0); + } } } @@ -97,9 +125,10 @@ ao_pad(void) int16_t time_difference; uint8_t c; - ao_led_off(AO_LED_RED); ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); ao_pad_box = ao_74hc497_read(); + ao_led_set(0); + ao_led_on(AO_LED_POWER); for (;;) { flush(); while (ao_pad_disabled) @@ -209,8 +238,10 @@ ao_pad_manual(void) ao_cmd_white(); if (!ao_match_word("DoIt")) return; - ao_cmd_white(); - ao_pad_ignite = 1; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_pad_ignite = 1 << ao_cmd_lex_i; ao_wakeup(&ao_pad_ignite); } @@ -220,7 +251,7 @@ static __xdata struct ao_task ao_pad_status_task; __code struct ao_cmds ao_pad_cmds[] = { { ao_pad_test, "t\0Test pad continuity" }, - { ao_pad_manual, "i \0Fire igniter. is doit with D&I" }, + { ao_pad_manual, "i \0Fire igniter. is doit with D&I" }, { 0, NULL } }; diff --git a/src/drivers/ao_pad.h b/src/drivers/ao_pad.h index d5ca3a88..3b0cf1fe 100644 --- a/src/drivers/ao_pad.h +++ b/src/drivers/ao_pad.h @@ -50,7 +50,7 @@ struct ao_pad_query { */ #define AO_PAD_FIRE 3 -#define AO_PAD_FIRE_TIME AO_MS_TO_TICKS(200) +#define AO_PAD_FIRE_TIME AO_MS_TO_TICKS(1000) #define AO_PAD_ARM_STATUS_DISARMED 0 #define AO_PAD_ARM_STATUS_ARMED 1 -- cgit v1.2.3 From ea4db73328e865fd658b573da256ca0004c69c61 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 Aug 2012 09:45:03 -0700 Subject: altos: Add debug command for 74hc597 driver This dumps the current state of the 74hc597 chip. Note that this shows that the 74hc597 driver doesn't work, and that the circuit used in telefire v0.1 can't work. Signed-off-by: Keith Packard --- src/drivers/ao_74hc497.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_74hc497.c b/src/drivers/ao_74hc497.c index 93c544c3..4c13ee71 100644 --- a/src/drivers/ao_74hc497.c +++ b/src/drivers/ao_74hc497.c @@ -28,13 +28,28 @@ ao_74hc497_read(void) { static __xdata state; ao_spi_get_bit(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, AO_74HC497_SPI_BUS, AO_SPI_SPEED_FAST); - ao_spi_send(&state, 1, AO_74HC497_SPI_BUS); + ao_spi_recv(&state, 1, AO_74HC497_SPI_BUS); ao_spi_put_bit(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, AO_74HC497_SPI_BUS); return state; } +static void +ao_74hc497_cmd(void) +{ + uint8_t v; + + v = ao_74hc497_read(); + printf ("Switches: 0x%02x\n", v); +} + +static const struct ao_cmds ao_74hc497_cmds[] = { + { ao_74hc497_cmd, "L\0Show 74hc497" }, + { 0, NULL } +}; + void ao_74hc497_init(void) { ao_enable_output(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, 1); + ao_cmd_register(&ao_74hc497_cmds[0]); } -- cgit v1.2.3 From 1c9baa88d6cd931c66d453674322908eb267ba4c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 Aug 2012 09:47:05 -0700 Subject: altos: Make 'pad' driver useful with telefire v0.1 This reports correct status bits over the radio and to the LEDs for all four channels, and also makes the firing test command control all four relays. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 108 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 69 insertions(+), 39 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index dfa5f9f5..791c9a47 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -19,15 +19,16 @@ #include #include -__xdata uint8_t ao_pad_ignite; - -#define ao_pad_igniter_status(c) AO_PAD_IGNITER_STATUS_UNKNOWN -#define ao_pad_arm_status() AO_PAD_ARM_STATUS_UNKNOWN +static __xdata uint8_t ao_pad_ignite; +static __xdata struct ao_pad_command command; +static __xdata struct ao_pad_query query; #if 0 #define PRINTD(...) printf(__VA_ARGS__) +#define FLUSHD() flush() #else #define PRINTD(...) +#define FLUSHD() #endif static void @@ -49,12 +50,12 @@ ao_pad_run(void) } static void -ao_pad_status(void) +ao_pad_monitor(void) { uint8_t c; uint8_t sample; - __pdata uint8_t prev = 0, cur = 0; - __pdata uint8_t beeping = 0; + __pdata uint8_t prev = 0, cur = 0; + __pdata uint8_t beeping = 0; __xdata struct ao_data *packet; sample = ao_data_head; @@ -73,13 +74,45 @@ ao_pad_status(void) #define VOLTS_TO_PYRO(x) ((int16_t) ((x) * 27.0 / 127.0 / 3.3 * 32767.0)) cur = 0; - if (pyro > VOLTS_TO_PYRO(4)) { - for (c = 0; c < AO_PAD_NUM; c++) { - int16_t sense = packet->adc.sense[c]; + if (pyro > VOLTS_TO_PYRO(4)) + query.arm_status = AO_PAD_ARM_STATUS_ARMED; + else if (pyro < VOLTS_TO_PYRO(1)) + query.arm_status = AO_PAD_ARM_STATUS_DISARMED; + else + query.arm_status = AO_PAD_ARM_STATUS_UNKNOWN; + + for (c = 0; c < AO_PAD_NUM; c++) { + int16_t sense = packet->adc.sense[c]; + uint8_t status = AO_PAD_IGNITER_STATUS_UNKNOWN; + + if (query.arm_status == AO_PAD_ARM_STATUS_ARMED) { + /* + * pyro is run through a divider, so pyro = v_pyro * 27 / 127 ~= v_pyro / 20 + * v_pyro = pyro * 127 / 27 + * + * v_pyro \ + * 100k igniter + * output / + * 100k \ + * sense relay + * 27k / + * gnd --- + * + * If the relay is closed, then sense will be 0 + * If no igniter is present, then sense will be v_pyro * 27k/227k = pyro * 127 / 227 ~= pyro/2 + * If igniter is present, then sense will be v_pyro * 27k/127k ~= v_pyro / 20 = pyro + */ - if (sense >= pyro / 4 * 3) + if (sense <= pyro / 8) + status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED; + else if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5) + status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; + else if (pyro / 8 * 7 <= sense) { + status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN; cur |= AO_LED_CONTINUITY(c); + } } + query.igniter_status[c] = status; } if (cur != prev) { ao_led_set_mask(cur, AO_LED_CONTINUITY_MASK); @@ -120,17 +153,14 @@ ao_pad_enable(void) static void ao_pad(void) { - static __xdata struct ao_pad_command command; - static __xdata struct ao_pad_query query; int16_t time_difference; - uint8_t c; ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); ao_pad_box = ao_74hc497_read(); ao_led_set(0); ao_led_on(AO_LED_POWER); for (;;) { - flush(); + FLUSHD(); while (ao_pad_disabled) ao_sleep(&ao_pad_disabled); if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) @@ -173,9 +203,6 @@ ao_pad(void) query.box = ao_pad_box; query.channels = AO_PAD_ALL_PINS; query.armed = ao_pad_armed; - query.arm_status = ao_pad_arm_status(); - for (c = 0; c < AO_PAD_NUM; c++) - query.igniter_status[c] = ao_pad_igniter_status(c); PRINTD ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", query.tick, query.serial, query.channel, query.valid, query.arm_status, query.igniter_status); @@ -209,27 +236,30 @@ ao_pad(void) void ao_pad_test(void) { -#if 0 - switch (ao_igniter_status(ao_igniter_drogue)) { - case ao_igniter_ready: - case ao_igniter_active: - printf ("Armed: "); - switch (ao_igniter_status(ao_igniter_main)) { - default: - printf("unknown status\n"); - break; - case ao_igniter_ready: - printf("igniter good\n"); - break; - case ao_igniter_open: - printf("igniter bad\n"); - break; - } + uint8_t c; + + printf ("Arm switch: "); + switch (query.arm_status) { + case AO_PAD_ARM_STATUS_ARMED: + printf ("Armed\n"); + break; + case AO_PAD_ARM_STATUS_DISARMED: + printf ("Disarmed\n"); + break; + case AO_PAD_ARM_STATUS_UNKNOWN: + printf ("Unknown\n"); break; - default: - printf("Disarmed\n"); } -#endif + + for (c = 0; c < AO_PAD_NUM; c++) { + printf ("Pad %d: "); + switch (query.igniter_status[c]) { + case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED: printf ("No igniter. Relay closed\n"); break; + case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN: printf ("No igniter. Relay open\n"); break; + case AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN: printf ("Good igniter. Relay open\n"); break; + case AO_PAD_IGNITER_STATUS_UNKNOWN: printf ("Unknown\n"); break; + } + } } void @@ -247,7 +277,7 @@ ao_pad_manual(void) static __xdata struct ao_task ao_pad_task; static __xdata struct ao_task ao_pad_ignite_task; -static __xdata struct ao_task ao_pad_status_task; +static __xdata struct ao_task ao_pad_monitor_task; __code struct ao_cmds ao_pad_cmds[] = { { ao_pad_test, "t\0Test pad continuity" }, @@ -273,5 +303,5 @@ ao_pad_init(void) ao_cmd_register(&ao_pad_cmds[0]); ao_add_task(&ao_pad_task, ao_pad, "pad listener"); ao_add_task(&ao_pad_ignite_task, ao_pad_run, "pad igniter"); - ao_add_task(&ao_pad_status_task, ao_pad_status, "pad status"); + ao_add_task(&ao_pad_monitor_task, ao_pad_monitor, "pad monitor"); } -- cgit v1.2.3 From f89e7de20374141b367205aa517a08ee203bfaf3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 Aug 2012 09:53:16 -0700 Subject: altos: Trigger sample complete when all data are ready This has each sensor mark a bit in the current data record which is then sent for processing when all of the data are present. Signed-off-by: Keith Packard --- src/core/ao_data.h | 50 +++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_hmc5883.c | 23 ++++++++----------- src/drivers/ao_hmc5883.h | 4 ---- src/drivers/ao_mma655x.c | 23 ++++++++++++++++--- src/drivers/ao_mpu6000.c | 30 +++++++++---------------- src/drivers/ao_mpu6000.h | 3 --- src/drivers/ao_ms5607.c | 26 ++++++++++----------- src/drivers/ao_ms5607.h | 3 --- src/megametrum-v0.1/Makefile | 2 ++ src/megametrum-v0.1/ao_pins.h | 2 +- src/megametrum-v0.1/stlink-pins | 8 +++++++ src/stm-demo/Makefile | 1 + src/stm/ao_adc_stm.c | 42 +--------------------------------- src/stm/ao_timer.c | 19 +++++++++------- 14 files changed, 126 insertions(+), 110 deletions(-) (limited to 'src/drivers') diff --git a/src/core/ao_data.h b/src/core/ao_data.h index fdc49ca2..3b66ef5d 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -18,18 +18,42 @@ #ifndef _AO_DATA_H_ #define _AO_DATA_H_ +#if HAS_ADC +#define AO_DATA_ADC (1 << 0) +#else +#define AO_DATA_ADC 0 +#endif + #if HAS_MS5607 #include +#define AO_DATA_MS5607 (1 << 1) +#else +#define AO_DATA_MS5607 (1 << 1) #endif #if HAS_MPU6000 #include +#define AO_DATA_MPU6000 (1 << 2) +#else +#define AO_DATA_MPU6000 0 #endif #if HAS_HMC5883 #include +#define AO_DATA_HMC5883 (1 << 3) +#else +#define AO_DATA_HMC5883 0 +#endif + +#if HAS_MMA655X +#include +#define AO_DATA_MMA655X (1 << 4) +#else +#define AO_DATA_MMA655X 0 #endif +#define AO_DATA_ALL (AO_DATA_ADC|AO_DATA_MS5607|AO_DATA_MPU6000|AO_DATA_HMC5883|AO_DATA_MMA655X) + struct ao_data { uint16_t tick; #if HAS_ADC @@ -45,6 +69,9 @@ struct ao_data { #if HAS_HMC5883 struct ao_hmc5883_sample hmc5883; #endif +#if HAS_MMA655X + uint16_t mma655x; +#endif }; #define ao_data_ring_next(n) (((n) + 1) & (AO_DATA_RING - 1)) @@ -52,6 +79,29 @@ struct ao_data { extern volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; extern volatile __data uint8_t ao_data_head; +extern volatile __data uint8_t ao_data_present; +extern volatile __data uint8_t ao_data_count; + +/* + * Mark a section of data as ready, check for data complete + */ +#define AO_DATA_PRESENT(bit) do { \ + if ((ao_data_present |= (bit)) == AO_DATA_ALL) { \ + ao_data_ring[ao_data_head].tick = ao_tick_count; \ + ao_data_head = ao_data_ring_next(ao_data_head); \ + ao_data_present = 0; \ + ao_wakeup((void *) &ao_data_head); \ + } \ + } while (0); + +/* + * Wait for data to be completed by looking at the + * indicated bit + */ +#define AO_DATA_WAIT() do { \ + ao_sleep((void *) &ao_data_count); \ + } while (0) + #if HAS_MS5607 diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index dbeb66b8..ade6c263 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -19,7 +19,7 @@ #include #include -uint8_t ao_hmc5883_valid; +#if HAS_HMC5883 static uint8_t ao_hmc5883_configured; @@ -123,21 +123,16 @@ ao_hmc5883_setup(void) return 1; } -struct ao_hmc5883_sample ao_hmc5883_current; - static void ao_hmc5883(void) { ao_hmc5883_setup(); for (;;) { - struct ao_hmc5883_sample ao_hmc5883_next; - - ao_hmc5883_sample(&ao_hmc5883_next); + ao_hmc5883_sample((struct ao_hmc5883_sample *) &ao_data_ring[ao_data_head].hmc5883); ao_arch_critical( - ao_hmc5883_current = ao_hmc5883_next; - ao_hmc5883_valid = 1; + AO_DATA_PRESENT(AO_DATA_HMC5883); + AO_DATA_WAIT(); ); - ao_delay(0); } } @@ -146,11 +141,10 @@ static struct ao_task ao_hmc5883_task; static void ao_hmc5883_show(void) { - struct ao_hmc5883_sample sample; - - sample = ao_hmc5883_current; + struct ao_data sample; + ao_data_get(&sample); printf ("X: %d Y: %d Z: %d missed irq: %lu\n", - sample.x, sample.y, sample.z, ao_hmc5883_missed_irq); + sample.hmc5883.x, sample.hmc5883.y, sample.hmc5883.z, ao_hmc5883_missed_irq); } static const struct ao_cmds ao_hmc5883_cmds[] = { @@ -162,7 +156,6 @@ void ao_hmc5883_init(void) { ao_hmc5883_configured = 0; - ao_hmc5883_valid = 0; ao_enable_port(AO_HMC5883_INT_PORT); ao_exti_setup(AO_HMC5883_INT_PORT, @@ -173,3 +166,5 @@ ao_hmc5883_init(void) ao_add_task(&ao_hmc5883_task, ao_hmc5883, "hmc5883"); ao_cmd_register(&ao_hmc5883_cmds[0]); } + +#endif diff --git a/src/drivers/ao_hmc5883.h b/src/drivers/ao_hmc5883.h index 8d726510..55690978 100644 --- a/src/drivers/ao_hmc5883.h +++ b/src/drivers/ao_hmc5883.h @@ -75,14 +75,10 @@ #define HMC5883_ID_B 11 #define HMC5883_ID_C 12 -extern uint8_t ao_hmc5883_valid; - struct ao_hmc5883_sample { int16_t x, y, z; }; -extern struct ao_hmc5883_sample ao_hmc5883_current; - void ao_hmc5883_init(void); diff --git a/src/drivers/ao_mma655x.c b/src/drivers/ao_mma655x.c index e4e41627..cd304d80 100644 --- a/src/drivers/ao_mma655x.c +++ b/src/drivers/ao_mma655x.c @@ -18,8 +18,9 @@ #include #include +#if HAS_MMA655X + static uint8_t mma655x_configured; -uint8_t ao_mma655x_valid; static void ao_mma655x_start(void) { @@ -197,14 +198,30 @@ __code struct ao_cmds ao_mma655x_cmds[] = { { 0, NULL }, }; +static void +ao_mma655x(void) +{ + ao_mma655x_setup(); + for (;;) { + ao_data_ring[ao_data_head].mma655x = ao_mma655x_value(); + ao_arch_critical( + AO_DATA_PRESENT(AO_DATA_MMA655X); + AO_DATA_WAIT(); + ); + } +} + +static __xdata struct ao_task ao_mma655x_task; + void ao_mma655x_init(void) { mma655x_configured = 0; - ao_mma655x_valid = 0; ao_cmd_register(&ao_mma655x_cmds[0]); ao_spi_init_cs(AO_MMA655X_CS_GPIO, (1 << AO_MMA655X_CS)); -// ao_add_task(&ao_mma655x_task, ao_mma655x, "mma655x"); + ao_add_task(&ao_mma655x_task, ao_mma655x, "mma655x"); } + +#endif diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index a1c32d4d..e8c80f12 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -240,22 +240,17 @@ ao_mpu6000_setup(void) ao_mpu6000_configured = 1; } -struct ao_mpu6000_sample ao_mpu6000_current; -uint8_t ao_mpu6000_valid; - static void ao_mpu6000(void) { ao_mpu6000_setup(); for (;;) { - struct ao_mpu6000_sample ao_mpu6000_next; - ao_mpu6000_sample(&ao_mpu6000_next); + ao_mpu6000_sample((struct ao_mpu6000_sample *) &ao_data_ring[ao_data_head].mpu6000); ao_arch_critical( - ao_mpu6000_current = ao_mpu6000_next; - ao_mpu6000_valid = 1; + AO_DATA_PRESENT(AO_DATA_MPU6000); + AO_DATA_WAIT(); ); - ao_delay(0); } } @@ -264,18 +259,16 @@ static struct ao_task ao_mpu6000_task; static void ao_mpu6000_show(void) { - struct ao_mpu6000_sample sample; + struct ao_data sample; - ao_arch_critical( - sample = ao_mpu6000_current; - ); + ao_data_get(&sample); printf ("Accel: %7d %7d %7d Gyro: %7d %7d %7d\n", - sample.accel_x, - sample.accel_y, - sample.accel_z, - sample.gyro_x, - sample.gyro_y, - sample.gyro_z); + sample.mpu6000.accel_x, + sample.mpu6000.accel_y, + sample.mpu6000.accel_z, + sample.mpu6000.gyro_x, + sample.mpu6000.gyro_y, + sample.mpu6000.gyro_z); } static const struct ao_cmds ao_mpu6000_cmds[] = { @@ -287,7 +280,6 @@ void ao_mpu6000_init(void) { ao_mpu6000_configured = 0; - ao_mpu6000_valid = 0; ao_add_task(&ao_mpu6000_task, ao_mpu6000, "mpu6000"); ao_cmd_register(&ao_mpu6000_cmds[0]); diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h index fc7af1e0..ca76b081 100644 --- a/src/drivers/ao_mpu6000.h +++ b/src/drivers/ao_mpu6000.h @@ -155,9 +155,6 @@ struct ao_mpu6000_sample { int16_t gyro_z; }; -extern struct ao_mpu6000_sample ao_mpu6000_current; -extern uint8_t ao_mpu6000_valid; - void ao_mpu6000_init(void); diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 1b55b7fd..ec0d2202 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -19,6 +19,8 @@ #include #include "ao_ms5607.h" +#if HAS_MS5607 + static struct ao_ms5607_prom ms5607_prom; static uint8_t ms5607_configured; @@ -201,22 +203,17 @@ ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value value->temp = TEMP; } -struct ao_ms5607_sample ao_ms5607_current; -uint8_t ao_ms5607_valid; - static void ao_ms5607(void) { ao_ms5607_setup(); for (;;) { - static struct ao_ms5607_sample ao_ms5607_next; - ao_ms5607_sample(&ao_ms5607_next); + ao_ms5607_sample((struct ao_ms5607_sample *) &ao_data_ring[ao_data_head].ms5607_raw); ao_arch_critical( - ao_ms5607_current = ao_ms5607_next; - ao_ms5607_valid = 1; + AO_DATA_PRESENT(AO_DATA_MS5607); + AO_DATA_WAIT(); ); - ao_delay(0); } } @@ -238,13 +235,13 @@ ao_ms5607_info(void) static void ao_ms5607_dump(void) { - struct ao_ms5607_sample sample; + struct ao_data sample; struct ao_ms5607_value value; - sample = ao_ms5607_current; - ao_ms5607_convert(&sample, &value); - printf ("Pressure: %8u %8d\n", sample.pres, value.pres); - printf ("Temperature: %8u %8d\n", sample.temp, value.temp); + ao_data_get(&sample); + ao_ms5607_convert(&sample.ms5607_raw, &value); + printf ("Pressure: %8u %8d\n", sample.ms5607_raw.pres, value.pres); + printf ("Temperature: %8u %8d\n", sample.ms5607_raw.temp, value.temp); printf ("Altitude: %ld\n", ao_pa_to_altitude(value.pres)); } @@ -257,7 +254,6 @@ void ao_ms5607_init(void) { ms5607_configured = 0; - ao_ms5607_valid = 0; ao_cmd_register(&ao_ms5607_cmds[0]); ao_spi_init_cs(AO_MS5607_CS_GPIO, (1 << AO_MS5607_CS)); @@ -279,3 +275,5 @@ ao_ms5607_init(void) AO_MS5607_MISO, STM_MODER_ALTERNATE); } + +#endif diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index fa3b1c5b..e9c364d9 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -51,9 +51,6 @@ struct ao_ms5607_sample { uint32_t temp; /* raw 24 bit sensor */ }; -extern uint8_t ao_ms5607_valid; -extern struct ao_ms5607_sample ao_ms5607_current; - struct ao_ms5607_value { int32_t pres; /* in Pa * 10 */ int32_t temp; /* in °C * 100 */ diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 1dfebca0..a93f6f17 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -56,8 +56,10 @@ ALTOS_SRC = \ ao_cc1120.c \ ao_fec_tx.c \ ao_fec_rx.c \ + ao_data.c \ ao_ms5607.c \ ao_mma655x.c \ + ao_hmc5883.c \ ao_adc_stm.c \ ao_beep_stm.c \ ao_storage.c \ diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 6256d2f6..8b631ae9 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -309,7 +309,7 @@ struct ao_adc { * mma655x */ -#define HAS_MMA655X 1 +#define HAS_MMA655X 0 #define AO_MMA655X_SPI_INDEX AO_SPI_1_PA5_PA6_PA7 #define AO_MMA655X_CS_GPIO (&stm_gpiod) #define AO_MMA655X_CS 4 diff --git a/src/megametrum-v0.1/stlink-pins b/src/megametrum-v0.1/stlink-pins index 71042acc..e6094372 100644 --- a/src/megametrum-v0.1/stlink-pins +++ b/src/megametrum-v0.1/stlink-pins @@ -34,6 +34,14 @@ GND 3 7 JTMS 4 8 NRST 5 2 +TL debug connector: + + TL ST +GND 1 3 +NRST 2 5 +SWDIO 3 4 +SWCLK 4 2 + MegaAccel: Jumpers diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 340967fc..09c9c3ca 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -32,6 +32,7 @@ ALTOS_SRC = \ ao_dma_stm.c \ ao_spi_stm.c \ ao_adc_stm.c \ + ao_data.c \ ao_i2c_stm.c \ ao_usb_stm.c \ ao_exti_stm.c \ diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 7564c7fa..18ca6ea0 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -17,15 +17,6 @@ #include #include -#if HAS_MPU6000 -#include -#endif -#if HAS_MS5607 -#include -#endif - -volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; -volatile __data uint8_t ao_data_head; static uint8_t ao_adc_ready; @@ -50,27 +41,7 @@ static uint8_t ao_adc_ready; */ static void ao_adc_done(int index) { - uint8_t step = 1; - ao_data_ring[ao_data_head].tick = ao_time(); -#if HAS_MPU6000 - if (!ao_mpu6000_valid) - step = 0; - ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current; -#endif -#if HAS_MS5607 - if (!ao_ms5607_valid) - step = 0; - ao_data_ring[ao_data_head].ms5607_raw = ao_ms5607_current; -#endif -#if HAS_HMC5883 - if (!ao_hmc5883_valid) - step = 0; - ao_data_ring[ao_data_head].hmc5883 = ao_hmc5883_current; -#endif - if (step) { - ao_data_head = ao_data_ring_next(ao_data_head); - ao_wakeup((void *) &ao_data_head); - } + AO_DATA_PRESENT(AO_DATA_ADC); ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); ao_adc_ready = 1; } @@ -117,17 +88,6 @@ ao_adc_get(__xdata struct ao_adc *packet) memcpy(packet, (void *) &ao_data_ring[i].adc, sizeof (struct ao_adc)); } -void -ao_data_get(__xdata struct ao_data *packet) -{ -#if HAS_FLIGHT - uint8_t i = ao_data_ring_prev(ao_sample_data); -#else - uint8_t i = ao_data_ring_prev(ao_data_head); -#endif - memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data)); -} - static void ao_adc_dump(void) __reentrant { diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index adec7aad..78228e65 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -37,9 +37,9 @@ ao_delay(uint16_t ticks) ao_sleep(&ao_forever); } -#if HAS_ADC -volatile __data uint8_t ao_adc_interval = 1; -volatile __data uint8_t ao_adc_count; +#if AO_DATA_ALL +volatile __data uint8_t ao_data_interval = 1; +volatile __data uint8_t ao_data_count; #endif void @@ -51,10 +51,13 @@ void stm_tim6_isr(void) if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) { stm_tim6.sr = 0; ++ao_tick_count; -#if HAS_ADC - if (++ao_adc_count == ao_adc_interval) { - ao_adc_count = 0; +#if AO_DATA_ALL + if (++ao_data_count == ao_data_interval) { + ao_data_count = 0; ao_adc_poll(); +#if (AO_DATA_ALL & ~(AO_DATA_ADC)) + ao_wakeup((void *) &ao_data_count); +#endif } #endif } @@ -64,8 +67,8 @@ void stm_tim6_isr(void) void ao_timer_set_adc_interval(uint8_t interval) __critical { - ao_adc_interval = interval; - ao_adc_count = 0; + ao_data_interval = interval; + ao_data_count = 0; } #endif -- cgit v1.2.3 From c1168f40223ca09df23215f2e2fc445a8a03aea9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:32:41 -0700 Subject: altos: Rename drivers/ao_lco to drivers/ao_lco_cmd These contain command line functions for testing the cmac and lco features. Now that there's a telelco-specific ao_lco interface file, it's useful to have both for testing. Signed-off-by: Keith Packard --- src/drivers/ao_lco.c | 193 ---------------------------------- src/drivers/ao_lco.h | 24 ----- src/drivers/ao_lco_cmd.c | 266 +++++++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_lco_cmd.h | 24 +++++ 4 files changed, 290 insertions(+), 217 deletions(-) delete mode 100644 src/drivers/ao_lco.c delete mode 100644 src/drivers/ao_lco.h create mode 100644 src/drivers/ao_lco_cmd.c create mode 100644 src/drivers/ao_lco_cmd.h (limited to 'src/drivers') diff --git a/src/drivers/ao_lco.c b/src/drivers/ao_lco.c deleted file mode 100644 index f30f3379..00000000 --- a/src/drivers/ao_lco.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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 - -static __xdata struct ao_launch_command command; -static __xdata struct ao_launch_query query; -static __pdata uint16_t launch_serial; -static __pdata uint8_t launch_channel; -static __pdata uint16_t tick_offset; - -static void -launch_args(void) __reentrant -{ - ao_cmd_decimal(); - launch_serial = ao_cmd_lex_i; - ao_cmd_decimal(); - launch_channel = ao_cmd_lex_i; -} - -static int8_t -launch_query(void) -{ - uint8_t i; - int8_t r = AO_RADIO_CMAC_OK; - - tick_offset = ao_time(); - for (i = 0; i < 10; i++) { - printf ("."); flush(); - command.tick = ao_time(); - command.serial = launch_serial; - command.cmd = AO_LAUNCH_QUERY; - command.channel = launch_channel; - ao_radio_cmac_send(&command, sizeof (command)); - r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); - if (r == AO_RADIO_CMAC_OK) - break; - } - tick_offset -= query.tick; - printf("\n"); flush(); - return r; -} - -static void -launch_report_cmd(void) __reentrant -{ - int8_t r; - - launch_args(); - if (ao_cmd_status != ao_cmd_success) - return; - r = launch_query(); - switch (r) { - case AO_RADIO_CMAC_OK: - if (query.valid) { - switch (query.arm_status) { - case ao_igniter_ready: - case ao_igniter_active: - printf ("Armed: "); - break; - default: - printf("Disarmed: "); - } - switch (query.igniter_status) { - default: - printf("unknown\n"); - break; - case ao_igniter_ready: - printf("igniter good\n"); - break; - case ao_igniter_open: - printf("igniter bad\n"); - break; - } - } else { - printf("Invalid channel %d\n", launch_channel); - } - printf("Rssi: %d\n", ao_radio_cmac_rssi); - break; - default: - printf("Error %d\n", r); - break; - } -} - -static void -launch_arm(void) __reentrant -{ - command.tick = ao_time() - tick_offset; - command.serial = launch_serial; - command.cmd = AO_LAUNCH_ARM; - command.channel = launch_channel; - ao_radio_cmac_send(&command, sizeof (command)); -} - -static void -launch_ignite(void) __reentrant -{ - command.tick = ao_time() - tick_offset; - command.serial = launch_serial; - command.cmd = AO_LAUNCH_FIRE; - command.channel = 0; - ao_radio_cmac_send(&command, sizeof (command)); -} - -static void -launch_fire_cmd(void) __reentrant -{ - static __xdata struct ao_launch_command command; - uint8_t secs; - uint8_t i; - int8_t r; - - launch_args(); - ao_cmd_decimal(); - secs = ao_cmd_lex_i; - if (ao_cmd_status != ao_cmd_success) - return; - r = launch_query(); - if (r != AO_RADIO_CMAC_OK) { - printf("query failed %d\n", r); - return; - } - - for (i = 0; i < 4; i++) { - printf("arm %d\n", i); flush(); - launch_arm(); - } - - secs = secs * 10 - 5; - if (secs > 100) - secs = 100; - for (i = 0; i < secs; i++) { - printf("fire %d\n", i); flush(); - launch_ignite(); - ao_delay(AO_MS_TO_TICKS(100)); - } -} - -static void -launch_arm_cmd(void) __reentrant -{ - uint8_t i; - int8_t r; - launch_args(); - r = launch_query(); - if (r != AO_RADIO_CMAC_OK) { - printf("query failed %d\n", r); - return; - } - for (i = 0; i < 4; i++) - launch_arm(); -} - -static void -launch_ignite_cmd(void) __reentrant -{ - uint8_t i; - launch_args(); - for (i = 0; i < 4; i++) - launch_ignite(); -} - -static __code struct ao_cmds ao_lco_cmds[] = { - { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, - { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, - { launch_report_cmd, "l \0Get remote launch status" }, - { launch_fire_cmd, "f \0Fire remote igniter" }, - { launch_arm_cmd, "a \0Arm remote igniter" }, - { launch_ignite_cmd, "i \0Pulse remote igniter" }, - { 0, NULL }, -}; - -void -ao_lco_init(void) -{ - ao_cmd_register(&ao_lco_cmds[0]); -} diff --git a/src/drivers/ao_lco.h b/src/drivers/ao_lco.h deleted file mode 100644 index 253f9702..00000000 --- a/src/drivers/ao_lco.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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. - */ - -#ifndef _AO_LCO_H_ -#define _AO_LCO_H_ - -void -ao_lco_init(void); - -#endif /* _AO_LCO_H_ */ diff --git a/src/drivers/ao_lco_cmd.c b/src/drivers/ao_lco_cmd.c new file mode 100644 index 00000000..3fe0d9cc --- /dev/null +++ b/src/drivers/ao_lco_cmd.c @@ -0,0 +1,266 @@ +/* + * 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 + +static __xdata struct ao_launch_command command; +static __xdata struct ao_launch_query query; +static __pdata uint16_t launch_serial; +static __pdata uint8_t launch_channel; +static __pdata uint16_t tick_offset; + +static void +launch_args(void) __reentrant +{ + ao_cmd_decimal(); + launch_serial = ao_cmd_lex_i; + ao_cmd_decimal(); + launch_channel = ao_cmd_lex_i; +} + +static int8_t +launch_query(void) +{ + uint8_t i; + int8_t r = AO_RADIO_CMAC_OK; + + tick_offset = ao_time(); + for (i = 0; i < 10; i++) { + printf ("."); flush(); + command.tick = ao_time(); + command.serial = launch_serial; + command.cmd = AO_LAUNCH_QUERY; + command.channel = launch_channel; + ao_radio_cmac_send(&command, sizeof (command)); + r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); + if (r == AO_RADIO_CMAC_OK) + break; + } + tick_offset -= query.tick; + printf("\n"); flush(); + return r; +} + +static void +launch_report_cmd(void) __reentrant +{ + int8_t r; + + launch_args(); + if (ao_cmd_status != ao_cmd_success) + return; + r = launch_query(); + switch (r) { + case AO_RADIO_CMAC_OK: + if (query.valid) { + switch (query.arm_status) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + break; + default: + printf("Disarmed: "); + } + switch (query.igniter_status) { + default: + printf("unknown\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; + } + } else { + printf("Invalid channel %d\n", launch_channel); + } + printf("Rssi: %d\n", ao_radio_cmac_rssi); + break; + default: + printf("Error %d\n", r); + break; + } +} + +static void +launch_arm(void) __reentrant +{ + command.tick = ao_time() - tick_offset; + command.serial = launch_serial; + command.cmd = AO_LAUNCH_ARM; + command.channel = launch_channel; + ao_radio_cmac_send(&command, sizeof (command)); +} + +static void +launch_ignite(void) __reentrant +{ + command.tick = ao_time() - tick_offset; + command.serial = launch_serial; + command.cmd = AO_LAUNCH_FIRE; + command.channel = 0; + ao_radio_cmac_send(&command, sizeof (command)); +} + +static void +launch_fire_cmd(void) __reentrant +{ + static __xdata struct ao_launch_command command; + uint8_t secs; + uint8_t i; + int8_t r; + + launch_args(); + ao_cmd_decimal(); + secs = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + r = launch_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } + + for (i = 0; i < 4; i++) { + printf("arm %d\n", i); flush(); + launch_arm(); + } + + secs = secs * 10 - 5; + if (secs > 100) + secs = 100; + for (i = 0; i < secs; i++) { + printf("fire %d\n", i); flush(); + launch_ignite(); + ao_delay(AO_MS_TO_TICKS(100)); + } +} + +static void +launch_arm_cmd(void) __reentrant +{ + uint8_t i; + int8_t r; + launch_args(); + r = launch_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } + for (i = 0; i < 4; i++) + launch_arm(); +} + +static void +launch_ignite_cmd(void) __reentrant +{ + uint8_t i; + launch_args(); + for (i = 0; i < 4; i++) + launch_ignite(); +} + +static uint8_t +getnibble(void) +{ + int8_t b; + + b = ao_cmd_hexchar(getchar()); + if (b < 0) { + ao_cmd_status = ao_cmd_lex_error; + return 0; + } + return (uint8_t) b; +} + +static uint8_t +getbyte(void) +{ + uint8_t b; + b = getnibble() << 4; + b |= getnibble(); + return b; +} + +static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN]; + +static void +radio_cmac_send_cmd(void) __reentrant +{ + uint8_t i; + uint8_t len; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + len = ao_cmd_lex_i; + if (len > AO_CMAC_MAX_LEN) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + flush(); + len = ao_cmd_lex_i; + for (i = 0; i < len; i++) { + cmac_data[i] = getbyte(); + if (ao_cmd_status != ao_cmd_success) + return; + } + ao_radio_cmac_send(cmac_data, len); +} + +static void +radio_cmac_recv_cmd(void) __reentrant +{ + uint8_t len, i; + uint16_t timeout; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + len = ao_cmd_lex_i; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + timeout = AO_MS_TO_TICKS(ao_cmd_lex_i); + i = ao_radio_cmac_recv(cmac_data, len, timeout); + if (i == AO_RADIO_CMAC_OK) { + printf ("PACKET "); + for (i = 0; i < len; i++) + printf("%02x", cmac_data[i]); + printf (" %d\n", ao_radio_cmac_rssi); + } else + printf ("ERROR %d %d\n", i, ao_radio_cmac_rssi); +} + +static __code struct ao_cmds ao_lco_cmds[] = { + { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, + { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, + { launch_report_cmd, "l \0Get remote launch status" }, + { launch_fire_cmd, "f \0Fire remote igniter" }, + { launch_arm_cmd, "a \0Arm remote igniter" }, + { launch_ignite_cmd, "i \0Pulse remote igniter" }, + { 0, NULL }, +}; + +void +ao_lco_cmd_init(void) +{ + ao_cmd_register(&ao_lco_cmds[0]); +} diff --git a/src/drivers/ao_lco_cmd.h b/src/drivers/ao_lco_cmd.h new file mode 100644 index 00000000..c55448cd --- /dev/null +++ b/src/drivers/ao_lco_cmd.h @@ -0,0 +1,24 @@ +/* + * 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. + */ + +#ifndef _AO_LCO_CMD_H_ +#define _AO_LCO_CMD_H_ + +void +ao_lco_cmd_init(void); + +#endif /* _AO_LCO_CMD_H_ */ -- cgit v1.2.3 From 8bfe8157cd9fe488d1ee961f200ffa0866322f2c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:38:44 -0700 Subject: altos: Seven segment display driver Hex numbers and the decimal point. Signed-off-by: Keith Packard --- src/drivers/ao_seven_segment.c | 216 +++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_seven_segment.h | 34 +++++++ 2 files changed, 250 insertions(+) create mode 100644 src/drivers/ao_seven_segment.c create mode 100644 src/drivers/ao_seven_segment.h (limited to 'src/drivers') diff --git a/src/drivers/ao_seven_segment.c b/src/drivers/ao_seven_segment.c new file mode 100644 index 00000000..1a643eff --- /dev/null +++ b/src/drivers/ao_seven_segment.c @@ -0,0 +1,216 @@ +/* + * 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 + +/* + * 0 + * ------- + * | | + * 1 | | 2 + * | 3 | + * ------- + * | | + * 4 | | 5 + * | 6 | + * ------- + * [] 7 + * + */ + +static const uint8_t ao_segments[] = { + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (0 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* 0 */ + + (0 << AO_SEGMENT_0) | + (0 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (0 << AO_SEGMENT_3) | + (0 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (0 << AO_SEGMENT_6), /* 1 */ + + (1 << AO_SEGMENT_0) | + (0 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (0 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* 2 */ + + (1 << AO_SEGMENT_0) | + (0 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (0 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* 3 */ + + (0 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (0 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (0 << AO_SEGMENT_6), /* 4 */ + + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (0 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (0 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* 5 */ + + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (0 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* 6 */ + + (1 << AO_SEGMENT_0) | + (0 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (0 << AO_SEGMENT_3) | + (0 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (0 << AO_SEGMENT_6), /* 7 */ + + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* 8 */ + + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (0 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* 9 */ + + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (0 << AO_SEGMENT_6), /* A */ + + (0 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (0 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* b */ + + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (0 << AO_SEGMENT_2) | + (0 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (0 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* c */ + + (0 << AO_SEGMENT_0) | + (0 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* d */ + + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (0 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (0 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* E */ + + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (0 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (0 << AO_SEGMENT_5) | + (0 << AO_SEGMENT_6), /* F */ +}; + +void +ao_seven_segment_set(uint8_t digit, uint8_t value) +{ + uint8_t s; + uint8_t segments; + + if (value == AO_SEVEN_SEGMENT_CLEAR) + segments = 0; + else { + segments = ao_segments[value & 0xf]; + + /* Check for decimal point */ + if (value & 0x10) + segments |= (1 << AO_SEGMENT_7); + } + + for (s = 0; s <= 7; s++) + ao_lcd_set(digit, s, !!(segments & (1 << s))); + ao_lcd_flush(); +} + +void +ao_seven_segment_clear(void) +{ + ao_lcd_clear(); +} + + +static void +ao_seven_segment_show(void) +{ + uint8_t digit, value; + ao_cmd_decimal(); + digit = ao_cmd_lex_i; + ao_cmd_decimal(); + value = ao_cmd_lex_i; + ao_seven_segment_set(digit, value); +} + + +static const struct ao_cmds ao_seven_segment_cmds[] = { + { ao_seven_segment_show, "S \0Set LCD digit" }, + { 0, NULL }, +}; + +void +ao_seven_segment_init(void) +{ + ao_cmd_register(ao_seven_segment_cmds); +} diff --git a/src/drivers/ao_seven_segment.h b/src/drivers/ao_seven_segment.h new file mode 100644 index 00000000..5b29deaf --- /dev/null +++ b/src/drivers/ao_seven_segment.h @@ -0,0 +1,34 @@ +/* + * 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. + */ + +#ifndef _AO_SEVEN_SEGMENT_H_ +#define _AO_SEVEN_SEGMENT_H_ + +#define AO_SEVEN_SEGMENT_DECIMAL 0x10 + +#define AO_SEVEN_SEGMENT_CLEAR 0xff + +void +ao_seven_segment_set(uint8_t digit, uint8_t value); + +void +ao_seven_segment_clear(void); + +void +ao_seven_segment_init(void); + +#endif /* _AO_SEVEN_SEGMENT_H_ */ -- cgit v1.2.3 From 708d49e498bbdc59bb5af9bf4ca5fcea5689547a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:41:13 -0700 Subject: altos: Test multiple quadrature devices. Export quadrature count. Signed-off-by: Keith Packard --- src/drivers/ao_quadrature.c | 28 ++++++---------------------- src/drivers/ao_quadrature.h | 2 ++ 2 files changed, 8 insertions(+), 22 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index 6a2c1bba..6cc2467a 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -88,38 +88,22 @@ ao_quadrature_wait(uint8_t q) static void ao_quadrature_test(void) { -#if 1 + uint8_t q; + + ao_cmd_decimal(); + q = ao_cmd_lex_i; for (;;) { int32_t c; flush(); - c = ao_quadrature_wait(0); + c = ao_quadrature_wait(q); 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; - 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 count %ld\n", a, b, ao_quadrature_count); - flush(); - ao_yield(); - old_a = a; - old_b = b; - } - if (ao_stdin_ready) - break; - } -#endif } static const struct ao_cmds ao_quadrature_cmds[] = { - { ao_quadrature_test, "q\0Test quadrature" }, + { ao_quadrature_test, "q \0Test quadrature" }, { 0, NULL } }; diff --git a/src/drivers/ao_quadrature.h b/src/drivers/ao_quadrature.h index f0b73b68..d7dda682 100644 --- a/src/drivers/ao_quadrature.h +++ b/src/drivers/ao_quadrature.h @@ -18,6 +18,8 @@ #ifndef _AO_QUADRATURE_H_ #define _AO_QUADRATURE_H_ +extern __xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT]; + int32_t ao_quadrature_wait(uint8_t q); -- cgit v1.2.3 From 0f3483f93137f41a61f3fcbe06afcaffb1b9e17b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:47:16 -0700 Subject: altos: Clean up radio APIs Move api to ao_radio_cmac.h include file. Expose ao_radio_test as standard API. Signed-off-by: Keith Packard --- src/cc1111/ao_launch.c | 3 +- src/cc1111/ao_radio.c | 69 +++++++++++++++++++++++---------------- src/core/ao.h | 6 ++-- src/core/ao_aes.h | 17 ---------- src/core/ao_radio_cmac.c | 84 +++--------------------------------------------- src/core/ao_radio_cmac.h | 43 +++++++++++++++++++++++++ src/drivers/ao_cc1120.c | 4 +-- src/drivers/ao_pad.c | 1 + 8 files changed, 97 insertions(+), 130 deletions(-) create mode 100644 src/core/ao_radio_cmac.h (limited to 'src/drivers') diff --git a/src/cc1111/ao_launch.c b/src/cc1111/ao_launch.c index a593d0b2..420f7568 100644 --- a/src/cc1111/ao_launch.c +++ b/src/cc1111/ao_launch.c @@ -15,7 +15,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" +#include +#include __xdata uint16_t ao_launch_ignite; diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 46b2362d..cb2c2fdd 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -470,8 +470,44 @@ ao_radio_rdf_abort(void) /* Output carrier */ + +static __xdata ao_radio_test_on; + void -ao_radio_test(void) +ao_radio_test(uint8_t on) +{ + if (on) { + if (!ao_radio_test_on) { +#if HAS_MONITOR + ao_monitor_disable(); +#endif +#if PACKET_HAS_SLAVE + ao_packet_slave_stop(); +#endif +#if HAS_PAD + ao_pad_disable(); +#endif + ao_radio_get(0xff); + RFST = RFST_STX; + ao_radio_test_on = 1; + } + } else { + if (ao_radio_test_on) { + ao_radio_idle(); + ao_radio_put(); + ao_radio_test_on = 0; +#if HAS_MONITOR + ao_monitor_enable(); +#endif +#if HAS_PAD + ao_pad_enable(); +#endif + } + } +} + +static void +ao_radio_test_cmd(void) { uint8_t mode = 2; static __xdata radio_on; @@ -481,40 +517,19 @@ ao_radio_test(void) mode = (uint8_t) ao_cmd_lex_u32; } mode++; - if ((mode & 2) && !radio_on) { -#if HAS_MONITOR - ao_monitor_disable(); -#endif -#if PACKET_HAS_SLAVE - ao_packet_slave_stop(); -#endif -#if HAS_PAD - ao_pad_disable(); -#endif - ao_radio_get(0xff); - RFST = RFST_STX; - radio_on = 1; - } + if ((mode & 2)) + ao_radio_test(1); if (mode == 3) { printf ("Hit a character to stop..."); flush(); getchar(); putchar('\n'); } - if ((mode & 1) && radio_on) { - ao_radio_idle(); - ao_radio_put(); - radio_on = 0; -#if HAS_MONITOR - ao_monitor_enable(); -#endif -#if HAS_PAD - ao_pad_enable(); -#endif - } + if ((mode & 1)) + ao_radio_test(0); } __code struct ao_cmds ao_radio_cmds[] = { - { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, + { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" }, { 0, NULL }, }; diff --git a/src/core/ao.h b/src/core/ao.h index 5e1fbb9d..b8bedd85 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -543,9 +543,6 @@ ao_telemetry_tiny_init(void); */ extern __xdata uint8_t ao_radio_dma; -extern __xdata uint8_t ao_radio_dma_done; -extern __xdata uint8_t ao_radio_done; -extern __xdata uint8_t ao_radio_mutex; #ifdef PKT_APPEND_STATUS_1_CRC_OK #define AO_RADIO_STATUS_CRC_OK PKT_APPEND_STATUS_1_CRC_OK @@ -566,6 +563,9 @@ ao_radio_recv(__xdata void *d, uint8_t size) __reentrant; void ao_radio_recv_abort(void); +void +ao_radio_test(uint8_t on); + /* * Compute the packet length as follows: * diff --git a/src/core/ao_aes.h b/src/core/ao_aes.h index ab3e367e..c47bc2db 100644 --- a/src/core/ao_aes.h +++ b/src/core/ao_aes.h @@ -51,21 +51,4 @@ ao_aes_run(__xdata uint8_t *in, void ao_aes_init(void); -/* ao_radio_cmac.c */ - -int8_t -ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant; - -#define AO_RADIO_CMAC_OK 0 -#define AO_RADIO_CMAC_LEN_ERROR -1 -#define AO_RADIO_CMAC_CRC_ERROR -2 -#define AO_RADIO_CMAC_MAC_ERROR -3 -#define AO_RADIO_CMAC_TIMEOUT -4 - -int8_t -ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant; - -void -ao_radio_cmac_init(void); - #endif /* _AO_AES_H_ */ diff --git a/src/core/ao_radio_cmac.c b/src/core/ao_radio_cmac.c index 3e8dce53..fc0ca8b1 100644 --- a/src/core/ao_radio_cmac.c +++ b/src/core/ao_radio_cmac.c @@ -15,38 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" - -#define AO_CMAC_KEY_LEN AO_AES_LEN -#define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) +#include +#include static __xdata uint8_t ao_radio_cmac_mutex; -__pdata int16_t ao_radio_cmac_rssi; +__pdata int8_t ao_radio_cmac_rssi; static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN]; static __pdata uint8_t ao_radio_cmac_len; -static uint8_t -getnibble(void) -{ - int8_t b; - - b = ao_cmd_hexchar(getchar()); - if (b < 0) { - ao_cmd_status = ao_cmd_lex_error; - return 0; - } - return (uint8_t) b; -} - -static uint8_t -getbyte(void) -{ - uint8_t b; - b = getnibble() << 4; - b |= getnibble(); - return b; -} - static uint8_t round_len(uint8_t len) { @@ -120,7 +96,7 @@ radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant return AO_RADIO_CMAC_TIMEOUT; } - ao_radio_cmac_rssi = (int16_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74; + ao_radio_cmac_rssi = (int8_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74; if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & AO_RADIO_STATUS_CRC_OK)) return AO_RADIO_CMAC_CRC_ERROR; @@ -191,55 +167,3 @@ ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentr return i; } -static void -radio_cmac_send_cmd(void) __reentrant -{ - uint8_t i; - uint8_t len; - - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - len = ao_cmd_lex_i; - if (len > AO_CMAC_MAX_LEN) { - ao_cmd_status = ao_cmd_syntax_error; - return; - } - flush(); - ao_mutex_get(&ao_radio_cmac_mutex); - len = ao_cmd_lex_i; - for (i = 0; i < len; i++) { - cmac_data[i] = getbyte(); - if (ao_cmd_status != ao_cmd_success) - return; - } - radio_cmac_send(len); - ao_mutex_put(&ao_radio_cmac_mutex); -} - -static void -radio_cmac_recv_cmd(void) __reentrant -{ - uint8_t len, i; - uint16_t timeout; - - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - len = ao_cmd_lex_i; - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - timeout = AO_MS_TO_TICKS(ao_cmd_lex_i); - ao_mutex_get(&ao_radio_cmac_mutex); - i = radio_cmac_recv(len, timeout); - if (i == AO_RADIO_CMAC_OK) { - printf ("PACKET "); - for (i = 0; i < len; i++) - printf("%02x", cmac_data[i]); - printf (" %d\n", ao_radio_cmac_rssi); - } else - printf ("ERROR %d %d\n", i, ao_radio_cmac_rssi); - ao_mutex_put(&ao_radio_cmac_mutex); -} - diff --git a/src/core/ao_radio_cmac.h b/src/core/ao_radio_cmac.h new file mode 100644 index 00000000..e86f31e9 --- /dev/null +++ b/src/core/ao_radio_cmac.h @@ -0,0 +1,43 @@ +/* + * 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. + */ + +#ifndef _AO_RADIO_CMAC_H_ +#define _AO_RADIO_CMAC_H_ + +#include + +#define AO_CMAC_KEY_LEN AO_AES_LEN +#define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) + +extern __pdata int8_t ao_radio_cmac_rssi; + +int8_t +ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant; + +#define AO_RADIO_CMAC_OK 0 +#define AO_RADIO_CMAC_LEN_ERROR -1 +#define AO_RADIO_CMAC_CRC_ERROR -2 +#define AO_RADIO_CMAC_MAC_ERROR -3 +#define AO_RADIO_CMAC_TIMEOUT -4 + +int8_t +ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant; + +void +ao_radio_cmac_init(void); + +#endif /* _AO_RADIO_CMAC_H_ */ diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 97a434d8..4df931b5 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -515,7 +515,7 @@ ao_radio_rdf_abort(void) } static void -ao_radio_test(void) +ao_radio_test_cmd(void) { uint8_t mode = 2; uint8_t radio_on; @@ -1008,7 +1008,7 @@ ao_radio_test_recv() #endif static const struct ao_cmds ao_radio_cmds[] = { - { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, + { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" }, #if CC1120_DEBUG { ao_radio_show, "R\0Show CC1120 status" }, { ao_radio_beep, "b\0Emit an RDF beacon" }, diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 791c9a47..b33a5ffd 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -18,6 +18,7 @@ #include #include #include +#include static __xdata uint8_t ao_pad_ignite; static __xdata struct ao_pad_command command; -- cgit v1.2.3 From c31d07fb35a5b4d283facf649bed3f0f9802d1fc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:49:07 -0700 Subject: altos: Add SPI linked radio API Forward the necessary radio functions over the SPI link Signed-off-by: Keith Packard --- src/drivers/ao_radio_master.c | 266 ++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_radio_slave.c | 127 ++++++++++++++++++++ src/drivers/ao_radio_spi.h | 58 +++++++++ 3 files changed, 451 insertions(+) create mode 100644 src/drivers/ao_radio_master.c create mode 100644 src/drivers/ao_radio_slave.c create mode 100644 src/drivers/ao_radio_spi.h (limited to 'src/drivers') diff --git a/src/drivers/ao_radio_master.c b/src/drivers/ao_radio_master.c new file mode 100644 index 00000000..6edea66d --- /dev/null +++ b/src/drivers/ao_radio_master.c @@ -0,0 +1,266 @@ +/* + * 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 +#include + +static __xdata struct ao_radio_spi_reply ao_radio_spi_reply; +static __xdata struct ao_radio_spi_request ao_radio_spi_request; +static __xdata uint8_t ao_radio_done; +static __xdata uint8_t ao_radio_mutex; + +__xdata int8_t ao_radio_cmac_rssi; + +static void +ao_radio_isr(void) +{ + ao_exti_disable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN); + ao_radio_done = 1; + ao_wakeup(&ao_radio_done); +} + +static void +ao_radio_master_start(void) +{ + ao_spi_get_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS, + AO_RADIO_SPI_BUS, + AO_SPI_SPEED_1MHz); +} + +static void +ao_radio_master_stop(void) +{ + ao_spi_put_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS, + AO_RADIO_SPI_BUS); +} + + +static uint8_t +ao_radio_master_send(void) +{ + ao_radio_done = 0; + ao_exti_enable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN); + ao_radio_master_start(); + ao_spi_send(&ao_radio_spi_request, + ao_radio_spi_request.len, + AO_RADIO_SPI_BUS); + ao_radio_master_stop(); + cli(); + while (!ao_radio_done) + if (ao_sleep(&ao_radio_done)) + break; + sei(); + return ao_radio_done; +} + +static void +ao_radio_master_recv(uint16_t len) +{ + ao_radio_master_start(); + ao_spi_recv(&ao_radio_spi_reply, + len, + AO_RADIO_SPI_BUS); + ao_radio_master_stop(); +} + +static void +ao_radio_get(uint8_t req, uint8_t len) +{ + ao_config_get(); + ao_mutex_get(&ao_radio_mutex); + ao_radio_spi_request.len = AO_RADIO_SPI_REQUEST_HEADER_LEN + len; + ao_radio_spi_request.request = req; + ao_radio_spi_request.setting = ao_config.radio_setting; +} + +static void +ao_radio_put(void) +{ + ao_mutex_put(&ao_radio_mutex); +} + +static void +ao_radio_get_data(__xdata void *d, uint8_t size) +{ + ao_radio_master_start(); + ao_spi_recv(&ao_radio_spi_reply, + AO_RADIO_SPI_REPLY_HEADER_LEN + size, + AO_RADIO_SPI_BUS); + ao_radio_master_stop(); + ao_xmemcpy(d, ao_radio_spi_reply.payload, size); +} + +void +ao_radio_recv_abort(void) +{ + ao_radio_get(AO_RADIO_SPI_RECV_ABORT, 0); + ao_radio_master_send(); + ao_radio_put(); +} + +void +ao_radio_send(const void *d, uint8_t size) +{ + ao_radio_get(AO_RADIO_SPI_SEND, size); + ao_xmemcpy(&ao_radio_spi_request.payload, d, size); + ao_radio_master_send(); + ao_radio_put(); +} + + +uint8_t +ao_radio_recv(__xdata void *d, uint8_t size) +{ + int8_t ret; + uint8_t recv; + + /* Recv the data + */ + + ao_radio_get(AO_RADIO_SPI_RECV, 0); + ao_radio_spi_request.recv_len = size; + recv = ao_radio_master_send(); + if (!recv) { + ao_radio_put(); + ao_radio_recv_abort(); + return 0; + } + ao_radio_get_data(d, size); + recv = ao_radio_spi_reply.status; + ao_radio_put(); + return recv; +} + +int8_t +ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant +{ + if (len > AO_CMAC_MAX_LEN) + return AO_RADIO_CMAC_LEN_ERROR; + + /* Set the key. + */ + ao_radio_get(AO_RADIO_SPI_CMAC_KEY, AO_AES_LEN); + ao_xmemcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN); + ao_radio_master_send(); + ao_radio_put(); + + /* Send the data + */ + + ao_radio_get(AO_RADIO_SPI_CMAC_SEND, len); + ao_xmemcpy(&ao_radio_spi_request.payload, packet, len); + ao_radio_master_send(); + ao_radio_put(); + return AO_RADIO_CMAC_OK; +} + +int8_t +ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant +{ + int8_t ret; + uint8_t recv; + + if (len > AO_CMAC_MAX_LEN) + return AO_RADIO_CMAC_LEN_ERROR; + + /* Set the key. + */ + ao_radio_get(AO_RADIO_SPI_CMAC_KEY, AO_AES_LEN); + ao_radio_spi_request.timeout = timeout; + ao_xmemcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN); + ao_radio_master_send(); + ao_radio_put(); + + /* Recv the data + */ + + ao_radio_get(AO_RADIO_SPI_CMAC_RECV, 0); + ao_radio_spi_request.recv_len = len; + recv = ao_radio_master_send(); + if (!recv) { + ao_radio_put(); + ao_radio_recv_abort(); + return AO_RADIO_CMAC_TIMEOUT; + } + ao_radio_get_data(packet, len); + recv = ao_radio_spi_reply.status; + ao_radio_put(); + return recv; +} + +static uint8_t ao_radio_test_on; + +void +ao_radio_test(uint8_t on) +{ + if (on) { + if (!ao_radio_test_on) { + ao_radio_get(AO_RADIO_SPI_TEST_ON, 0); + ao_radio_test_on = 1; + ao_radio_master_send(); + } + } else { + if (ao_radio_test_on) { + ao_radio_spi_request.len = AO_RADIO_SPI_REQUEST_HEADER_LEN; + ao_radio_spi_request.request = AO_RADIO_SPI_TEST_OFF; + ao_radio_master_send(); + ao_radio_test_on = 0; + ao_radio_put(); + } + } +} + +static void +ao_radio_test_cmd(void) +{ + uint8_t mode = 2; + ao_cmd_white(); + if (ao_cmd_lex_c != '\n') { + ao_cmd_decimal(); + mode = (uint8_t) ao_cmd_lex_u32; + } + mode++; + if ((mode & 2)) + ao_radio_test(1); + if (mode == 3) { + printf ("Hit a character to stop..."); flush(); + getchar(); + putchar('\n'); + } + if ((mode & 1)) + ao_radio_test(0); +} + +__code struct ao_cmds ao_radio_cmds[] = { + { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" }, + { 0, NULL }, +}; + +void +ao_radio_init(void) +{ + ao_spi_init_cs(AO_RADIO_CS_PORT, (1 << AO_RADIO_CS_PIN)); + + ao_enable_port(AO_RADIO_INT_PORT); + ao_exti_setup(AO_RADIO_INT_PORT, + AO_RADIO_INT_PIN, + AO_EXTI_MODE_FALLING, + ao_radio_isr); + ao_cmd_register(&ao_radio_cmds[0]); +} diff --git a/src/drivers/ao_radio_slave.c b/src/drivers/ao_radio_slave.c new file mode 100644 index 00000000..9dff511b --- /dev/null +++ b/src/drivers/ao_radio_slave.c @@ -0,0 +1,127 @@ +/* + * 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 + +static __xdata struct ao_radio_spi_reply ao_radio_spi_reply; + +static __xdata struct ao_radio_spi_request ao_radio_spi_request; + +static __xdata uint8_t ao_radio_spi_recv_request; +static __xdata uint8_t ao_radio_spi_recv_len; +static __xdata uint16_t ao_radio_spi_recv_timeout; + +static void +ao_radio_slave_signal(void) +{ + ao_gpio_set(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 0); + ao_arch_nop(); + ao_arch_nop(); + ao_arch_nop(); + ao_gpio_set(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 0); +} + +static void +ao_radio_slave_spi(void) +{ + for (;;) { + ao_spi_get_slave(AO_RADIO_SLAVE_BUS); + ao_spi_recv(&ao_radio_spi_request, (2 << 13) | sizeof (ao_radio_spi_request), AO_RADIO_SLAVE_BUS); + ao_spi_put_slave(AO_RADIO_SLAVE_BUS); + ao_led_for(AO_LED_RED, AO_MS_TO_TICKS(1000)); + switch (ao_radio_spi_request.request) { + case AO_RADIO_SPI_RECV: + case AO_RADIO_SPI_CMAC_RECV: + ao_config.radio_setting = ao_radio_spi_request.setting; + ao_radio_spi_recv_request = ao_radio_spi_request.request; + ao_radio_spi_recv_len = ao_radio_spi_request.recv_len; + ao_radio_spi_recv_timeout = ao_radio_spi_request.timeout; + ao_wakeup(&ao_radio_spi_recv_len); + break; + case AO_RADIO_SPI_RECV_FETCH: + ao_spi_get_slave(AO_RADIO_SLAVE_BUS); + ao_spi_send(&ao_radio_spi_reply, + ao_radio_spi_request.recv_len + AO_RADIO_SPI_REPLY_HEADER_LEN, + AO_RADIO_SLAVE_BUS); + ao_spi_put_slave(AO_RADIO_SLAVE_BUS); + break; + case AO_RADIO_SPI_RECV_ABORT: + ao_radio_recv_abort(); + break; + case AO_RADIO_SPI_SEND: + ao_config.radio_setting = ao_radio_spi_request.setting; + ao_radio_send(&ao_radio_spi_request.payload, ao_radio_spi_request.len - AO_RADIO_SPI_REQUEST_HEADER_LEN); + ao_radio_slave_signal(); + break; + + case AO_RADIO_SPI_CMAC_SEND: + ao_config.radio_setting = ao_radio_spi_request.setting; + ao_radio_cmac_send(&ao_radio_spi_request.payload, ao_radio_spi_request.len - AO_RADIO_SPI_REQUEST_HEADER_LEN); + ao_radio_slave_signal(); + break; + + case AO_RADIO_SPI_CMAC_KEY: + ao_xmemcpy(&ao_config.aes_key, ao_radio_spi_request.payload, AO_AES_LEN); + ao_radio_slave_signal(); + break; + + case AO_RADIO_SPI_TEST_ON: + ao_radio_test(1); + ao_radio_slave_signal(); + break; + + case AO_RADIO_SPI_TEST_OFF: + ao_radio_test(0); + ao_radio_slave_signal(); + break; + } + } +} + +static void +ao_radio_slave_recv(void) +{ + uint8_t len; + for (;;) { + while (!ao_radio_spi_recv_len) + ao_sleep(&ao_radio_spi_recv_len); + len = ao_radio_spi_recv_len; + ao_radio_spi_recv_len = 0; + if (ao_radio_spi_recv_request == AO_RADIO_SPI_RECV) { + ao_radio_spi_reply.status = ao_radio_recv(&ao_radio_spi_reply.payload, len); + ao_radio_spi_reply.rssi = 0; + } else { + ao_radio_spi_reply.status = ao_radio_cmac_recv(&ao_radio_spi_reply.payload, len, + ao_radio_spi_recv_timeout); + ao_radio_spi_reply.rssi = ao_radio_cmac_rssi; + } + ao_radio_slave_signal(); + } +} + +static __xdata struct ao_task ao_radio_slave_spi_task; +static __xdata struct ao_task ao_radio_slave_recv_task; + +void +ao_radio_slave_init(void) +{ + ao_add_task(&ao_radio_slave_spi_task, ao_radio_slave_spi, "radio_spi"); + ao_add_task(&ao_radio_slave_recv_task, ao_radio_slave_recv, "radio_recv"); + ao_enable_output(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 1); +} diff --git a/src/drivers/ao_radio_spi.h b/src/drivers/ao_radio_spi.h new file mode 100644 index 00000000..2957f70d --- /dev/null +++ b/src/drivers/ao_radio_spi.h @@ -0,0 +1,58 @@ +/* + * 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. + */ + +#ifndef _AO_RADIO_SPI_H_ +#define _AO_RADIO_SPI_H_ + +#define AO_RADIO_SPI_RECV 0 +#define AO_RADIO_SPI_RECV_ABORT 1 +#define AO_RADIO_SPI_RECV_FETCH 2 +#define AO_RADIO_SPI_SEND 3 + +#define AO_RADIO_SPI_CMAC_KEY 4 +#define AO_RADIO_SPI_CMAC_RECV 5 +#define AO_RADIO_SPI_CMAC_SEND 6 + +#define AO_RADIO_SPI_TEST_ON 7 +#define AO_RADIO_SPI_TEST_OFF 8 + +#define AO_RADIO_SPI_MAX_PAYLOAD 128 + +struct ao_radio_spi_request { + uint8_t len; /* required to be first by cc1111 DMA engine */ + uint8_t request; + uint8_t recv_len; + uint8_t pad; + uint32_t setting; + uint16_t timeout; + uint8_t payload[AO_RADIO_SPI_MAX_PAYLOAD]; +}; + +#define AO_RADIO_SPI_REQUEST_HEADER_LEN (sizeof (struct ao_radio_spi_request) - AO_RADIO_SPI_MAX_PAYLOAD) + +struct ao_radio_spi_reply { + uint8_t status; + int8_t rssi; + uint8_t payload[AO_RADIO_SPI_MAX_PAYLOAD]; +}; + +#define AO_RADIO_SPI_REPLY_HEADER_LEN (sizeof (struct ao_radio_spi_reply) - AO_RADIO_SPI_MAX_PAYLOAD) + +void +ao_radio_slave_init(void); + +#endif /* _AO_RADIO_SPI_H_ */ -- cgit v1.2.3