diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/ao.h | 20 | ||||
-rw-r--r-- | src/core/ao_aes.h | 19 | ||||
-rw-r--r-- | src/core/ao_config.c | 3 | ||||
-rw-r--r-- | src/core/ao_data.h | 50 | ||||
-rw-r--r-- | src/core/ao_led.h | 4 | ||||
-rw-r--r-- | src/core/ao_radio_cmac.c | 169 | ||||
-rw-r--r-- | src/core/ao_radio_cmac.h | 43 | ||||
-rw-r--r-- | src/core/ao_send_packet.c | 74 | ||||
-rw-r--r-- | src/core/ao_send_packet.h | 24 | ||||
-rw-r--r-- | src/core/ao_storage.c | 1 | ||||
-rw-r--r-- | src/core/ao_task.c | 29 |
11 files changed, 399 insertions, 37 deletions
diff --git a/src/core/ao.h b/src/core/ao.h index 65b9eb18..b8bedd85 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 @@ -432,6 +437,7 @@ ao_gps_report_mega_init(void); * ao_telemetry_orig.c */ +#if LEGACY_MONITOR struct ao_adc_orig { uint16_t tick; /* tick when the sample was read */ int16_t accel; /* accelerometer */ @@ -489,6 +495,8 @@ struct ao_telemetry_tiny_recv { uint8_t status; }; +#endif /* LEGACY_MONITOR */ + /* Unfortunately, we've exposed the CC1111 rssi units as the 'usual' method * for reporting RSSI. So, now we use these values everywhere */ @@ -535,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 @@ -558,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: * @@ -582,6 +590,8 @@ ao_radio_init(void); * ao_monitor.c */ +#if HAS_MONITOR + extern const char const * const ao_state_names[]; #define AO_MONITOR_RING 8 @@ -618,6 +628,8 @@ ao_monitor_enable(void); void ao_monitor_init(void) __reentrant; +#endif + /* * ao_stdio.c */ diff --git a/src/core/ao_aes.h b/src/core/ao_aes.h index 7f67374d..c47bc2db 100644 --- a/src/core/ao_aes.h +++ b/src/core/ao_aes.h @@ -29,9 +29,11 @@ enum ao_aes_mode { }; #if HAS_AES +#ifdef SDCC void ao_aes_isr(void) __interrupt 4; #endif +#endif void ao_aes_set_mode(enum ao_aes_mode mode); @@ -49,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_config.c b/src/core/ao_config.c index e2095e65..f19dd9cd 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -17,8 +17,11 @@ #include "ao.h" #include "ao_log.h" +#include <ao_storage.h> +#if HAS_FLIGHT #include <ao_sample.h> #include <ao_data.h> +#endif __xdata struct ao_config ao_config; __pdata uint8_t ao_config_loaded; 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 <ao_ms5607.h> +#define AO_DATA_MS5607 (1 << 1) +#else +#define AO_DATA_MS5607 (1 << 1) #endif #if HAS_MPU6000 #include <ao_mpu6000.h> +#define AO_DATA_MPU6000 (1 << 2) +#else +#define AO_DATA_MPU6000 0 #endif #if HAS_HMC5883 #include <ao_hmc5883.h> +#define AO_DATA_HMC5883 (1 << 3) +#else +#define AO_DATA_HMC5883 0 +#endif + +#if HAS_MMA655X +#include <ao_mma655x.h> +#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/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/core/ao_radio_cmac.c b/src/core/ao_radio_cmac.c new file mode 100644 index 00000000..fc0ca8b1 --- /dev/null +++ b/src/core/ao_radio_cmac.c @@ -0,0 +1,169 @@ +/* + * Copyright © 2011 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> +#include <ao_radio_cmac.h> + +static __xdata uint8_t ao_radio_cmac_mutex; +__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 +round_len(uint8_t len) +{ + uint8_t rem; + + /* Make sure we transfer at least one packet, and + * then make sure every packet is full. Note that + * there is no length encoded, and that the receiver + * must deal with any extra bytes in the packet + */ + if (len < AO_CMAC_KEY_LEN) + len = AO_CMAC_KEY_LEN; + rem = len % AO_CMAC_KEY_LEN; + if (rem != 0) + len += (AO_CMAC_KEY_LEN - rem); + return len; +} + +/* + * Sign and deliver the data sitting in the cmac buffer + */ +static void +radio_cmac_send(uint8_t len) __reentrant +{ + uint8_t i; + + len = round_len(len); + /* Make sure the AES key is loaded */ + ao_config_get(); + +#if HAS_MONITOR + ao_monitor_set(0); +#endif + + ao_mutex_get(&ao_aes_mutex); + ao_aes_set_mode(ao_aes_mode_cbc_mac); + ao_aes_set_key(ao_config.aes_key); + ao_aes_zero_iv(); + for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < len) + ao_aes_run(&cmac_data[i], NULL); + else + ao_aes_run(&cmac_data[i], &cmac_data[len]); + } + ao_mutex_put(&ao_aes_mutex); + + ao_radio_send(cmac_data, len + AO_CMAC_KEY_LEN); +} + +/* + * Receive and validate an incoming packet + */ + +static int8_t +radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant +{ + uint8_t i; + + len = round_len(len); +#if HAS_MONITOR + ao_monitor_set(0); +#endif + if (timeout) + ao_alarm(timeout); + + i = ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2); + ao_clear_alarm(); + + if (!i) { + ao_radio_cmac_rssi = 0; + return AO_RADIO_CMAC_TIMEOUT; + } + + 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; + + ao_config_get(); + + /* Compute the packet signature + */ + ao_mutex_get(&ao_aes_mutex); + ao_aes_set_mode(ao_aes_mode_cbc_mac); + ao_aes_set_key(ao_config.aes_key); + ao_aes_zero_iv(); + for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < len) + ao_aes_run(&cmac_data[i], NULL); + else + ao_aes_run(&cmac_data[i], &cmac_data[len + AO_CMAC_KEY_LEN + 2]); + } + ao_mutex_put(&ao_aes_mutex); + + /* Check the packet signature against the signature provided + * over the link + */ + + if (memcmp(&cmac_data[len], + &cmac_data[len + AO_CMAC_KEY_LEN + 2], + AO_CMAC_KEY_LEN) != 0) { + return AO_RADIO_CMAC_MAC_ERROR; + } + + return AO_RADIO_CMAC_OK; +} + +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; + ao_mutex_get(&ao_radio_cmac_mutex); + ao_xmemcpy(cmac_data, packet, len); +#if AO_LED_TX + ao_led_on(AO_LED_TX); +#endif + radio_cmac_send(len); +#if AO_LED_TX + ao_led_off(AO_LED_TX); +#endif + ao_mutex_put(&ao_radio_cmac_mutex); + return AO_RADIO_CMAC_OK; +} + +int8_t +ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant +{ + uint8_t i; + if (len > AO_CMAC_MAX_LEN) + return AO_RADIO_CMAC_LEN_ERROR; + ao_mutex_get(&ao_radio_cmac_mutex); +#if AO_LED_RX + ao_led_on(AO_LED_RX); +#endif + i = radio_cmac_recv(len, timeout); +#if AO_LED_RX + ao_led_off(AO_LED_RX); +#endif + if (i == AO_RADIO_CMAC_OK) + ao_xmemcpy(packet, cmac_data, len); + ao_mutex_put(&ao_radio_cmac_mutex); + return i; +} + 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 <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_RADIO_CMAC_H_ +#define _AO_RADIO_CMAC_H_ + +#include <ao_aes.h> + +#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/core/ao_send_packet.c b/src/core/ao_send_packet.c new file mode 100644 index 00000000..1a8e74de --- /dev/null +++ b/src/core/ao_send_packet.c @@ -0,0 +1,74 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +#define AO_MAX_SEND 128 + +static __xdata uint8_t ao_send[AO_MAX_SEND]; + +static uint8_t +getnibble(void) +{ + char c; + + c = getchar(); + if ('0' <= c && c <= '9') + return c - '0'; + if ('a' <= c && c <= 'f') + return c - ('a' - 10); + if ('A' <= c && c <= 'F') + return c - ('A' - 10); + ao_cmd_status = ao_cmd_lex_error; + return 0; +} + +static void +ao_send_packet(void) +{ + __pdata uint16_t count; + uint8_t b; + __pdata uint8_t i; + + ao_cmd_hex(); + count = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + if (count > AO_MAX_SEND - 2) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + for (i = 0; i < count; i++) { + b = getnibble() << 4; + b |= getnibble(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_send[i] = b; + } + ao_radio_send(ao_send, count); +} + +static __code struct ao_cmds ao_send_packet_cmds[] = { + { ao_send_packet, "S <len>\0Send packet. Data on next line" }, + { 0, NULL } +}; + +void +ao_send_packet_init(void) +{ + ao_cmd_register(&ao_send_packet_cmds[0]); +} diff --git a/src/core/ao_send_packet.h b/src/core/ao_send_packet.h new file mode 100644 index 00000000..526f7b55 --- /dev/null +++ b/src/core/ao_send_packet.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_SEND_PACKET_H_ +#define _AO_SEND_PACKET_H_ + +void +ao_send_packet_init(void); + +#endif /* _AO_SEND_PACKET_H_ */ diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c index b2dd435b..adf7e4d4 100644 --- a/src/core/ao_storage.c +++ b/src/core/ao_storage.c @@ -16,6 +16,7 @@ */ #include <ao.h> +#include <ao_storage.h> uint8_t ao_storage_read(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 4011a36e..4593bd79 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -82,39 +82,36 @@ ao_yield(void) ao_arch_naked_define ao_arch_isr_stack(); -#if CHECK_STACK +#if AO_CHECK_STACK in_yield = 1; #endif /* Find a task to run. If there isn't any runnable task, * this loop will run forever, which is just fine */ { - __pdata uint8_t ao_next_task_index = ao_cur_task_index; + __pdata uint8_t ao_last_task_index = ao_cur_task_index; for (;;) { - ++ao_next_task_index; - if (ao_next_task_index == ao_num_tasks) - ao_next_task_index = 0; + ++ao_cur_task_index; + if (ao_cur_task_index == ao_num_tasks) + ao_cur_task_index = 0; + + ao_cur_task = ao_tasks[ao_cur_task_index]; - ao_cur_task = ao_tasks[ao_next_task_index]; - if (ao_cur_task->wchan == NULL) { - ao_cur_task_index = ao_next_task_index; + /* Check for ready task */ + if (ao_cur_task->wchan == NULL) break; - } /* Check if the alarm is set for a time which has passed */ if (ao_cur_task->alarm && - (int16_t) (ao_time() - ao_cur_task->alarm) >= 0) { - ao_cur_task_index = ao_next_task_index; + (int16_t) (ao_time() - ao_cur_task->alarm) >= 0) break; - } /* Enter lower power mode when there isn't anything to do */ - if (ao_next_task_index == ao_cur_task_index) { + if (ao_cur_task_index == ao_last_task_index) ao_arch_cpu_idle(); - } } } -#if CHECK_STACK +#if AO_CHECK_STACK cli(); in_yield = 0; #endif @@ -177,7 +174,7 @@ ao_exit(void) void ao_task_info(void) { - uint8_t i; + uint8_t i; __xdata struct ao_task *task; for (i = 0; i < ao_num_tasks; i++) { |