From 30abbdc7ffcfc809b4a3fc31486fe968161ea225 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jul 2011 16:59:16 -0700 Subject: [PATCH] altos: Add SPI-based companion board support This sends current flight state information and retrieves companion data to include in telemetry. Signed-off-by: Keith Packard --- src/Makefile.proto | 6 ++ src/ao.h | 72 ++++++++++++++++++++++- src/ao_companion.c | 96 +++++++++++++++++++++++++++++++ src/ao_ee.c | 14 +---- src/ao_flash.c | 14 +---- src/ao_m25.c | 4 +- src/ao_pins.h | 16 ++++++ src/ao_spi.c | 8 +-- src/ao_telemetrum.c | 3 + src/ao_telemetry.c | 45 ++++++++++++++- src/telemetrum-v1.0/Makefile.defs | 1 + src/telemetrum-v1.1/Makefile.defs | 1 + 12 files changed, 248 insertions(+), 32 deletions(-) create mode 100644 src/ao_companion.c diff --git a/src/Makefile.proto b/src/Makefile.proto index d4a8c4ea..8f98d354 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -150,6 +150,12 @@ SKY_DRIVER_SRC = \ BTM_DRIVER_SRC = \ ao_btm.c +# +# Companion port driver source +# +COMPANION_SRC = \ + ao_companion.c + # # Tasks run on TeleMetrum # diff --git a/src/ao.h b/src/ao.h index 1c8f5bbf..de47f3df 100644 --- a/src/ao.h +++ b/src/ao.h @@ -965,6 +965,34 @@ ao_serial_init(void); * ao_spi.c */ +extern __xdata uint8_t ao_spi_mutex; + +#define ao_spi_get_mask(reg,mask) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (reg) &= ~(mask); \ + } while (0) + +#define ao_spi_put_mask(reg,mask) do { \ + (reg) |= (mask); \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +#define ao_spi_get_bit(bit) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (bit) = 0; \ + } while (0) + +#define ao_spi_put_bit(bit) do { \ + (bit) = 1; \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +/* + * The SPI mutex must be held to call either of these + * functions -- this mutex covers the entire SPI operation, + * from chip select low to chip select high + */ + void ao_spi_send(void __xdata *block, uint16_t len) __reentrant; @@ -1089,12 +1117,29 @@ struct ao_telemetry_satellite { /* 32 */ }; +#define AO_TELEMETRY_COMPANION 0x07 + +#define AO_COMPANION_MAX_CHANNELS 12 + +struct ao_telemetry_companion { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t board_id; /* 5 */ + + uint8_t update_period; /* 6 */ + uint8_t channels; /* 7 */ + uint16_t companion_data[AO_COMPANION_MAX_CHANNELS]; /* 8 */ + /* 32 */ +}; + union ao_telemetry_all { struct ao_telemetry_generic generic; struct ao_telemetry_sensor sensor; struct ao_telemetry_configuration configuration; struct ao_telemetry_location location; struct ao_telemetry_satellite satellite; + struct ao_telemetry_companion companion; }; /* @@ -1529,8 +1574,33 @@ ao_btm_isr(void) #endif ; - void ao_btm_init(void); +/* ao_companion.c */ + +#define AO_COMPANION_SETUP 1 +#define AO_COMPANION_FETCH 2 + +struct ao_companion_command { + uint8_t command; + uint8_t flight_state; + uint16_t tick; +}; + +struct ao_companion_setup { + uint16_t board_id; + uint16_t board_id_inverse; + uint8_t update_period; + uint8_t channels; +}; + +extern __pdata uint8_t ao_companion_running; +extern __xdata struct ao_companion_setup ao_companion_setup; +extern __xdata uint8_t ao_companion_mutex; +extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; + +void +ao_companion_init(void); + #endif /* _AO_H_ */ diff --git a/src/ao_companion.c b/src/ao_companion.c new file mode 100644 index 00000000..8db3273e --- /dev/null +++ b/src/ao_companion.c @@ -0,0 +1,96 @@ +/* + * Copyright © 2011 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 "ao.h" + +#define COMPANION_SELECT() ao_spi_get_bit(COMPANION_CS) +#define COMPANION_DESELECT() ao_spi_put_bit(COMPANION_CS) + +static __xdata struct ao_companion_command ao_companion_command; +__xdata struct ao_companion_setup ao_companion_setup; + +__xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; +__pdata uint8_t ao_companion_running; +__xdata uint8_t ao_companion_mutex; + +static void +ao_companion_send_command(uint8_t command) +{ + ao_companion_command.command = command; + ao_companion_command.flight_state = ao_flight_state; + ao_companion_command.tick = ao_time(); + ao_spi_send(&ao_companion_command, sizeof (ao_companion_command)); +} + +static uint8_t +ao_companion_get_setup(void) +{ + COMPANION_SELECT(); + ao_companion_send_command(AO_COMPANION_SETUP); + ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup)); + COMPANION_DESELECT(); + if (ao_companion_setup.board_id != ~ao_companion_setup.board_id) + return 0; + return 1; +} + +static void +ao_companion_get_data(void) +{ + COMPANION_SELECT(); + ao_companion_send_command(AO_COMPANION_FETCH); + ao_mutex_get(&ao_companion_mutex); + ao_spi_recv(&ao_companion_data, ao_companion_setup.channels * 2); + ao_mutex_put(&ao_companion_mutex); + COMPANION_DESELECT(); +} + +void +ao_companion(void) +{ + if (!ao_companion_get_setup()) + ao_exit(); + ao_companion_running = 1; + for (;;) { + ao_delay(ao_companion_setup.update_period); + ao_companion_get_data(); + } +} + +void +ao_companion_status(void) __reentrant +{ +} + +__code struct ao_cmds ao_companion_cmds[] = { + { ao_companion_status, "L\0Companion link status" }, + { 0, NULL }, +}; + +static __xdata struct ao_task ao_companion_task; + +void +ao_companion_init(void) +{ + COMPANION_CS_PORT |= COMPANION_CS_MASK; /* raise all CS pins */ + COMPANION_CS_DIR |= COMPANION_CS_MASK; /* set CS pins as outputs */ + COMPANION_CS_SEL &= ~COMPANION_CS_MASK; /* set CS pins as GPIO */ + + ao_cmd_register(&ao_companion_cmds[0]); + + ao_add_task(&ao_companion_task, ao_companion, "companion"); +} diff --git a/src/ao_ee.c b/src/ao_ee.c index 83863af5..a2fe8dc1 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -49,19 +49,9 @@ static __xdata uint8_t ao_ee_mutex; _asm nop _endasm; \ } while(0) -static void ao_ee_cs_low(void) -{ - ao_ee_delay(); - EE_CS = 0; - ao_ee_delay(); -} +#define ao_ee_cs_low() ao_spi_get_bit(EE_CS) -static void ao_ee_cs_high(void) -{ - ao_ee_delay(); - EE_CS = 1; - ao_ee_delay(); -} +#define ao_ee_cs_high() ao_spi_put_bit(EE_CS) struct ao_ee_instruction { uint8_t instruction; diff --git a/src/ao_flash.c b/src/ao_flash.c index 00e96398..bb40f6f7 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -43,19 +43,9 @@ __xdata uint8_t ao_flash_mutex; _asm nop _endasm; \ } while(0) -void ao_flash_cs_low(void) -{ - ao_flash_delay(); - FLASH_CS = 0; - ao_flash_delay(); -} +#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS) -void ao_flash_cs_high(void) -{ - ao_flash_delay(); - FLASH_CS = 1; - ao_flash_delay(); -} +#define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS) struct ao_flash_instruction { uint8_t instruction; diff --git a/src/ao_m25.c b/src/ao_m25.c index 208c69ba..d7208273 100644 --- a/src/ao_m25.c +++ b/src/ao_m25.c @@ -99,8 +99,8 @@ static __xdata uint8_t ao_m25_mutex; static __xdata uint8_t ao_m25_instruction[4]; -#define M25_SELECT(cs) (SPI_CS_PORT &= ~(cs)) -#define M25_DESELECT(cs) (SPI_CS_PORT |= (cs)) +#define M25_SELECT(cs) ao_spi_get_mask(SPI_CS_PORT,cs) +#define M25_DESELECT(cs) ao_spi_put_mask(SPI_CS_PORT,cs) #define M25_BLOCK_SHIFT 16 #define M25_BLOCK 65536L diff --git a/src/ao_pins.h b/src/ao_pins.h index 89907b9c..e1f5459f 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -36,6 +36,11 @@ #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 @@ -63,6 +68,11 @@ #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 @@ -328,6 +338,12 @@ #endif /* DBG_ON_P0 */ +#if COMPANION_CS_ON_P1 + #define COMPANION_CS_PORT P1 + #define COMPANION_CS_SEL P1SEL + #define COMPANION_CS_DIR P1DIR +#endif + #if SPI_CS_ON_P1 #define SPI_CS_PORT P1 #define SPI_CS_SEL P1SEL diff --git a/src/ao_spi.c b/src/ao_spi.c index bd52a0d4..fbe613c7 100644 --- a/src/ao_spi.c +++ b/src/ao_spi.c @@ -17,6 +17,10 @@ #include "ao.h" +/* Shared mutex to protect SPI bus, must cover the entire + * operation, from CS low to CS high. This means that any SPI + * user must protect the SPI bus with this mutex + */ __xdata uint8_t ao_spi_mutex; __xdata uint8_t ao_spi_dma_in_done; __xdata uint8_t ao_spi_dma_out_done; @@ -36,7 +40,6 @@ static __xdata uint8_t ao_spi_const = 0xff; void ao_spi_send(void __xdata *block, uint16_t len) __reentrant { - ao_mutex_get(&ao_spi_mutex); ao_dma_set_transfer(ao_spi_dma_in_id, &U0DBUFXADDR, &ao_spi_const, @@ -64,7 +67,6 @@ ao_spi_send(void __xdata *block, uint16_t len) __reentrant ao_dma_trigger(ao_spi_dma_out_id); __critical while (!ao_spi_dma_in_done) ao_sleep(&ao_spi_dma_in_done); - ao_mutex_put(&ao_spi_mutex); } /* Receive bytes over SPI. @@ -76,7 +78,6 @@ ao_spi_send(void __xdata *block, uint16_t len) __reentrant void ao_spi_recv(void __xdata *block, uint16_t len) __reentrant { - ao_mutex_get(&ao_spi_mutex); ao_dma_set_transfer(ao_spi_dma_in_id, &U0DBUFXADDR, block, @@ -104,7 +105,6 @@ ao_spi_recv(void __xdata *block, uint16_t len) __reentrant ao_dma_trigger(ao_spi_dma_out_id); __critical while (!ao_spi_dma_in_done) ao_sleep(&ao_spi_dma_in_done); - ao_mutex_put(&ao_spi_mutex); } /* diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 6fa70b3a..f560740a 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -61,6 +61,9 @@ main(void) ao_igniter_init(); #if HAS_DBG ao_dbg_init(); +#endif +#if HAS_COMPANION + ao_companion_init(); #endif ao_config_init(); ao_start_scheduler(); diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 52f818ed..15ba4302 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -25,6 +25,10 @@ static __pdata int8_t ao_telemetry_config_cur; static __pdata int8_t ao_telemetry_loc_cur; static __pdata int8_t ao_telemetry_sat_cur; #endif +#if HAS_COMPANION +static __pdata int8_t ao_telemetry_companion_max; +static __pdata int8_t ao_telemetry_companion_cur; +#endif static __pdata uint8_t ao_rdf = 0; static __pdata uint16_t ao_rdf_time; @@ -149,6 +153,26 @@ ao_send_satellite(void) } #endif +#if HAS_COMPANION +static void +ao_send_companion(void) +{ + if (--ao_telemetry_companion_cur <= 0) { + telemetry.generic.type = AO_TELEMETRY_COMPANION; + telemetry.companion.board_id = ao_companion_setup.board_id; + telemetry.companion.update_period = ao_companion_setup.update_period; + telemetry.companion.channels = ao_companion_setup.channels; + ao_mutex_get(&ao_companion_mutex); + memcpy(&telemetry.companion.companion_data, + ao_companion_data, + ao_companion_setup.channels * 2); + ao_mutex_put(&ao_companion_mutex); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_companion_cur = ao_telemetry_companion_max; + } +} +#endif + void ao_telemetry(void) { @@ -168,6 +192,10 @@ ao_telemetry(void) ao_send_sensor(); +#if HAS_COMPANION + if (ao_companion_running) + ao_send_companion(); +#endif ao_send_configuration(); #if HAS_GPS ao_send_location(); @@ -193,10 +221,25 @@ void ao_telemetry_set_interval(uint16_t interval) { ao_telemetry_interval = interval; + +#if HAS_COMPANION + if (!ao_companion_setup.update_period) + ao_companion_setup.update_period = AO_SEC_TO_TICKS(1); + ao_telemetry_companion_max = ao_companion_setup.update_period / interval; + ao_telemetry_companion_cur = 1; +#endif + ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval; +#if HAS_COMPANION + ao_telemetry_config_cur = ao_telemetry_companion_cur; + if (ao_telemetry_config_max > ao_telemetry_config_cur) + ao_telemetry_config_cur++; +#else ao_telemetry_config_cur = 1; +#endif + #if HAS_GPS - ao_telemetry_loc_cur = 1; + ao_telemetry_loc_cur = ao_telemetry_config_cur; if (ao_telemetry_config_max > ao_telemetry_loc_cur) ao_telemetry_loc_cur++; ao_telemetry_sat_cur = ao_telemetry_loc_cur; diff --git a/src/telemetrum-v1.0/Makefile.defs b/src/telemetrum-v1.0/Makefile.defs index a60a501a..5eefc392 100644 --- a/src/telemetrum-v1.0/Makefile.defs +++ b/src/telemetrum-v1.0/Makefile.defs @@ -5,6 +5,7 @@ SRC = \ $(SPI_DRIVER_SRC) \ $(FLASH_DRIVER_SRC) \ $(SKY_DRIVER_SRC) \ + $(COMPANION_SRC) \ $(DBG_SRC) PRODUCT=TeleMetrum-v1.0 diff --git a/src/telemetrum-v1.1/Makefile.defs b/src/telemetrum-v1.1/Makefile.defs index f38226c6..3c8b8793 100644 --- a/src/telemetrum-v1.1/Makefile.defs +++ b/src/telemetrum-v1.1/Makefile.defs @@ -5,6 +5,7 @@ SRC = \ $(SPI_DRIVER_SRC) \ $(M25_DRIVER_SRC) \ $(SKY_DRIVER_SRC) \ + $(COMPANION_SRC) \ $(DBG_SRC) PRODUCT=TeleMetrum-v1.1 -- 2.30.2