From 9513be7f9d3d0b0ec29f6487fa9dc8f1ac24d0de Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Aug 2011 20:43:44 -0700 Subject: altos: Restructure altos build to prepare for multi-arch support Split out sources into separate directories: core: architecture and product independent bits cc1111: cc1111-specific code drivers: architecture independent drivers product: product-specific sources and Makefile fragments util: scripts for building stuff This should have no effect on the built products, but testing is encouraged Signed-off-by: Keith Packard --- src/core/altitude.h | 132 ++++ src/core/ao.h | 1610 ++++++++++++++++++++++++++++++++++++++++++++ src/core/ao_cmd.c | 320 +++++++++ src/core/ao_config.c | 542 +++++++++++++++ src/core/ao_convert.c | 85 +++ src/core/ao_convert_test.c | 75 +++ src/core/ao_ee_fake.c | 37 + src/core/ao_flight.c | 315 +++++++++ src/core/ao_flight_nano.c | 120 ++++ src/core/ao_gps_print.c | 112 +++ src/core/ao_gps_report.c | 99 +++ src/core/ao_host.h | 127 ++++ src/core/ao_kalman.c | 292 ++++++++ src/core/ao_log.c | 284 ++++++++ src/core/ao_log_big.c | 158 +++++ src/core/ao_log_telem.c | 30 + src/core/ao_log_tiny.c | 161 +++++ src/core/ao_monitor.c | 277 ++++++++ src/core/ao_mutex.c | 41 ++ src/core/ao_panic.c | 66 ++ src/core/ao_pins.h | 408 +++++++++++ src/core/ao_product.c | 155 +++++ src/core/ao_report.c | 180 +++++ src/core/ao_rssi.c | 53 ++ src/core/ao_sample.c | 209 ++++++ src/core/ao_state.c | 23 + src/core/ao_stdio.c | 84 +++ src/core/ao_storage.c | 184 +++++ src/core/ao_task.c | 275 ++++++++ src/core/ao_telem.h | 172 +++++ src/core/ao_telemetry.c | 270 ++++++++ 31 files changed, 6896 insertions(+) create mode 100644 src/core/altitude.h create mode 100644 src/core/ao.h create mode 100644 src/core/ao_cmd.c create mode 100644 src/core/ao_config.c create mode 100644 src/core/ao_convert.c create mode 100644 src/core/ao_convert_test.c create mode 100644 src/core/ao_ee_fake.c create mode 100644 src/core/ao_flight.c create mode 100644 src/core/ao_flight_nano.c create mode 100644 src/core/ao_gps_print.c create mode 100644 src/core/ao_gps_report.c create mode 100644 src/core/ao_host.h create mode 100644 src/core/ao_kalman.c create mode 100644 src/core/ao_log.c create mode 100644 src/core/ao_log_big.c create mode 100644 src/core/ao_log_telem.c create mode 100644 src/core/ao_log_tiny.c create mode 100644 src/core/ao_monitor.c create mode 100644 src/core/ao_mutex.c create mode 100644 src/core/ao_panic.c create mode 100644 src/core/ao_pins.h create mode 100644 src/core/ao_product.c create mode 100644 src/core/ao_report.c create mode 100644 src/core/ao_rssi.c create mode 100644 src/core/ao_sample.c create mode 100644 src/core/ao_state.c create mode 100644 src/core/ao_stdio.c create mode 100644 src/core/ao_storage.c create mode 100644 src/core/ao_task.c create mode 100644 src/core/ao_telem.h create mode 100644 src/core/ao_telemetry.c (limited to 'src/core') diff --git a/src/core/altitude.h b/src/core/altitude.h new file mode 100644 index 00000000..a278bbc6 --- /dev/null +++ b/src/core/altitude.h @@ -0,0 +1,132 @@ +/*max error 3.197865153490684 at 0.782%. Average error 0.260150920474668*/ +#define NALT 129 +#define ALT_FRAC_BITS 8 + 15835, /* 10.56 kPa 0.000% */ + 15332, /* 11.42 kPa 0.781% */ + 14868, /* 12.29 kPa 1.563% */ + 14435, /* 13.16 kPa 2.344% */ + 14030, /* 14.02 kPa 3.125% */ + 13649, /* 14.90 kPa 3.906% */ + 13290, /* 15.76 kPa 4.688% */ + 12950, /* 16.63 kPa 5.469% */ + 12627, /* 17.50 kPa 6.250% */ + 12320, /* 18.37 kPa 7.031% */ + 12027, /* 19.24 kPa 7.813% */ + 11747, /* 20.10 kPa 8.594% */ + 11479, /* 20.97 kPa 9.375% */ + 11222, /* 21.84 kPa 10.156% */ + 10975, /* 22.71 kPa 10.938% */ + 10736, /* 23.58 kPa 11.719% */ + 10504, /* 24.44 kPa 12.500% */ + 10278, /* 25.31 kPa 13.281% */ + 10059, /* 26.18 kPa 14.063% */ + 9846, /* 27.05 kPa 14.844% */ + 9638, /* 27.91 kPa 15.625% */ + 9435, /* 28.78 kPa 16.406% */ + 9237, /* 29.65 kPa 17.188% */ + 9044, /* 30.52 kPa 17.969% */ + 8855, /* 31.39 kPa 18.750% */ + 8670, /* 32.26 kPa 19.531% */ + 8490, /* 33.13 kPa 20.313% */ + 8313, /* 33.99 kPa 21.094% */ + 8140, /* 34.86 kPa 21.875% */ + 7970, /* 35.73 kPa 22.656% */ + 7803, /* 36.60 kPa 23.438% */ + 7640, /* 37.47 kPa 24.219% */ + 7480, /* 38.33 kPa 25.000% */ + 7322, /* 39.20 kPa 25.781% */ + 7168, /* 40.07 kPa 26.563% */ + 7016, /* 40.94 kPa 27.344% */ + 6867, /* 41.80 kPa 28.125% */ + 6720, /* 42.67 kPa 28.906% */ + 6575, /* 43.54 kPa 29.688% */ + 6433, /* 44.41 kPa 30.469% */ + 6294, /* 45.28 kPa 31.250% */ + 6156, /* 46.15 kPa 32.031% */ + 6020, /* 47.01 kPa 32.813% */ + 5887, /* 47.88 kPa 33.594% */ + 5755, /* 48.75 kPa 34.375% */ + 5625, /* 49.62 kPa 35.156% */ + 5497, /* 50.49 kPa 35.938% */ + 5371, /* 51.35 kPa 36.719% */ + 5247, /* 52.22 kPa 37.500% */ + 5124, /* 53.09 kPa 38.281% */ + 5003, /* 53.96 kPa 39.063% */ + 4883, /* 54.83 kPa 39.844% */ + 4765, /* 55.69 kPa 40.625% */ + 4648, /* 56.56 kPa 41.406% */ + 4533, /* 57.43 kPa 42.188% */ + 4419, /* 58.30 kPa 42.969% */ + 4307, /* 59.17 kPa 43.750% */ + 4196, /* 60.03 kPa 44.531% */ + 4086, /* 60.90 kPa 45.313% */ + 3977, /* 61.77 kPa 46.094% */ + 3870, /* 62.63 kPa 46.875% */ + 3764, /* 63.51 kPa 47.656% */ + 3659, /* 64.38 kPa 48.438% */ + 3555, /* 65.24 kPa 49.219% */ + 3453, /* 66.11 kPa 50.000% */ + 3351, /* 66.98 kPa 50.781% */ + 3250, /* 67.85 kPa 51.563% */ + 3151, /* 68.72 kPa 52.344% */ + 3052, /* 69.58 kPa 53.125% */ + 2955, /* 70.45 kPa 53.906% */ + 2858, /* 71.32 kPa 54.688% */ + 2763, /* 72.19 kPa 55.469% */ + 2668, /* 73.06 kPa 56.250% */ + 2574, /* 73.92 kPa 57.031% */ + 2482, /* 74.79 kPa 57.813% */ + 2390, /* 75.66 kPa 58.594% */ + 2298, /* 76.52 kPa 59.375% */ + 2208, /* 77.40 kPa 60.156% */ + 2119, /* 78.26 kPa 60.938% */ + 2030, /* 79.13 kPa 61.719% */ + 1942, /* 80.00 kPa 62.500% */ + 1855, /* 80.87 kPa 63.281% */ + 1769, /* 81.74 kPa 64.063% */ + 1683, /* 82.60 kPa 64.844% */ + 1598, /* 83.47 kPa 65.625% */ + 1514, /* 84.34 kPa 66.406% */ + 1430, /* 85.21 kPa 67.188% */ + 1347, /* 86.08 kPa 67.969% */ + 1265, /* 86.94 kPa 68.750% */ + 1184, /* 87.81 kPa 69.531% */ + 1103, /* 88.68 kPa 70.313% */ + 1023, /* 89.55 kPa 71.094% */ + 943, /* 90.41 kPa 71.875% */ + 864, /* 91.28 kPa 72.656% */ + 786, /* 92.15 kPa 73.438% */ + 708, /* 93.02 kPa 74.219% */ + 631, /* 93.89 kPa 75.000% */ + 554, /* 94.76 kPa 75.781% */ + 478, /* 95.63 kPa 76.563% */ + 403, /* 96.49 kPa 77.344% */ + 328, /* 97.36 kPa 78.125% */ + 254, /* 98.23 kPa 78.906% */ + 180, /* 99.10 kPa 79.688% */ + 106, /* 99.97 kPa 80.469% */ + 34, /* 100.83 kPa 81.250% */ + -39, /* 101.70 kPa 82.031% */ + -111, /* 102.57 kPa 82.813% */ + -182, /* 103.44 kPa 83.594% */ + -253, /* 104.30 kPa 84.375% */ + -323, /* 105.17 kPa 85.156% */ + -393, /* 106.04 kPa 85.938% */ + -462, /* 106.91 kPa 86.719% */ + -531, /* 107.78 kPa 87.500% */ + -600, /* 108.65 kPa 88.281% */ + -668, /* 109.51 kPa 89.063% */ + -736, /* 110.38 kPa 89.844% */ + -803, /* 111.25 kPa 90.625% */ + -870, /* 112.12 kPa 91.406% */ + -936, /* 112.99 kPa 92.188% */ + -1002, /* 113.85 kPa 92.969% */ + -1068, /* 114.72 kPa 93.750% */ + -1133, /* 115.59 kPa 94.531% */ + -1198, /* 116.46 kPa 95.313% */ + -1262, /* 117.33 kPa 96.094% */ + -1326, /* 118.19 kPa 96.875% */ + -1389, /* 119.06 kPa 97.656% */ + -1453, /* 119.93 kPa 98.438% */ + -1516, /* 120.80 kPa 99.219% */ + -1578, /* 121.67 kPa 100.000% */ diff --git a/src/core/ao.h b/src/core/ao.h new file mode 100644 index 00000000..8ac9ac3d --- /dev/null +++ b/src/core/ao.h @@ -0,0 +1,1610 @@ +/* + * Copyright © 2009 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_H_ +#define _AO_H_ + +#include +#include +#include +#include +#include "cc1111.h" +#include "ao_pins.h" + +#define TRUE 1 +#define FALSE 0 + +/* Convert a __data pointer into an __xdata pointer */ +#define DATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xff00)) + +/* Stack runs from above the allocated __data space to 0xfe, which avoids + * writing to 0xff as that triggers the stack overflow indicator + */ +#define AO_STACK_START 0x90 +#define AO_STACK_END 0xfe +#define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1) + +/* An AltOS task */ +struct ao_task { + __xdata void *wchan; /* current wait channel (NULL if running) */ + uint16_t alarm; /* abort ao_sleep time */ + uint8_t stack_count; /* amount of saved stack */ + uint8_t task_id; /* unique id */ + __code char *name; /* task name */ + uint8_t stack[AO_STACK_SIZE]; /* saved stack */ +}; + +extern __xdata struct ao_task *__data ao_cur_task; + +#define AO_NUM_TASKS 16 /* maximum number of tasks */ +#define AO_NO_TASK 0 /* no task id */ + +/* + ao_task.c + */ + +/* Suspend the current task until wchan is awoken. + * returns: + * 0 on normal wake + * 1 on alarm + */ +uint8_t +ao_sleep(__xdata void *wchan); + +/* Wake all tasks sleeping on wchan */ +void +ao_wakeup(__xdata void *wchan); + +/* set an alarm to go off in 'delay' ticks */ +void +ao_alarm(uint16_t delay); + +/* Yield the processor to another task */ +void +ao_yield(void) __naked; + +/* Add a task to the run queue */ +void +ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant; + +/* Terminate the current task */ +void +ao_exit(void); + +/* Dump task info to console */ +void +ao_task_info(void); + +/* Start the scheduler. This will not return */ +void +ao_start_scheduler(void); + +/* + * ao_panic.c + */ + +#define AO_PANIC_NO_TASK 1 /* AO_NUM_TASKS is not large enough */ +#define AO_PANIC_DMA 2 /* Attempt to start DMA while active */ +#define AO_PANIC_MUTEX 3 /* Mis-using mutex API */ +#define AO_PANIC_EE 4 /* Mis-using eeprom API */ +#define AO_PANIC_LOG 5 /* Failing to read/write log data */ +#define AO_PANIC_CMD 6 /* Too many command sets registered */ +#define AO_PANIC_STDIO 7 /* Too many stdio handlers registered */ +#define AO_PANIC_REBOOT 8 /* Reboot failed */ +#define AO_PANIC_FLASH 9 /* Invalid flash part (or wrong blocksize) */ +#define AO_PANIC_USB 10 /* Trying to send USB packet while busy */ +#define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ + +/* Stop the operating system, beeping and blinking the reason */ +void +ao_panic(uint8_t reason); + +/* + * ao_timer.c + */ + +/* Our timer runs at 100Hz */ +#define AO_HERTZ 100 +#define AO_MS_TO_TICKS(ms) ((ms) / (1000 / AO_HERTZ)) +#define AO_SEC_TO_TICKS(s) ((s) * AO_HERTZ) + +/* Returns the current time in ticks */ +uint16_t +ao_time(void); + +/* Suspend the current task until ticks time has passed */ +void +ao_delay(uint16_t ticks); + +/* Set the ADC interval */ +void +ao_timer_set_adc_interval(uint8_t interval) __critical; + +/* Timer interrupt */ +void +ao_timer_isr(void) __interrupt 9; + +/* Initialize the timer */ +void +ao_timer_init(void); + +/* Initialize the hardware clock. Must be called first */ +void +ao_clock_init(void); + +/* + * One set of samples read from the A/D converter or telemetry + */ +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +}; + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC + +#if HAS_ACCEL +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif +#else +#define HAS_ACCEL_REF 0 +#endif + +/* + * ao_adc.c + */ + +#define AO_ADC_RING 32 +#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) +#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) + + +/* + * A/D data is stored in a ring, with the next sample to be written + * at ao_adc_head + */ +extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; +extern volatile __data uint8_t ao_adc_head; +#if HAS_ACCEL_REF +extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; +#endif + +/* Trigger a conversion sequence (called from the timer interrupt) */ +void +ao_adc_poll(void); + +/* Suspend the current task until another A/D sample is converted */ +void +ao_adc_sleep(void); + +/* Get a copy of the last complete A/D sample set */ +void +ao_adc_get(__xdata struct ao_adc *packet); + +/* The A/D interrupt handler */ + +void +ao_adc_isr(void) __interrupt 1; + +/* Initialize the A/D converter */ +void +ao_adc_init(void); + +#endif /* HAS_ADC */ + +/* + * ao_beep.c + */ + +/* + * Various pre-defined beep frequencies + * + * frequency = 1/2 (24e6/32) / beep + */ + +#define AO_BEEP_LOW 150 /* 2500Hz */ +#define AO_BEEP_MID 94 /* 3989Hz */ +#define AO_BEEP_HIGH 75 /* 5000Hz */ +#define AO_BEEP_OFF 0 /* off */ + +#define AO_BEEP_g 240 /* 1562.5Hz */ +#define AO_BEEP_gs 227 /* 1652Hz (1655Hz) */ +#define AO_BEEP_aa 214 /* 1752Hz (1754Hz) */ +#define AO_BEEP_bbf 202 /* 1856Hz (1858Hz) */ +#define AO_BEEP_bb 190 /* 1974Hz (1969Hz) */ +#define AO_BEEP_cc 180 /* 2083Hz (2086Hz) */ +#define AO_BEEP_ccs 170 /* 2205Hz (2210Hz) */ +#define AO_BEEP_dd 160 /* 2344Hz (2341Hz) */ +#define AO_BEEP_eef 151 /* 2483Hz (2480Hz) */ +#define AO_BEEP_ee 143 /* 2622Hz (2628Hz) */ +#define AO_BEEP_ff 135 /* 2778Hz (2784Hz) */ +#define AO_BEEP_ffs 127 /* 2953Hz (2950Hz) */ +#define AO_BEEP_gg 120 /* 3125Hz */ +#define AO_BEEP_ggs 113 /* 3319Hz (3311Hz) */ +#define AO_BEEP_aaa 107 /* 3504Hz (3508Hz) */ +#define AO_BEEP_bbbf 101 /* 3713Hz (3716Hz) */ +#define AO_BEEP_bbb 95 /* 3947Hz (3937Hz) */ +#define AO_BEEP_ccc 90 /* 4167Hz (4171Hz) */ +#define AO_BEEP_cccs 85 /* 4412Hz (4419Hz) */ +#define AO_BEEP_ddd 80 /* 4688Hz (4682Hz) */ +#define AO_BEEP_eeef 76 /* 4934Hz (4961Hz) */ +#define AO_BEEP_eee 71 /* 5282Hz (5256Hz) */ +#define AO_BEEP_fff 67 /* 5597Hz (5568Hz) */ +#define AO_BEEP_fffs 64 /* 5859Hz (5899Hz) */ +#define AO_BEEP_ggg 60 /* 6250Hz */ + +/* Set the beeper to the specified tone */ +void +ao_beep(uint8_t beep); + +/* Turn on the beeper for the specified time */ +void +ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant; + +/* Initialize the beeper */ +void +ao_beep_init(void); + +/* + * ao_led.c + */ + +#define AO_LED_NONE 0 + +/* Turn on the specified LEDs */ +void +ao_led_on(uint8_t colors); + +/* Turn off the specified LEDs */ +void +ao_led_off(uint8_t colors); + +/* Set all of the LEDs to the specified state */ +void +ao_led_set(uint8_t colors); + +/* Toggle the specified LEDs */ +void +ao_led_toggle(uint8_t colors); + +/* Turn on the specified LEDs for the indicated interval */ +void +ao_led_for(uint8_t colors, uint16_t ticks) __reentrant; + +/* Initialize the LEDs */ +void +ao_led_init(uint8_t enable); + +/* + * ao_romconfig.c + */ + +#define AO_ROMCONFIG_VERSION 2 + +extern __code __at (0x00a0) uint16_t ao_romconfig_version; +extern __code __at (0x00a2) uint16_t ao_romconfig_check; +extern __code __at (0x00a4) uint16_t ao_serial_number; +extern __code __at (0x00a6) uint32_t ao_radio_cal; + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +#if HAS_USB +extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; +#endif + +/* + * ao_usb.c + */ + +/* Put one character to the USB output queue */ +void +ao_usb_putchar(char c); + +/* Get one character from the USB input queue */ +char +ao_usb_getchar(void); + +/* Poll for a charcter on the USB input queue. + * returns AO_READ_AGAIN if none are available + */ +char +ao_usb_pollchar(void); + +/* Flush the USB output queue */ +void +ao_usb_flush(void); + +#if HAS_USB +/* USB interrupt handler */ +void +ao_usb_isr(void) __interrupt 6; +#endif + +/* Enable the USB controller */ +void +ao_usb_enable(void); + +/* Disable the USB controller */ +void +ao_usb_disable(void); + +/* Initialize the USB system */ +void +ao_usb_init(void); + +/* + * ao_cmd.c + */ + +enum ao_cmd_status { + ao_cmd_success = 0, + ao_cmd_lex_error = 1, + ao_cmd_syntax_error = 2, +}; + +extern __pdata uint16_t ao_cmd_lex_i; +extern __pdata uint32_t ao_cmd_lex_u32; +extern __pdata char ao_cmd_lex_c; +extern __pdata enum ao_cmd_status ao_cmd_status; + +void +ao_cmd_lex(void); + +void +ao_cmd_put8(uint8_t v); + +void +ao_cmd_put16(uint16_t v); + +void +ao_cmd_white(void); + +void +ao_cmd_hex(void); + +void +ao_cmd_decimal(void); + +uint8_t +ao_match_word(__code char *word); + +struct ao_cmds { + void (*func)(void); + __code char *help; +}; + +void +ao_cmd_register(__code struct ao_cmds *cmds); + +void +ao_cmd_init(void); + +#if HAS_CMD_FILTER +/* + * Provided by an external module to filter raw command lines + */ +uint8_t +ao_cmd_filter(void); +#endif + +/* + * ao_dma.c + */ + +/* Allocate a DMA channel. the 'done' parameter will be set when the + * dma is finished and will be used to wakeup any waiters + */ + +uint8_t +ao_dma_alloc(__xdata uint8_t * done); + +/* Setup a DMA channel */ +void +ao_dma_set_transfer(uint8_t id, + void __xdata *srcaddr, + void __xdata *dstaddr, + uint16_t count, + uint8_t cfg0, + uint8_t cfg1); + +/* Start a DMA channel */ +void +ao_dma_start(uint8_t id); + +/* Manually trigger a DMA channel */ +void +ao_dma_trigger(uint8_t id); + +/* Abort a running DMA transfer */ +void +ao_dma_abort(uint8_t id); + +/* DMA interrupt routine */ +void +ao_dma_isr(void) __interrupt 8; + +/* + * ao_mutex.c + */ + +void +ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant; + +void +ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant; + +/* + * Storage interface, provided by one of the eeprom or flash + * drivers + */ + +/* Total bytes of available storage */ +extern __pdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +extern __pdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +extern __pdata uint32_t ao_storage_config; + +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +extern __pdata uint16_t ao_storage_unit; + +#define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) + +/* Initialize above values. Can only be called once the OS is running */ +void +ao_storage_setup(void) __reentrant; + +/* Write data. Returns 0 on failure, 1 on success */ +uint8_t +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Read data. Returns 0 on failure, 1 on success */ +uint8_t +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Erase a block of storage. This always clears ao_storage_block bytes */ +uint8_t +ao_storage_erase(uint32_t pos) __reentrant; + +/* Flush any pending writes to stable storage */ +void +ao_storage_flush(void) __reentrant; + +/* Initialize the storage code */ +void +ao_storage_init(void); + +/* + * Low-level functions wrapped by ao_storage.c + */ + +/* Read data within a storage unit */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Write data within a storage unit */ +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Initialize low-level device bits */ +void +ao_storage_device_init(void); + +/* Print out information about flash chips */ +void +ao_storage_device_info(void) __reentrant; + +/* + * ao_log.c + */ + +/* We record flight numbers in the first record of + * the log. Tasks may wait for this to be initialized + * by sleeping on this variable. + */ +extern __xdata uint16_t ao_flight_number; + +extern __pdata uint32_t ao_log_current_pos; +extern __pdata uint32_t ao_log_end_pos; +extern __pdata uint32_t ao_log_start_pos; +extern __xdata uint8_t ao_log_running; +extern __pdata enum flight_state ao_log_state; + +/* required functions from the underlying log system */ + +#define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ +#define AO_LOG_FORMAT_FULL 1 /* 8 byte typed log records */ +#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ +#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ +#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ +#define AO_LOG_FORMAT_NONE 127 /* No log at all */ + +extern __code uint8_t ao_log_format; + +/* Return the flight number from the given log slot, 0 if none */ +uint16_t +ao_log_flight(uint8_t slot); + +/* Flush the log */ +void +ao_log_flush(void); + +/* Logging thread main routine */ +void +ao_log(void); + +/* functions provided in ao_log.c */ + +/* Figure out the current flight number */ +void +ao_log_scan(void) __reentrant; + +/* Return the position of the start of the given log slot */ +uint32_t +ao_log_pos(uint8_t slot); + +/* Start logging to eeprom */ +void +ao_log_start(void); + +/* Stop logging */ +void +ao_log_stop(void); + +/* Initialize the logging system */ +void +ao_log_init(void); + +/* Write out the current flight number to the erase log */ +void +ao_log_write_erase(uint8_t pos); + +/* Returns true if there are any logs stored in eeprom */ +uint8_t +ao_log_present(void); + +/* Returns true if there is no more storage space available */ +uint8_t +ao_log_full(void); + +/* + * ao_log_big.c + */ + +/* + * The data log is recorded in the eeprom as a sequence + * of data packets. + * + * Each packet starts with a 4-byte header that has the + * packet type, the packet checksum and the tick count. Then + * they all contain 2 16 bit values which hold packet-specific + * data. + * + * For each flight, the first packet + * is FLIGHT packet, indicating the serial number of the + * device and a unique number marking the number of flights + * recorded by this device. + * + * During flight, data from the accelerometer and barometer + * are recorded in SENSOR packets, using the raw 16-bit values + * read from the A/D converter. + * + * Also during flight, but at a lower rate, the deployment + * sensors are recorded in DEPLOY packets. The goal here is to + * detect failure in the deployment circuits. + * + * STATE packets hold state transitions as the flight computer + * transitions through different stages of the flight. + */ +#define AO_LOG_FLIGHT 'F' +#define AO_LOG_SENSOR 'A' +#define AO_LOG_TEMP_VOLT 'T' +#define AO_LOG_DEPLOY 'D' +#define AO_LOG_STATE 'S' +#define AO_LOG_GPS_TIME 'G' +#define AO_LOG_GPS_LAT 'N' +#define AO_LOG_GPS_LON 'W' +#define AO_LOG_GPS_ALT 'H' +#define AO_LOG_GPS_SAT 'V' +#define AO_LOG_GPS_DATE 'Y' + +#define AO_LOG_POS_NONE (~0UL) + +struct ao_log_record { + char type; + uint8_t csum; + uint16_t tick; + union { + struct { + int16_t ground_accel; + uint16_t flight; + } flight; + struct { + int16_t accel; + int16_t pres; + } sensor; + struct { + int16_t temp; + int16_t v_batt; + } temp_volt; + struct { + int16_t drogue; + int16_t main; + } deploy; + struct { + uint16_t state; + uint16_t reason; + } state; + struct { + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + } gps_time; + int32_t gps_latitude; + int32_t gps_longitude; + struct { + int16_t altitude; + uint16_t unused; + } gps_altitude; + struct { + uint16_t svid; + uint8_t unused; + uint8_t c_n; + } gps_sat; + struct { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t extra; + } gps_date; + struct { + uint16_t d0; + uint16_t d1; + } anon; + } u; +}; + +/* Write a record to the eeprom log */ +uint8_t +ao_log_data(__xdata struct ao_log_record *log) __reentrant; + +/* + * ao_flight.c + */ + +enum ao_flight_state { + ao_flight_startup = 0, + ao_flight_idle = 1, + ao_flight_pad = 2, + ao_flight_boost = 3, + ao_flight_fast = 4, + ao_flight_coast = 5, + ao_flight_drogue = 6, + ao_flight_main = 7, + ao_flight_landed = 8, + ao_flight_invalid = 9 +}; + +extern __pdata enum ao_flight_state ao_flight_state; + +extern __pdata uint16_t ao_launch_time; +extern __pdata uint8_t ao_flight_force_idle; + +/* Flight thread */ +void +ao_flight(void); + +/* Initialize flight thread */ +void +ao_flight_init(void); + +/* + * ao_flight_nano.c + */ + +void +ao_flight_nano_init(void); + +/* + * ao_sample.c + */ + +/* + * Barometer calibration + * + * We directly sample the barometer. The specs say: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * If we want to detect launch with the barometer, we need + * a large enough bump to not be fooled by noise. At typical + * launch elevations (0-2000m), a 200Pa pressure change cooresponds + * to about a 20m elevation change. This is 5.4mV, or about 3LSB. + * As all of our calculations are done in 16 bits, we'll actually see a change + * of 16 times this though + * + * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa + */ + +/* Accelerometer calibration + * + * We're sampling the accelerometer through a resistor divider which + * consists of 5k and 10k resistors. This multiplies the values by 2/3. + * That goes into the cc1111 A/D converter, which is running at 11 bits + * of precision with the bits in the MSB of the 16 bit value. Only positive + * values are used, so values should range from 0-32752 for 0-3.3V. The + * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what + * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV, + * for a final computation of: + * + * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g + * + * Zero g was measured at 16000 (we would expect 16384). + * Note that this value is only require to tell if the + * rocket is standing upright. Once that is determined, + * the value of the accelerometer is averaged for 100 samples + * to find the resting accelerometer value, which is used + * for all further flight computations + */ + +#define GRAVITY 9.80665 + +/* + * Above this height, the baro sensor doesn't work + */ +#define AO_MAX_BARO_HEIGHT 12000 + +/* + * Above this speed, baro measurements are unreliable + */ +#define AO_MAX_BARO_SPEED 200 + +#define ACCEL_NOSE_UP (ao_accel_2g >> 2) + +/* + * Speed and acceleration are scaled by 16 to provide a bit more + * resolution while still having reasonable range. Note that this + * limits speed to 2047m/s (around mach 6) and acceleration to + * 2047m/s² (over 200g) + */ + +#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) +#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) +#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) + +extern __pdata uint16_t ao_sample_tick; /* time of last data */ +extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */ +extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */ +extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */ +extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ + +#if HAS_ACCEL +extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ +#endif + +extern __pdata int16_t ao_ground_pres; /* startup pressure */ +extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +extern __pdata int16_t ao_ground_accel; /* startup acceleration */ +extern __pdata int16_t ao_accel_2g; /* factory accel calibration */ +extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +void ao_sample_init(void); + +/* returns FALSE in preflight mode, TRUE in flight mode */ +uint8_t ao_sample(void); + +/* + * ao_kalman.c + */ + +#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) +#define from_fix(x) ((x) >> 16) + +extern __pdata int16_t ao_height; /* meters */ +extern __pdata int16_t ao_speed; /* m/s * 16 */ +extern __pdata int16_t ao_accel; /* m/s² * 16 */ +extern __pdata int16_t ao_max_height; /* max of ao_height */ +extern __pdata int16_t ao_avg_height; /* running average of height */ + +extern __pdata int16_t ao_error_h; +extern __pdata int16_t ao_error_h_sq_avg; + +#if HAS_ACCEL +extern __pdata int16_t ao_error_a; +#endif + +void ao_kalman(void); + +/* + * ao_report.c + */ + +void +ao_report_init(void); + +/* + * ao_convert.c + * + * Given raw data, convert to SI units + */ + +/* pressure from the sensor to altitude in meters */ +int16_t +ao_pres_to_altitude(int16_t pres) __reentrant; + +int16_t +ao_altitude_to_pres(int16_t alt) __reentrant; + +int16_t +ao_temp_to_dC(int16_t temp) __reentrant; + +/* + * ao_dbg.c + * + * debug another telemetrum board + */ + +/* Send a byte to the dbg target */ +void +ao_dbg_send_byte(uint8_t byte); + +/* Receive a byte from the dbg target */ +uint8_t +ao_dbg_recv_byte(void); + +/* Start a bulk transfer to/from dbg target memory */ +void +ao_dbg_start_transfer(uint16_t addr); + +/* End a bulk transfer to/from dbg target memory */ +void +ao_dbg_end_transfer(void); + +/* Write a byte to dbg target memory */ +void +ao_dbg_write_byte(uint8_t byte); + +/* Read a byte from dbg target memory */ +uint8_t +ao_dbg_read_byte(void); + +/* Enable dbg mode, switching use of the pins */ +void +ao_dbg_debug_mode(void); + +/* Reset the dbg target */ +void +ao_dbg_reset(void); + +void +ao_dbg_init(void); + +/* + * ao_serial.c + */ + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#if HAS_SERIAL_1 +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +void +ao_serial_rx1_isr(void) __interrupt 3; + +void +ao_serial_tx1_isr(void) __interrupt 14; + +char +ao_serial_getchar(void) __critical; + +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) __critical; + +void +ao_serial_set_stdin(uint8_t stdin); +#endif + +void +ao_serial_putchar(char c) __critical; + +void +ao_serial_drain(void) __critical; + +#define AO_SERIAL_SPEED_4800 0 +#define AO_SERIAL_SPEED_9600 1 +#define AO_SERIAL_SPEED_19200 2 +#define AO_SERIAL_SPEED_57600 3 + +void +ao_serial_set_speed(uint8_t speed); + +void +ao_serial_init(void); +#endif + +/* + * 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; + +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_init(void); + +/* + * ao_telemetry.c + */ +#define AO_MAX_CALLSIGN 8 +#define AO_MAX_VERSION 8 +#define AO_MAX_TELEMETRY 128 + +struct ao_telemetry_generic { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t payload[27]; /* 5 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 +#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 +#define AO_TELEMETRY_SENSOR_TELENANO 0x03 + +struct ao_telemetry_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + int16_t accel; /* 6 accelerometer (TM only) */ + int16_t pres; /* 8 pressure sensor */ + int16_t temp; /* 10 temperature sensor */ + int16_t v_batt; /* 12 battery voltage */ + int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ + int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ + + int16_t acceleration; /* 18 m/s² * 16 */ + int16_t speed; /* 20 m/s * 16 */ + int16_t height; /* 22 m */ + + int16_t ground_pres; /* 24 average pres on pad */ + int16_t ground_accel; /* 26 average accel on pad */ + int16_t accel_plus_g; /* 28 accel calibration at +1g */ + int16_t accel_minus_g; /* 30 accel calibration at -1g */ + /* 32 */ +}; + +#define AO_TELEMETRY_CONFIGURATION 0x04 + +struct ao_telemetry_configuration { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t device; /* 5 device type */ + uint16_t flight; /* 6 flight number */ + uint8_t config_major; /* 8 Config major version */ + uint8_t config_minor; /* 9 Config minor version */ + uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ + uint16_t main_deploy; /* 12 Main deploy alt in meters */ + uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ + char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ + char version[AO_MAX_VERSION]; /* 24 Software version */ + /* 32 */ +}; + +#define AO_TELEMETRY_LOCATION 0x05 + +#define AO_GPS_MODE_NOT_VALID 'N' +#define AO_GPS_MODE_AUTONOMOUS 'A' +#define AO_GPS_MODE_DIFFERENTIAL 'D' +#define AO_GPS_MODE_ESTIMATED 'E' +#define AO_GPS_MODE_MANUAL 'M' +#define AO_GPS_MODE_SIMULATED 'S' + +struct ao_telemetry_location { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t flags; /* 5 Number of sats and other flags */ + int16_t altitude; /* 6 GPS reported altitude (m) */ + int32_t latitude; /* 8 latitude (degrees * 10⁷) */ + int32_t longitude; /* 12 longitude (degrees * 10⁷) */ + uint8_t year; /* 16 (- 2000) */ + uint8_t month; /* 17 (1-12) */ + uint8_t day; /* 18 (1-31) */ + uint8_t hour; /* 19 (0-23) */ + uint8_t minute; /* 20 (0-59) */ + uint8_t second; /* 21 (0-59) */ + uint8_t pdop; /* 22 (m * 5) */ + uint8_t hdop; /* 23 (m * 5) */ + uint8_t vdop; /* 24 (m * 5) */ + uint8_t mode; /* 25 */ + uint16_t ground_speed; /* 26 cm/s */ + int16_t climb_rate; /* 28 cm/s */ + uint8_t course; /* 30 degrees / 2 */ + uint8_t unused[1]; /* 31 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SATELLITE 0x06 + +struct ao_telemetry_satellite_info { + uint8_t svid; + uint8_t c_n_1; +}; + +struct ao_telemetry_satellite { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t channels; /* 5 number of reported sats */ + + struct ao_telemetry_satellite_info sats[12]; /* 6 */ + uint8_t unused[2]; /* 30 */ + /* 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; +}; + +/* + * ao_gps.c + */ + +#define AO_GPS_NUM_SAT_MASK (0xf << 0) +#define AO_GPS_NUM_SAT_SHIFT (0) + +#define AO_GPS_VALID (1 << 4) +#define AO_GPS_RUNNING (1 << 5) +#define AO_GPS_DATE_VALID (1 << 6) +#define AO_GPS_COURSE_VALID (1 << 7) + +extern __pdata uint16_t ao_gps_tick; +extern __xdata uint8_t ao_gps_mutex; +extern __xdata struct ao_telemetry_location ao_gps_data; +extern __xdata struct ao_telemetry_satellite ao_gps_tracking_data; + +struct ao_gps_orig { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + int32_t latitude; /* degrees * 10⁷ */ + int32_t longitude; /* degrees * 10⁷ */ + int16_t altitude; /* m */ + uint16_t ground_speed; /* cm/s */ + uint8_t course; /* degrees / 2 */ + uint8_t hdop; /* * 5 */ + int16_t climb_rate; /* cm/s */ + uint16_t h_error; /* m */ + uint16_t v_error; /* m */ +}; + +struct ao_gps_sat_orig { + uint8_t svid; + uint8_t c_n_1; +}; + +#define AO_MAX_GPS_TRACKING 12 + +struct ao_gps_tracking_orig { + uint8_t channels; + struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; +}; + +void +ao_gps(void); + +void +ao_gps_print(__xdata struct ao_gps_orig *gps_data); + +void +ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data); + +void +ao_gps_init(void); + +/* + * ao_gps_report.c + */ + +void +ao_gps_report(void); + +void +ao_gps_report_init(void); + +/* + * ao_telemetry_orig.c + */ + +struct ao_telemetry_orig { + uint16_t serial; + uint16_t flight; + uint8_t flight_state; + int16_t accel; + int16_t ground_accel; + union { + struct { + int16_t speed; + int16_t unused; + } k; + int32_t flight_vel; + } u; + int16_t height; + int16_t ground_pres; + int16_t accel_plus_g; + int16_t accel_minus_g; + struct ao_adc adc; + struct ao_gps_orig gps; + char callsign[AO_MAX_CALLSIGN]; + struct ao_gps_tracking_orig gps_tracking; +}; + +struct ao_telemetry_tiny { + uint16_t serial; + uint16_t flight; + uint8_t flight_state; + int16_t height; /* AGL in meters */ + int16_t speed; /* in m/s * 16 */ + int16_t accel; /* in m/s² * 16 */ + int16_t ground_pres; /* sensor units */ + struct ao_adc adc; /* raw ADC readings */ + char callsign[AO_MAX_CALLSIGN]; +}; + +/* + * ao_radio_recv tacks on rssi and status bytes + */ + +struct ao_telemetry_raw_recv { + uint8_t packet[AO_MAX_TELEMETRY + 2]; +}; + +struct ao_telemetry_orig_recv { + struct ao_telemetry_orig telemetry_orig; + int8_t rssi; + uint8_t status; +}; + +struct ao_telemetry_tiny_recv { + struct ao_telemetry_tiny telemetry_tiny; + int8_t rssi; + uint8_t status; +}; + +/* Set delay between telemetry reports (0 to disable) */ + +#define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) +#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100) +#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000) + +void +ao_telemetry_set_interval(uint16_t interval); + +void +ao_rdf_set(uint8_t rdf); + +void +ao_telemetry_init(void); + +void +ao_telemetry_orig_init(void); + +void +ao_telemetry_tiny_init(void); + +/* + * ao_radio.c + */ + +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; + +void +ao_radio_general_isr(void) __interrupt 16; + +void +ao_radio_get(uint8_t len); + +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) + +void +ao_radio_set_packet(void); + +void +ao_radio_send(__xdata void *data, uint8_t size) __reentrant; + +uint8_t +ao_radio_recv(__xdata void *data, uint8_t size) __reentrant; + +void +ao_radio_recv_abort(void); + +void +ao_radio_rdf(int ms); + +void +ao_radio_rdf_abort(void); + +void +ao_radio_idle(void); + +void +ao_radio_init(void); + +/* + * ao_monitor.c + */ + +extern const char const * const ao_state_names[]; + +void +ao_monitor(void); + +#define AO_MONITORING_OFF 0 +#define AO_MONITORING_ORIG 1 +#define AO_MONITORING_TINY 2 + +void +ao_set_monitor(uint8_t monitoring); + +void +ao_monitor_init(uint8_t led, uint8_t monitoring) __reentrant; + +/* + * ao_stdio.c + */ + +#define AO_READ_AGAIN ((char) -1) + +struct ao_stdio { + char (*pollchar)(void); + void (*putchar)(char c) __reentrant; + void (*flush)(void); + uint8_t echo; +}; + +extern __xdata struct ao_stdio ao_stdios[]; +extern __pdata int8_t ao_cur_stdio; +extern __pdata int8_t ao_num_stdios; + +void +flush(void); + +extern __xdata uint8_t ao_stdin_ready; + +uint8_t +ao_echo(void); + +int8_t +ao_add_stdio(char (*pollchar)(void), + void (*putchar)(char) __reentrant, + void (*flush)(void)) __reentrant; + +/* + * ao_ignite.c + */ + +enum ao_igniter { + ao_igniter_drogue = 0, + ao_igniter_main = 1 +}; + +void +ao_ignite(enum ao_igniter igniter); + +enum ao_igniter_status { + ao_igniter_unknown, /* unknown status (ambiguous voltage) */ + ao_igniter_ready, /* continuity detected */ + ao_igniter_active, /* igniter firing */ + ao_igniter_open, /* open circuit detected */ +}; + +enum ao_igniter_status +ao_igniter_status(enum ao_igniter igniter); + +void +ao_ignite_set_pins(void); + +void +ao_igniter_init(void); + +/* + * ao_config.c + */ + +#define AO_CONFIG_MAJOR 1 +#define AO_CONFIG_MINOR 8 + +struct ao_config { + uint8_t major; + uint8_t minor; + uint16_t main_deploy; + int16_t accel_plus_g; /* changed for minor version 2 */ + uint8_t radio_channel; + char callsign[AO_MAX_CALLSIGN + 1]; + uint8_t apogee_delay; /* minor version 1 */ + int16_t accel_minus_g; /* minor version 2 */ + uint32_t radio_cal; /* minor version 3 */ + uint32_t flight_log_max; /* minor version 4 */ + uint8_t ignite_mode; /* minor version 5 */ + uint8_t pad_orientation; /* minor version 6 */ + uint32_t radio_setting; /* minor version 7 */ + uint8_t radio_enable; /* minor version 8 */ +}; + +#define AO_IGNITE_MODE_DUAL 0 +#define AO_IGNITE_MODE_APOGEE 1 +#define AO_IGNITE_MODE_MAIN 2 + +#define AO_PAD_ORIENTATION_ANTENNA_UP 0 +#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1 + +extern __xdata struct ao_config ao_config; + +#define AO_CONFIG_MAX_SIZE 128 + +void +ao_config_get(void); + +void +ao_config_put(void); + +void +ao_config_init(void); + +/* + * ao_rssi.c + */ + +void +ao_rssi_set(int rssi_value); + +void +ao_rssi_init(uint8_t rssi_led); + +/* + * ao_product.c + * + * values which need to be defined for + * each instance of a product + */ + +extern const char ao_version[]; +extern const char ao_manufacturer[]; +extern const char ao_product[]; + +/* + * Fifos + */ + +#define AO_FIFO_SIZE 32 + +struct ao_fifo { + uint8_t insert; + uint8_t remove; + char fifo[AO_FIFO_SIZE]; +}; + +#define ao_fifo_insert(f,c) do { \ + (f).fifo[(f).insert] = (c); \ + (f).insert = ((f).insert + 1) & (AO_FIFO_SIZE-1); \ +} while(0) + +#define ao_fifo_remove(f,c) do {\ + c = (f).fifo[(f).remove]; \ + (f).remove = ((f).remove + 1) & (AO_FIFO_SIZE-1); \ +} while(0) + +#define ao_fifo_full(f) ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove) +#define ao_fifo_empty(f) ((f).insert == (f).remove) + +/* + * ao_packet.c + * + * Packet-based command interface + */ + +#define AO_PACKET_MAX 64 +#define AO_PACKET_SYN (uint8_t) 0xff + +struct ao_packet { + uint8_t addr; + uint8_t len; + uint8_t seq; + uint8_t ack; + uint8_t d[AO_PACKET_MAX]; + uint8_t callsign[AO_MAX_CALLSIGN]; +}; + +struct ao_packet_recv { + struct ao_packet packet; + int8_t rssi; + uint8_t status; +}; + +extern __xdata struct ao_packet_recv ao_rx_packet; +extern __xdata struct ao_packet ao_tx_packet; +extern __xdata struct ao_task ao_packet_task; +extern __xdata uint8_t ao_packet_enable; +extern __xdata uint8_t ao_packet_master_sleeping; +extern __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; + +void +ao_packet_send(void); + +uint8_t +ao_packet_recv(void); + +void +ao_packet_flush(void); + +void +ao_packet_putchar(char c) __reentrant; + +char +ao_packet_pollchar(void) __critical; + +/* ao_packet_master.c */ + +void +ao_packet_master_init(void); + +/* ao_packet_slave.c */ + +void +ao_packet_slave_start(void); + +void +ao_packet_slave_stop(void); + +void +ao_packet_slave_init(uint8_t enable); + +/* ao_btm.c */ + +/* If bt_link is on P2, this interrupt is shared by USB, so the USB + * code calls this function. Otherwise, it's a regular ISR. + */ + +void +ao_btm_isr(void) +#if BT_LINK_ON_P1 + __interrupt 15 +#endif + ; + +void +ao_btm_init(void); + +/* ao_companion.c */ + +#define AO_COMPANION_SETUP 1 +#define AO_COMPANION_FETCH 2 +#define AO_COMPANION_NOTIFY 3 + +struct ao_companion_command { + uint8_t command; + uint8_t flight_state; + uint16_t tick; + uint16_t serial; + uint16_t flight; +}; + +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/core/ao_cmd.c b/src/core/ao_cmd.c new file mode 100644 index 00000000..1442ebea --- /dev/null +++ b/src/core/ao_cmd.c @@ -0,0 +1,320 @@ +/* + * Copyright © 2009 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" + +__pdata uint16_t ao_cmd_lex_i; +__pdata uint32_t ao_cmd_lex_u32; +__pdata char ao_cmd_lex_c; +__pdata enum ao_cmd_status ao_cmd_status; + +#define CMD_LEN 32 + +static __xdata char cmd_line[CMD_LEN]; +static __pdata uint8_t cmd_len; +static __pdata uint8_t cmd_i; + +static void +put_string(__code char *s) +{ + char c; + while (c = *s++) + putchar(c); +} + +static void +readline(void) +{ + __pdata char c; + if (ao_echo()) + put_string("> "); + cmd_len = 0; + for (;;) { + flush(); + c = getchar(); + /* backspace/delete */ + if (c == '\010' || c == '\177') { + if (cmd_len != 0) { + if (ao_echo()) + put_string("\010 \010"); + --cmd_len; + } + continue; + } + + /* ^U */ + if (c == '\025') { + while (cmd_len != 0) { + if (ao_echo()) + put_string("\010 \010"); + --cmd_len; + } + continue; + } + + /* map CR to NL */ + if (c == '\r') + c = '\n'; + + if (c == '\n') { + if (ao_echo()) + putchar('\n'); + break; + } + + if (cmd_len >= CMD_LEN - 2) { + if (ao_echo()) + putchar('\007'); + continue; + } + cmd_line[cmd_len++] = c; + if (ao_echo()) + putchar(c); + } + cmd_line[cmd_len++] = '\n'; + cmd_line[cmd_len++] = '\0'; + cmd_i = 0; +} + +void +ao_cmd_lex(void) +{ + ao_cmd_lex_c = '\n'; + if (cmd_i < cmd_len) + ao_cmd_lex_c = cmd_line[cmd_i++]; +} + +static void +putnibble(uint8_t v) +{ + if (v < 10) + putchar(v + '0'); + else + putchar(v + ('a' - 10)); +} + +void +ao_cmd_put16(uint16_t v) +{ + ao_cmd_put8(v >> 8); + ao_cmd_put8(v); +} + +void +ao_cmd_put8(uint8_t v) +{ + putnibble((v >> 4) & 0xf); + putnibble(v & 0xf); +} + +void +ao_cmd_white(void) +{ + while (ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t') + ao_cmd_lex(); +} + +void +ao_cmd_hex(void) +{ + __pdata uint8_t r = ao_cmd_lex_error; + uint8_t n; + + ao_cmd_lex_i = 0; + ao_cmd_white(); + for(;;) { + if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') + n = (ao_cmd_lex_c - '0'); + else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f') + n = (ao_cmd_lex_c - 'a' + 10); + else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F') + n = (ao_cmd_lex_c - 'A' + 10); + else + break; + ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n; + r = ao_cmd_success; + ao_cmd_lex(); + } + if (r != ao_cmd_success) + ao_cmd_status = r; +} + +void +ao_cmd_decimal(void) +{ + __pdata uint8_t r = ao_cmd_lex_error; + + ao_cmd_lex_u32 = 0; + ao_cmd_white(); + for(;;) { + if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') + ao_cmd_lex_u32 = (ao_cmd_lex_u32 * 10) + (ao_cmd_lex_c - '0'); + else + break; + r = ao_cmd_success; + ao_cmd_lex(); + } + if (r != ao_cmd_success) + ao_cmd_status = r; + ao_cmd_lex_i = (uint16_t) ao_cmd_lex_u32; +} + +uint8_t +ao_match_word(__code char *word) +{ + while (*word) { + if (ao_cmd_lex_c != *word) { + ao_cmd_status = ao_cmd_syntax_error; + return 0; + } + word++; + ao_cmd_lex(); + } + return 1; +} + +static void +eol(void) +{ + while (ao_cmd_lex_c != '\n') + ao_cmd_lex(); +} + +static void +echo(void) +{ + ao_cmd_hex(); + if (ao_cmd_status == ao_cmd_success) + ao_stdios[ao_cur_stdio].echo = ao_cmd_lex_i != 0; +} + +static void +ao_reboot(void) +{ + ao_cmd_white(); + if (!ao_match_word("eboot")) + return; + WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; + ao_delay(AO_SEC_TO_TICKS(2)); + ao_panic(AO_PANIC_REBOOT); +} + +static void +version(void) +{ + printf("manufacturer %s\n", ao_manufacturer); + printf("product %s\n", ao_product); + printf("serial-number %u\n", ao_serial_number); +#if HAS_EEPROM + printf("log-format %u\n", ao_log_format); +#endif + printf("software-version %s\n", ao_version); +} + +#define NUM_CMDS 11 + +static __code struct ao_cmds *__xdata (ao_cmds[NUM_CMDS]); +static __pdata uint8_t ao_ncmds; + +static void +help(void) +{ + register uint8_t cmds; + register uint8_t cmd; + register __code struct ao_cmds * cs; + + for (cmds = 0; cmds < ao_ncmds; cmds++) { + cs = ao_cmds[cmds]; + for (cmd = 0; cs[cmd].func; cmd++) + printf("%-45s %s\n", + cs[cmd].help, + cs[cmd].help+1+strlen(cs[cmd].help)); + } +} + +static void +report(void) +{ + switch(ao_cmd_status) { + case ao_cmd_lex_error: + case ao_cmd_syntax_error: + puts("Syntax error"); + ao_cmd_status = 0; + break; + } +} + +void +ao_cmd_register(__code struct ao_cmds *cmds) +{ + if (ao_ncmds >= NUM_CMDS) + ao_panic(AO_PANIC_CMD); + ao_cmds[ao_ncmds++] = cmds; +} + +void +ao_cmd(void) +{ + char c; + uint8_t cmd, cmds; + __code struct ao_cmds * __xdata cs; + void (*__xdata func)(void); + + for (;;) { + readline(); + ao_cmd_lex(); + ao_cmd_white(); + c = ao_cmd_lex_c; + ao_cmd_lex(); + if (c == '\r' || c == '\n') + continue; + func = (void (*)(void)) NULL; + for (cmds = 0; cmds < ao_ncmds; cmds++) { + cs = ao_cmds[cmds]; + for (cmd = 0; cs[cmd].func; cmd++) + if (cs[cmd].help[0] == c) { + func = cs[cmd].func; + break; + } + if (func) + break; + } + if (func) + (*func)(); + else + ao_cmd_status = ao_cmd_syntax_error; + report(); + } +} + +__xdata struct ao_task ao_cmd_task; + +__code struct ao_cmds ao_base_cmds[] = { + { help, "?\0Help" }, + { ao_task_info, "T\0Show tasks" }, + { echo, "E <0 off, 1 on>\0Set echo mode" }, + { ao_reboot, "r eboot\0Reboot" }, + { version, "v\0Version" }, + { 0, NULL }, +}; + +void +ao_cmd_init(void) +{ + ao_cmd_register(&ao_base_cmds[0]); + ao_add_task(&ao_cmd_task, ao_cmd, "cmd"); +} diff --git a/src/core/ao_config.c b/src/core/ao_config.c new file mode 100644 index 00000000..0c10e608 --- /dev/null +++ b/src/core/ao_config.c @@ -0,0 +1,542 @@ +/* + * Copyright © 2009 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" + +__xdata struct ao_config ao_config; +__pdata uint8_t ao_config_loaded; +__pdata uint8_t ao_config_dirty; +__xdata uint8_t ao_config_mutex; + +#define AO_CONFIG_DEFAULT_MAIN_DEPLOY 250 +#define AO_CONFIG_DEFAULT_RADIO_CHANNEL 0 +#define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" +#define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 +#define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 +#define AO_CONFIG_DEFAULT_IGNITE_MODE AO_IGNITE_MODE_DUAL +#define AO_CONFIG_DEFAULT_PAD_ORIENTATION AO_PAD_ORIENTATION_ANTENNA_UP +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif +#if USE_INTERNAL_FLASH +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config +#else +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024) +#endif + +#if HAS_EEPROM +static void +_ao_config_put(void) +{ + ao_storage_setup(); + ao_storage_erase(ao_storage_config); + ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config)); + ao_log_write_erase(0); + ao_storage_flush(); +} + +void +ao_config_put(void) +{ + ao_mutex_get(&ao_config_mutex); + _ao_config_put(); + ao_mutex_put(&ao_config_mutex); +} +#endif + +static void +_ao_config_get(void) +{ + if (ao_config_loaded) + return; +#if HAS_EEPROM + ao_storage_setup(); + ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config)); +#endif + if (ao_config.major != AO_CONFIG_MAJOR) { + ao_config.major = AO_CONFIG_MAJOR; + ao_config.minor = 0; + ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; + ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; + memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); + memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, + sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); + } + if (ao_config.minor < AO_CONFIG_MINOR) { + /* Fixups for minor version 1 */ + if (ao_config.minor < 1) + ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; + /* Fixups for minor version 2 */ + if (ao_config.minor < 2) { + ao_config.accel_plus_g = 0; + ao_config.accel_minus_g = 0; + } + /* Fixups for minor version 3 */ + if (ao_config.minor < 3) + ao_config.radio_cal = ao_radio_cal; + /* Fixups for minor version 4 */ + if (ao_config.minor < 4) + ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; + /* Fixupes for minor version 5 */ + if (ao_config.minor < 5) + ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; + if (ao_config.minor < 6) + ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; + if (ao_config.minor < 7) + ao_config.radio_setting = ao_config.radio_cal; + if (ao_config.minor < 8) + ao_config.radio_enable = TRUE; + ao_config.minor = AO_CONFIG_MINOR; + ao_config_dirty = 1; + } + ao_config_loaded = 1; +} + +static void +_ao_config_edit_start(void) +{ + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); +} + +static void +_ao_config_edit_finish(void) +{ + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); +} + +void +ao_config_get(void) +{ + _ao_config_edit_start(); + ao_mutex_put(&ao_config_mutex); +} + +void +ao_config_callsign_show(void) +{ + printf ("Callsign: \"%s\"\n", ao_config.callsign); +} + +void +ao_config_callsign_set(void) __reentrant +{ + uint8_t c; + static __xdata char callsign[AO_MAX_CALLSIGN + 1]; + + memset(callsign, '\0', sizeof callsign); + ao_cmd_white(); + c = 0; + while (ao_cmd_lex_c != '\n') { + if (c < AO_MAX_CALLSIGN) + callsign[c++] = ao_cmd_lex_c; + else + ao_cmd_status = ao_cmd_lex_error; + ao_cmd_lex(); + } + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + memcpy(&ao_config.callsign, &callsign, + AO_MAX_CALLSIGN + 1); + _ao_config_edit_finish(); +} + +void +ao_config_radio_channel_show(void) __reentrant +{ + printf("Radio channel: %d\n", + ao_config.radio_channel); +} + +void +ao_config_radio_channel_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.radio_channel = ao_cmd_lex_i; + _ao_config_edit_finish(); + ao_radio_recv_abort(); +} + +#if HAS_ADC + +void +ao_config_main_deploy_show(void) __reentrant +{ + printf("Main deploy: %d meters\n", + ao_config.main_deploy); +} + +void +ao_config_main_deploy_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.main_deploy = ao_cmd_lex_i; + _ao_config_edit_finish(); +} + +#if HAS_ACCEL +void +ao_config_accel_calibrate_show(void) __reentrant +{ + printf("Accel cal +1g: %d -1g: %d\n", + ao_config.accel_plus_g, ao_config.accel_minus_g); +} + +#define ACCEL_CALIBRATE_SAMPLES 1024 +#define ACCEL_CALIBRATE_SHIFT 10 + +static int16_t +ao_config_accel_calibrate_auto(char *orientation) __reentrant +{ + uint16_t i; + int32_t accel_total; + uint8_t cal_adc_ring; + + printf("Orient antenna %s and press a key...", orientation); + flush(); + (void) getchar(); + puts("\r\n"); flush(); + puts("Calibrating..."); flush(); + i = ACCEL_CALIBRATE_SAMPLES; + accel_total = 0; + cal_adc_ring = ao_sample_adc; + while (i) { + ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); + while (i && cal_adc_ring != ao_sample_adc) { + accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel; + cal_adc_ring = ao_adc_ring_next(cal_adc_ring); + i--; + } + } + return accel_total >> ACCEL_CALIBRATE_SHIFT; +} + +void +ao_config_accel_calibrate_set(void) __reentrant +{ + int16_t up, down; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_cmd_lex_i == 0) { + up = ao_config_accel_calibrate_auto("up"); + down = ao_config_accel_calibrate_auto("down"); + } else { + up = ao_cmd_lex_i; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + down = ao_cmd_lex_i; + } + if (up >= down) { + printf("Invalid accel: up (%d) down (%d)\n", + up, down); + return; + } + _ao_config_edit_start(); + ao_config.accel_plus_g = up; + ao_config.accel_minus_g = down; + _ao_config_edit_finish(); +} +#endif /* HAS_ACCEL */ + +void +ao_config_apogee_delay_show(void) __reentrant +{ + printf("Apogee delay: %d seconds\n", + ao_config.apogee_delay); +} + +void +ao_config_apogee_delay_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.apogee_delay = ao_cmd_lex_i; + _ao_config_edit_finish(); +} + +#endif /* HAS_ADC */ + +void +ao_config_radio_cal_show(void) __reentrant +{ + printf("Radio cal: %ld\n", ao_config.radio_cal); +} + +void +ao_config_radio_cal_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.radio_setting = ao_config.radio_cal = ao_cmd_lex_u32; + _ao_config_edit_finish(); +} + +#if HAS_EEPROM +void +ao_config_log_show(void) __reentrant +{ + printf("Max flight log: %d kB\n", (int16_t) (ao_config.flight_log_max >> 10)); +} + +void +ao_config_log_set(void) __reentrant +{ + uint16_t block = (uint16_t) (ao_storage_block >> 10); + uint16_t config = (uint16_t) (ao_storage_config >> 10); + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_log_present()) + printf("Storage must be empty before changing log size\n"); + else if (block > 1024 && (ao_cmd_lex_i & (block - 1))) + printf("Flight log size must be multiple of %d kB\n", block); + else if (ao_cmd_lex_i > config) + printf("Flight log max %d kB\n", config); + else { + _ao_config_edit_start(); + ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10; + _ao_config_edit_finish(); + } +} +#endif /* HAS_EEPROM */ + +#if HAS_IGNITE +void +ao_config_ignite_mode_show(void) __reentrant +{ + printf("Ignite mode: %d\n", ao_config.ignite_mode); +} + +void +ao_config_ignite_mode_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.ignite_mode = ao_cmd_lex_i; + _ao_config_edit_finish(); +} +#endif + +#if HAS_ACCEL +void +ao_config_pad_orientation_show(void) __reentrant +{ + printf("Pad orientation: %d\n", ao_config.pad_orientation); +} + +void +ao_config_pad_orientation_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_cmd_lex_i &= 1; + if (ao_config.pad_orientation != ao_cmd_lex_i) { + uint16_t t; + t = ao_config.accel_plus_g; + ao_config.accel_plus_g = 0x7fff - ao_config.accel_minus_g; + ao_config.accel_minus_g = 0x7fff - t; + } + ao_config.pad_orientation = ao_cmd_lex_i; + _ao_config_edit_finish(); +} +#endif + +void +ao_config_radio_setting_show(void) __reentrant +{ + printf("Radio setting: %ld\n", ao_config.radio_setting); +} + +void +ao_config_radio_setting_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.radio_setting = ao_cmd_lex_u32; + ao_config.radio_channel = 0; + _ao_config_edit_finish(); + ao_radio_recv_abort(); +} + +void +ao_config_radio_enable_show(void) __reentrant +{ + printf("Radio enable: %d\n", ao_config.radio_enable); +} + +void +ao_config_radio_enable_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.radio_enable = ao_cmd_lex_i; + _ao_config_edit_finish(); +} + +struct ao_config_var { + __code char *str; + void (*set)(void) __reentrant; + void (*show)(void) __reentrant; +}; + +static void +ao_config_help(void) __reentrant; + +static void +ao_config_show(void) __reentrant; + +static void +ao_config_write(void) __reentrant; + +__code struct ao_config_var ao_config_vars[] = { +#if HAS_ADC + { "m \0Main deploy (in meters)", + ao_config_main_deploy_set, ao_config_main_deploy_show, }, + { "d \0Apogee delay (in seconds)", + ao_config_apogee_delay_set, ao_config_apogee_delay_show }, +#endif /* HAS_ADC */ + { "r \0Radio channel (freq = 434.550 + chan * .1)", + ao_config_radio_channel_set, ao_config_radio_channel_show }, + { "c \0Callsign (8 char max)", + ao_config_callsign_set, ao_config_callsign_show }, + { "R \0Radio freq control (freq = 434.550 * setting/cal)", + ao_config_radio_setting_set, ao_config_radio_setting_show }, + { "e <0 disable, 1 enable>\0Enable telemetry and RDF", + ao_config_radio_enable_set, ao_config_radio_enable_show }, +#if HAS_ACCEL + { "a <+g> <-g>\0Accel calib (0 for auto)", + ao_config_accel_calibrate_set,ao_config_accel_calibrate_show }, +#endif /* HAS_ACCEL */ + { "f \0Radio calib (cal = rf/(xtal/2^16))", + ao_config_radio_cal_set, ao_config_radio_cal_show }, +#if HAS_EEPROM + { "l \0Flight log size in kB", + ao_config_log_set, ao_config_log_show }, +#endif +#if HAS_IGNITE + { "i <0 dual, 1 apogee, 2 main>\0Set igniter mode", + ao_config_ignite_mode_set, ao_config_ignite_mode_show }, +#endif +#if HAS_ACCEL + { "o <0 antenna up, 1 antenna down>\0Set pad orientation", + ao_config_pad_orientation_set,ao_config_pad_orientation_show }, +#endif + { "s\0Show", + ao_config_show, 0 }, +#if HAS_EEPROM + { "w\0Write to eeprom", + ao_config_write, 0 }, +#endif + { "?\0Help", + ao_config_help, 0 }, + { 0, 0, 0 } +}; + +void +ao_config_set(void) +{ + char c; + uint8_t cmd; + void (*__xdata func)(void) __reentrant; + + ao_cmd_white(); + c = ao_cmd_lex_c; + ao_cmd_lex(); + func = 0; + for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) + if (ao_config_vars[cmd].str[0] == c) { + (*ao_config_vars[cmd].set)(); + return; + } + ao_cmd_status = ao_cmd_syntax_error; +} + +static void +ao_config_help(void) __reentrant +{ + uint8_t cmd; + for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) + printf("%-20s %s\n", + ao_config_vars[cmd].str, + ao_config_vars[cmd].str+1+strlen(ao_config_vars[cmd].str)); +} + +static void +ao_config_show(void) __reentrant +{ + uint8_t cmd; + printf("Config version: %d.%d\n", + ao_config.major, ao_config.minor); + for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) + if (ao_config_vars[cmd].show) + (*ao_config_vars[cmd].show)(); +} + +#if HAS_EEPROM +static void +ao_config_write(void) __reentrant +{ + uint8_t saved = 0; + ao_mutex_get(&ao_config_mutex); + if (ao_config_dirty) { + _ao_config_put(); + ao_config_dirty = 0; + saved = 1; + } + ao_mutex_put(&ao_config_mutex); + if (saved) + puts("Saved"); + else + puts("Nothing to save"); +} +#endif + +__code struct ao_cmds ao_config_cmds[] = { + { ao_config_set, "c \0Set config variable (? for help, s to show)" }, + { 0, NULL }, +}; + +void +ao_config_init(void) +{ + ao_cmd_register(&ao_config_cmds[0]); +} diff --git a/src/core/ao_convert.c b/src/core/ao_convert.c new file mode 100644 index 00000000..0969f107 --- /dev/null +++ b/src/core/ao_convert.c @@ -0,0 +1,85 @@ +/* + * Copyright © 2009 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. + */ + +#if !defined(AO_CONVERT_TEST) && !defined(AO_FLIGHT_TEST) +#include "ao.h" +#endif + +static const int16_t altitude_table[] = { +#include "altitude.h" +}; + +#define ALT_FRAC_SCALE (1 << ALT_FRAC_BITS) +#define ALT_FRAC_MASK (ALT_FRAC_SCALE - 1) + +int16_t +ao_pres_to_altitude(int16_t pres) __reentrant +{ + uint8_t o; + int16_t part; + + if (pres < 0) + pres = 0; + o = pres >> ALT_FRAC_BITS; + part = pres & ALT_FRAC_MASK; + + return ((int32_t) altitude_table[o] * (ALT_FRAC_SCALE - part) + + (int32_t) altitude_table[o+1] * part + (ALT_FRAC_SCALE >> 1)) >> ALT_FRAC_BITS; +} + +int16_t +ao_altitude_to_pres(int16_t alt) __reentrant +{ + int16_t span, sub_span; + uint8_t l, h, m; + int32_t pres; + + l = 0; + h = NALT - 1; + while ((h - l) != 1) { + m = (l + h) >> 1; + if (altitude_table[m] < alt) + h = m; + else + l = m; + } + span = altitude_table[l] - altitude_table[h]; + sub_span = altitude_table[l] - alt; + pres = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_FRAC_BITS) + (span >> 1)) / span; + if (pres > 32767) + pres = 32767; + if (pres < 0) + pres = 0; + return (int16_t) pres; +} + +int16_t +ao_temp_to_dC(int16_t temp) __reentrant +{ + int16_t ret; + + /* Output voltage at 0°C = 0.755V + * Coefficient = 0.00247V/°C + * Reference voltage = 1.25V + * + * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 + * = (value - 19791.268) / 32768 * 1.25 / 0.00247 + * ≃ (value - 19791) * 1012 / 65536 + */ + ret = ((temp - 19791) * 1012L) >> 16; + return ret; +} diff --git a/src/core/ao_convert_test.c b/src/core/ao_convert_test.c new file mode 100644 index 00000000..e2c28b73 --- /dev/null +++ b/src/core/ao_convert_test.c @@ -0,0 +1,75 @@ +/* + * Copyright © 2010 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 +#define AO_CONVERT_TEST +#include "ao_host.h" +#include "ao_convert.c" + +#define STEP 1 + +static inline i_abs(int i) { return i < 0 ? -i : i; } + +main () +{ + int i; + int16_t p_to_a, p_to_a_to_p; + int16_t a_to_p, a_to_p_to_a; + int max_p_error = 0, max_p_error_p = -1; + int max_a_error = 0, max_a_error_a = -1; + int p_error; + int a_error; + int ret = 0; + + for (i = 0; i < 32767 + STEP; i += STEP) { + if (i > 32767) + i = 32767; + p_to_a = ao_pres_to_altitude(i); + p_to_a_to_p = ao_altitude_to_pres(p_to_a); + p_error = i_abs(p_to_a_to_p - i); + if (p_error > max_p_error) { + max_p_error = p_error; + max_p_error_p = i; + } +// printf ("pres %d alt %d pres %d\n", +// i, p_to_a, p_to_a_to_p); + } + for (i = -1578; i < 15835 + STEP; i += STEP) { + if (i > 15835) + i = 15835; + a_to_p = ao_altitude_to_pres(i); + a_to_p_to_a = ao_pres_to_altitude(a_to_p); + a_error = i_abs(a_to_p_to_a - i); + if (a_error > max_a_error) { + max_a_error = a_error; + max_a_error_a = i; + } +// printf ("alt %d pres %d alt %d\n", +// i, a_to_p, a_to_p_to_a); + } + if (max_p_error > 2) { + printf ("max p error %d at %d\n", max_p_error, + max_p_error_p); + ret++; + } + if (max_a_error > 1) { + printf ("max a error %d at %d\n", max_a_error, + max_a_error_a); + ret++; + } + return ret; +} diff --git a/src/core/ao_ee_fake.c b/src/core/ao_ee_fake.c new file mode 100644 index 00000000..b0c1d61e --- /dev/null +++ b/src/core/ao_ee_fake.c @@ -0,0 +1,37 @@ +/* + * Copyright © 2009 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" + +/* + * For hardware without eeprom, the config code still + * wants to call these functions + */ +uint8_t +ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant +{ + (void) buf; + (void) len; + return 1; +} + +uint8_t +ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant +{ + memset(buf, '\0', len); + return 1; +} diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c new file mode 100644 index 00000000..85c1825b --- /dev/null +++ b/src/core/ao_flight.c @@ -0,0 +1,315 @@ +/* + * Copyright © 2009 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_FLIGHT_TEST +#include "ao.h" +#endif + +#ifndef HAS_ACCEL +#error Please define HAS_ACCEL +#endif + +#ifndef HAS_GPS +#error Please define HAS_GPS +#endif + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ +__pdata uint16_t ao_launch_tick; /* time of launch detect */ + +/* + * track min/max data over a long interval to detect + * resting + */ +__pdata uint16_t ao_interval_end; +__pdata int16_t ao_interval_min_height; +__pdata int16_t ao_interval_max_height; +__pdata uint8_t ao_flight_force_idle; + +/* We also have a clock, which can be used to sanity check things in + * case of other failures + */ + +#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) + +/* Landing is detected by getting constant readings from both pressure and accelerometer + * for a fairly long time (AO_INTERVAL_TICKS) + */ +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) + +#define abs(a) ((a) < 0 ? -(a) : (a)) + +void +ao_flight(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + for (;;) { + + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + + /* Check to see what mode we should go to. + * - Invalid mode if accel cal appears to be out + * - pad mode if we're upright, + * - idle mode otherwise + */ +#if HAS_ACCEL + if (ao_config.accel_plus_g == 0 || + ao_config.accel_minus_g == 0 || + ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) + { + /* Detected an accel value outside -1.5g to 1.5g + * (or uncalibrated values), so we go into invalid mode + */ + ao_flight_state = ao_flight_invalid; + + } else +#endif + if (!ao_flight_force_idle +#if HAS_ACCEL + && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP +#endif + ) + { + /* Set pad mode - we can fly! */ + ao_flight_state = ao_flight_pad; +#if HAS_USB + /* Disable the USB controller in flight mode + * to save power + */ + ao_usb_disable(); +#endif + + /* Disable packet mode in pad state */ + ao_packet_slave_stop(); + + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } else { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + + break; + case ao_flight_pad: + + /* pad to boost: + * + * barometer: > 20m vertical motion + * OR + * accelerometer: > 2g AND velocity > 5m/s + * + * The accelerometer should always detect motion before + * the barometer, but we use both to make sure this + * transition is detected. If the device + * doesn't have an accelerometer, then ignore the + * speed and acceleration as they are quite noisy + * on the pad. + */ + if (ao_height > AO_M_TO_HEIGHT(20) +#if HAS_ACCEL + || (ao_accel > AO_MSS_TO_ACCEL(20) && + ao_speed > AO_MS_TO_SPEED(5)) +#endif + ) + { + ao_flight_state = ao_flight_boost; + ao_launch_tick = ao_sample_tick; + + /* start logging data */ + ao_log_start(); + + /* Increase telemetry rate */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); + + /* disable RDF beacon */ + ao_rdf_set(0); + +#if HAS_GPS + /* Record current GPS position by waking up GPS log tasks */ + ao_wakeup(&ao_gps_data); + ao_wakeup(&ao_gps_tracking_data); +#endif + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_boost: + + /* boost to fast: + * + * accelerometer: start to fall at > 1/4 G + * OR + * time: boost for more than 15 seconds + * + * Detects motor burn out by the switch from acceleration to + * deceleration, or by waiting until the maximum burn duration + * (15 seconds) has past. + */ + if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || + (int16_t) (ao_sample_tick - ao_launch_tick) > BOOST_TICKS_MAX) + { +#if HAS_ACCEL + ao_flight_state = ao_flight_fast; +#else + ao_flight_state = ao_flight_coast; +#endif + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; +#if HAS_ACCEL + case ao_flight_fast: + /* + * This is essentially the same as coast, + * but the barometer is being ignored as + * it may be unreliable. + */ + if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) + { + ao_flight_state = ao_flight_coast; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; +#endif + case ao_flight_coast: + + /* apogee detect: coast to drogue deploy: + * + * speed: < 0 + * + * Also make sure the model altitude is tracking + * the measured altitude reasonably closely; otherwise + * we're probably transsonic. + */ + if (ao_speed < 0 +#if !HAS_ACCEL + && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) +#endif + ) + { + /* ignite the drogue charge */ + ao_ignite(ao_igniter_drogue); + + /* slow down the telemetry system */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); + + /* Turn the RDF beacon back on */ + ao_rdf_set(1); + + /* and enter drogue state */ + ao_flight_state = ao_flight_drogue; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + + break; + case ao_flight_drogue: + + /* drogue to main deploy: + * + * barometer: reach main deploy altitude + * + * Would like to use the accelerometer for this test, but + * the orientation of the flight computer is unknown after + * drogue deploy, so we ignore it. Could also detect + * high descent rate using the pressure sensor to + * recognize drogue deploy failure and eject the main + * at that point. Perhaps also use the drogue sense lines + * to notice continutity? + */ + if (ao_height <= ao_config.main_deploy) + { + ao_ignite(ao_igniter_main); + + /* + * Start recording min/max height + * to figure out when the rocket has landed + */ + + /* initialize interval values */ + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + + ao_flight_state = ao_flight_main; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + + /* fall through... */ + case ao_flight_main: + + /* main to land: + * + * barometer: altitude stable + */ + + if (ao_avg_height < ao_interval_min_height) + ao_interval_min_height = ao_avg_height; + if (ao_avg_height > ao_interval_max_height) + ao_interval_max_height = ao_avg_height; + + if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { + if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) + { + ao_flight_state = ao_flight_landed; + + /* turn off the ADC capture */ + ao_timer_set_adc_interval(0); + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + } + break; + case ao_flight_landed: + break; + } + } +} + +static __xdata struct ao_task flight_task; + +void +ao_flight_init(void) +{ + ao_flight_state = ao_flight_startup; + ao_add_task(&flight_task, ao_flight, "flight"); +} diff --git a/src/core/ao_flight_nano.c b/src/core/ao_flight_nano.c new file mode 100644 index 00000000..2e332b12 --- /dev/null +++ b/src/core/ao_flight_nano.c @@ -0,0 +1,120 @@ +/* + * 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" + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ +__pdata uint16_t ao_launch_tick; /* time of launch detect */ + +/* + * track min/max data over a long interval to detect + * resting + */ +__pdata uint16_t ao_interval_end; +__pdata int16_t ao_interval_min_height; +__pdata int16_t ao_interval_max_height; + +__pdata uint8_t ao_flight_force_idle; + +/* Landing is detected by getting constant readings from both pressure and accelerometer + * for a fairly long time (AO_INTERVAL_TICKS) + */ +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(5) + +static void +ao_flight_nano(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + + for (;;) { + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + if (ao_flight_force_idle) { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + } else { + ao_flight_state = ao_flight_pad; + /* Disable packet mode in pad state */ + ao_packet_slave_stop(); + + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); + } + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + break; + case ao_flight_pad: + if (ao_height> AO_M_TO_HEIGHT(20)) { + ao_flight_state = ao_flight_drogue; + ao_launch_tick = ao_sample_tick; + + /* start logging data */ + ao_log_start(); + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_drogue: + /* drogue/main to land: + * + * barometer: altitude stable + */ + + if (ao_height < ao_interval_min_height) + ao_interval_min_height = ao_height; + if (ao_height > ao_interval_max_height) + ao_interval_max_height = ao_height; + + if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { + if (ao_interval_max_height - ao_interval_min_height < AO_M_TO_HEIGHT(5)) + { + ao_flight_state = ao_flight_landed; + + /* turn off the ADC capture */ + ao_timer_set_adc_interval(0); + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + ao_interval_min_height = ao_interval_max_height = ao_height; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + } + break; + } + } +} + +static __xdata struct ao_task flight_task; + +void +ao_flight_nano_init(void) +{ + ao_flight_state = ao_flight_startup; + ao_add_task(&flight_task, ao_flight_nano, "flight"); +} diff --git a/src/core/ao_gps_print.c b/src/core/ao_gps_print.c new file mode 100644 index 00000000..fcdedd30 --- /dev/null +++ b/src/core/ao_gps_print.c @@ -0,0 +1,112 @@ +/* + * Copyright © 2009 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_GPS_TEST +#include "ao.h" +#endif +#include "ao_telem.h" + +void +ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant +{ + char state; + + if (gps_data->flags & AO_GPS_VALID) + state = AO_TELEM_GPS_STATE_LOCKED; + else if (gps_data->flags & AO_GPS_RUNNING) + state = AO_TELEM_GPS_STATE_UNLOCKED; + else + state = AO_TELEM_GPS_STATE_ERROR; + printf(AO_TELEM_GPS_STATE " %c " + AO_TELEM_GPS_NUM_SAT " %d ", + state, + (gps_data->flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT); + if (!(gps_data->flags & AO_GPS_VALID)) + return; + printf(AO_TELEM_GPS_LATITUDE " %ld " + AO_TELEM_GPS_LONGITUDE " %ld " + AO_TELEM_GPS_ALTITUDE " %d ", + gps_data->latitude, + gps_data->longitude, + gps_data->altitude); + + if (gps_data->flags & AO_GPS_DATE_VALID) + printf(AO_TELEM_GPS_YEAR " %d " + AO_TELEM_GPS_MONTH " %d " + AO_TELEM_GPS_DAY " %d ", + gps_data->year, + gps_data->month, + gps_data->day); + + printf(AO_TELEM_GPS_HOUR " %d " + AO_TELEM_GPS_MINUTE " %d " + AO_TELEM_GPS_SECOND " %d ", + gps_data->hour, + gps_data->minute, + gps_data->second); + + printf(AO_TELEM_GPS_HDOP " %d ", + gps_data->hdop * 2); + + if (gps_data->flags & AO_GPS_COURSE_VALID) { + printf(AO_TELEM_GPS_HERROR " %d " + AO_TELEM_GPS_VERROR " %d " + AO_TELEM_GPS_VERTICAL_SPEED " %d " + AO_TELEM_GPS_HORIZONTAL_SPEED " %d " + AO_TELEM_GPS_COURSE " %d ", + gps_data->h_error, + gps_data->v_error, + gps_data->climb_rate, + gps_data->ground_speed, + (int) gps_data->course * 2); + } +} + +void +ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data) __reentrant +{ + uint8_t c, n, v; + __xdata struct ao_gps_sat_orig *sat; + + n = gps_tracking_data->channels; + if (n == 0) + return; + + sat = gps_tracking_data->sats; + v = 0; + for (c = 0; c < n; c++) { + if (sat->svid) + v++; + sat++; + } + + printf (AO_TELEM_SAT_NUM " %d ", + v); + + sat = gps_tracking_data->sats; + v = 0; + for (c = 0; c < n; c++) { + if (sat->svid) { + printf (AO_TELEM_SAT_SVID "%d %d " + AO_TELEM_SAT_C_N_0 "%d %d ", + v, sat->svid, + v, sat->c_n_1); + v++; + } + sat++; + } +} diff --git a/src/core/ao_gps_report.c b/src/core/ao_gps_report.c new file mode 100644 index 00000000..e57f8744 --- /dev/null +++ b/src/core/ao_gps_report.c @@ -0,0 +1,99 @@ +/* + * Copyright © 2009 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" + +void +ao_gps_report(void) +{ + static __xdata struct ao_log_record gps_log; + static __xdata struct ao_telemetry_location gps_data; + uint8_t date_reported = 0; + + for (;;) { + ao_sleep(&ao_gps_data); + ao_mutex_get(&ao_gps_mutex); + memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); + ao_mutex_put(&ao_gps_mutex); + + if (!(gps_data.flags & AO_GPS_VALID)) + continue; + + gps_log.tick = ao_gps_tick; + gps_log.type = AO_LOG_GPS_TIME; + gps_log.u.gps_time.hour = gps_data.hour; + gps_log.u.gps_time.minute = gps_data.minute; + gps_log.u.gps_time.second = gps_data.second; + gps_log.u.gps_time.flags = gps_data.flags; + ao_log_data(&gps_log); + gps_log.type = AO_LOG_GPS_LAT; + gps_log.u.gps_latitude = gps_data.latitude; + ao_log_data(&gps_log); + gps_log.type = AO_LOG_GPS_LON; + gps_log.u.gps_longitude = gps_data.longitude; + ao_log_data(&gps_log); + gps_log.type = AO_LOG_GPS_ALT; + gps_log.u.gps_altitude.altitude = gps_data.altitude; + gps_log.u.gps_altitude.unused = 0xffff; + ao_log_data(&gps_log); + if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) { + gps_log.type = AO_LOG_GPS_DATE; + gps_log.u.gps_date.year = gps_data.year; + gps_log.u.gps_date.month = gps_data.month; + gps_log.u.gps_date.day = gps_data.day; + gps_log.u.gps_date.extra = 0; + date_reported = ao_log_data(&gps_log); + } + } +} + +void +ao_gps_tracking_report(void) +{ + static __xdata struct ao_log_record gps_log; + static __xdata struct ao_telemetry_satellite gps_tracking_data; + uint8_t c, n; + + for (;;) { + ao_sleep(&ao_gps_tracking_data); + ao_mutex_get(&ao_gps_mutex); + gps_log.tick = ao_gps_tick; + memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); + + if (!(n = gps_tracking_data.channels)) + continue; + + gps_log.type = AO_LOG_GPS_SAT; + for (c = 0; c < n; c++) + if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid)) + { + gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1; + ao_log_data(&gps_log); + } + } +} + +__xdata struct ao_task ao_gps_report_task; +__xdata struct ao_task ao_gps_tracking_report_task; + +void +ao_gps_report_init(void) +{ + ao_add_task(&ao_gps_report_task, ao_gps_report, "gps_report"); + ao_add_task(&ao_gps_tracking_report_task, ao_gps_tracking_report, "gps_tracking_report"); +} diff --git a/src/core/ao_host.h b/src/core/ao_host.h new file mode 100644 index 00000000..65c25fe5 --- /dev/null +++ b/src/core/ao_host.h @@ -0,0 +1,127 @@ +/* + * Copyright © 2009 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. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +#define AO_ADC_RING 64 +#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) +#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) + +/* + * One set of samples read from the A/D converter + */ +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +}; + +#define __pdata +#define __data +#define __xdata +#define __code +#define __reentrant + +enum ao_flight_state { + ao_flight_startup = 0, + ao_flight_idle = 1, + ao_flight_pad = 2, + ao_flight_boost = 3, + ao_flight_fast = 4, + ao_flight_coast = 5, + ao_flight_drogue = 6, + ao_flight_main = 7, + ao_flight_landed = 8, + ao_flight_invalid = 9 +}; + +struct ao_adc ao_adc_ring[AO_ADC_RING]; +uint8_t ao_adc_head; + +#define ao_led_on(l) +#define ao_led_off(l) +#define ao_timer_set_adc_interval(i) +#define ao_wakeup(wchan) ao_dump_state(wchan) +#define ao_cmd_register(c) +#define ao_usb_disable() +#define ao_telemetry_set_interval(x) +#define ao_delay(x) + +enum ao_igniter { + ao_igniter_drogue = 0, + ao_igniter_main = 1 +}; + +void +ao_ignite(enum ao_igniter igniter) +{ + printf ("ignite %s\n", igniter == ao_igniter_drogue ? "drogue" : "main"); +} + +struct ao_task { + int dummy; +}; + +#define ao_add_task(t,f,n) + +#define ao_log_start() +#define ao_log_stop() + +#define AO_MS_TO_TICKS(ms) ((ms) / 10) +#define AO_SEC_TO_TICKS(s) ((s) * 100) + +#define AO_FLIGHT_TEST + +struct ao_adc ao_adc_static; + +FILE *emulator_in; + +void +ao_dump_state(void *wchan); + +void +ao_sleep(void *wchan); + +const char const * const ao_state_names[] = { + "startup", "idle", "pad", "boost", "fast", + "coast", "drogue", "main", "landed", "invalid" +}; + +struct ao_cmds { + void (*func)(void); + const char *help; +}; + + +struct ao_config { + uint16_t main_deploy; + int16_t accel_zero_g; +}; + +#define ao_config_get() + +struct ao_config ao_config = { 250, 16000 }; diff --git a/src/core/ao_kalman.c b/src/core/ao_kalman.c new file mode 100644 index 00000000..ee01949e --- /dev/null +++ b/src/core/ao_kalman.c @@ -0,0 +1,292 @@ +/* + * 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. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#endif + +#include "ao_kalman.h" + +static __pdata int32_t ao_k_height; +static __pdata int32_t ao_k_speed; +static __pdata int32_t ao_k_accel; + +#define AO_K_STEP_100 to_fix16(0.01) +#define AO_K_STEP_2_2_100 to_fix16(0.00005) + +#define AO_K_STEP_10 to_fix16(0.1) +#define AO_K_STEP_2_2_10 to_fix16(0.005) + +#define AO_K_STEP_1 to_fix16(1) +#define AO_K_STEP_2_2_1 to_fix16(0.5) + +__pdata int16_t ao_height; +__pdata int16_t ao_speed; +__pdata int16_t ao_accel; +__pdata int16_t ao_max_height; +static __pdata int32_t ao_avg_height_scaled; +__pdata int16_t ao_avg_height; + +__pdata int16_t ao_error_h; +__pdata int16_t ao_error_h_sq_avg; + +#if HAS_ACCEL +__pdata int16_t ao_error_a; +#endif + +static void +ao_kalman_predict(void) +{ +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_1 + + (int32_t) ao_accel * AO_K_STEP_2_2_1) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_1; + + return; + } + if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 + + (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10; + + return; + } + if (ao_flight_debug) { + printf ("predict speed %g + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0, + (ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0)); + } +#endif + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 + + (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100; +} + +static void +ao_kalman_err_height(void) +{ + int16_t e; + int16_t height_distrust; +#if HAS_ACCEL + int16_t speed_distrust; +#endif + + ao_error_h = ao_sample_height - (int16_t) (ao_k_height >> 16); + + e = ao_error_h; + if (e < 0) + e = -e; + if (e > 127) + e = 127; +#if HAS_ACCEL + ao_error_h_sq_avg -= ao_error_h_sq_avg >> 2; + ao_error_h_sq_avg += (e * e) >> 2; +#else + ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4; + ao_error_h_sq_avg += (e * e) >> 4; +#endif + + if (ao_flight_state >= ao_flight_drogue) + return; + height_distrust = ao_sample_alt - AO_MAX_BARO_HEIGHT; +#if HAS_ACCEL + /* speed is stored * 16, but we need to ramp between 200 and 328, so + * we want to multiply by 2. The result is a shift by 3. + */ + speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> (4 - 1); + if (speed_distrust <= 0) + speed_distrust = 0; + else if (speed_distrust > height_distrust) + height_distrust = speed_distrust; +#endif + if (height_distrust > 0) { +#ifdef AO_FLIGHT_TEST + int old_ao_error_h = ao_error_h; +#endif + if (height_distrust > 0x100) + height_distrust = 0x100; + ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8); +#ifdef AO_FLIGHT_TEST + if (ao_flight_debug) { + printf("over height %g over speed %g distrust: %g height: error %d -> %d\n", + (double) (ao_sample_alt - AO_MAX_BARO_HEIGHT), + (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) / 16.0, + height_distrust / 256.0, + old_ao_error_h, ao_error_h); + } +#endif + } +} + +static void +ao_kalman_correct_baro(void) +{ + ao_kalman_err_height(); +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + ao_k_height += (int32_t) AO_BARO_K0_1 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_1 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_1 * ao_error_h; + return; + } + if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_10 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_10 * ao_error_h; + return; + } +#endif + ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_100 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_100 * ao_error_h; +} + +#if HAS_ACCEL + +static void +ao_kalman_err_accel(void) +{ + int32_t accel; + + accel = (ao_ground_accel - ao_sample_accel) * ao_accel_scale; + + /* Can't use ao_accel here as it is the pre-prediction value still */ + ao_error_a = (accel - ao_k_accel) >> 16; +} + +static void +ao_kalman_correct_both(void) +{ + ao_kalman_err_height(); + ao_kalman_err_accel(); + +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_1 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_1 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_1 * ao_error_h + + (int32_t) AO_BOTH_K11_1 * ao_error_a) / (65536.0 * 16.0)); + } + ao_k_height += + (int32_t) AO_BOTH_K00_1 * ao_error_h + + (int32_t) AO_BOTH_K01_1 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_1 * ao_error_h + + (int32_t) AO_BOTH_K11_1 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_1 * ao_error_h + + (int32_t) AO_BOTH_K21_1 * ao_error_a; + return; + } + if (ao_sample_tick - ao_sample_prev_tick > 5) { + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_10 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_10 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_10 * ao_error_h + + (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0)); + } + ao_k_height += + (int32_t) AO_BOTH_K00_10 * ao_error_h + + (int32_t) AO_BOTH_K01_10 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_10 * ao_error_h + + (int32_t) AO_BOTH_K11_10 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_10 * ao_error_h + + (int32_t) AO_BOTH_K21_10 * ao_error_a; + return; + } + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_100 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_100 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_100 * ao_error_h + + (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0)); + } +#endif + ao_k_height += + (int32_t) AO_BOTH_K00_100 * ao_error_h + + (int32_t) AO_BOTH_K01_100 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_100 * ao_error_h + + (int32_t) AO_BOTH_K11_100 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_100 * ao_error_h + + (int32_t) AO_BOTH_K21_100 * ao_error_a; +} + +#ifdef FORCE_ACCEL +static void +ao_kalman_correct_accel(void) +{ + ao_kalman_err_accel(); + + if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a; + ao_k_speed += (int32_t) AO_ACCEL_K1_10 * ao_error_a; + ao_k_accel += (int32_t) AO_ACCEL_K2_10 * ao_error_a; + return; + } + ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a; + ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a; + ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a; +} +#endif +#endif /* HAS_ACCEL */ + +void +ao_kalman(void) +{ + ao_kalman_predict(); +#if HAS_ACCEL + if (ao_flight_state <= ao_flight_coast) { +#ifdef FORCE_ACCEL + ao_kalman_correct_accel(); +#else + ao_kalman_correct_both(); +#endif + } else +#endif + ao_kalman_correct_baro(); + ao_height = from_fix(ao_k_height); + ao_speed = from_fix(ao_k_speed); + ao_accel = from_fix(ao_k_accel); + if (ao_height > ao_max_height) + ao_max_height = ao_height; + ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_sample_height; +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) + ao_avg_height = (ao_avg_height_scaled + 1) >> 1; + else if (ao_sample_tick - ao_sample_prev_tick > 5) + ao_avg_height = (ao_avg_height_scaled + 7) >> 4; + else +#endif + ao_avg_height = (ao_avg_height_scaled + 63) >> 7; +#ifdef AO_FLIGHT_TEST + ao_sample_prev_tick = ao_sample_tick; +#endif +} diff --git a/src/core/ao_log.c b/src/core/ao_log.c new file mode 100644 index 00000000..6d3ad535 --- /dev/null +++ b/src/core/ao_log.c @@ -0,0 +1,284 @@ +/* + * Copyright © 2009 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" + +__pdata uint32_t ao_log_current_pos; +__pdata uint32_t ao_log_end_pos; +__pdata uint32_t ao_log_start_pos; +__xdata uint8_t ao_log_running; +__pdata enum flight_state ao_log_state; +__xdata uint16_t ao_flight_number; + +__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL; + +void +ao_log_flush(void) +{ + ao_storage_flush(); +} + +/* + * When erasing a flight log, make sure the config block + * has an up-to-date version of the current flight number + */ + +struct ao_log_erase { + uint8_t unused; + uint16_t flight; +}; + +static __xdata struct ao_log_erase erase; + +#define LOG_MAX_ERASE 16 + +static uint32_t +ao_log_erase_pos(uint8_t i) +{ + return i * sizeof (struct ao_log_erase) + AO_STORAGE_ERASE_LOG; +} + +void +ao_log_write_erase(uint8_t pos) +{ + erase.unused = 0x00; + erase.flight = ao_flight_number; + ao_storage_write(ao_log_erase_pos(pos), &erase, sizeof (erase)); + ao_storage_flush(); +} + +static void +ao_log_read_erase(uint8_t pos) +{ + ao_storage_read(ao_log_erase_pos(pos), &erase, sizeof (erase)); +} + + +static void +ao_log_erase_mark(void) +{ + uint8_t i; + + for (i = 0; i < LOG_MAX_ERASE; i++) { + ao_log_read_erase(i); + if (erase.unused == 0 && erase.flight == ao_flight_number) + return; + if (erase.unused == 0xff) { + ao_log_write_erase(i); + return; + } + } + ao_config_put(); +} + +static uint8_t +ao_log_slots() +{ + return (uint8_t) (ao_storage_config / ao_config.flight_log_max); +} + +uint32_t +ao_log_pos(uint8_t slot) +{ + return ((slot) * ao_config.flight_log_max); +} + +static uint16_t +ao_log_max_flight(void) +{ + uint8_t log_slot; + uint8_t log_slots; + uint16_t log_flight; + uint16_t max_flight = 0; + + /* Scan the log space looking for the biggest flight number */ + log_slots = ao_log_slots(); + for (log_slot = 0; log_slot < log_slots; log_slot++) { + log_flight = ao_log_flight(log_slot); + if (!log_flight) + continue; + if (max_flight == 0 || (int16_t) (log_flight - max_flight) > 0) + max_flight = log_flight; + } + return max_flight; +} + +void +ao_log_scan(void) __reentrant +{ + uint8_t log_slot; + uint8_t log_slots; + uint8_t log_want; + + ao_config_get(); + + ao_flight_number = ao_log_max_flight(); + if (ao_flight_number) + if (++ao_flight_number == 0) + ao_flight_number = 1; + + /* Now look through the log of flight numbers from erase operations and + * see if the last one is bigger than what we found above + */ + for (log_slot = LOG_MAX_ERASE; log_slot-- > 0;) { + ao_log_read_erase(log_slot); + if (erase.unused == 0) { + if (ao_flight_number == 0 || + (int16_t) (erase.flight - ao_flight_number) > 0) + ao_flight_number = erase.flight; + break; + } + } + if (ao_flight_number == 0) + ao_flight_number = 1; + + /* With a flight number in hand, find a place to write a new log, + * use the target flight number to index the available log slots so + * that we write logs to each spot about the same number of times. + */ + + /* Find a log slot for the next flight, if available */ + ao_log_current_pos = ao_log_end_pos = 0; + log_slots = ao_log_slots(); + log_want = (ao_flight_number - 1) % log_slots; + log_slot = log_want; + do { + if (ao_log_flight(log_slot) == 0) { + ao_log_current_pos = ao_log_pos(log_slot); + ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; + break; + } + if (++log_slot >= log_slots) + log_slot = 0; + } while (log_slot != log_want); + + ao_wakeup(&ao_flight_number); +} + +void +ao_log_start(void) +{ + /* start logging */ + ao_log_running = 1; + ao_wakeup(&ao_log_running); +} + +void +ao_log_stop(void) +{ + ao_log_running = 0; + ao_log_flush(); +} + +uint8_t +ao_log_present(void) +{ + return ao_log_max_flight() != 0; +} + +uint8_t +ao_log_full(void) +{ + return ao_log_current_pos == ao_log_end_pos; +} + +static __xdata struct ao_task ao_log_task; + +void +ao_log_list(void) __reentrant +{ + uint8_t slot; + uint8_t slots; + uint16_t flight; + + slots = ao_log_slots(); + for (slot = 0; slot < slots; slot++) + { + flight = ao_log_flight(slot); + if (flight) + printf ("flight %d start %x end %x\n", + flight, + (uint16_t) (ao_log_pos(slot) >> 8), + (uint16_t) (ao_log_pos(slot+1) >> 8)); + } + printf ("done\n"); +} + +void +ao_log_delete(void) __reentrant +{ + uint8_t slot; + uint8_t slots; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + + slots = ao_log_slots(); + /* Look for the flight log matching the requested flight */ + if (ao_cmd_lex_i) { + for (slot = 0; slot < slots; slot++) { + if (ao_log_flight(slot) == ao_cmd_lex_i) { + ao_log_erase_mark(); + ao_log_current_pos = ao_log_pos(slot); + ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; + while (ao_log_current_pos < ao_log_end_pos) { + uint8_t i; + static __xdata uint8_t b; + + /* + * Check to see if we've reached the end of + * the used memory to avoid re-erasing the same + * memory over and over again + */ + for (i = 0; i < 16; i++) { + if (ao_storage_read(ao_log_current_pos + i, &b, 1)) + if (b != 0xff) + break; + } + if (i == 16) + break; + ao_storage_erase(ao_log_current_pos); + ao_log_current_pos += ao_storage_block; + } + puts("Erased"); + return; + } + } + } + printf("No such flight: %d\n", ao_cmd_lex_i); +} + +__code struct ao_cmds ao_log_cmds[] = { + { ao_log_list, "l\0List flight logs" }, + { ao_log_delete, "d \0Delete flight" }, + { 0, NULL }, +}; + +void +ao_log_init(void) +{ + ao_log_running = 0; + + /* For now, just log the flight starting at the begining of eeprom */ + ao_log_state = ao_flight_invalid; + + ao_cmd_register(&ao_log_cmds[0]); + + /* Create a task to log events to eeprom */ + ao_add_task(&ao_log_task, ao_log, "log"); +} diff --git a/src/core/ao_log_big.c b/src/core/ao_log_big.c new file mode 100644 index 00000000..74d94c4b --- /dev/null +++ b/src/core/ao_log_big.c @@ -0,0 +1,158 @@ +/* + * 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" + +static __xdata uint8_t ao_log_mutex; +static __xdata struct ao_log_record log; + +static uint8_t +ao_log_csum(__xdata uint8_t *b) __reentrant +{ + uint8_t sum = 0x5a; + uint8_t i; + + for (i = 0; i < sizeof (struct ao_log_record); i++) + sum += *b++; + return -sum; +} + +uint8_t +ao_log_data(__xdata struct ao_log_record *log) __reentrant +{ + uint8_t wrote = 0; + /* set checksum */ + log->csum = 0; + log->csum = ao_log_csum((__xdata uint8_t *) log); + ao_mutex_get(&ao_log_mutex); { + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + log, + sizeof (struct ao_log_record)); + ao_log_current_pos += sizeof (struct ao_log_record); + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_dump_check_data(void) +{ + if (ao_log_csum((uint8_t *) &log) != 0) + return 0; + return 1; +} + +static __data uint8_t ao_log_adc_pos; + +/* a hack to make sure that ao_log_records fill the eeprom block in even units */ +typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; + +#define AO_SENSOR_INTERVAL_ASCENT 1 +#define AO_SENSOR_INTERVAL_DESCENT 10 +#define AO_OTHER_INTERVAL 32 + +void +ao_log(void) +{ + __pdata uint16_t next_sensor, next_other; + + ao_storage_setup(); + + ao_log_scan(); + + while (!ao_log_running) + ao_sleep(&ao_log_running); + + log.type = AO_LOG_FLIGHT; + log.tick = ao_sample_tick; +#if HAS_ACCEL + log.u.flight.ground_accel = ao_ground_accel; +#endif + log.u.flight.flight = ao_flight_number; + ao_log_data(&log); + + /* Write the whole contents of the ring to the log + * when starting up. + */ + ao_log_adc_pos = ao_adc_ring_next(ao_sample_adc); + next_other = next_sensor = ao_adc_ring[ao_log_adc_pos].tick; + ao_log_state = ao_flight_startup; + for (;;) { + /* Write samples to EEPROM */ + while (ao_log_adc_pos != ao_sample_adc) { + log.tick = ao_adc_ring[ao_log_adc_pos].tick; + if ((int16_t) (log.tick - next_sensor) >= 0) { + log.type = AO_LOG_SENSOR; + log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; + log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; + ao_log_data(&log); + if (ao_log_state <= ao_flight_coast) + next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; + else + next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT; + } + if ((int16_t) (log.tick - next_other) >= 0) { + log.type = AO_LOG_TEMP_VOLT; + log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp; + log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt; + ao_log_data(&log); + log.type = AO_LOG_DEPLOY; + log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d; + log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m; + ao_log_data(&log); + next_other = log.tick + AO_OTHER_INTERVAL; + } + ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); + } + /* Write state change to EEPROM */ + if (ao_flight_state != ao_log_state) { + ao_log_state = ao_flight_state; + log.type = AO_LOG_STATE; + log.tick = ao_sample_tick; + log.u.state.state = ao_log_state; + log.u.state.reason = 0; + ao_log_data(&log); + + if (ao_log_state == ao_flight_landed) + ao_log_stop(); + } + + /* Wait for a while */ + ao_delay(AO_MS_TO_TICKS(100)); + + /* Stop logging when told to */ + while (!ao_log_running) + ao_sleep(&ao_log_running); + } +} + +uint16_t +ao_log_flight(uint8_t slot) +{ + if (!ao_storage_read(ao_log_pos(slot), + &log, + sizeof (struct ao_log_record))) + return 0; + + if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) + return log.u.flight.flight; + return 0; +} diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c new file mode 100644 index 00000000..1b472efe --- /dev/null +++ b/src/core/ao_log_telem.c @@ -0,0 +1,30 @@ +/* + * 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" + +void +ao_log_write_erase(uint8_t pos) +{ + (void) pos; +} + +uint8_t +ao_log_present(void) +{ + return 0; +} diff --git a/src/core/ao_log_tiny.c b/src/core/ao_log_tiny.c new file mode 100644 index 00000000..d5a3b99f --- /dev/null +++ b/src/core/ao_log_tiny.c @@ -0,0 +1,161 @@ +/* + * 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" + +static __data uint16_t ao_log_tiny_interval; + +#define AO_LOG_TINY_INTERVAL_DEFAULT AO_MS_TO_TICKS(1000) +#if USE_FAST_ASCENT_LOG +#define AO_LOG_TINY_INTERVAL_ASCENT AO_MS_TO_TICKS(100) +#define AO_PAD_RING 8 +#else +#define AO_LOG_TINY_INTERVAL_ASCENT AO_LOG_TINY_INTERVAL_DEFAULT +#define AO_PAD_RING 2 +#endif + +__code uint8_t ao_log_format = AO_LOG_FORMAT_TINY; + +void +ao_log_tiny_set_interval(uint16_t ticks) +{ + ao_log_tiny_interval = ticks; +} + + +static void ao_log_tiny_data(uint16_t d) +{ + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + ao_storage_write(ao_log_current_pos, DATA_TO_XDATA(&d), 2); + ao_log_current_pos += 2; + } +} + +static __xdata uint16_t ao_log_pad_ring[AO_PAD_RING]; +static __pdata uint8_t ao_log_pad_ring_pos; + +#define ao_pad_ring_next(n) (((n) + 1) & (AO_PAD_RING - 1)) + +static void ao_log_tiny_queue(uint16_t d) +{ + ao_log_pad_ring[ao_log_pad_ring_pos] = d; + ao_log_pad_ring_pos = ao_pad_ring_next(ao_log_pad_ring_pos); +} + +static void ao_log_tiny_start(void) +{ + uint8_t p; + uint16_t d; + + ao_log_tiny_data(ao_flight_number); + ao_log_tiny_data(ao_ground_pres); + p = ao_log_pad_ring_pos; + do { + d = ao_log_pad_ring[p]; + /* + * ignore unwritten slots + */ + if (d) + ao_log_tiny_data(d); + p = ao_pad_ring_next(p); + } while (p != ao_log_pad_ring_pos); +} + +void +ao_log(void) +{ + uint16_t last_time; + uint16_t now; + enum ao_flight_state ao_log_tiny_state; + int32_t sum; + int16_t count; + uint8_t ao_log_adc; + uint8_t ao_log_started = 0; + + ao_storage_setup(); + + ao_log_scan(); + + ao_log_tiny_state = ao_flight_invalid; + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; + sum = 0; + count = 0; + ao_log_adc = ao_sample_adc; + last_time = ao_time(); + for (;;) { + + /* + * Add in pending sample data + */ + ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); + while (ao_log_adc != ao_sample_adc) { + sum += ao_adc_ring[ao_log_adc].pres; + count++; + ao_log_adc = ao_adc_ring_next(ao_log_adc); + } + if (ao_log_running) { + if (!ao_log_started) { + ao_log_tiny_start(); + ao_log_started = 1; + } + if (ao_flight_state != ao_log_tiny_state) { + ao_log_tiny_data(ao_flight_state | 0x8000); + ao_log_tiny_state = ao_flight_state; + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; +#if AO_LOG_TINY_INTERVAL_ASCENT != AO_LOG_TINY_INTERVAL_DEFAULT + if (ao_log_tiny_state <= ao_flight_coast) + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; +#endif + if (ao_log_tiny_state == ao_flight_landed) + ao_log_stop(); + } + } + + /* Stop logging when told to */ + if (!ao_log_running && ao_log_started) + ao_exit(); + + /* + * Write out the sample when finished + */ + now = ao_time(); + if ((int16_t) (now - (last_time + ao_log_tiny_interval)) >= 0 && count) { + count = sum / count; + if (ao_log_started) + ao_log_tiny_data(count); + else + ao_log_tiny_queue(count); + sum = 0; + count = 0; + last_time = now; + } + } +} + +uint16_t +ao_log_flight(uint8_t slot) +{ + static __xdata uint16_t flight; + + (void) slot; + ao_storage_read(0, &flight, 2); + if (flight == 0xffff) + flight = 0; + return flight; +} diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c new file mode 100644 index 00000000..69eb58e8 --- /dev/null +++ b/src/core/ao_monitor.c @@ -0,0 +1,277 @@ +/* + * Copyright © 2009 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" +#include "ao_telem.h" + +#if !HAS_MONITOR +#error Must define HAS_MONITOR to 1 +#endif + +__xdata uint8_t ao_monitoring; +__pdata uint8_t ao_monitor_led; + +#define AO_MONITOR_RING 8 + +__xdata union ao_monitor { + struct ao_telemetry_raw_recv raw; + struct ao_telemetry_orig_recv orig; + struct ao_telemetry_tiny_recv tiny; +} ao_monitor_ring[AO_MONITOR_RING]; + +#define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) + +__data uint8_t ao_monitor_head; + +void +ao_monitor_get(void) +{ + uint8_t size; + + for (;;) { + switch (ao_monitoring) { + case 0: + ao_sleep(&ao_monitoring); + continue; + case AO_MONITORING_ORIG: + size = sizeof (struct ao_telemetry_orig_recv); + break; + case AO_MONITORING_TINY: + size = sizeof (struct ao_telemetry_tiny_recv); + break; + default: + if (ao_monitoring > AO_MAX_TELEMETRY) + ao_monitoring = AO_MAX_TELEMETRY; + size = ao_monitoring; + break; + } + if (!ao_radio_recv(&ao_monitor_ring[ao_monitor_head], size + 2)) + continue; + ao_monitor_head = ao_monitor_ring_next(ao_monitor_head); + ao_wakeup(DATA_TO_XDATA(&ao_monitor_head)); + ao_led_toggle(ao_monitor_led); + } +} + +void +ao_monitor_put(void) +{ + __xdata char callsign[AO_MAX_CALLSIGN+1]; + + uint8_t ao_monitor_tail; + uint8_t state; + uint8_t sum, byte; + int16_t rssi; + __xdata union ao_monitor *m; + +#define recv_raw ((m->raw)) +#define recv_orig ((m->orig)) +#define recv_tiny ((m->tiny)) + + ao_monitor_tail = ao_monitor_head; + for (;;) { + while (ao_monitor_tail == ao_monitor_head) + ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + m = &ao_monitor_ring[ao_monitor_tail]; + ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail); + switch (ao_monitoring) { + case AO_MONITORING_ORIG: + state = recv_orig.telemetry_orig.flight_state; + + /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ + rssi = (int16_t) (recv_orig.rssi >> 1) - 74; + memcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN); + if (state > ao_flight_invalid) + state = ao_flight_invalid; + if (recv_orig.status & PKT_APPEND_STATUS_1_CRC_OK) { + + /* General header fields */ + printf(AO_TELEM_VERSION " %d " + AO_TELEM_CALL " %s " + AO_TELEM_SERIAL " %d " + AO_TELEM_FLIGHT " %d " + AO_TELEM_RSSI " %d " + AO_TELEM_STATE " %s " + AO_TELEM_TICK " %d ", + AO_TELEMETRY_VERSION, + callsign, + recv_orig.telemetry_orig.serial, + recv_orig.telemetry_orig.flight, + rssi, + ao_state_names[state], + recv_orig.telemetry_orig.adc.tick); + + /* Raw sensor values */ + printf(AO_TELEM_RAW_ACCEL " %d " + AO_TELEM_RAW_BARO " %d " + AO_TELEM_RAW_THERMO " %d " + AO_TELEM_RAW_BATT " %d " + AO_TELEM_RAW_DROGUE " %d " + AO_TELEM_RAW_MAIN " %d ", + recv_orig.telemetry_orig.adc.accel, + recv_orig.telemetry_orig.adc.pres, + recv_orig.telemetry_orig.adc.temp, + recv_orig.telemetry_orig.adc.v_batt, + recv_orig.telemetry_orig.adc.sense_d, + recv_orig.telemetry_orig.adc.sense_m); + + /* Sensor calibration values */ + printf(AO_TELEM_CAL_ACCEL_GROUND " %d " + AO_TELEM_CAL_BARO_GROUND " %d " + AO_TELEM_CAL_ACCEL_PLUS " %d " + AO_TELEM_CAL_ACCEL_MINUS " %d ", + recv_orig.telemetry_orig.ground_accel, + recv_orig.telemetry_orig.ground_pres, + recv_orig.telemetry_orig.accel_plus_g, + recv_orig.telemetry_orig.accel_minus_g); + + if (recv_orig.telemetry_orig.u.k.unused == 0x8000) { + /* Kalman state values */ + printf(AO_TELEM_KALMAN_HEIGHT " %d " + AO_TELEM_KALMAN_SPEED " %d " + AO_TELEM_KALMAN_ACCEL " %d ", + recv_orig.telemetry_orig.height, + recv_orig.telemetry_orig.u.k.speed, + recv_orig.telemetry_orig.accel); + } else { + /* Ad-hoc flight values */ + printf(AO_TELEM_ADHOC_ACCEL " %d " + AO_TELEM_ADHOC_SPEED " %ld " + AO_TELEM_ADHOC_BARO " %d ", + recv_orig.telemetry_orig.accel, + recv_orig.telemetry_orig.u.flight_vel, + recv_orig.telemetry_orig.height); + } + ao_gps_print(&recv_orig.telemetry_orig.gps); + ao_gps_tracking_print(&recv_orig.telemetry_orig.gps_tracking); + putchar('\n'); + ao_rssi_set(rssi); + } else { + printf("CRC INVALID RSSI %3d\n", rssi); + } + break; + case AO_MONITORING_TINY: + state = recv_tiny.telemetry_tiny.flight_state; + + /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ + rssi = (int16_t) (recv_tiny.rssi >> 1) - 74; + memcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN); + if (state > ao_flight_invalid) + state = ao_flight_invalid; + if (recv_tiny.status & PKT_APPEND_STATUS_1_CRC_OK) { + /* General header fields */ + printf(AO_TELEM_VERSION " %d " + AO_TELEM_CALL " %s " + AO_TELEM_SERIAL " %d " + AO_TELEM_FLIGHT " %d " + AO_TELEM_RSSI " %d " + AO_TELEM_STATE " %s " + AO_TELEM_TICK " %d ", + AO_TELEMETRY_VERSION, + callsign, + recv_tiny.telemetry_tiny.serial, + recv_tiny.telemetry_tiny.flight, + rssi, + ao_state_names[state], + recv_tiny.telemetry_tiny.adc.tick); + + /* Raw sensor values */ + printf(AO_TELEM_RAW_BARO " %d " + AO_TELEM_RAW_THERMO " %d " + AO_TELEM_RAW_BATT " %d " + AO_TELEM_RAW_DROGUE " %d " + AO_TELEM_RAW_MAIN " %d ", + recv_tiny.telemetry_tiny.adc.pres, + recv_tiny.telemetry_tiny.adc.temp, + recv_tiny.telemetry_tiny.adc.v_batt, + recv_tiny.telemetry_tiny.adc.sense_d, + recv_tiny.telemetry_tiny.adc.sense_m); + + /* Sensor calibration values */ + printf(AO_TELEM_CAL_BARO_GROUND " %d ", + recv_tiny.telemetry_tiny.ground_pres); + +#if 1 + /* Kalman state values */ + printf(AO_TELEM_KALMAN_HEIGHT " %d " + AO_TELEM_KALMAN_SPEED " %d " + AO_TELEM_KALMAN_ACCEL " %d\n", + recv_tiny.telemetry_tiny.height, + recv_tiny.telemetry_tiny.speed, + recv_tiny.telemetry_tiny.accel); +#else + /* Ad-hoc flight values */ + printf(AO_TELEM_ADHOC_ACCEL " %d " + AO_TELEM_ADHOC_SPEED " %ld " + AO_TELEM_ADHOC_BARO " %d\n", + recv_tiny.telemetry_tiny.flight_accel, + recv_tiny.telemetry_tiny.flight_vel, + recv_tiny.telemetry_tiny.flight_pres); +#endif + ao_rssi_set(rssi); + } else { + printf("CRC INVALID RSSI %3d\n", rssi); + } + break; + default: + printf ("TELEM %02x", ao_monitoring + 2); + sum = 0x5a; + for (state = 0; state < ao_monitoring + 2; state++) { + byte = recv_raw.packet[state]; + sum += byte; + printf("%02x", byte); + } + printf("%02x\n", sum); + break; + } + ao_usb_flush(); + } +} + +__xdata struct ao_task ao_monitor_get_task; +__xdata struct ao_task ao_monitor_put_task; + +void +ao_set_monitor(uint8_t monitoring) +{ + if (ao_monitoring) + ao_radio_recv_abort(); + ao_monitoring = monitoring; + ao_wakeup(&ao_monitoring); +} + +static void +set_monitor(void) +{ + ao_cmd_hex(); + ao_set_monitor(ao_cmd_lex_i); +} + +__code struct ao_cmds ao_monitor_cmds[] = { + { set_monitor, "m <0 off, 1 full, 2 tiny>\0Enable/disable radio monitoring" }, + { 0, NULL }, +}; + +void +ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant +{ + ao_monitor_led = monitor_led; + ao_monitoring = monitoring; + ao_cmd_register(&ao_monitor_cmds[0]); + ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); + ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); +} diff --git a/src/core/ao_mutex.c b/src/core/ao_mutex.c new file mode 100644 index 00000000..c82a7d57 --- /dev/null +++ b/src/core/ao_mutex.c @@ -0,0 +1,41 @@ +/* + * Copyright © 2009 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" + +void +ao_mutex_get(__xdata uint8_t *mutex) __reentrant +{ + if (*mutex == ao_cur_task->task_id) + ao_panic(AO_PANIC_MUTEX); + __critical { + while (*mutex) + ao_sleep(mutex); + *mutex = ao_cur_task->task_id; + } +} + +void +ao_mutex_put(__xdata uint8_t *mutex) __reentrant +{ + if (*mutex != ao_cur_task->task_id) + ao_panic(AO_PANIC_MUTEX); + __critical { + *mutex = 0; + ao_wakeup(mutex); + } +} diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c new file mode 100644 index 00000000..fdada201 --- /dev/null +++ b/src/core/ao_panic.c @@ -0,0 +1,66 @@ +/* + * Copyright © 2009 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" + +#ifndef HAS_BEEP +#error Please define HAS_BEEP +#endif + +#if !HAS_BEEP +#define ao_beep(x) +#endif + +static void +ao_panic_delay(uint8_t n) +{ + uint8_t i = 0, j = 0; + + while (n--) + while (--j) + while (--i) + _asm nop _endasm; +} + +void +ao_panic(uint8_t reason) +{ + uint8_t n; + + __critical for (;;) { + ao_panic_delay(20); + for (n = 0; n < 5; n++) { + ao_led_on(AO_LED_RED); + ao_beep(AO_BEEP_HIGH); + ao_panic_delay(1); + ao_led_off(AO_LED_RED); + ao_beep(AO_BEEP_LOW); + ao_panic_delay(1); + } + ao_beep(AO_BEEP_OFF); + ao_panic_delay(2); +#pragma disable_warning 126 + for (n = 0; n < reason; n++) { + ao_led_on(AO_LED_RED); + ao_beep(AO_BEEP_MID); + ao_panic_delay(10); + ao_led_off(AO_LED_RED); + ao_beep(AO_BEEP_OFF); + ao_panic_delay(10); + } + } +} diff --git a/src/core/ao_pins.h b/src/core/ao_pins.h new file mode 100644 index 00000000..e1f5459f --- /dev/null +++ b/src/core/ao_pins.h @@ -0,0 +1,408 @@ +/* + * Copyright © 2010 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_PINS_H_ +#define _AO_PINS_H_ + +#if defined(TELEMETRUM_V_1_0) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define HAS_ADC 1 + #define USE_SERIAL_STDIN 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #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 + #define HAS_ACCEL_REF 0 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEMETRUM_V_1_1) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #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 + #define HAS_ACCEL_REF 1 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEDONGLE_V_0_2) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEMINI_V_1_0) + #define HAS_FLIGHT 1 + #define HAS_USB 0 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 + #define HAS_DBG 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 1 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define USE_FAST_ASCENT_LOG 1 + + #define AO_LED_GREEN 1 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELENANO_V_0_1) + #define HAS_FLIGHT 1 + #define HAS_USB 0 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 + #define HAS_DBG 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 1 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define AO_LED_GREEN 1 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEMETRUM_V_0_1) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_DBG 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 1 + #define HAS_ACCEL_REF 0 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEDONGLE_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 0 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TIDONGLE) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED) + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEBT_V_0_0) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define HAS_BTM 1 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_IGNITE 0 + #define BT_LINK_ON_P2 1 + #define BT_LINK_ON_P1 0 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P2_1 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEBT_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_SERIAL_1 1 + #define HAS_SERIAL_1_ALT_1 1 + #define HAS_SERIAL_1_ALT_2 0 + #define HAS_SERIAL_1_HW_FLOW 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_BTM 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x04 /* CS0 is P1_2 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define BT_LINK_ON_P2 0 + #define BT_LINK_ON_P1 1 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P1_7 + #define HAS_MONITOR 1 +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#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 + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif +#endif /* _AO_PINS_H_ */ diff --git a/src/core/ao_product.c b/src/core/ao_product.c new file mode 100644 index 00000000..fb59580b --- /dev/null +++ b/src/core/ao_product.c @@ -0,0 +1,155 @@ +/* + * Copyright © 2009 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" +#include "ao_product.h" + +/* Defines which mark this particular AltOS product */ + +const char ao_version[AO_MAX_VERSION] = AO_iVersion_STRING; +const char ao_manufacturer[] = AO_iManufacturer_STRING; +const char ao_product[] = AO_iProduct_STRING; + +#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) + +#if HAS_USB +#include "ao_usb.h" +/* USB descriptors in one giant block of bytes */ +__code __at(0x00aa) uint8_t ao_usb_descriptors [] = +{ + /* Device descriptor */ + 0x12, + AO_USB_DESC_DEVICE, + LE_WORD(0x0110), /* bcdUSB */ + 0x02, /* bDeviceClass */ + 0x00, /* bDeviceSubClass */ + 0x00, /* bDeviceProtocol */ + AO_USB_CONTROL_SIZE, /* bMaxPacketSize */ + LE_WORD(0xFFFE), /* idVendor */ + LE_WORD(AO_idProduct_NUMBER), /* idProduct */ + LE_WORD(0x0100), /* bcdDevice */ + 0x01, /* iManufacturer */ + 0x02, /* iProduct */ + 0x03, /* iSerialNumber */ + 0x01, /* bNumConfigurations */ + + /* Configuration descriptor */ + 0x09, + AO_USB_DESC_CONFIGURATION, + LE_WORD(67), /* wTotalLength */ + 0x02, /* bNumInterfaces */ + 0x01, /* bConfigurationValue */ + 0x00, /* iConfiguration */ + 0xC0, /* bmAttributes */ + 0x32, /* bMaxPower */ + + /* Control class interface */ + 0x09, + AO_USB_DESC_INTERFACE, + 0x00, /* bInterfaceNumber */ + 0x00, /* bAlternateSetting */ + 0x01, /* bNumEndPoints */ + 0x02, /* bInterfaceClass */ + 0x02, /* bInterfaceSubClass */ + 0x01, /* bInterfaceProtocol, linux requires value of 1 for the cdc_acm module */ + 0x00, /* iInterface */ + + /* Header functional descriptor */ + 0x05, + CS_INTERFACE, + 0x00, /* bDescriptor SubType Header */ + LE_WORD(0x0110), /* CDC version 1.1 */ + + /* Call management functional descriptor */ + 0x05, + CS_INTERFACE, + 0x01, /* bDescriptor SubType Call Management */ + 0x01, /* bmCapabilities = device handles call management */ + 0x01, /* bDataInterface call management interface number */ + + /* ACM functional descriptor */ + 0x04, + CS_INTERFACE, + 0x02, /* bDescriptor SubType Abstract Control Management */ + 0x02, /* bmCapabilities = D1 (Set_line_Coding, Set_Control_Line_State, Get_Line_Coding and Serial_State) */ + + /* Union functional descriptor */ + 0x05, + CS_INTERFACE, + 0x06, /* bDescriptor SubType Union Functional descriptor */ + 0x00, /* bMasterInterface */ + 0x01, /* bSlaveInterface0 */ + + /* Notification EP */ + 0x07, + AO_USB_DESC_ENDPOINT, + AO_USB_INT_EP|0x80, /* bEndpointAddress */ + 0x03, /* bmAttributes = intr */ + LE_WORD(8), /* wMaxPacketSize */ + 0x0A, /* bInterval */ + + /* Data class interface descriptor */ + 0x09, + AO_USB_DESC_INTERFACE, + 0x01, /* bInterfaceNumber */ + 0x00, /* bAlternateSetting */ + 0x02, /* bNumEndPoints */ + 0x0A, /* bInterfaceClass = data */ + 0x00, /* bInterfaceSubClass */ + 0x00, /* bInterfaceProtocol */ + 0x00, /* iInterface */ + + /* Data EP OUT */ + 0x07, + AO_USB_DESC_ENDPOINT, + AO_USB_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes = bulk */ + LE_WORD(AO_USB_OUT_SIZE),/* wMaxPacketSize */ + 0x00, /* bInterval */ + + /* Data EP in */ + 0x07, + AO_USB_DESC_ENDPOINT, + AO_USB_IN_EP|0x80, /* bEndpointAddress */ + 0x02, /* bmAttributes = bulk */ + LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */ + 0x00, /* bInterval */ + + /* String descriptors */ + 0x04, + AO_USB_DESC_STRING, + LE_WORD(0x0409), + + /* iManufacturer */ + AO_iManufacturer_LEN, + AO_USB_DESC_STRING, + AO_iManufacturer_UCS2, + + /* iProduct */ + AO_iProduct_LEN, + AO_USB_DESC_STRING, + AO_iProduct_UCS2, + + /* iSerial */ + AO_iSerial_LEN, + AO_USB_DESC_STRING, + AO_iSerial_UCS2, + + /* Terminating zero */ + 0 +}; +#endif diff --git a/src/core/ao_report.c b/src/core/ao_report.c new file mode 100644 index 00000000..3cf558e1 --- /dev/null +++ b/src/core/ao_report.c @@ -0,0 +1,180 @@ +/* + * Copyright © 2009 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 BIT(i,x) ((x) ? (1 << (i)) : 0) +#define MORSE1(a) (1 | BIT(3,a)) +#define MORSE2(a,b) (2 | BIT(3,a) | BIT(4,b)) +#define MORSE3(a,b,c) (3 | BIT(3,a) | BIT(4,b) | BIT(5,c)) +#define MORSE4(a,b,c,d) (4 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d)) +#define MORSE5(a,b,c,d,e) (5 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d) | BIT(7,e)) + +static const uint8_t flight_reports[] = { + MORSE3(0,0,0), /* startup, 'S' */ + MORSE2(0,0), /* idle 'I' */ + MORSE4(0,1,1,0), /* pad 'P' */ + MORSE4(1,0,0,0), /* boost 'B' */ + MORSE4(0,0,1,0), /* fast 'F' */ + MORSE4(1,0,1,0), /* coast 'C' */ + MORSE3(1,0,0), /* drogue 'D' */ + MORSE2(1,1), /* main 'M' */ + MORSE4(0,1,0,0), /* landed 'L' */ + MORSE4(1,0,0,1), /* invalid 'X' */ +}; + +#if HAS_BEEP +#define low(time) ao_beep_for(AO_BEEP_LOW, time) +#define mid(time) ao_beep_for(AO_BEEP_MID, time) +#define high(time) ao_beep_for(AO_BEEP_HIGH, time) +#else +#define low(time) ao_led_for(AO_LED_GREEN, time) +#define mid(time) ao_led_for(AO_LED_RED, time) +#define high(time) ao_led_for(AO_LED_GREEN|AO_LED_RED, time) +#endif +#define pause(time) ao_delay(time) + +static __pdata enum ao_flight_state ao_report_state; + +static void +ao_report_beep(void) __reentrant +{ + uint8_t r = flight_reports[ao_flight_state]; + uint8_t l = r & 7; + + if (!r) + return; + while (l--) { + if (r & 8) + mid(AO_MS_TO_TICKS(600)); + else + mid(AO_MS_TO_TICKS(200)); + pause(AO_MS_TO_TICKS(200)); + r >>= 1; + } + pause(AO_MS_TO_TICKS(400)); +} + +static void +ao_report_digit(uint8_t digit) __reentrant +{ + if (!digit) { + mid(AO_MS_TO_TICKS(500)); + pause(AO_MS_TO_TICKS(200)); + } else { + while (digit--) { + mid(AO_MS_TO_TICKS(200)); + pause(AO_MS_TO_TICKS(200)); + } + } + pause(AO_MS_TO_TICKS(300)); +} + +static void +ao_report_altitude(void) +{ + __pdata int16_t agl = ao_max_height; + __xdata uint8_t digits[10]; + __pdata uint8_t ndigits, i; + + if (agl < 0) + agl = 0; + ndigits = 0; + do { + digits[ndigits++] = agl % 10; + agl /= 10; + } while (agl); + + for (;;) { + ao_report_beep(); + i = ndigits; + do + ao_report_digit(digits[--i]); + while (i != 0); + pause(AO_SEC_TO_TICKS(5)); + } +} + +#if HAS_IGNITE +static uint8_t +ao_report_igniter_ready(enum ao_igniter igniter) +{ + return ao_igniter_status(igniter) == ao_igniter_ready ? 1 : 0; +} + +static void +ao_report_continuity(void) __reentrant +{ + uint8_t c = (ao_report_igniter_ready(ao_igniter_drogue) | + (ao_report_igniter_ready(ao_igniter_main) << 1)); + if (c) { + while (c--) { + high(AO_MS_TO_TICKS(25)); + pause(AO_MS_TO_TICKS(100)); + } + } else { + c = 10; + while (c--) { + high(AO_MS_TO_TICKS(20)); + low(AO_MS_TO_TICKS(20)); + } + } + if (ao_log_full()) { + pause(AO_MS_TO_TICKS(100)); + c = 2; + while (c--) { + low(AO_MS_TO_TICKS(100)); + mid(AO_MS_TO_TICKS(100)); + high(AO_MS_TO_TICKS(100)); + mid(AO_MS_TO_TICKS(100)); + } + } + c = 50; + while (c-- && ao_flight_state == ao_flight_pad) + pause(AO_MS_TO_TICKS(100)); +} +#endif + +void +ao_report(void) +{ + ao_report_state = ao_flight_state; + for(;;) { + if (ao_flight_state == ao_flight_landed) + ao_report_altitude(); + ao_report_beep(); +#if HAS_IGNITE + if (ao_flight_state == ao_flight_idle) + ao_report_continuity(); + while (ao_flight_state == ao_flight_pad) + ao_report_continuity(); +#endif + __critical { + while (ao_report_state == ao_flight_state) + ao_sleep(DATA_TO_XDATA(&ao_flight_state)); + ao_report_state = ao_flight_state; + } + } +} + +static __xdata struct ao_task ao_report_task; + +void +ao_report_init(void) +{ + ao_add_task(&ao_report_task, ao_report, "report"); +} diff --git a/src/core/ao_rssi.c b/src/core/ao_rssi.c new file mode 100644 index 00000000..e3964d2d --- /dev/null +++ b/src/core/ao_rssi.c @@ -0,0 +1,53 @@ +/* + * Copyright © 2009 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" + +static __xdata volatile uint16_t ao_rssi_time; +static __pdata volatile uint16_t ao_rssi_delay; +static __pdata uint8_t ao_rssi_led; + +void +ao_rssi(void) +{ + for (;;) { + while ((int16_t) (ao_time() - ao_rssi_time) > AO_SEC_TO_TICKS(3)) + ao_sleep(&ao_rssi_time); + ao_led_for(ao_rssi_led, AO_MS_TO_TICKS(100)); + ao_delay(ao_rssi_delay); + } +} + +void +ao_rssi_set(int rssi_value) +{ + if (rssi_value > 0) + rssi_value = 0; + ao_rssi_delay = AO_MS_TO_TICKS((-rssi_value) * 5); + ao_rssi_time = ao_time(); + ao_wakeup(&ao_rssi_time); +} + +__xdata struct ao_task ao_rssi_task; + +void +ao_rssi_init(uint8_t rssi_led) +{ + ao_rssi_led = rssi_led; + ao_rssi_delay = 0; + ao_add_task(&ao_rssi_task, ao_rssi, "rssi"); +} diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c new file mode 100644 index 00000000..b2b8e9f6 --- /dev/null +++ b/src/core/ao_sample.c @@ -0,0 +1,209 @@ +/* + * 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. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#endif + +/* + * Current sensor values + */ + +__pdata uint16_t ao_sample_tick; /* time of last data */ +__pdata int16_t ao_sample_pres; +__pdata int16_t ao_sample_alt; +__pdata int16_t ao_sample_height; +#if HAS_ACCEL +__pdata int16_t ao_sample_accel; +#endif + +__data uint8_t ao_sample_adc; + +/* + * Sensor calibration values + */ + +__pdata int16_t ao_ground_pres; /* startup pressure */ +__pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +__pdata int16_t ao_ground_accel; /* startup acceleration */ +__pdata int16_t ao_accel_2g; /* factory accel calibration */ +__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +static __pdata uint8_t ao_preflight; /* in preflight mode */ + +static __pdata uint16_t nsamples; +__pdata int32_t ao_sample_pres_sum; +#if HAS_ACCEL +__pdata int32_t ao_sample_accel_sum; +#endif + +static void +ao_sample_preflight(void) +{ + /* startup state: + * + * Collect 512 samples of acceleration and pressure + * data and average them to find the resting values + */ + if (nsamples < 512) { +#if HAS_ACCEL + ao_sample_accel_sum += ao_sample_accel; +#endif + ao_sample_pres_sum += ao_sample_pres; + ++nsamples; + } else { + ao_config_get(); +#if HAS_ACCEL + ao_ground_accel = ao_sample_accel_sum >> 9; + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; +#endif + ao_ground_pres = ao_sample_pres_sum >> 9; + ao_ground_height = ao_pres_to_altitude(ao_ground_pres); + ao_preflight = FALSE; + } +} + +uint8_t +ao_sample(void) +{ + ao_wakeup(DATA_TO_XDATA(&ao_sample_adc)); + ao_sleep(DATA_TO_XDATA(&ao_adc_head)); + while (ao_sample_adc != ao_adc_head) { + __xdata struct ao_adc *ao_adc; + + /* Capture a sample */ + ao_adc = &ao_adc_ring[ao_sample_adc]; + ao_sample_tick = ao_adc->tick; + ao_sample_pres = ao_adc->pres; + ao_sample_alt = ao_pres_to_altitude(ao_sample_pres); + ao_sample_height = ao_sample_alt - ao_ground_height; +#if HAS_ACCEL + ao_sample_accel = ao_adc->accel; +#if HAS_ACCEL_REF + /* + * Ok, the math here is a bit tricky. + * + * ao_sample_accel: ADC output for acceleration + * ao_accel_ref: ADC output for the 5V reference. + * ao_cook_accel: Corrected acceleration value + * Vcc: 3.3V supply to the CC1111 + * Vac: 5V supply to the accelerometer + * accel: input voltage to accelerometer ADC pin + * ref: input voltage to 5V reference ADC pin + * + * + * Measured acceleration is ratiometric to Vcc: + * + * ao_sample_accel accel + * ------------ = ----- + * 32767 Vcc + * + * Measured 5v reference is also ratiometric to Vcc: + * + * ao_accel_ref ref + * ------------ = ----- + * 32767 Vcc + * + * + * ao_accel_ref = 32767 * (ref / Vcc) + * + * Acceleration is measured ratiometric to the 5V supply, + * so what we want is: + * + * ao_cook_accel accel + * ------------- = ----- + * 32767 ref + * + * + * accel Vcc + * = ----- * --- + * Vcc ref + * + * ao_sample_accel 32767 + * = ------------ * ------------ + * 32767 ao_accel_ref + * + * Multiply through by 32767: + * + * ao_sample_accel * 32767 + * ao_cook_accel = -------------------- + * ao_accel_ref + * + * Now, the tricky part. Getting this to compile efficiently + * and keeping all of the values in-range. + * + * First off, we need to use a shift of 16 instead of * 32767 as SDCC + * does the obvious optimizations for byte-granularity shifts: + * + * ao_cook_accel = (ao_sample_accel << 16) / ao_accel_ref + * + * Next, lets check our input ranges: + * + * 0 <= ao_sample_accel <= 0x7fff (singled ended ADC conversion) + * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) + * + * Plugging in our input ranges, we get an output range of 0 - 0x12490, + * which is 17 bits. That won't work. If we take the accel ref and shift + * by a bit, we'll change its range: + * + * 0xe000 <= ao_accel_ref<<1 <= 0xfffe + * + * ao_cook_accel = (ao_sample_accel << 16) / (ao_accel_ref << 1) + * + * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It + * is, however, one bit too large for our signed computations. So, we + * take the result and shift that by a bit: + * + * ao_cook_accel = ((ao_sample_accel << 16) / (ao_accel_ref << 1)) >> 1 + * + * This finally creates an output range of 0 - 0x4924. As the ADC only + * provides 11 bits of data, we haven't actually lost any precision, + * just dropped a bit of noise off the low end. + */ + ao_sample_accel = (uint16_t) ((((uint32_t) ao_sample_accel << 16) / (ao_accel_ref[ao_sample_adc] << 1))) >> 1; + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) + ao_sample_accel = 0x7fff - ao_sample_accel; + ao_adc->accel = ao_sample_accel; +#endif +#endif + + if (ao_preflight) + ao_sample_preflight(); + else + ao_kalman(); + ao_sample_adc = ao_adc_ring_next(ao_sample_adc); + } + return !ao_preflight; +} + +void +ao_sample_init(void) +{ + nsamples = 0; + ao_sample_pres_sum = 0; + ao_sample_pres = 0; +#if HAS_ACCEL + ao_sample_accel_sum = 0; + ao_sample_accel = 0; +#endif + ao_sample_adc = ao_adc_head; + ao_preflight = TRUE; +} diff --git a/src/core/ao_state.c b/src/core/ao_state.c new file mode 100644 index 00000000..ed197aa5 --- /dev/null +++ b/src/core/ao_state.c @@ -0,0 +1,23 @@ +/* + * Copyright © 2009 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" + +const char const * const ao_state_names[] = { + "startup", "idle", "pad", "boost", "fast", + "coast", "drogue", "main", "landed", "invalid" +}; diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c new file mode 100644 index 00000000..c0138a30 --- /dev/null +++ b/src/core/ao_stdio.c @@ -0,0 +1,84 @@ +/* + * Copyright © 2009 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" + +/* + * Basic I/O functions to support SDCC stdio package + */ + +#define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) + +__xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS]; +__pdata int8_t ao_cur_stdio; +__pdata int8_t ao_num_stdios; + +void +putchar(char c) +{ + if (c == '\n') + (*ao_stdios[ao_cur_stdio].putchar)('\r'); + (*ao_stdios[ao_cur_stdio].putchar)(c); +} + +void +flush(void) +{ + if (ao_stdios[ao_cur_stdio].flush) + ao_stdios[ao_cur_stdio].flush(); +} + +__xdata uint8_t ao_stdin_ready; + +char +getchar(void) __reentrant __critical +{ + char c; + int8_t stdio = ao_cur_stdio; + + for (;;) { + c = ao_stdios[stdio].pollchar(); + if (c != AO_READ_AGAIN) + break; + if (++stdio == ao_num_stdios) + stdio = 0; + if (stdio == ao_cur_stdio) + ao_sleep(&ao_stdin_ready); + } + ao_cur_stdio = stdio; + return c; +} + +uint8_t +ao_echo(void) +{ + return ao_stdios[ao_cur_stdio].echo; +} + +int8_t +ao_add_stdio(char (*pollchar)(void), + void (*putchar)(char), + void (*flush)(void)) __reentrant +{ + if (ao_num_stdios == AO_NUM_STDIOS) + ao_panic(AO_PANIC_STDIO); + ao_stdios[ao_num_stdios].pollchar = pollchar; + ao_stdios[ao_num_stdios].putchar = putchar; + ao_stdios[ao_num_stdios].flush = flush; + ao_stdios[ao_num_stdios].echo = 1; + return ao_num_stdios++; +} diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c new file mode 100644 index 00000000..6ffca0e5 --- /dev/null +++ b/src/core/ao_storage.c @@ -0,0 +1,184 @@ +/* + * 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" + +uint8_t +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t this_len; + uint16_t this_off; + + ao_storage_setup(); + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + while (len) { + + /* Compute portion of transfer within + * a single block + */ + this_off = (uint16_t) pos & (ao_storage_unit - 1); + this_len = ao_storage_unit - this_off; + if (this_len > len) + this_len = len; + + if (!ao_storage_device_read(pos, buf, this_len)) + return 0; + + /* See how much is left */ + buf += this_len; + len -= this_len; + pos += this_len; + } + return 1; +} + +uint8_t +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t this_len; + uint16_t this_off; + + ao_storage_setup(); + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + while (len) { + + /* Compute portion of transfer within + * a single block + */ + this_off = (uint16_t) pos & (ao_storage_unit - 1); + this_len = ao_storage_unit - this_off; + if (this_len > len) + this_len = len; + + if (!ao_storage_device_write(pos, buf, this_len)) + return 0; + + /* See how much is left */ + buf += this_len; + len -= this_len; + pos += this_len; + } + return 1; +} + +static __xdata uint8_t storage_data[8]; + +static void +ao_storage_dump(void) __reentrant +{ + uint8_t i, j; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + for (i = 0; ; i += 8) { + if (ao_storage_read(((uint32_t) (ao_cmd_lex_i) << 8) + i, + storage_data, + 8)) { + ao_cmd_put16((uint16_t) i); + for (j = 0; j < 8; j++) { + putchar(' '); + ao_cmd_put8(storage_data[j]); + } + putchar ('\n'); + } + if (i == 248) + break; + } +} + +#if 0 + +/* not enough space for this today + */ +static void +ao_storage_store(void) __reentrant +{ + uint16_t block; + uint8_t i; + uint16_t len; + static __xdata uint8_t b; + uint32_t addr; + + ao_cmd_hex(); + block = ao_cmd_lex_i; + ao_cmd_hex(); + i = ao_cmd_lex_i; + addr = ((uint32_t) block << 8) | i; + ao_cmd_hex(); + len = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + while (len--) { + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + b = ao_cmd_lex_i; + ao_storage_write(addr, &b, 1); + addr++; + } +} +#endif + +void +ao_storage_zap(void) __reentrant +{ + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_storage_erase((uint32_t) ao_cmd_lex_i << 8); +} + +void +ao_storage_zapall(void) __reentrant +{ + uint32_t pos; + + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) + ao_storage_erase(pos); +} + +void +ao_storage_info(void) __reentrant +{ + printf("Storage size: %ld\n", ao_storage_total); + printf("Storage erase unit: %ld\n", ao_storage_block); + ao_storage_device_info(); +} + +__code struct ao_cmds ao_storage_cmds[] = { + { ao_storage_info, "f\0Show storage" }, + { ao_storage_dump, "e \0Dump flash" }, +#ifdef HAS_STORAGE_DBG + { ao_storage_store, "w ...\0Write data to flash" }, +#endif + { ao_storage_zap, "z \0Erase " }, + { ao_storage_zapall,"Z \0Erase all. is doit with D&I" }, + { 0, NULL }, +}; + +void +ao_storage_init(void) +{ + ao_storage_device_init(); + ao_cmd_register(&ao_storage_cmds[0]); +} diff --git a/src/core/ao_task.c b/src/core/ao_task.c new file mode 100644 index 00000000..f5850fa4 --- /dev/null +++ b/src/core/ao_task.c @@ -0,0 +1,275 @@ +/* + * Copyright © 2009 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 AO_NO_TASK_INDEX 0xff + +__xdata struct ao_task * __xdata ao_tasks[AO_NUM_TASKS]; +__data uint8_t ao_num_tasks; +__data uint8_t ao_cur_task_index; +__xdata struct ao_task *__data ao_cur_task; + +void +ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant +{ + uint8_t __xdata *stack; + uint8_t task_id; + uint8_t t; + if (ao_num_tasks == AO_NUM_TASKS) + ao_panic(AO_PANIC_NO_TASK); + for (task_id = 1; task_id != 0; task_id++) { + for (t = 0; t < ao_num_tasks; t++) + if (ao_tasks[t]->task_id == task_id) + break; + if (t == ao_num_tasks) + break; + } + ao_tasks[ao_num_tasks++] = task; + task->task_id = task_id; + task->name = name; + /* + * Construct a stack frame so that it will 'return' + * to the start of the task + */ + stack = task->stack; + + *stack++ = ((uint16_t) start); /* 0 */ + *stack++ = ((uint16_t) start) >> 8; /* 1 */ + + /* and the stuff saved by ao_switch */ + *stack++ = 0; /* 2 acc */ + *stack++ = 0x80; /* 3 IE */ + + /* 4 DPL + * 5 DPH + * 6 B + * 7 R2 + * 8 R3 + * 9 R4 + * 10 R5 + * 11 R6 + * 12 R7 + * 13 R0 + * 14 R1 + * 15 PSW + * 16 BP + */ + for (t = 0; t < 13; t++) + *stack++ = 0; + + task->stack_count = 17; + task->wchan = NULL; +} + +/* Task switching function. This must not use any stack variables */ +void +ao_yield(void) __naked +{ + + /* Save current context */ + _asm + /* Push ACC first, as when restoring the context it must be restored + * last (it is used to set the IE register). */ + push ACC + /* Store the IE register then enable interrupts. */ + push _IEN0 + setb _EA + push DPL + push DPH + push b + push ar2 + push ar3 + push ar4 + push ar5 + push ar6 + push ar7 + push ar0 + push ar1 + push PSW + _endasm; + PSW = 0; + _asm + push _bp + _endasm; + + if (ao_cur_task_index == AO_NO_TASK_INDEX) + ao_cur_task_index = ao_num_tasks-1; + else + { + uint8_t stack_len; + __data uint8_t *stack_ptr; + __xdata uint8_t *save_ptr; + /* Save the current stack */ + stack_len = SP - (AO_STACK_START - 1); + ao_cur_task->stack_count = stack_len; + stack_ptr = (uint8_t __data *) AO_STACK_START; + save_ptr = (uint8_t __xdata *) ao_cur_task->stack; + do + *save_ptr++ = *stack_ptr++; + while (--stack_len); + } + + /* Empty the stack; might as well let interrupts have the whole thing */ + SP = AO_STACK_START - 1; + + /* 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; + for (;;) { + ++ao_next_task_index; + if (ao_next_task_index == ao_num_tasks) + ao_next_task_index = 0; + + ao_cur_task = ao_tasks[ao_next_task_index]; + if (ao_cur_task->wchan == NULL) { + ao_cur_task_index = ao_next_task_index; + 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; + break; + } + + /* Enter lower power mode when there isn't anything to do */ + if (ao_next_task_index == ao_cur_task_index) + PCON = PCON_IDLE; + } + } + + { + uint8_t stack_len; + __data uint8_t *stack_ptr; + __xdata uint8_t *save_ptr; + + /* Restore the old stack */ + stack_len = ao_cur_task->stack_count; + SP = AO_STACK_START - 1 + stack_len; + + stack_ptr = (uint8_t __data *) AO_STACK_START; + save_ptr = (uint8_t __xdata *) ao_cur_task->stack; + do + *stack_ptr++ = *save_ptr++; + while (--stack_len); + } + + _asm + pop _bp + pop PSW + pop ar1 + pop ar0 + pop ar7 + pop ar6 + pop ar5 + pop ar4 + pop ar3 + pop ar2 + pop b + pop DPH + pop DPL + /* The next byte of the stack is the IE register. Only the global + enable bit forms part of the task context. Pop off the IE then set + the global enable bit to match that of the stored IE register. */ + pop ACC + JB ACC.7,0098$ + CLR _EA + LJMP 0099$ + 0098$: + SETB _EA + 0099$: + /* Finally pop off the ACC, which was the first register saved. */ + pop ACC + ret + _endasm; +} + +uint8_t +ao_sleep(__xdata void *wchan) +{ + __critical { + ao_cur_task->wchan = wchan; + } + ao_yield(); + ao_cur_task->alarm = 0; + if (ao_cur_task->wchan) { + ao_cur_task->wchan = NULL; + return 1; + } + return 0; +} + +void +ao_wakeup(__xdata void *wchan) +{ + uint8_t i; + + for (i = 0; i < ao_num_tasks; i++) + if (ao_tasks[i]->wchan == wchan) + ao_tasks[i]->wchan = NULL; +} + +void +ao_alarm(uint16_t delay) +{ + /* Make sure we sleep *at least* delay ticks, which means adding + * one to account for the fact that we may be close to the next tick + */ + if (!(ao_cur_task->alarm = ao_time() + delay + 1)) + ao_cur_task->alarm = 1; +} + +void +ao_exit(void) __critical +{ + uint8_t i; + ao_num_tasks--; + for (i = ao_cur_task_index; i < ao_num_tasks; i++) + ao_tasks[i] = ao_tasks[i+1]; + ao_cur_task_index = AO_NO_TASK_INDEX; + ao_yield(); + /* we'll never get back here */ +} + +void +ao_task_info(void) +{ + uint8_t i; + uint8_t pc_loc; + __xdata struct ao_task *task; + + for (i = 0; i < ao_num_tasks; i++) { + task = ao_tasks[i]; + pc_loc = task->stack_count - 17; + printf("%12s: wchan %04x pc %04x\n", + task->name, + (int16_t) task->wchan, + (task->stack[pc_loc]) | (task->stack[pc_loc+1] << 8)); + } +} + +void +ao_start_scheduler(void) +{ + ao_cur_task_index = AO_NO_TASK_INDEX; + ao_cur_task = NULL; + ao_yield(); +} diff --git a/src/core/ao_telem.h b/src/core/ao_telem.h new file mode 100644 index 00000000..1a8da291 --- /dev/null +++ b/src/core/ao_telem.h @@ -0,0 +1,172 @@ +/* + * 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. + */ + +#ifndef _AO_TELEM_H_ +#define _AO_TELEM_H_ + +#define AO_TELEMETRY_VERSION 4 + +/* + * Telemetry version 4 and higher format: + * + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + */ + +#define AO_TELEM_VERSION "VERSION" +#define AO_TELEM_CALL "c" +#define AO_TELEM_SERIAL "n" +#define AO_TELEM_FLIGHT "f" +#define AO_TELEM_RSSI "r" +#define AO_TELEM_STATE "s" +#define AO_TELEM_TICK "t" + +/* + * Raw sensor values + * + * Name Value + * r_a Accelerometer reading (integer) + * r_b Barometer reading (integer) + * r_t Thermometer reading (integer) + * r_v Battery reading (integer) + * r_d Drogue continuity (integer) + * r_m Main continuity (integer) + */ + +#define AO_TELEM_RAW_ACCEL "r_a" +#define AO_TELEM_RAW_BARO "r_b" +#define AO_TELEM_RAW_THERMO "r_t" +#define AO_TELEM_RAW_BATT "r_v" +#define AO_TELEM_RAW_DROGUE "r_d" +#define AO_TELEM_RAW_MAIN "r_m" + +/* + * Sensor calibration values + * + * Name Value + * c_a Ground accelerometer reading (integer) + * c_b Ground barometer reading (integer) + * c_p Accelerometer reading for +1g + * c_m Accelerometer reading for -1g + */ + +#define AO_TELEM_CAL_ACCEL_GROUND "c_a" +#define AO_TELEM_CAL_BARO_GROUND "c_b" +#define AO_TELEM_CAL_ACCEL_PLUS "c_p" +#define AO_TELEM_CAL_ACCEL_MINUS "c_m" + +/* + * Kalman state values + * + * Name Value + * k_h Height above pad (integer, meters) + * k_s Vertical speeed (integer, m/s * 16) + * k_a Vertical acceleration (integer, m/s² * 16) + */ + +#define AO_TELEM_KALMAN_HEIGHT "k_h" +#define AO_TELEM_KALMAN_SPEED "k_s" +#define AO_TELEM_KALMAN_ACCEL "k_a" + +/* + * Ad-hoc flight values + * + * Name Value + * a_a Acceleration (integer, sensor units) + * a_s Speed (integer, integrated acceleration value) + * a_b Barometer reading (integer, sensor units) + */ + +#define AO_TELEM_ADHOC_ACCEL "a_a" +#define AO_TELEM_ADHOC_SPEED "a_s" +#define AO_TELEM_ADHOC_BARO "a_b" + +/* + * GPS values + * + * Name Value + * g GPS state (string): + * l locked + * u unlocked + * e error (missing or broken) + * g_n Number of sats used in solution + * g_ns Latitude (degrees * 10e7) + * g_ew Longitude (degrees * 10e7) + * g_a Altitude (integer meters) + * g_Y GPS year (integer) + * g_M GPS month (integer - 1-12) + * g_D GPS day (integer - 1-31) + * g_h GPS hour (integer - 0-23) + * g_m GPS minute (integer - 0-59) + * g_s GPS second (integer - 0-59) + * g_v GPS vertical speed (integer, cm/sec) + * g_g GPS horizontal speed (integer, cm/sec) + * g_c GPS course (integer, 0-359) + * g_hd GPS hdop (integer * 10) + * g_vd GPS vdop (integer * 10) + * g_he GPS h error (integer) + * g_ve GPS v error (integer) + */ + +#define AO_TELEM_GPS_STATE "g" +#define AO_TELEM_GPS_STATE_LOCKED 'l' +#define AO_TELEM_GPS_STATE_UNLOCKED 'u' +#define AO_TELEM_GPS_STATE_ERROR 'e' +#define AO_TELEM_GPS_NUM_SAT "g_n" +#define AO_TELEM_GPS_LATITUDE "g_ns" +#define AO_TELEM_GPS_LONGITUDE "g_ew" +#define AO_TELEM_GPS_ALTITUDE "g_a" +#define AO_TELEM_GPS_YEAR "g_Y" +#define AO_TELEM_GPS_MONTH "g_M" +#define AO_TELEM_GPS_DAY "g_D" +#define AO_TELEM_GPS_HOUR "g_h" +#define AO_TELEM_GPS_MINUTE "g_m" +#define AO_TELEM_GPS_SECOND "g_s" +#define AO_TELEM_GPS_VERTICAL_SPEED "g_v" +#define AO_TELEM_GPS_HORIZONTAL_SPEED "g_g" +#define AO_TELEM_GPS_COURSE "g_c" +#define AO_TELEM_GPS_HDOP "g_hd" +#define AO_TELEM_GPS_VDOP "g_vd" +#define AO_TELEM_GPS_HERROR "g_he" +#define AO_TELEM_GPS_VERROR "g_ve" + +/* + * GPS satellite values + * + * Name Value + * s_n Number of satellites reported (integer) + * s_v0 Space vehicle ID (integer) for report 0 + * s_c0 C/N0 number (integer) for report 0 + * s_v1 Space vehicle ID (integer) for report 1 + * s_c1 C/N0 number (integer) for report 1 + * ... + */ + +#define AO_TELEM_SAT_NUM "s_n" +#define AO_TELEM_SAT_SVID "s_v" +#define AO_TELEM_SAT_C_N_0 "s_c" + +#endif /* _AO_TELEM_H_ */ diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c new file mode 100644 index 00000000..c7338a58 --- /dev/null +++ b/src/core/ao_telemetry.c @@ -0,0 +1,270 @@ +/* + * 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" +#include "ao_product.h" + +static __pdata uint16_t ao_telemetry_interval; +static __pdata int8_t ao_telemetry_config_max; +static __pdata int8_t ao_telemetry_config_cur; +#if HAS_GPS +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; + +#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) +#define AO_RDF_LENGTH_MS 500 + +#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM +#endif + +#if defined(TELEMINI_V_1_0) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMINI +#endif + +#if defined(TELENANO_V_0_1) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELENANO +#endif + +static __xdata union ao_telemetry_all telemetry; + +/* Send sensor packet */ +static void +ao_send_sensor(void) +{ + uint8_t sample; + sample = ao_sample_adc; + + telemetry.generic.tick = ao_adc_ring[sample].tick; + telemetry.generic.type = AO_TELEMETRY_SENSOR; + + telemetry.sensor.state = ao_flight_state; +#if HAS_ACCEL + telemetry.sensor.accel = ao_adc_ring[sample].accel; +#else + telemetry.sensor.accel = 0; +#endif + telemetry.sensor.pres = ao_adc_ring[sample].pres; + telemetry.sensor.temp = ao_adc_ring[sample].temp; + telemetry.sensor.v_batt = ao_adc_ring[sample].v_batt; +#if HAS_IGNITE + telemetry.sensor.sense_d = ao_adc_ring[sample].sense_d; + telemetry.sensor.sense_m = ao_adc_ring[sample].sense_m; +#else + telemetry.sensor.sense_d = 0; + telemetry.sensor.sense_m = 0; +#endif + + telemetry.sensor.acceleration = ao_accel; + telemetry.sensor.speed = ao_speed; + telemetry.sensor.height = ao_height; + + telemetry.sensor.ground_pres = ao_ground_pres; +#if HAS_ACCEL + telemetry.sensor.ground_accel = ao_ground_accel; + telemetry.sensor.accel_plus_g = ao_config.accel_plus_g; + telemetry.sensor.accel_minus_g = ao_config.accel_minus_g; +#else + telemetry.sensor.ground_accel = 0; + telemetry.sensor.accel_plus_g = 0; + telemetry.sensor.accel_minus_g = 0; +#endif + + ao_radio_send(&telemetry, sizeof (telemetry)); +} + +static void +ao_send_configuration(void) +{ + if (--ao_telemetry_config_cur <= 0) + { + telemetry.generic.type = AO_TELEMETRY_CONFIGURATION; + telemetry.configuration.device = AO_idProduct_NUMBER; + telemetry.configuration.flight = ao_log_full() ? 0 : ao_flight_number; + telemetry.configuration.config_major = AO_CONFIG_MAJOR; + telemetry.configuration.config_minor = AO_CONFIG_MINOR; + telemetry.configuration.apogee_delay = ao_config.apogee_delay; + telemetry.configuration.main_deploy = ao_config.main_deploy; + telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10; + memcpy (telemetry.configuration.callsign, + ao_config.callsign, + AO_MAX_CALLSIGN); + memcpy (telemetry.configuration.version, + ao_version, + AO_MAX_VERSION); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_config_cur = ao_telemetry_config_max; + } +} + +#if HAS_GPS +static void +ao_send_location(void) +{ + if (--ao_telemetry_loc_cur <= 0) + { + telemetry.generic.type = AO_TELEMETRY_LOCATION; + ao_mutex_get(&ao_gps_mutex); + memcpy(&telemetry.location.flags, + &ao_gps_data.flags, + 26); + ao_mutex_put(&ao_gps_mutex); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_loc_cur = ao_telemetry_config_max; + } +} + +static void +ao_send_satellite(void) +{ + if (--ao_telemetry_sat_cur <= 0) + { + telemetry.generic.type = AO_TELEMETRY_SATELLITE; + ao_mutex_get(&ao_gps_mutex); + telemetry.satellite.channels = ao_gps_tracking_data.channels; + memcpy(&telemetry.satellite.sats, + &ao_gps_tracking_data.sats, + AO_MAX_GPS_TRACKING * sizeof (struct ao_telemetry_satellite_info)); + ao_mutex_put(&ao_gps_mutex); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_sat_cur = ao_telemetry_config_max; + } +} +#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) +{ + uint16_t time; + int16_t delay; + + ao_config_get(); + if (!ao_config.radio_enable) + ao_exit(); + while (!ao_flight_number) + ao_sleep(&ao_flight_number); + + telemetry.generic.serial = ao_serial_number; + for (;;) { + while (ao_telemetry_interval == 0) + ao_sleep(&telemetry); + time = ao_rdf_time = ao_time(); + while (ao_telemetry_interval) { + + + ao_send_sensor(); +#if HAS_COMPANION + if (ao_companion_running) + ao_send_companion(); +#endif + ao_send_configuration(); +#if HAS_GPS + ao_send_location(); + ao_send_satellite(); +#endif + if (ao_rdf && + (int16_t) (ao_time() - ao_rdf_time) >= 0) + { + ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; + ao_radio_rdf(AO_RDF_LENGTH_MS); + } + time += ao_telemetry_interval; + delay = time - ao_time(); + if (delay > 0) + ao_delay(delay); + else + time = ao_time(); + } + } +} + +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 = 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; + if (ao_telemetry_config_max > ao_telemetry_sat_cur) + ao_telemetry_sat_cur++; +#endif + ao_wakeup(&telemetry); +} + +void +ao_rdf_set(uint8_t rdf) +{ + ao_rdf = rdf; + if (rdf == 0) + ao_radio_rdf_abort(); + else + ao_rdf_time = ao_time(); +} + +__xdata struct ao_task ao_telemetry_task; + +void +ao_telemetry_init() +{ + ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry"); +} -- cgit v1.2.3 From a588092a7d76dab92e4ab11e0fdb457d2ddc9025 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Aug 2011 21:10:56 -0700 Subject: altos: AVR changes - create ao_arch.h files, define ao_arch_reboot Start pulling changes needed for avr port; architecture-specific code will live in /ao_arch.h. This first change defines the ao_arch_reboot macro to reboot the microcontroller. Signed-off-by: Keith Packard --- src/avr/ao_arch.h | 36 ++++++++++++++++++++++++++++++++++++ src/cc1111/ao_arch.h | 32 ++++++++++++++++++++++++++++++++ src/core/ao.h | 2 +- src/core/ao_cmd.c | 13 +++---------- 4 files changed, 72 insertions(+), 11 deletions(-) create mode 100644 src/avr/ao_arch.h create mode 100644 src/cc1111/ao_arch.h (limited to 'src/core') diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h new file mode 100644 index 00000000..2b566814 --- /dev/null +++ b/src/avr/ao_arch.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifndef _AO_ARCH_H_ +#define _AO_ARCH_H_ + +#include "avr.h" + + +/* + * AVR definitions and code fragments for AltOS + */ + +#define AO_STACK_SIZE 128 + +/* Various definitions to make GCC look more like SDCC */ + +#define __naked __attribute__((naked)) + +#define ao_arch_reboot() /* XXX */ + +#endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h new file mode 100644 index 00000000..585fffe5 --- /dev/null +++ b/src/cc1111/ao_arch.h @@ -0,0 +1,32 @@ +/* + * 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. + */ + +/* + * CC1111 definitions and code fragments for AltOS + */ + +#ifndef _AO_ARCH_H_ +#define _AO_ARCH_H_ + +#include "cc1111.h" + +#define ao_arch_reboot() do { \ + WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; \ + ao_delay(AO_SEC_TO_TICKS(2)); \ + } while (0) + +#endif /* _AO_ARCH_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 8ac9ac3d..0f1a24ad 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -22,7 +22,7 @@ #include #include #include -#include "cc1111.h" +#include #include "ao_pins.h" #define TRUE 1 diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 1442ebea..7663d875 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -32,7 +32,7 @@ static void put_string(__code char *s) { char c; - while (c = *s++) + while ((c = *s++)) putchar(c); } @@ -187,13 +187,6 @@ ao_match_word(__code char *word) return 1; } -static void -eol(void) -{ - while (ao_cmd_lex_c != '\n') - ao_cmd_lex(); -} - static void echo(void) { @@ -208,8 +201,7 @@ ao_reboot(void) ao_cmd_white(); if (!ao_match_word("eboot")) return; - WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; - ao_delay(AO_SEC_TO_TICKS(2)); + ao_arch_reboot(); ao_panic(AO_PANIC_REBOOT); } @@ -254,6 +246,7 @@ report(void) case ao_cmd_syntax_error: puts("Syntax error"); ao_cmd_status = 0; + default: break; } } -- cgit v1.2.3 From e9fab7dc99a0e7c22b511c5919adf7df85213252 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Aug 2011 22:04:36 -0700 Subject: altos: add GCC/SDCC compat macros, init_stack, save_context and GCC stdio hooks More arch-indepdency bits. GCC stdio is different from SDCC, so create suitable code in avr/ao_avr_stdio.c Create macros to initialize the task stack frame and save the task context. Add GCC/SDCC type definition compatibility macros Signed-off-by: Keith Packard --- src/avr-demo/Makefile | 102 ++++++++++ src/avr/ao_arch.h | 67 ++++++- src/avr/ao_avr_stdio.c | 52 +++++ src/avr/ao_pins.h | 31 +++ src/cc1111/ao_arch.h | 99 ++++++++++ src/cc1111/ao_pins.h | 425 ++++++++++++++++++++++++++++++++++++++++ src/core/ao.h | 76 ++----- src/core/ao_panic.c | 2 +- src/core/ao_pins.h | 408 -------------------------------------- src/core/ao_task.c | 60 +----- src/product/Makefile.telebt | 2 +- src/product/Makefile.teledongle | 2 +- src/product/Makefile.telemetrum | 2 +- src/product/Makefile.telemini | 2 +- src/product/Makefile.telenano | 2 +- src/tidongle/Makefile | 2 +- 16 files changed, 805 insertions(+), 529 deletions(-) create mode 100644 src/avr-demo/Makefile create mode 100644 src/avr/ao_avr_stdio.c create mode 100644 src/avr/ao_pins.h create mode 100644 src/cc1111/ao_pins.h delete mode 100644 src/core/ao_pins.h (limited to 'src/core') diff --git a/src/avr-demo/Makefile b/src/avr-demo/Makefile new file mode 100644 index 00000000..ea356654 --- /dev/null +++ b/src/avr-demo/Makefile @@ -0,0 +1,102 @@ +# +# AltOS build +# +# +vpath % ..:../core:../product:../driver +vpath make-altitude .. +vpath make-kalman .. +vpath kalman.5c ../kalman +vpath kalman_filter.5c ../kalman +vpath load_csv.5c ../kalman +vpath matrix.5c ../kalman +vpath ao-make-product.5c ../util + +MCU=atmega32u4 +DUDECPUTYPE=m32u4 +#PROGRAMMER=stk500v2 -P usb +PROGRAMMER=usbtiny +LOADCMD=avrdude +LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: +CC=avr-gcc +OBJCOPY=avr-objcopy + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + altitude.h \ + ao_kalman.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_cmd.c \ + ao_mutex.c \ + ao_panic.c \ + ao_product.c \ + ao_serial_avr.c \ + ao_avr_stdio.c \ + ao_stdio.c \ + ao_task.c \ + ao_timer.c \ + ao_led.c + +PRODUCT=AvrDemo-v0.0 +MCU=atmega32u4 +PRODUCT_DEF=-DAVR_DEMO +IDPRODUCT=0x000a +CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I.. +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -Os -mcall-prologues + +NICKLE=nickle + +PROG=avr-demo + +SRC=$(ALTOS_SRC) ao_demo.c ao_debug_avr.c +OBJ=$(SRC:.c=.o) + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: $(PROG) + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) + +$(PROG).hex: $(PROG) + avr-size $(PROG) + $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ + + +load: $(PROG).hex + $(LOADCMD) $(LOADARG)$(PROG).hex + +../altitude.h: make-altitude + nickle $< > $@ + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.rel: ao_product.c ao_product.h + $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean: clean + +clean: + rm -f $(OBJ) + rm -f ao_product.h + +install: + +uninstall: + +$(OBJ): ao.h ao_product.h \ No newline at end of file diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index 2b566814..51a65880 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -18,8 +18,18 @@ #ifndef _AO_ARCH_H_ #define _AO_ARCH_H_ -#include "avr.h" +#include +#include +#ifdef AVR_DEMO +#define TEENSY 1 +#endif + +#if TEENSY +#define F_CPU 16000000UL // 16 MHz +#else +#define F_CPU 8000000UL // 8 MHz +#endif /* * AVR definitions and code fragments for AltOS @@ -29,8 +39,61 @@ /* Various definitions to make GCC look more like SDCC */ -#define __naked __attribute__((naked)) +#define ao_arch_naked_declare __attribute__((naked)) +#define ao_arch_naked_define +#define __pdata +#define __data +#define __xdata +#define __code const +#define __reentrant +#define __critical +#define __interrupt(n) #define ao_arch_reboot() /* XXX */ +#define ao_arch_nop() asm("nop") + +#define ao_arch_interrupt(n) /* nothing */ + +#undef putchar +#undef getchar +#define putchar(c) ao_putchar(c) +#define getchar ao_getchar + +extern void putchar(char c); +extern char getchar(void); + +extern int ao_serial_number; + +#define ao_arch_init_stack(task, start) do { \ + uint8_t *sp = task->stack + AO_STACK_SIZE - 1; \ + uint16_t a = (uint16_t) start; \ + int i; \ + \ + /* Return address */ \ + PUSH8(sp, a); \ + PUSH8(sp, (a >> 8)); \ + \ + /* Clear register values */ \ + i = 32; \ + while (i--) \ + PUSH8(sp, 0); \ + \ + /* SREG with interrupts enabled */ \ + PUSH8(sp, 0x80); \ + task->sp = sp; \ +} while (0); + +#define ao_arch_save_context() do { \ + asm("push r31" "\n\t" "push r30"); \ + asm("push r29" "\n\t" "push r28" "\n\t" "push r27" "\n\t" "push r26" "\n\t" "push r25"); \ + asm("push r24" "\n\t" "push r23" "\n\t" "push r22" "\n\t" "push r21" "\n\t" "push r20"); \ + asm("push r19" "\n\t" "push r18" "\n\t" "push r17" "\n\t" "push r16" "\n\t" "push r15"); \ + asm("push r14" "\n\t" "push r13" "\n\t" "push r12" "\n\t" "push r11" "\n\t" "push r10"); \ + asm("push r9" "\n\t" "push r8" "\n\t" "push r7" "\n\t" "push r6" "\n\t" "push r5"); \ + asm("push r4" "\n\t" "push r3" "\n\t" "push r2" "\n\t" "push r1" "\n\t" "push r0"); \ + asm("in r0, __SREG__" "\n\t" "push r0"); \ + sei(); \ + } while (0) + #endif /* _AO_ARCH_H_ */ diff --git a/src/avr/ao_avr_stdio.c b/src/avr/ao_avr_stdio.c new file mode 100644 index 00000000..2f358eb5 --- /dev/null +++ b/src/avr/ao_avr_stdio.c @@ -0,0 +1,52 @@ +/* + * 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" + +int +stdio_put(char c, FILE *stream) +{ + if (ao_cur_task && ao_num_stdios) + putchar(c); + else + { + if (c == '\n') + stdio_put('\r', stream); + loop_until_bit_is_set(UCSR1A, UDRE1); + UDR1 = c; + } + + return 0; +} + +int +stdio_get(FILE *stream) +{ + return (int) getchar() & 0xff; +} + +static FILE mystdout = FDEV_SETUP_STREAM(stdio_put, NULL, _FDEV_SETUP_WRITE); + +static FILE mystdin = FDEV_SETUP_STREAM(NULL, stdio_get, _FDEV_SETUP_READ); + +void +ao_stdio_init(void) +{ + stdout = &mystdout; + stdin = &mystdin; + printf("%d stdios registered\n", ao_num_stdios); +} diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h new file mode 100644 index 00000000..ef41b59c --- /dev/null +++ b/src/avr/ao_pins.h @@ -0,0 +1,31 @@ +/* + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#ifdef AVR_DEMO + #define AO_LED_RED (1<<7) + #define LEDS_AVAILABLE (AO_LED_RED) + #define USE_SERIAL_STDIN 1 + #define HAS_USB 0 + #define PACKET_HAS_SLAVE 0 + #define HAS_SERIAL_1 1 + #define HAS_BEEP 0 +#endif + +#endif /* _AO_PINS_H_ */ diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 585fffe5..35fd66f8 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -24,9 +24,108 @@ #include "cc1111.h" +/* Convert a __data pointer into an __xdata pointer */ +#define DATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xff00)) + +/* Stack runs from above the allocated __data space to 0xfe, which avoids + * writing to 0xff as that triggers the stack overflow indicator + */ +#define AO_STACK_START 0x90 +#define AO_STACK_END 0xfe +#define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1) + #define ao_arch_reboot() do { \ WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; \ ao_delay(AO_SEC_TO_TICKS(2)); \ } while (0) +#define ao_arch_nop() _asm nop _endasm +#define ao_arch_interrupt(n) __interrupt n + +#define ao_arch_naked_declare __naked +#define ao_arch_naked_define __naked + +/* CC1111-specific drivers */ + +/* + * ao_romconfig.c + */ + +#define AO_ROMCONFIG_VERSION 2 + +extern __code __at (0x00a0) uint16_t ao_romconfig_version; +extern __code __at (0x00a2) uint16_t ao_romconfig_check; +extern __code __at (0x00a4) uint16_t ao_serial_number; +extern __code __at (0x00a6) uint32_t ao_radio_cal; + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +#if HAS_USB +extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; +#endif + +/* Initialize stack */ +#define ao_arch_init_stack(task, start) { \ + uint8_t __xdata *stack = task->stack; \ + uint8_t t; \ + *stack++ = ((uint16_t) start); /* 0 */ \ + *stack++ = ((uint16_t) start) >> 8; /* 1 */ \ + \ + /* and the stuff saved by ao_switch */ \ + *stack++ = 0; /* 2 acc */ \ + *stack++ = 0x80; /* 3 IE */ \ + \ + /* 4 DPL \ + * 5 DPH \ + * 6 B \ + * 7 R2 \ + * 8 R3 \ + * 9 R4 \ + * 10 R5 \ + * 11 R6 \ + * 12 R7 \ + * 13 R0 \ + * 14 R1 \ + * 15 PSW \ + * 16 BP \ + */ \ + for (t = 0; t < 13; t++) \ + *stack++ = 0; \ + task->stack_count = 17; \ + } + + + +/* Save current context */ + +#define ao_arch_save_context() \ + _asm \ + /* Push ACC first, as when restoring the context it must be restored \ + * last (it is used to set the IE register). */ \ + push ACC \ + /* Store the IE register then enable interrupts. */ \ + push _IEN0 \ + setb _EA \ + push DPL \ + push DPH \ + push b \ + push ar2 \ + push ar3 \ + push ar4 \ + push ar5 \ + push ar6 \ + push ar7 \ + push ar0 \ + push ar1 \ + push PSW \ + _endasm; \ + PSW = 0; \ + _asm \ + push _bp \ + _endasm + + + #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h new file mode 100644 index 00000000..4ac6a84b --- /dev/null +++ b/src/cc1111/ao_pins.h @@ -0,0 +1,425 @@ +/* + * Copyright © 2010 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_PINS_H_ +#define _AO_PINS_H_ + +#if defined(TELEMETRUM_V_1_0) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define HAS_ADC 1 + #define USE_SERIAL_STDIN 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #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 + #define HAS_ACCEL_REF 0 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEMETRUM_V_1_1) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #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 + #define HAS_ACCEL_REF 1 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEDONGLE_V_0_2) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEMINI_V_1_0) + #define HAS_FLIGHT 1 + #define HAS_USB 0 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 + #define HAS_DBG 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 1 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define USE_FAST_ASCENT_LOG 1 + + #define AO_LED_GREEN 1 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELENANO_V_0_1) + #define HAS_FLIGHT 1 + #define HAS_USB 0 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 + #define HAS_DBG 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 1 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define AO_LED_GREEN 1 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEMETRUM_V_0_1) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_DBG 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 1 + #define HAS_ACCEL_REF 0 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEDONGLE_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 0 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TIDONGLE) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED) + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEBT_V_0_0) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define HAS_BTM 1 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_IGNITE 0 + #define BT_LINK_ON_P2 1 + #define BT_LINK_ON_P1 0 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P2_1 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEBT_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_SERIAL_1 1 + #define HAS_SERIAL_1_ALT_1 1 + #define HAS_SERIAL_1_ALT_2 0 + #define HAS_SERIAL_1_HW_FLOW 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_BTM 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x04 /* CS0 is P1_2 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define BT_LINK_ON_P2 0 + #define BT_LINK_ON_P1 1 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P1_7 + #define HAS_MONITOR 1 +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#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 + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC + +#if HAS_ACCEL +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif +#else +#define HAS_ACCEL_REF 0 +#endif + +#endif /* HAS_ADC */ + +#endif /* _AO_PINS_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 0f1a24ad..9b0bb545 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -22,21 +22,16 @@ #include #include #include -#include #include "ao_pins.h" +#include #define TRUE 1 #define FALSE 0 /* Convert a __data pointer into an __xdata pointer */ -#define DATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xff00)) - -/* Stack runs from above the allocated __data space to 0xfe, which avoids - * writing to 0xff as that triggers the stack overflow indicator - */ -#define AO_STACK_START 0x90 -#define AO_STACK_END 0xfe -#define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1) +#ifndef DATA_TO_XDATA +#define DATA_TO_XDATA(a) (a) +#endif /* An AltOS task */ struct ao_task { @@ -75,7 +70,7 @@ ao_alarm(uint16_t delay); /* Yield the processor to another task */ void -ao_yield(void) __naked; +ao_yield(void) ao_arch_naked_declare; /* Add a task to the run queue */ void @@ -136,7 +131,7 @@ ao_timer_set_adc_interval(uint8_t interval) __critical; /* Timer interrupt */ void -ao_timer_isr(void) __interrupt 9; +ao_timer_isr(void) ao_arch_interrupt(9); /* Initialize the timer */ void @@ -159,20 +154,8 @@ struct ao_adc { int16_t sense_m; /* main continuity sense */ }; -#ifndef HAS_ADC -#error Please define HAS_ADC -#endif - #if HAS_ADC -#if HAS_ACCEL -#ifndef HAS_ACCEL_REF -#error Please define HAS_ACCEL_REF -#endif -#else -#define HAS_ACCEL_REF 0 -#endif - /* * ao_adc.c */ @@ -207,7 +190,7 @@ ao_adc_get(__xdata struct ao_adc *packet); /* The A/D interrupt handler */ void -ao_adc_isr(void) __interrupt 1; +ao_adc_isr(void) ao_arch_interrupt(1); /* Initialize the A/D converter */ void @@ -298,25 +281,6 @@ ao_led_for(uint8_t colors, uint16_t ticks) __reentrant; void ao_led_init(uint8_t enable); -/* - * ao_romconfig.c - */ - -#define AO_ROMCONFIG_VERSION 2 - -extern __code __at (0x00a0) uint16_t ao_romconfig_version; -extern __code __at (0x00a2) uint16_t ao_romconfig_check; -extern __code __at (0x00a4) uint16_t ao_serial_number; -extern __code __at (0x00a6) uint32_t ao_radio_cal; - -#ifndef HAS_USB -#error Please define HAS_USB -#endif - -#if HAS_USB -extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; -#endif - /* * ao_usb.c */ @@ -342,7 +306,7 @@ ao_usb_flush(void); #if HAS_USB /* USB interrupt handler */ void -ao_usb_isr(void) __interrupt 6; +ao_usb_isr(void) ao_arch_interrupt(6); #endif /* Enable the USB controller */ @@ -446,7 +410,7 @@ ao_dma_abort(uint8_t id); /* DMA interrupt routine */ void -ao_dma_isr(void) __interrupt 8; +ao_dma_isr(void) ao_arch_interrupt(8); /* * ao_mutex.c @@ -927,10 +891,10 @@ ao_dbg_init(void); #endif void -ao_serial_rx1_isr(void) __interrupt 3; +ao_serial_rx1_isr(void) ao_arch_interrupt(3); void -ao_serial_tx1_isr(void) __interrupt 14; +ao_serial_tx1_isr(void) ao_arch_interrupt(14); char ao_serial_getchar(void) __critical; @@ -1251,14 +1215,6 @@ struct ao_telemetry_tiny { char callsign[AO_MAX_CALLSIGN]; }; -/* - * ao_radio_recv tacks on rssi and status bytes - */ - -struct ao_telemetry_raw_recv { - uint8_t packet[AO_MAX_TELEMETRY + 2]; -}; - struct ao_telemetry_orig_recv { struct ao_telemetry_orig telemetry_orig; int8_t rssi; @@ -1271,6 +1227,14 @@ struct ao_telemetry_tiny_recv { uint8_t status; }; +/* + * ao_radio_recv tacks on rssi and status bytes + */ + +struct ao_telemetry_raw_recv { + uint8_t packet[AO_MAX_TELEMETRY + 2]; +}; + /* Set delay between telemetry reports (0 to disable) */ #define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) @@ -1302,7 +1266,7 @@ extern __xdata uint8_t ao_radio_done; extern __xdata uint8_t ao_radio_mutex; void -ao_radio_general_isr(void) __interrupt 16; +ao_radio_general_isr(void) ao_arch_interrupt(16); void ao_radio_get(uint8_t len); diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index fdada201..cbfdf399 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -33,7 +33,7 @@ ao_panic_delay(uint8_t n) while (n--) while (--j) while (--i) - _asm nop _endasm; + ao_arch_nop(); } void diff --git a/src/core/ao_pins.h b/src/core/ao_pins.h deleted file mode 100644 index e1f5459f..00000000 --- a/src/core/ao_pins.h +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright © 2010 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_PINS_H_ -#define _AO_PINS_H_ - -#if defined(TELEMETRUM_V_1_0) - #define HAS_FLIGHT 1 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_GPS 1 - #define HAS_SERIAL_1 1 - #define HAS_ADC 1 - #define USE_SERIAL_STDIN 0 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define HAS_DBG 1 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 1 - #define IGNITE_ON_P0 0 - #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 - #define HAS_ACCEL_REF 0 - #define HAS_ACCEL 1 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEMETRUM_V_1_1) - #define HAS_FLIGHT 1 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_GPS 1 - #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define HAS_DBG 1 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 1 - #define IGNITE_ON_P0 0 - #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 - #define HAS_ACCEL_REF 1 - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ - #define M25_MAX_CHIPS 1 - #define HAS_ACCEL 1 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEDONGLE_V_0_2) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 0 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 1 - #define AO_LED_GREEN 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define HAS_IGNITE 0 - #define HAS_MONITOR 1 -#endif - -#if defined(TELEMINI_V_1_0) - #define HAS_FLIGHT 1 - #define HAS_USB 0 - #define HAS_BEEP 0 - #define HAS_GPS 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 1 - #define HAS_DBG 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 1 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - #define USE_FAST_ASCENT_LOG 1 - - #define AO_LED_GREEN 1 - #define AO_LED_RED 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL 0 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELENANO_V_0_1) - #define HAS_FLIGHT 1 - #define HAS_USB 0 - #define HAS_BEEP 0 - #define HAS_GPS 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 1 - #define HAS_DBG 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 1 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - - #define AO_LED_GREEN 1 - #define AO_LED_RED 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL 0 - #define HAS_IGNITE 0 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEMETRUM_V_0_1) - #define HAS_FLIGHT 1 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_GPS 1 - #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_DBG 0 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 1 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - #define AO_LED_RED 2 - #define AO_LED_GREEN 1 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define HAS_EXTERNAL_TEMP 1 - #define HAS_ACCEL_REF 0 - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define HAS_ACCEL 1 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEDONGLE_V_0_1) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 0 - #define HAS_DBG 0 - #define HAS_EEPROM 0 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 2 - #define AO_LED_GREEN 1 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 0 - #define SPI_CS_ON_P0 1 - #define HAS_IGNITE 0 - #define HAS_MONITOR 1 -#endif - -#if defined(TIDONGLE) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 0 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 2 - #define LEDS_AVAILABLE (AO_LED_RED) - #define SPI_CS_ON_P1 0 - #define SPI_CS_ON_P0 1 - #define HAS_IGNITE 0 - #define HAS_MONITOR 1 -#endif - -#if defined(TELEBT_V_0_0) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 1 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 0 - #define HAS_BTM 1 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 2 - #define AO_LED_GREEN 1 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define HAS_IGNITE 0 - #define BT_LINK_ON_P2 1 - #define BT_LINK_ON_P1 0 - #define BT_LINK_PIN_INDEX 7 - #define BT_LINK_PIN P2_1 - #define HAS_MONITOR 1 -#endif - -#if defined(TELEBT_V_0_1) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_SERIAL_1 1 - #define HAS_SERIAL_1_ALT_1 1 - #define HAS_SERIAL_1_ALT_2 0 - #define HAS_SERIAL_1_HW_FLOW 1 - #define USE_SERIAL_STDIN 1 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define HAS_BTM 1 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 1 - #define AO_LED_GREEN 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define M25_CS_MASK 0x04 /* CS0 is P1_2 */ - #define M25_MAX_CHIPS 1 - #define HAS_ACCEL 0 - #define HAS_IGNITE 0 - #define BT_LINK_ON_P2 0 - #define BT_LINK_ON_P1 1 - #define BT_LINK_PIN_INDEX 7 - #define BT_LINK_PIN P1_7 - #define HAS_MONITOR 1 -#endif - -#if DBG_ON_P1 - - #define DBG_CLOCK (1 << 4) /* mi0 */ - #define DBG_DATA (1 << 5) /* mo0 */ - #define DBG_RESET_N (1 << 3) /* c0 */ - - #define DBG_CLOCK_PIN (P1_4) - #define DBG_DATA_PIN (P1_5) - #define DBG_RESET_N_PIN (P1_3) - - #define DBG_PORT_NUM 1 - #define DBG_PORT P1 - #define DBG_PORT_SEL P1SEL - #define DBG_PORT_INP P1INP - #define DBG_PORT_DIR P1DIR - -#endif /* DBG_ON_P1 */ - -#if DBG_ON_P0 - - #define DBG_CLOCK (1 << 3) - #define DBG_DATA (1 << 4) - #define DBG_RESET_N (1 << 5) - - #define DBG_CLOCK_PIN (P0_3) - #define DBG_DATA_PIN (P0_4) - #define DBG_RESET_N_PIN (P0_5) - - #define DBG_PORT_NUM 0 - #define DBG_PORT P0 - #define DBG_PORT_SEL P0SEL - #define DBG_PORT_INP P0INP - #define DBG_PORT_DIR P0DIR - -#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 - #define SPI_CS_DIR P1DIR -#endif - -#if SPI_CS_ON_P0 - #define SPI_CS_PORT P0 - #define SPI_CS_SEL P0SEL - #define SPI_CS_DIR P0DIR -#endif - -#ifndef IGNITE_ON_P2 -#error Please define IGNITE_ON_P2 -#endif - -#ifndef IGNITE_ON_P0 -#error Please define IGNITE_ON_P0 -#endif - -#ifndef HAS_SERIAL_1 -#error Please define HAS_SERIAL_1 -#endif - -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - -#ifndef HAS_ADC -#error Please define HAS_ADC -#endif - -#ifndef HAS_EEPROM -#error Please define HAS_EEPROM -#endif - -#if HAS_EEPROM -#ifndef USE_INTERNAL_FLASH -#error Please define USE_INTERNAL_FLASH -#endif -#endif - -#ifndef HAS_DBG -#error Please define HAS_DBG -#endif - -#ifndef HAS_IGNITE -#error Please define HAS_IGNITE -#endif - -#ifndef PACKET_HAS_MASTER -#error Please define PACKET_HAS_MASTER -#endif - -#ifndef PACKET_HAS_SLAVE -#error Please define PACKET_HAS_SLAVE -#endif - -#ifndef HAS_MONITOR -#error Please define HAS_MONITOR -#endif -#endif /* _AO_PINS_H_ */ diff --git a/src/core/ao_task.c b/src/core/ao_task.c index f5850fa4..41520476 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -27,7 +27,6 @@ __xdata struct ao_task *__data ao_cur_task; void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant { - uint8_t __xdata *stack; uint8_t task_id; uint8_t t; if (ao_num_tasks == AO_NUM_TASKS) @@ -42,70 +41,19 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam ao_tasks[ao_num_tasks++] = task; task->task_id = task_id; task->name = name; + task->wchan = NULL; /* * Construct a stack frame so that it will 'return' * to the start of the task */ - stack = task->stack; - - *stack++ = ((uint16_t) start); /* 0 */ - *stack++ = ((uint16_t) start) >> 8; /* 1 */ - - /* and the stuff saved by ao_switch */ - *stack++ = 0; /* 2 acc */ - *stack++ = 0x80; /* 3 IE */ - - /* 4 DPL - * 5 DPH - * 6 B - * 7 R2 - * 8 R3 - * 9 R4 - * 10 R5 - * 11 R6 - * 12 R7 - * 13 R0 - * 14 R1 - * 15 PSW - * 16 BP - */ - for (t = 0; t < 13; t++) - *stack++ = 0; - - task->stack_count = 17; - task->wchan = NULL; + ao_arch_init_stack(task, start); } /* Task switching function. This must not use any stack variables */ void -ao_yield(void) __naked +ao_yield(void) ao_arch_naked_define { - - /* Save current context */ - _asm - /* Push ACC first, as when restoring the context it must be restored - * last (it is used to set the IE register). */ - push ACC - /* Store the IE register then enable interrupts. */ - push _IEN0 - setb _EA - push DPL - push DPH - push b - push ar2 - push ar3 - push ar4 - push ar5 - push ar6 - push ar7 - push ar0 - push ar1 - push PSW - _endasm; - PSW = 0; - _asm - push _bp - _endasm; + ao_arch_save_context(); if (ao_cur_task_index == AO_NO_TASK_INDEX) ao_cur_task_index = ao_num_tasks-1; diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index 99730b9f..d9ef1ea7 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -79,7 +79,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index f32c037f..cfd9b806 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -78,7 +78,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index fd958aea..2759ac52 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -93,7 +93,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 3bd14226..7f251897 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -82,7 +82,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index 72043044..c47e95ff 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -81,7 +81,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index fc8df1f4..247f4fe0 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -73,7 +73,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ -- cgit v1.2.3 From 8125acc030574afed6f23aa8aa302d9c768bb04e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Aug 2011 22:55:33 -0700 Subject: altos: get avr-demo to build. Pull in AVR drivers and LCD driver This completes the basic task of making an AVR version of altos by getting the Teensy 'avr-demo' program to build. Signed-off-by: Keith Packard --- src/avr-demo/Makefile | 7 +- src/avr-demo/ao_demo.c | 52 ++++ src/avr/ao_arch.h | 80 ++++-- src/avr/ao_avr_stdio.c | 2 +- src/avr/ao_debug_avr.c | 78 ++++++ src/avr/ao_led.c | 67 +++++ src/avr/ao_pins.h | 28 +- src/avr/ao_romconfig.c | 20 ++ src/avr/ao_serial_avr.c | 166 ++++++++++++ src/avr/ao_timer.c | 147 +++++++++++ src/avr/ao_usb.h | 100 +++++++ src/avr/ao_usb_avr.c | 688 ++++++++++++++++++++++++++++++++++++++++++++++++ src/cc1111/ao_arch.h | 118 +++++++-- src/core/ao.h | 11 +- src/core/ao_panic.c | 2 +- src/core/ao_task.c | 99 ++----- 16 files changed, 1542 insertions(+), 123 deletions(-) create mode 100644 src/avr-demo/ao_demo.c create mode 100644 src/avr/ao_debug_avr.c create mode 100644 src/avr/ao_led.c create mode 100644 src/avr/ao_romconfig.c create mode 100644 src/avr/ao_serial_avr.c create mode 100644 src/avr/ao_timer.c create mode 100644 src/avr/ao_usb.h create mode 100644 src/avr/ao_usb_avr.c (limited to 'src/core') diff --git a/src/avr-demo/Makefile b/src/avr-demo/Makefile index ea356654..93295166 100644 --- a/src/avr-demo/Makefile +++ b/src/avr-demo/Makefile @@ -2,7 +2,7 @@ # AltOS build # # -vpath % ..:../core:../product:../driver +vpath % ..:../core:../product:../drivers:../avr vpath make-altitude .. vpath make-kalman .. vpath kalman.5c ../kalman @@ -38,12 +38,15 @@ ALTOS_SRC = \ ao_mutex.c \ ao_panic.c \ ao_product.c \ + ao_romconfig.c \ ao_serial_avr.c \ ao_avr_stdio.c \ ao_stdio.c \ ao_task.c \ ao_timer.c \ - ao_led.c + ao_led.c \ + ao_usb_avr.c \ + ao_lcd.c PRODUCT=AvrDemo-v0.0 MCU=atmega32u4 diff --git a/src/avr-demo/ao_demo.c b/src/avr-demo/ao_demo.c new file mode 100644 index 00000000..756dd0d4 --- /dev/null +++ b/src/avr-demo/ao_demo.c @@ -0,0 +1,52 @@ +/* + * 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" + +struct ao_task demo_task; + +void +ao_demo(void) +{ + for (;;) { + ao_led_toggle(AO_LED_RED); + printf ("hello %d\n", ao_time()); + ao_delay(AO_MS_TO_TICKS(200)); + } +} + +int +main(void) +{ + ao_clock_init(); + + ao_serial_init(); + + ao_led_init(LEDS_AVAILABLE); + ao_avr_stdio_init(); + printf ("stdio initialized\n"); +// ao_debug_init(); + ao_timer_init(); + ao_cmd_init(); + ao_usb_init(); + ao_lcd_init(); + +// ao_add_task(&demo_task, ao_demo, "demo"); + /* Turn on the LED until the system is stable */ + ao_start_scheduler(); + return 0; +} diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index 51a65880..0ed97361 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -18,8 +18,10 @@ #ifndef _AO_ARCH_H_ #define _AO_ARCH_H_ +#include #include #include +#include #ifdef AVR_DEMO #define TEENSY 1 @@ -48,6 +50,7 @@ #define __reentrant #define __critical #define __interrupt(n) +#define __at(n) #define ao_arch_reboot() /* XXX */ @@ -62,8 +65,18 @@ extern void putchar(char c); extern char getchar(void); +extern void ao_avr_stdio_init(void); -extern int ao_serial_number; +extern const uint16_t ao_serial_number; + +#define AVR_PUSH8(stack, val) (*((stack)--) = (val)) + +extern uint8_t ao_cpu_sleep_disable; + +#define ao_arch_task_globals uint8_t ao_cpu_sleep_disable; + +#define ao_arch_task_members\ + uint8_t *sp; /* saved stack pointer */ #define ao_arch_init_stack(task, start) do { \ uint8_t *sp = task->stack + AO_STACK_SIZE - 1; \ @@ -71,29 +84,66 @@ extern int ao_serial_number; int i; \ \ /* Return address */ \ - PUSH8(sp, a); \ - PUSH8(sp, (a >> 8)); \ + AVR_PUSH8(sp, a); \ + AVR_PUSH8(sp, (a >> 8)); \ \ /* Clear register values */ \ i = 32; \ while (i--) \ - PUSH8(sp, 0); \ + AVR_PUSH8(sp, 0); \ \ /* SREG with interrupts enabled */ \ - PUSH8(sp, 0x80); \ + AVR_PUSH8(sp, 0x80); \ task->sp = sp; \ } while (0); -#define ao_arch_save_context() do { \ - asm("push r31" "\n\t" "push r30"); \ - asm("push r29" "\n\t" "push r28" "\n\t" "push r27" "\n\t" "push r26" "\n\t" "push r25"); \ - asm("push r24" "\n\t" "push r23" "\n\t" "push r22" "\n\t" "push r21" "\n\t" "push r20"); \ - asm("push r19" "\n\t" "push r18" "\n\t" "push r17" "\n\t" "push r16" "\n\t" "push r15"); \ - asm("push r14" "\n\t" "push r13" "\n\t" "push r12" "\n\t" "push r11" "\n\t" "push r10"); \ - asm("push r9" "\n\t" "push r8" "\n\t" "push r7" "\n\t" "push r6" "\n\t" "push r5"); \ - asm("push r4" "\n\t" "push r3" "\n\t" "push r2" "\n\t" "push r1" "\n\t" "push r0"); \ - asm("in r0, __SREG__" "\n\t" "push r0"); \ - sei(); \ +#define ao_arch_save_regs() do { \ + asm("push r31" "\n\t" "push r30"); \ + asm("push r29" "\n\t" "push r28" "\n\t" "push r27" "\n\t" "push r26" "\n\t" "push r25"); \ + asm("push r24" "\n\t" "push r23" "\n\t" "push r22" "\n\t" "push r21" "\n\t" "push r20"); \ + asm("push r19" "\n\t" "push r18" "\n\t" "push r17" "\n\t" "push r16" "\n\t" "push r15"); \ + asm("push r14" "\n\t" "push r13" "\n\t" "push r12" "\n\t" "push r11" "\n\t" "push r10"); \ + asm("push r9" "\n\t" "push r8" "\n\t" "push r7" "\n\t" "push r6" "\n\t" "push r5"); \ + asm("push r4" "\n\t" "push r3" "\n\t" "push r2" "\n\t" "push r1" "\n\t" "push r0"); \ + cli(); \ + asm("in r0, __SREG__" "\n\t" "push r0"); \ + sei(); \ + } while (0) + +#define ao_arch_save_stack() do { \ + uint8_t sp_l, sp_h; \ + asm("in %0,__SP_L__" : "=&r" (sp_l) ); \ + asm("in %0,__SP_H__" : "=&r" (sp_h) ); \ + ao_cur_task->sp = (uint8_t *) ((uint16_t) sp_l | ((uint16_t) sp_h << 8)); \ } while (0) +#define ao_arch_isr_stack() /* nothing */ + +#define ao_arch_cpu_idle() do { \ + if (!ao_cpu_sleep_disable) \ + sleep_cpu(); \ + } while (0) + +#define ao_arch_restore_stack() do { \ + uint8_t sp_l, sp_h; \ + sp_l = (uint16_t) ao_cur_task->sp; \ + sp_h = ((uint16_t) ao_cur_task->sp) >> 8; \ + cli(); \ + asm("out __SP_H__,%0" : : "r" (sp_h) ); \ + asm("out __SP_L__,%0" : : "r" (sp_l) ); \ + asm("pop r0" "\n\t" \ + "out __SREG__, r0"); \ + asm("pop r0" "\n\t" "pop r1" "\n\t" "pop r2" "\n\t" "pop r3" "\n\t" "pop r4"); \ + asm("pop r5" "\n\t" "pop r6" "\n\t" "pop r7" "\n\t" "pop r8" "\n\t" "pop r9"); \ + asm("pop r10" "\n\t" "pop r11" "\n\t" "pop r12" "\n\t" "pop r13" "\n\t" "pop r14"); \ + asm("pop r15" "\n\t" "pop r16" "\n\t" "pop r17" "\n\t" "pop r18" "\n\t" "pop r19"); \ + asm("pop r20" "\n\t" "pop r21" "\n\t" "pop r22" "\n\t" "pop r23" "\n\t" "pop r24"); \ + asm("pop r25" "\n\t" "pop r26" "\n\t" "pop r27" "\n\t" "pop r28" "\n\t" "pop r29"); \ + asm("pop r30" "\n\t" "pop r31"); \ + asm("ret"); \ + } while(0) + +#define ao_arch_critical(b) do { cli(); b; sei(); } while (0) + #endif /* _AO_ARCH_H_ */ + diff --git a/src/avr/ao_avr_stdio.c b/src/avr/ao_avr_stdio.c index 2f358eb5..ba562dbf 100644 --- a/src/avr/ao_avr_stdio.c +++ b/src/avr/ao_avr_stdio.c @@ -44,7 +44,7 @@ static FILE mystdout = FDEV_SETUP_STREAM(stdio_put, NULL, _FDEV_SETUP_WRITE); static FILE mystdin = FDEV_SETUP_STREAM(NULL, stdio_get, _FDEV_SETUP_READ); void -ao_stdio_init(void) +ao_avr_stdio_init(void) { stdout = &mystdout; stdin = &mystdin; diff --git a/src/avr/ao_debug_avr.c b/src/avr/ao_debug_avr.c new file mode 100644 index 00000000..2e41e15a --- /dev/null +++ b/src/avr/ao_debug_avr.c @@ -0,0 +1,78 @@ +/* + * 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" + +void +uart_send(char c) +{ + loop_until_bit_is_set(UCSR1A, UDRE1); + UDR1 = c; +} + +int +uart_put(char c, FILE *stream) +{ + if (c == '\n') + uart_send('\r'); + uart_send(c); + return 0; +} + +int +uart_get(FILE *stream) +{ + loop_until_bit_is_set(UCSR1A, RXC1); + return (int) UDR1 & 0xff; +} + +void +uart_init(uint16_t baud) +{ + PRR1 &= ~(1 << PRUSART1); + UBRR1L = baud; + UBRR1H = baud >> 8; + UCSR1A = 0; + UCSR1B = ((1 << RXEN1) | /* Enable receiver */ + (1 << TXEN1)); /* Enable transmitter */ + UCSR1C = ((0 << UMSEL10) | /* Asynchronous mode */ + (0 << UPM10) | /* No parity */ + (0 << USBS1) | /* 1 stop bit */ + (3 << UCSZ10) | /* 8 bit characters */ + (0 << UCPOL1)); /* MBZ for async mode */ +} + +static FILE mystdout = FDEV_SETUP_STREAM(uart_put, NULL, _FDEV_SETUP_WRITE); + +static FILE mystdin = FDEV_SETUP_STREAM(NULL, uart_get, _FDEV_SETUP_READ); + +void ao_debug_init(void) +{ + uart_init(F_CPU / (16UL * 9600UL) - 1); + + stdout = &mystdout; + stdin = &mystdin; + + if (DDRB & AO_LED_RED) { + printf ("oops, starting all over\n"); + for (;;) + ; + } + DDRB |= (1 << 7); + PORTB |= (1 << 7); + printf ("debug initialized\n"); +} diff --git a/src/avr/ao_led.c b/src/avr/ao_led.c new file mode 100644 index 00000000..91dfb85e --- /dev/null +++ b/src/avr/ao_led.c @@ -0,0 +1,67 @@ +/* + * Copyright © 2009 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" + +__pdata uint8_t ao_led_enable; + +#define LED_PORT PORTB +#define LED_DDR DDRB + +void +ao_led_on(uint8_t colors) +{ + LED_PORT |= (colors & ao_led_enable); +} + +void +ao_led_off(uint8_t colors) +{ + LED_PORT &= ~(colors & ao_led_enable); +} + +void +ao_led_set(uint8_t colors) +{ + LED_PORT = (LED_PORT & ~(ao_led_enable)) | (colors & ao_led_enable); +} + +void +ao_led_toggle(uint8_t colors) +{ + LED_PORT ^= (colors & ao_led_enable); +} + +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_led_enable = enable; + if ((LED_DDR & enable)) { + printf ("oops! restarted\n"); + ao_panic(AO_PANIC_REBOOT); + } + LED_PORT &= ~enable; + LED_DDR |= enable; +} diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index ef41b59c..56435f18 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -22,10 +22,36 @@ #define AO_LED_RED (1<<7) #define LEDS_AVAILABLE (AO_LED_RED) #define USE_SERIAL_STDIN 1 - #define HAS_USB 0 + #define HAS_USB 1 #define PACKET_HAS_SLAVE 0 #define HAS_SERIAL_1 1 + #define TEENSY 1 + #define AVR_VCC_5V 1 + #define AVR_VCC_3V3 0 + #define AVR_CLOCK 16000000UL #define HAS_BEEP 0 #endif +#ifdef TELESCIENCE + #define LEDS_AVAILABLE 0 + #define HAS_USB 1 + #define HAS_LOG 1 + #define TEENSY 0 + #define USE_SERIAL_STDIN 1 + #define HAS_SERIAL_1 1 + #define HAS_USB 1 + #define HAS_ADC 1 + #define PACKET_HAS_SLAVE 0 + #define HAS_BEEP 0 + + #define AVR_VCC_5V 0 + #define AVR_VCC_3V3 1 + #define AVR_CLOCK 8000000UL + + #define SPI_CS_PORT PORTE + #define SPI_CS_DIR DDRE + #define M25_CS_MASK (1 << PORTE6) + #define M25_MAX_CHIPS 1 +#endif + #endif /* _AO_PINS_H_ */ diff --git a/src/avr/ao_romconfig.c b/src/avr/ao_romconfig.c new file mode 100644 index 00000000..bbb677e2 --- /dev/null +++ b/src/avr/ao_romconfig.c @@ -0,0 +1,20 @@ +/* + * 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" + +const uint16_t ao_serial_number = 0; diff --git a/src/avr/ao_serial_avr.c b/src/avr/ao_serial_avr.c new file mode 100644 index 00000000..2fe39755 --- /dev/null +++ b/src/avr/ao_serial_avr.c @@ -0,0 +1,166 @@ +/* + * 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" + +__xdata struct ao_fifo ao_usart1_rx_fifo; +__xdata struct ao_fifo ao_usart1_tx_fifo; + +void +ao_debug_out(char c) +{ + if (c == '\n') + ao_debug_out('\r'); + loop_until_bit_is_set(UCSR1A, UDRE1); + UDR1 = c; +} + +ISR(USART1_RX_vect) +{ + if (!ao_fifo_full(ao_usart1_rx_fifo)) + ao_fifo_insert(ao_usart1_rx_fifo, UDR1); + ao_wakeup(&ao_usart1_rx_fifo); +#if USE_SERIAL_STDIN + ao_wakeup(&ao_stdin_ready); +#endif +} + +static __xdata uint8_t ao_serial_tx1_started; + +static void +ao_serial_tx1_start(void) +{ + if (!ao_fifo_empty(ao_usart1_tx_fifo) && + !ao_serial_tx1_started) + { + ao_serial_tx1_started = 1; + ao_fifo_remove(ao_usart1_tx_fifo, UDR1); + } +} + +ISR(USART1_UDRE_vect) +{ + ao_serial_tx1_started = 0; + ao_serial_tx1_start(); + ao_wakeup(&ao_usart1_tx_fifo); +} + +char +ao_serial_getchar(void) __critical +{ + char c; + cli(); + while (ao_fifo_empty(ao_usart1_rx_fifo)) + ao_sleep(&ao_usart1_rx_fifo); + ao_fifo_remove(ao_usart1_rx_fifo, c); + sei(); + return c; +} + +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) __critical +{ + char c; + cli(); + if (ao_fifo_empty(ao_usart1_rx_fifo)) { + sei(); + return AO_READ_AGAIN; + } + ao_fifo_remove(ao_usart1_rx_fifo,c); + sei(); + return c; +} +#endif + +void +ao_serial_putchar(char c) __critical +{ + cli(); + while (ao_fifo_full(ao_usart1_tx_fifo)) + ao_sleep(&ao_usart1_tx_fifo); + ao_fifo_insert(ao_usart1_tx_fifo, c); + ao_serial_tx1_start(); + sei(); +} + +void +ao_serial_drain(void) __critical +{ + cli(); + while (!ao_fifo_empty(ao_usart1_tx_fifo)) + ao_sleep(&ao_usart1_tx_fifo); + sei(); +} + +static const struct { + uint16_t ubrr; +} ao_serial_speeds[] = { + /* [AO_SERIAL_SPEED_4800] = */ { + F_CPU / (16UL * 4800UL) - 1 + }, + /* [AO_SERIAL_SPEED_9600] = */ { + F_CPU / (16UL * 9600UL) - 1 + }, + /* [AO_SERIAL_SPEED_19200] = */ { + F_CPU / (16UL * 19200UL) - 1 + }, + /* [AO_SERIAL_SPEED_57600] = */ { + F_CPU / (16UL * 57600UL) - 1 + }, +}; + +void +ao_serial_set_speed(uint8_t speed) +{ + ao_serial_drain(); + if (speed > AO_SERIAL_SPEED_57600) + return; + UBRR1L = ao_serial_speeds[speed].ubrr; + UBRR1H = ao_serial_speeds[speed].ubrr >> 8; +} + +void +ao_serial_init(void) +{ + /* Ensure the uart is powered up */ + + PRR1 &= ~(1 << PRUSART1); + + /* Pick a 9600 baud rate */ + ao_serial_set_speed(AO_SERIAL_SPEED_9600); + + UCSR1A = 0; + UCSR1C = ((0 << UMSEL10) | /* Asynchronous mode */ + (0 << UPM10) | /* No parity */ + (0 << USBS1) | /* 1 stop bit */ + (3 << UCSZ10) | /* 8 bit characters */ + (0 << UCPOL1)); /* MBZ for async mode */ + UCSR1B = ((1 << RXEN1) | /* Enable receiver */ + (1 << TXEN1) | /* Enable transmitter */ + (1 << RXCIE1) | /* Enable receive interrupts */ + (1 << UDRIE1)); /* Enable transmit empty interrupts */ +#if 0 +#if USE_SERIAL_STDIN + int8_t i; + i = ao_add_stdio(ao_serial_pollchar, + ao_serial_putchar, + NULL); + printf("Register serial stdio as %d\n", i); +#endif +#endif +} diff --git a/src/avr/ao_timer.c b/src/avr/ao_timer.c new file mode 100644 index 00000000..1e374c75 --- /dev/null +++ b/src/avr/ao_timer.c @@ -0,0 +1,147 @@ +/* + * Copyright © 2009 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" + +static volatile __data uint16_t ao_tick_count; + +uint16_t ao_time(void) +{ + uint16_t v; + ao_arch_critical( + v = ao_tick_count; + ); + return v; +} + +static __xdata uint8_t ao_forever; + +void +ao_delay(uint16_t ticks) +{ + ao_alarm(ticks); + ao_sleep(&ao_forever); +} + +#define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ +#define T1_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ + +#if HAS_ADC +volatile __data uint8_t ao_adc_interval = 1; +volatile __data uint8_t ao_adc_count; +#endif + +void +ao_debug_out(char c); + +ISR(TIMER1_COMPA_vect) +{ + ++ao_tick_count; +#if HAS_ADC + if (++ao_adc_count == ao_adc_interval) { + ao_adc_count = 0; + ao_adc_poll(); + } +#endif +} + +#if HAS_ADC +void +ao_timer_set_adc_interval(uint8_t interval) __critical +{ + ao_adc_interval = interval; + ao_adc_count = 0; +} +#endif + +void +ao_timer_init(void) +{ + TCCR1A = ((0 << WGM11) | /* CTC mode, OCR1A */ + (0 << WGM10)); /* CTC mode, OCR1A */ + TCCR1B = ((0 << ICNC1) | /* no input capture noise canceler */ + (0 << ICES1) | /* input capture on falling edge (don't care) */ + (0 << WGM13) | /* CTC mode, OCR1A */ + (1 << WGM12) | /* CTC mode, OCR1A */ + (3 << CS10)); /* clk/64 from prescaler */ + +#if TEENSY + OCR1A = 2500; /* 16MHz clock */ +#else + OCR1A = 1250; /* 8MHz clock */ +#endif + + TIMSK1 = (1 << OCIE1A); /* Interrupt on compare match */ +} + +/* + * AltOS always cranks the clock to the max frequency + */ +void +ao_clock_init(void) +{ + /* disable RC clock */ + CLKSEL0 &= ~(1 << RCE); + + /* Disable PLL */ + PLLCSR &= ~(1 << PLLE); + + /* Enable external clock */ + CLKSEL0 |= (1 << EXTE); + + /* wait for external clock to be ready */ + while ((CLKSTA & (1 << EXTON)) == 0) + ; + + /* select external clock */ + CLKSEL0 |= (1 << CLKS); + + /* Disable the clock prescaler */ + cli(); + CLKPR = (1 << CLKPCE); + + /* Always run the system clock at 8MHz */ +#if AVR_CLOCK > 12000000UL + CLKPR = 1; +#else + CLKPR = 0; +#endif + sei(); + + /* Set up the PLL to use the crystal */ + + /* Use primary system clock as PLL source */ + PLLFRQ = ((0 << PINMUX) | /* Use primary clock */ + (0 << PLLUSB) | /* No divide by 2 for USB */ + (0 << PLLTM0) | /* Disable high speed timer */ + (0x4 << PDIV0)); /* 48MHz PLL clock */ + + /* Set the frequency of the crystal */ +#if AVR_CLOCK > 12000000UL + PLLCSR |= (1 << PINDIV); /* For 16MHz crystal on Teensy board */ +#else + PLLCSR &= ~(1 << PINDIV); /* For 8MHz crystal on TeleScience board */ +#endif + + /* Enable the PLL */ + PLLCSR |= (1 << PLLE); + while (!(PLLCSR & (1 << PLOCK))) + ; + + set_sleep_mode(SLEEP_MODE_IDLE); + sleep_enable(); +} diff --git a/src/avr/ao_usb.h b/src/avr/ao_usb.h new file mode 100644 index 00000000..6633dafc --- /dev/null +++ b/src/avr/ao_usb.h @@ -0,0 +1,100 @@ +/* + * Copyright © 2009 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_USB_H_ +#define _AO_USB_H_ + +#define AO_USB_SETUP_DIR_MASK (0x01 << 7) +#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) +#define AO_USB_SETUP_RECIP_MASK (0x1f) + +#define AO_USB_DIR_OUT 0 +#define AO_USB_DIR_IN (1 << 7) + +#define AO_USB_TYPE_STANDARD 0 +#define AO_USB_TYPE_CLASS (1 << 5) +#define AO_USB_TYPE_VENDOR (2 << 5) +#define AO_USB_TYPE_RESERVED (3 << 5) + +#define AO_USB_RECIP_DEVICE 0 +#define AO_USB_RECIP_INTERFACE 1 +#define AO_USB_RECIP_ENDPOINT 2 +#define AO_USB_RECIP_OTHER 3 + +/* standard requests */ +#define AO_USB_REQ_GET_STATUS 0x00 +#define AO_USB_REQ_CLEAR_FEATURE 0x01 +#define AO_USB_REQ_SET_FEATURE 0x03 +#define AO_USB_REQ_SET_ADDRESS 0x05 +#define AO_USB_REQ_GET_DESCRIPTOR 0x06 +#define AO_USB_REQ_SET_DESCRIPTOR 0x07 +#define AO_USB_REQ_GET_CONFIGURATION 0x08 +#define AO_USB_REQ_SET_CONFIGURATION 0x09 +#define AO_USB_REQ_GET_INTERFACE 0x0A +#define AO_USB_REQ_SET_INTERFACE 0x0B +#define AO_USB_REQ_SYNCH_FRAME 0x0C + +#define AO_USB_DESC_DEVICE 1 +#define AO_USB_DESC_CONFIGURATION 2 +#define AO_USB_DESC_STRING 3 +#define AO_USB_DESC_INTERFACE 4 +#define AO_USB_DESC_ENDPOINT 5 +#define AO_USB_DESC_DEVICE_QUALIFIER 6 +#define AO_USB_DESC_OTHER_SPEED 7 +#define AO_USB_DESC_INTERFACE_POWER 8 + +#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) +#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) + +#define AO_USB_CONTROL_EP 0 +#define AO_USB_INT_EP 1 +#define AO_USB_OUT_EP 4 +#define AO_USB_IN_EP 5 +#define AO_USB_CONTROL_SIZE 32 +/* + * Double buffer IN and OUT EPs, so each + * gets half of the available space + * + * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 + * byte sizes, so we'll use 64 for everything + */ +#define AO_USB_IN_SIZE 64 +#define AO_USB_OUT_SIZE 64 + +#define AO_USB_EP0_IDLE 0 +#define AO_USB_EP0_DATA_IN 1 +#define AO_USB_EP0_DATA_OUT 2 + +#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) + +/* CDC definitions */ +#define CS_INTERFACE 0x24 +#define CS_ENDPOINT 0x25 + +#define SET_LINE_CODING 0x20 +#define GET_LINE_CODING 0x21 +#define SET_CONTROL_LINE_STATE 0x22 + +/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ +struct ao_usb_line_coding { + uint32_t rate; + uint8_t char_format; + uint8_t parity; + uint8_t data_bits; +} ; + +#endif /* _AO_USB_H_ */ diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c new file mode 100644 index 00000000..74bdea23 --- /dev/null +++ b/src/avr/ao_usb_avr.c @@ -0,0 +1,688 @@ +/* + * 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" +#include "ao_usb.h" + +#define USB_DEBUG 0 + +#if USB_DEBUG +#define debug(format, args...) printf(format, ## args) +#else +#define debug(format, args...) +#endif + +struct ao_task __xdata ao_usb_task; + +struct ao_usb_setup { + uint8_t dir_type_recip; + uint8_t request; + uint16_t value; + uint16_t index; + uint16_t length; +} __xdata ao_usb_setup; + +static __xdata uint8_t ao_usb_ep0_state; +static const uint8_t * __xdata ao_usb_ep0_in_data; +static __xdata uint8_t ao_usb_ep0_in_len; +static __xdata uint8_t ao_usb_ep0_in_pending; +static __xdata uint8_t ao_usb_addr_pending; +static __xdata uint8_t ao_usb_ep0_in_buf[2]; +static __xdata uint8_t ao_usb_ep0_out_len; +static __xdata uint8_t *__xdata ao_usb_ep0_out_data; + +static __xdata uint8_t ao_usb_in_flushed; +static __xdata uint8_t ao_usb_running; +static __xdata uint8_t ao_usb_configuration; +static __xdata uint8_t ueienx_0; + +void +ao_usb_set_address(uint8_t address) +{ + UDADDR = (0 << ADDEN) | address; + ao_usb_addr_pending = 1; +} + +#define EP_SIZE(s) ((s) == 64 ? 0x30 : \ + ((s) == 32 ? 0x20 : \ + ((s) == 16 ? 0x10 : \ + 0x00))) + +static void +ao_usb_dump_ep(uint8_t ep) +{ + UENUM = ep; + debug ("EP %d: UECONX %02x UECFG0X %02x UECFG1X %02x UEIENX %02x UESTA0X %02x UESTA1X %02X\n", + ep, UECONX, UECFG0X, UECFG1X, UEIENX, UESTA0X, UESTA1X); +} + +static void +ao_usb_set_ep0(void) +{ + debug ("set_ep0\n"); + /* Set the CONTROL max packet size, single buffered */ + UENUM = 0; + UECONX = (1 << EPEN); /* Enable */ + + UECFG0X = ((0 << EPTYPE0) | /* Control */ + (0 << EPDIR)); /* Out (ish) */ + + UECFG1X = (EP_SIZE(AO_USB_CONTROL_SIZE) | /* Size */ + (0 << EPBK0) | /* Single bank */ + (1 << ALLOC)); + + ueienx_0 = ((1 << RXSTPE) | /* Enable SETUP interrupt */ + (1 << RXOUTE)); /* Enable OUT interrupt */ + +// ao_usb_dump_ep(0); + ao_usb_addr_pending = 0; +} + +static void +ao_usb_set_configuration(void) +{ + /* Set the IN max packet size, double buffered */ + UENUM = AO_USB_IN_EP; + UECONX = (1 << EPEN); /* Enable */ + + UECFG0X = ((2 << EPTYPE0) | /* Bulk */ + (1 << EPDIR)); /* In */ + + UECFG1X = (EP_SIZE(AO_USB_IN_SIZE) | /* Size */ + (1 << EPBK0) | /* Double bank */ + (1 << ALLOC)); /* Allocate */ + +#if 0 + UEIENX = ((1 << TXINE)); /* Enable IN complete interrupt */ +#endif + + ao_usb_dump_ep(AO_USB_IN_EP); + + /* Set the OUT max packet size, double buffered */ + UENUM = AO_USB_OUT_EP; + UECONX |= (1 << EPEN); /* Enable */ + + UECFG0X = ((2 << EPTYPE0) | /* Bulk */ + (0 << EPDIR)); /* Out */ + + UECFG1X = (EP_SIZE(AO_USB_OUT_SIZE) | /* Size */ + (1 << EPBK0) | /* Double bank */ + (1 << ALLOC)); /* Allocate */ + + UEIENX = ((1 << RXOUTE)); /* Enable OUT complete interrupt */ + + ao_usb_dump_ep(AO_USB_OUT_EP); + ao_usb_running = 1; +} + +ISR(USB_GEN_vect) +{ + ao_wakeup(&ao_usb_task); +} + + +__xdata static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; + +/* Walk through the list of descriptors and find a match + */ +static void +ao_usb_get_descriptor(uint16_t value) +{ + const uint8_t *__xdata descriptor; + __xdata uint8_t type = value >> 8; + __xdata uint8_t index = value; + + descriptor = ao_usb_descriptors; + while (descriptor[0] != 0) { + if (descriptor[1] == type && index-- == 0) { + if (type == AO_USB_DESC_CONFIGURATION) + ao_usb_ep0_in_len = descriptor[2]; + else + ao_usb_ep0_in_len = descriptor[0]; + ao_usb_ep0_in_data = descriptor; + break; + } + descriptor += descriptor[0]; + } +} + +static void +ao_usb_ep0_set_in_pending(uint8_t in_pending) +{ + ao_usb_ep0_in_pending = in_pending; + + if (in_pending) + ueienx_0 = ((1 << RXSTPE) | (1 << RXOUTE) | (1 << TXINE)); /* Enable IN interrupt */ +} + +/* Send an IN data packet */ +static void +ao_usb_ep0_flush(void) +{ + __xdata uint8_t this_len; + + cli(); + UENUM = 0; + if (!(UEINTX & (1 << TXINI))) { + debug("EP0 not accepting IN data\n"); + ao_usb_ep0_set_in_pending(1); + } else { + this_len = ao_usb_ep0_in_len; + if (this_len > AO_USB_CONTROL_SIZE) + this_len = AO_USB_CONTROL_SIZE; + + ao_usb_ep0_in_len -= this_len; + + /* Set IN interrupt enable */ + if (ao_usb_ep0_in_len == 0 && this_len != AO_USB_CONTROL_SIZE) + ao_usb_ep0_set_in_pending(0); + else + ao_usb_ep0_set_in_pending(1); + + debug ("Flush EP0 len %d:", this_len); + while (this_len--) { + uint8_t c = *ao_usb_ep0_in_data++; + debug(" %02x", c); + UEDATX = c; + } + debug ("\n"); + + /* Clear the TXINI bit to send the packet */ + UEINTX &= ~(1 << TXINI); + } + sei(); +} + +/* Read data from the ep0 OUT fifo */ +static void +ao_usb_ep0_fill(uint8_t len, uint8_t ack) +{ + if (len > ao_usb_ep0_out_len) + len = ao_usb_ep0_out_len; + ao_usb_ep0_out_len -= len; + +// debug ("EP0 UEINTX %02x UEBCLX %d UEBCHX %d\n", +// UEINTX, UEBCLX, UEBCHX); + /* Pull all of the data out of the packet */ + debug ("Fill EP0 len %d:", len); + UENUM = 0; + while (len--) { + uint8_t c = UEDATX; + *ao_usb_ep0_out_data++ = c; + debug (" %02x", c); + } + debug ("\n"); + + /* ACK the packet */ + UEINTX &= ~ack; +} + +void +ao_usb_ep0_queue_byte(uint8_t a) +{ + ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; +} + +static void +ao_usb_ep0_setup(void) +{ + /* Pull the setup packet out of the fifo */ + ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_setup; + ao_usb_ep0_out_len = 8; + ao_usb_ep0_fill(8, (1 << RXSTPI) | (1 << RXOUTI) | (1 << TXINI)); + if (ao_usb_ep0_out_len != 0) { + debug ("invalid setup packet length\n"); + return; + } + + /* Figure out how to ACK the setup packet */ + if (ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) { + if (ao_usb_setup.length) + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + else + ao_usb_ep0_state = AO_USB_EP0_IDLE; + } else { + if (ao_usb_setup.length) + ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; + else + ao_usb_ep0_state = AO_USB_EP0_IDLE; + } +/* + UENUM = 0; + if (ao_usb_ep0_state == AO_USB_EP0_IDLE) + USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; + else + USBCS0 = USBCS0_CLR_OUTPKT_RDY; +*/ + + ao_usb_ep0_in_data = ao_usb_ep0_in_buf; + ao_usb_ep0_in_len = 0; + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) { + case AO_USB_TYPE_STANDARD: + debug ("Standard setup packet\n"); + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) { + case AO_USB_RECIP_DEVICE: + debug ("Device setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + debug ("get status\n"); + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_SET_ADDRESS: + debug ("set address %d\n", ao_usb_setup.value); + ao_usb_set_address(ao_usb_setup.value); + break; + case AO_USB_REQ_GET_DESCRIPTOR: + debug ("get descriptor %d\n", ao_usb_setup.value); + ao_usb_get_descriptor(ao_usb_setup.value); + break; + case AO_USB_REQ_GET_CONFIGURATION: + debug ("get configuration %d\n", ao_usb_configuration); + ao_usb_ep0_queue_byte(ao_usb_configuration); + break; + case AO_USB_REQ_SET_CONFIGURATION: + ao_usb_configuration = ao_usb_setup.value; + debug ("set configuration %d\n", ao_usb_configuration); + ao_usb_set_configuration(); + break; + } + break; + case AO_USB_RECIP_INTERFACE: +#ifndef AVR + #pragma disable_warning 110 +#endif + debug ("Interface setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_GET_INTERFACE: + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_SET_INTERFACE: + break; + } + break; + case AO_USB_RECIP_ENDPOINT: + debug ("Endpoint setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + } + break; + } + break; + case AO_USB_TYPE_CLASS: + debug ("Class setup packet\n"); + switch (ao_usb_setup.request) { + case SET_LINE_CODING: + debug ("set line coding\n"); + ao_usb_ep0_out_len = 7; + ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding; + break; + case GET_LINE_CODING: + debug ("get line coding\n"); + ao_usb_ep0_in_len = 7; + ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; + break; + case SET_CONTROL_LINE_STATE: + break; + } + break; + } + if (ao_usb_ep0_state != AO_USB_EP0_DATA_OUT) { + if (ao_usb_setup.length < ao_usb_ep0_in_len) + ao_usb_ep0_in_len = ao_usb_setup.length; + debug ("Start ep0 in delivery %d\n", ao_usb_ep0_in_len); + ao_usb_ep0_set_in_pending(1); + } +} + +/* End point 0 receives all of the control messages. */ +static void +ao_usb_ep0(void) +{ + uint8_t intx, udint; + + debug ("usb task started\n"); + ao_usb_ep0_state = AO_USB_EP0_IDLE; + for (;;) { + cli(); + for (;;) { + udint = UDINT; + UDINT = 0; +// debug ("UDINT %02x\n", udint); + if (udint & (1 << EORSTI)) { + ao_usb_configuration = 0; + ao_usb_set_ep0(); + } + UENUM = 0; + intx = UEINTX; +// debug ("UEINTX %02x\n", intx); + if (intx & ((1 << RXSTPI) | (1 << RXOUTI))) + break; + if ((intx & (1 << TXINI))) { + if (ao_usb_ep0_in_pending) + break; + else + { + if (ao_usb_addr_pending) { + UDADDR |= (1 << ADDEN); + ao_usb_addr_pending = 0; + } + ueienx_0 = ((1 << RXSTPE) | (1 << RXOUTE)); /* Disable IN interrupt */ + } + } +// debug ("usb task sleeping...\n"); + UENUM = 0; + UEIENX = ueienx_0; + ao_sleep(&ao_usb_task); + } + sei(); +// debug ("UEINTX for ep0 is %02x\n", intx); + if (intx & (1 << RXSTPI)) { + ao_usb_ep0_setup(); + } + if (intx & (1 << RXOUTI)) { + ao_usb_ep0_fill(UEBCLX, (1 << RXOUTI)); + ao_usb_ep0_set_in_pending(1); + } + if (intx & (1 << TXINI) && ao_usb_ep0_in_pending) { + debug ("continue sending ep0 IN data\n"); + ao_usb_ep0_flush(); + } + } +} + +/* Wait for a free IN buffer */ +static void +ao_usb_in_wait(void) +{ + for (;;) { + /* Check if the current buffer is writable */ + UENUM = AO_USB_IN_EP; + if (UEINTX & (1 << RWAL)) + break; + + cli(); + /* Wait for an IN buffer to be ready */ + for (;;) { + UENUM = AO_USB_IN_EP; + if ((UEINTX & (1 << TXINI))) + break; + UEIENX = (1 << TXINE); + ao_sleep(&ao_usb_in_flushed); + } + /* Ack the interrupt */ + UEINTX &= ~(1 << TXINI); + sei(); + } +} + +/* Queue the current IN buffer for transmission */ +static void +ao_usb_in_send(void) +{ + UENUM = AO_USB_IN_EP; + UEINTX &= ~(1 << FIFOCON); +} + +void +ao_usb_flush(void) __critical +{ + if (!ao_usb_running) + return; + + /* Anytime we've sent a character since + * the last time we flushed, we'll need + * to send a packet -- the only other time + * we would send a packet is when that + * packet was full, in which case we now + * want to send an empty packet + */ + if (!ao_usb_in_flushed) { + ao_usb_in_flushed = 1; + ao_usb_in_wait(); + ao_usb_in_send(); + } +} + +void +ao_usb_putchar(char c) __critical __reentrant +{ + if (!ao_usb_running) + return; + + ao_usb_in_wait(); + + /* Queue a byte */ + UENUM = AO_USB_IN_EP; + UEDATX = c; + + /* Send the packet when full */ + if ((UEINTX & (1 << RWAL)) == 0) + ao_usb_in_send(); + ao_usb_in_flushed = 0; +} + +static char +_ao_usb_pollchar(void) +{ + char c; + uint8_t intx; + + if (!ao_usb_running) + return AO_READ_AGAIN; + + for (;;) { + UENUM = AO_USB_OUT_EP; + intx = UEINTX; + debug("usb_pollchar UEINTX %02d\n", intx); + if (intx & (1 << RWAL)) + break; + + if (intx & (1 << FIFOCON)) { + /* Ack the last packet */ + UEINTX = (uint8_t) ~(1 << FIFOCON); + } + + /* Check to see if a packet has arrived */ + if ((intx & (1 << RXOUTI)) == 0) { + UENUM = AO_USB_OUT_EP; + UEIENX = (1 << RXOUTE); + return AO_READ_AGAIN; + } + + /* Ack the interrupt */ + UEINTX = ~(1 << RXOUTI); + } + + /* Pull a character out of the fifo */ + c = UEDATX; + return c; +} + +char +ao_usb_pollchar(void) +{ + char c; + cli(); + c = _ao_usb_pollchar(); + sei(); + return c; +} + +char +ao_usb_getchar(void) __critical +{ + char c; + + cli(); + while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) + ao_sleep(&ao_stdin_ready); + sei(); + return c; +} + +uint16_t control_count; +uint16_t in_count; +uint16_t out_count; + +/* Endpoint interrupt */ +ISR(USB_COM_vect) +{ + uint8_t old_num = UENUM; + uint8_t i = UEINT; + +#ifdef AO_LED_RED + ao_led_toggle(AO_LED_RED); +#endif + UEINT = 0; + if (i & (1 << 0)) { + UENUM = 0; + UEIENX = 0; + ao_wakeup(&ao_usb_task); + ++control_count; + } + if (i & (1 << AO_USB_IN_EP)) { + UENUM = AO_USB_IN_EP; + UEIENX = 0; + ao_wakeup(&ao_usb_in_flushed); + in_count++; + } + if (i & (1 << AO_USB_OUT_EP)) { + UENUM = AO_USB_OUT_EP; + UEIENX = 0; + ao_wakeup(&ao_stdin_ready); + ++out_count; + } + UENUM = old_num; +} + +#if AVR_VCC_5V +#define AO_PAD_REGULATOR_INIT (1 << UVREGE) /* Turn on pad regulator */ +#endif +#if AVR_VCC_3V3 +/* TeleScience V0.1 has a hardware bug -- UVcc is hooked up, but UCap is not + * Make this work by running power through UVcc to the USB system + */ +#define AO_PAD_REGULATOR_INIT (1 << UVREGE) /* Turn off pad regulator */ +#endif + +#if AVR_CLOCK == 16000000UL +#define AO_USB_PLL_INPUT_PRESCALER (1 << PINDIV) /* Divide 16MHz clock by 2 */ +#endif +#if AVR_CLOCK == 8000000UL +#define AO_USB_PLL_INPUT_PRESCALER 0 /* Don't divide clock */ +#endif + +void +ao_usb_disable(void) +{ + /* Unplug from the bus */ + UDCON = (1 << DETACH); + + /* Disable the interface */ + USBCON = 0; + + /* Disable the PLL */ + PLLCSR = 0; + + /* Turn off the pad regulator */ + UHWCON = 0; +} + +#define AO_USB_CON ((1 << USBE) | /* USB enable */ \ + (0 << RSTCPU) | /* do not reset CPU */ \ + (0 << LSM) | /* Full speed mode */ \ + (0 << RMWKUP)) /* no remote wake-up */ \ + +void +ao_usb_enable(void) +{ + /* Configure pad regulator */ + UHWCON = AO_PAD_REGULATOR_INIT; + + /* Enable USB device, but freeze the clocks until initialized */ + USBCON = AO_USB_CON | (1 <stack_count = stack_len; \ + stack_ptr = (uint8_t __data *) AO_STACK_START; \ + save_ptr = (uint8_t __xdata *) ao_cur_task->stack; \ + do \ + *save_ptr++ = *stack_ptr++; \ + while (--stack_len); \ + } +#define ao_arch_isr_stack() \ + /* Empty the stack; might as well let interrupts have the whole thing */ \ + (SP = AO_STACK_START - 1) + +#define ao_arch_cpu_idle() (PCON = PCON_IDLE) + +#define ao_arch_restore_stack() { \ + uint8_t stack_len; \ + __data uint8_t *stack_ptr; \ + __xdata uint8_t *save_ptr; \ + \ + /* Restore the old stack */ \ + stack_len = ao_cur_task->stack_count; \ + SP = AO_STACK_START - 1 + stack_len; \ + \ + stack_ptr = (uint8_t __data *) AO_STACK_START; \ + save_ptr = (uint8_t __xdata *) ao_cur_task->stack; \ + do \ + *stack_ptr++ = *save_ptr++; \ + while (--stack_len); \ + \ + _asm \ + pop _bp \ + pop PSW \ + pop ar1 \ + pop ar0 \ + pop ar7 \ + pop ar6 \ + pop ar5 \ + pop ar4 \ + pop ar3 \ + pop ar2 \ + pop b \ + pop DPH \ + pop DPL \ + /* The next byte of the stack is the IE register. Only the global \ + enable bit forms part of the task context. Pop off the IE then set \ + the global enable bit to match that of the stored IE register. */ \ + pop ACC \ + JB ACC.7,0098$ \ + CLR _EA \ + LJMP 0099$ \ + 0098$: \ + SETB _EA \ + 0099$: \ + /* Finally pop off the ACC, which was the first register saved. */ \ + pop ACC \ + ret \ + _endasm; \ +} + +#define ao_arch_critical(b) __critical { b } #endif /* _AO_ARCH_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 9b0bb545..98a01a4a 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -37,9 +37,9 @@ struct ao_task { __xdata void *wchan; /* current wait channel (NULL if running) */ uint16_t alarm; /* abort ao_sleep time */ - uint8_t stack_count; /* amount of saved stack */ uint8_t task_id; /* unique id */ __code char *name; /* task name */ + ao_arch_task_members /* any architecture-specific fields */ uint8_t stack[AO_STACK_SIZE]; /* saved stack */ }; @@ -321,6 +321,10 @@ ao_usb_disable(void); void ao_usb_init(void); +#if HAS_USB +extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; +#endif + /* * ao_cmd.c */ @@ -1571,4 +1575,9 @@ extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; void ao_companion_init(void); +/* ao_lcd.c */ + +void +ao_lcd_init(void); + #endif /* _AO_H_ */ diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index cbfdf399..0668dad2 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -53,7 +53,7 @@ ao_panic(uint8_t reason) } ao_beep(AO_BEEP_OFF); ao_panic_delay(2); -#pragma disable_warning 126 + for (n = 0; n < reason; n++) { ao_led_on(AO_LED_RED); ao_beep(AO_BEEP_MID); diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 41520476..32826114 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -24,6 +24,10 @@ __data uint8_t ao_num_tasks; __data uint8_t ao_cur_task_index; __xdata struct ao_task *__data ao_cur_task; +#ifdef ao_arch_task_globals +ao_arch_task_globals +#endif + void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant { @@ -53,27 +57,16 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam void ao_yield(void) ao_arch_naked_define { - ao_arch_save_context(); + ao_arch_save_regs(); if (ao_cur_task_index == AO_NO_TASK_INDEX) ao_cur_task_index = ao_num_tasks-1; else { - uint8_t stack_len; - __data uint8_t *stack_ptr; - __xdata uint8_t *save_ptr; - /* Save the current stack */ - stack_len = SP - (AO_STACK_START - 1); - ao_cur_task->stack_count = stack_len; - stack_ptr = (uint8_t __data *) AO_STACK_START; - save_ptr = (uint8_t __xdata *) ao_cur_task->stack; - do - *save_ptr++ = *stack_ptr++; - while (--stack_len); + ao_arch_save_stack(); } - /* Empty the stack; might as well let interrupts have the whole thing */ - SP = AO_STACK_START - 1; + ao_arch_isr_stack(); /* Find a task to run. If there isn't any runnable task, * this loop will run forever, which is just fine @@ -99,63 +92,20 @@ ao_yield(void) ao_arch_naked_define } /* Enter lower power mode when there isn't anything to do */ - if (ao_next_task_index == ao_cur_task_index) - PCON = PCON_IDLE; + if (ao_next_task_index == ao_cur_task_index) { + ao_arch_cpu_idle(); + } } } - - { - uint8_t stack_len; - __data uint8_t *stack_ptr; - __xdata uint8_t *save_ptr; - - /* Restore the old stack */ - stack_len = ao_cur_task->stack_count; - SP = AO_STACK_START - 1 + stack_len; - - stack_ptr = (uint8_t __data *) AO_STACK_START; - save_ptr = (uint8_t __xdata *) ao_cur_task->stack; - do - *stack_ptr++ = *save_ptr++; - while (--stack_len); - } - - _asm - pop _bp - pop PSW - pop ar1 - pop ar0 - pop ar7 - pop ar6 - pop ar5 - pop ar4 - pop ar3 - pop ar2 - pop b - pop DPH - pop DPL - /* The next byte of the stack is the IE register. Only the global - enable bit forms part of the task context. Pop off the IE then set - the global enable bit to match that of the stored IE register. */ - pop ACC - JB ACC.7,0098$ - CLR _EA - LJMP 0099$ - 0098$: - SETB _EA - 0099$: - /* Finally pop off the ACC, which was the first register saved. */ - pop ACC - ret - _endasm; + ao_arch_restore_stack(); } uint8_t ao_sleep(__xdata void *wchan) { - __critical { + ao_arch_critical( ao_cur_task->wchan = wchan; - } + ); ao_yield(); ao_cur_task->alarm = 0; if (ao_cur_task->wchan) { @@ -186,14 +136,16 @@ ao_alarm(uint16_t delay) } void -ao_exit(void) __critical +ao_exit(void) { - uint8_t i; - ao_num_tasks--; - for (i = ao_cur_task_index; i < ao_num_tasks; i++) - ao_tasks[i] = ao_tasks[i+1]; - ao_cur_task_index = AO_NO_TASK_INDEX; - ao_yield(); + ao_arch_critical( + uint8_t i; + ao_num_tasks--; + for (i = ao_cur_task_index; i < ao_num_tasks; i++) + ao_tasks[i] = ao_tasks[i+1]; + ao_cur_task_index = AO_NO_TASK_INDEX; + ao_yield(); + ); /* we'll never get back here */ } @@ -201,16 +153,13 @@ void ao_task_info(void) { uint8_t i; - uint8_t pc_loc; __xdata struct ao_task *task; for (i = 0; i < ao_num_tasks; i++) { task = ao_tasks[i]; - pc_loc = task->stack_count - 17; - printf("%12s: wchan %04x pc %04x\n", + printf("%12s: wchan %04x\n", task->name, - (int16_t) task->wchan, - (task->stack[pc_loc]) | (task->stack[pc_loc+1] << 8)); + (int16_t) task->wchan); } } -- cgit v1.2.3 From c32893ce79835a8f861d6ef414644c2ff9769ff6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 26 Aug 2011 15:02:43 -0700 Subject: altos: Integrate telescience support Adds a few drivers including an LCD driver Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/avr/ao_adc_avr.c | 129 +++++++++++++++++++ src/avr/ao_arch.h | 9 ++ src/avr/ao_spi_slave.c | 142 +++++++++++++++++++++ src/avr/ao_spi_usart.c | 112 +++++++++++++++++ src/cc1111/ao_arch.h | 12 ++ src/core/ao.h | 40 ++++-- src/core/ao_log_telescience.c | 274 ++++++++++++++++++++++++++++++++++++++++ src/core/ao_panic.c | 4 + src/drivers/ao_companion.c | 2 +- src/drivers/ao_lcd.c | 281 ++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_m25.c | 2 + src/product/ao_telescience.c | 39 ++++++ src/telescience-v0.1/Makefile | 109 ++++++++++++++++ src/util/check-avr-mem | 9 ++ 15 files changed, 1153 insertions(+), 13 deletions(-) create mode 100644 src/avr/ao_adc_avr.c create mode 100644 src/avr/ao_spi_slave.c create mode 100644 src/avr/ao_spi_usart.c create mode 100644 src/core/ao_log_telescience.c create mode 100644 src/drivers/ao_lcd.c create mode 100644 src/product/ao_telescience.c create mode 100644 src/telescience-v0.1/Makefile create mode 100644 src/util/check-avr-mem (limited to 'src/core') diff --git a/src/Makefile b/src/Makefile index 4e40c2bf..caa91e83 100644 --- a/src/Makefile +++ b/src/Makefile @@ -18,7 +18,7 @@ SUBDIRS=\ telemini-v1.0 telenano-v0.1 \ telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ - tidongle test + tidongle test telescience-v0.1 all: all-local all-recursive diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c new file mode 100644 index 00000000..5afced74 --- /dev/null +++ b/src/avr/ao_adc_avr.c @@ -0,0 +1,129 @@ +/* + * 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" + +volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; +volatile __data uint8_t ao_adc_head; + +const uint8_t adc_channels[AO_LOG_TELESCIENCE_NUM_ADC] = { + 0x00, + 0x01, + 0x04, + 0x05, + 0x06, + 0x07, + 0x20, + 0x21, + 0x22, + 0x23, + 0x24, + 0x25, +}; + +static uint8_t ao_adc_channel; + +#define ADC_CHANNEL_LOW(c) (((c) & 0x1f) << MUX0) +#define ADC_CHANNEL_HIGH(c) ((((c) & 0x20) >> 5) << MUX5) + +#define ADCSRA_INIT ((1 << ADEN) | /* Enable ADC */ \ + (0 << ADATE) | /* No auto ADC trigger */ \ + (1 << ADIF) | /* Clear interrupt */ \ + (0 << ADIE) | /* Enable interrupt */ \ + (6 << ADPS0)) /* Prescale clock by 64 */ + +#define ADCSRB_INIT ((0 << ADHSM) | /* No high-speed mode */ \ + (0 << ACME) | /* Some comparitor thing */ \ + (2 << ADTS0)) /* Free running mode (don't care) */ + +static void +ao_adc_start(void) +{ + uint8_t channel = adc_channels[ao_adc_channel]; + ADMUX = ((0 << REFS1) | /* AVcc reference */ + (1 << REFS0) | /* AVcc reference */ + (1 << ADLAR) | /* Left-shift results */ + (ADC_CHANNEL_LOW(channel))); /* Select channel */ + + ADCSRB = (ADCSRB_INIT | + ADC_CHANNEL_HIGH(channel)); /* High channel bit */ + + ADCSRA = (ADCSRA_INIT | + (1 << ADSC) | + (1 << ADIE)); /* Start conversion */ +} + +ISR(ADC_vect) +{ + uint16_t value; + + /* Must read ADCL first or the value there will be lost */ + value = ADCL; + value |= (ADCH << 8); + ao_adc_ring[ao_adc_head].adc[ao_adc_channel] = value; + if (++ao_adc_channel < AO_TELESCIENCE_NUM_ADC) + ao_adc_start(); + else { + ADCSRA = ADCSRA_INIT; + ao_adc_ring[ao_adc_head].tick = ao_time(); + ao_adc_head = ao_adc_ring_next(ao_adc_head); + ao_wakeup((void *) &ao_adc_head); + ao_cpu_sleep_disable = 0; + } +} + +void +ao_adc_poll(void) +{ + ao_cpu_sleep_disable = 1; + ao_adc_channel = 0; + ao_adc_start(); +} + +void +ao_adc_get(__xdata struct ao_adc *packet) +{ + uint8_t i = ao_adc_ring_prev(ao_adc_head); + memcpy(packet, (void *) &ao_adc_ring[i], sizeof (struct ao_adc)); +} + +static void +ao_adc_dump(void) __reentrant +{ + static __xdata struct ao_adc packet; + uint8_t i; + ao_adc_get(&packet); + printf("tick: %5u", packet.tick); + for (i = 0; i < AO_TELESCIENCE_NUM_ADC; i++) + printf (" %2d: %5u", i, packet.adc[i]); + printf ("\n"); +} + +__code struct ao_cmds ao_adc_cmds[] = { + { ao_adc_dump, "a\0Display current ADC values" }, + { 0, NULL }, +}; + +void +ao_adc_init(void) +{ + DIDR0 = 0xf3; + DIDR2 = 0x3f; + ADCSRB = ADCSRB_INIT; + ADCSRA = ADCSRA_INIT; + ao_cmd_register(&ao_adc_cmds[0]); +} diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index 0ed97361..c695a725 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -145,5 +145,14 @@ extern uint8_t ao_cpu_sleep_disable; #define ao_arch_critical(b) do { cli(); b; sei(); } while (0) +#define AO_TELESCIENCE_NUM_ADC 12 + +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + uint16_t adc[AO_TELESCIENCE_NUM_ADC]; /* samples */ +}; + +#define AO_ADC_RING 16 + #endif /* _AO_ARCH_H_ */ diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c new file mode 100644 index 00000000..4dde09f3 --- /dev/null +++ b/src/avr/ao_spi_slave.c @@ -0,0 +1,142 @@ +/* + * 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" +#include "ao_product.h" + +struct ao_companion_command ao_companion_command; + +static const struct ao_companion_setup ao_telescience_setup = { + .board_id = AO_idProduct_NUMBER, + .board_id_inverse = ~AO_idProduct_NUMBER, + .update_period = 50, + .channels = AO_LOG_TELESCIENCE_NUM_ADC, +}; + +static uint8_t +ao_spi_read(uint8_t *buf, uint8_t len) +{ + while (len--) { + while (!(SPSR & (1 << SPIF))) + if ((PINB & (1 << PINB0))) + return 0; + *buf++ = SPDR; + } + return 1; +} + +static void +ao_spi_write(uint8_t *buf, uint8_t len) +{ + while (len--) { + SPDR = *buf++; + while (!(SPSR & (1 << SPIF))) + if ((PINB & (1 << PINB0))) + return; + } + /* Clear pending SPIF bit by reading */ + (void) SPDR; +} + +static uint8_t ao_spi_slave_recv(void) +{ + if (!ao_spi_read((uint8_t *) &ao_companion_command, + sizeof (ao_companion_command))) + return 0; + + /* Figure out the outbound data */ + switch (ao_companion_command.command) { + case AO_COMPANION_SETUP: + ao_spi_write((uint8_t *) &ao_telescience_setup, + sizeof (ao_telescience_setup)); + break; + case AO_COMPANION_FETCH: + ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); + break; + case AO_COMPANION_NOTIFY: + break; + default: + return 0; + } + + ao_log_store.tm_tick = ao_companion_command.tick; + if (ao_log_store.tm_state != ao_companion_command.flight_state) { + ao_log_store.tm_state = ao_companion_command.flight_state; + return 1; + } + return 0; +} + +static uint8_t ao_spi_slave_running; + +ISR(PCINT0_vect) +{ + if ((PINB & (1 << PINB0)) == 0) { + if (!ao_spi_slave_running) { + uint8_t changed; + ao_spi_slave_running = 1; + cli(); + changed = ao_spi_slave_recv(); + sei(); + if (changed && ao_flight_boost <= ao_log_store.tm_state) { + if (ao_log_store.tm_state < ao_flight_landed) + ao_log_start(); + else + ao_log_stop(); + } + } + } else { + ao_spi_slave_running = 0; + } +} + +void ao_spi_slave_debug(void) { + printf ("slave running %d\n", ao_spi_slave_running); +} + +void +ao_spi_slave_init(void) +{ + PCMSK0 |= (1 << PCINT0); /* Enable PCINT0 pin change */ + PCICR |= (1 << PCIE0); /* Enable pin change interrupt */ + + DDRB = ((DDRB & 0xf0) | + (1 << 3) | /* MISO, output */ + (0 << 2) | /* MOSI, input */ + (0 << 1) | /* SCK, input */ + (0 << 0)); /* SS, input */ + + /* We'd like to have a pull-up on SS so that disconnecting the + * TM would cause any SPI transaction to abort. However, when + * I tried that, SPI transactions would spontaneously abort, + * making me assume that we needed a less aggressive pull-up + * than is offered inside the AVR + */ + PORTB = ((PORTB & 0xf0) | + (1 << 3) | /* MISO, output */ + (0 << 2) | /* MOSI, no pull-up */ + (0 << 1) | /* SCK, no pull-up */ + (0 << 0)); /* SS, no pull-up */ + + SPCR = (0 << SPIE) | /* Disable SPI interrupts */ + (1 << SPE) | /* Enable SPI */ + (0 << DORD) | /* MSB first */ + (0 << MSTR) | /* Slave mode */ + (0 << CPOL) | /* Clock low when idle */ + (0 << CPHA); /* Sample at leading clock edge */ +} diff --git a/src/avr/ao_spi_usart.c b/src/avr/ao_spi_usart.c new file mode 100644 index 00000000..6ed708ff --- /dev/null +++ b/src/avr/ao_spi_usart.c @@ -0,0 +1,112 @@ +/* + * 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" + +/* + * Atmega32u4 USART in MSPIM (master SPI mode) + */ + +__xdata uint8_t ao_spi_mutex; + +/* Send bytes over SPI. + * + * This just polls; the SPI is set to go as fast as possible, + * so using interrupts would take way too long + */ +void +ao_spi_send(void __xdata *block, uint16_t len) __reentrant +{ + uint8_t *d = block; + + ao_mutex_get(&ao_spi_mutex); + while (len--) { + while (!(UCSR1A & (1 << UDRE1))); + UDR1 = *d++; + while (!(UCSR1A & (1 << RXC1))); + (void) UDR1; + } + ao_mutex_put(&ao_spi_mutex); +} + +/* Receive bytes over SPI. + * + * This sets up tow DMA engines, one reading the data and another + * writing constant values to the SPI transmitter as that is what + * clocks the data coming in. + */ +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant +{ + uint8_t *d = block; + + ao_mutex_get(&ao_spi_mutex); + while (len--) { + while (!(UCSR1A & (1 << UDRE1))); + UDR1 = 0; + while (!(UCSR1A & (1 << RXC1))); + *d++ = UDR1; + } + ao_mutex_put(&ao_spi_mutex); +} + +/* + * Initialize USART0 for SPI using config alt 2 + * + * MO P1_5 + * MI P1_4 + * CLK P1_3 + * + * Chip select is the responsibility of the caller + */ + +#define XCK1_DDR DDRD +#define XCK1_PORT PORTD +#define XCK1 PORTD5 +#define XMS1_DDR DDRE +#define XMS1_PORT PORTE +#define XMS1 PORTE6 + +void +ao_spi_init(void) +{ + /* Ensure the USART is powered */ + PRR1 &= ~(1 << PRUSART1); + + /* + * Set pin directions + */ + XCK1_DDR |= (1 << XCK1); + + /* Clear chip select (which is negated) */ + XMS1_PORT |= (1 < XMS1); + XMS1_DDR |= (1 << XMS1); + + /* Set baud register to zero (required before turning transmitter on) */ + UBRR1 = 0; + + UCSR1C = ((0x3 << UMSEL10) | /* Master SPI mode */ + (0 << UCSZ10) | /* SPI mode 0 */ + (0 << UCPOL1)); /* SPI mode 0 */ + + /* Enable transmitter and receiver */ + UCSR1B = ((1 << RXEN1) | + (1 << TXEN1)); + + /* It says that 0 is a legal value; we'll see... */ + UBRR1 = 0; +} diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index c4972819..8a41791f 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -192,4 +192,16 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; #define ao_arch_critical(b) __critical { b } +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +}; + +#define AO_ADC_RING 32 + #endif /* _AO_ARCH_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 98a01a4a..05f056fd 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -144,15 +144,6 @@ ao_clock_init(void); /* * One set of samples read from the A/D converter or telemetry */ -struct ao_adc { - uint16_t tick; /* tick when the sample was read */ - int16_t accel; /* accelerometer */ - int16_t pres; /* pressure sensor */ - int16_t temp; /* temperature sensor */ - int16_t v_batt; /* battery voltage */ - int16_t sense_d; /* drogue continuity sense */ - int16_t sense_m; /* main continuity sense */ -}; #if HAS_ADC @@ -160,7 +151,6 @@ struct ao_adc { * ao_adc.c */ -#define AO_ADC_RING 32 #define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) #define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) @@ -505,6 +495,23 @@ extern __pdata uint32_t ao_log_start_pos; extern __xdata uint8_t ao_log_running; extern __pdata enum flight_state ao_log_state; +#define AO_LOG_TELESCIENCE_START ((uint8_t) 's') +#define AO_LOG_TELESCIENCE_DATA ((uint8_t) 'd') + +#define AO_LOG_TELESCIENCE_NUM_ADC 12 + +struct ao_log_telescience { + uint8_t type; + uint8_t csum; + uint16_t tick; + uint16_t tm_tick; + uint8_t tm_state; + uint8_t unused; + uint16_t adc[AO_LOG_TELESCIENCE_NUM_ADC]; +}; + +extern struct ao_log_telescience ao_log_store; + /* required functions from the underlying log system */ #define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ @@ -970,6 +977,16 @@ ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; void ao_spi_init(void); +/* + * ao_spi_slave.c + */ + +void +ao_spi_slave_debug(void); + +void +ao_spi_slave_init(void); + /* * ao_telemetry.c */ @@ -1568,8 +1585,9 @@ struct ao_companion_setup { }; 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 struct ao_companion_command ao_companion_command; +extern __xdata struct ao_companion_setup ao_companion_setup; extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; void diff --git a/src/core/ao_log_telescience.c b/src/core/ao_log_telescience.c new file mode 100644 index 00000000..aac780fa --- /dev/null +++ b/src/core/ao_log_telescience.c @@ -0,0 +1,274 @@ +/* + * 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" +#include "ao_product.h" + +static struct ao_task ao_log_task; +//static struct ao_task ao_spi_task; + +uint8_t ao_log_running; +uint8_t ao_log_mutex; +uint32_t ao_log_start_pos; +uint32_t ao_log_end_pos; +uint32_t ao_log_current_pos; + +#define AO_LOG_TELESCIENCE_START ((uint8_t) 's') +#define AO_LOG_TELESCIENCE_DATA ((uint8_t) 'd') + +struct ao_log_telescience ao_log_store; +struct ao_log_telescience ao_log_fetch; + +static uint8_t ao_log_adc_pos; + +__code uint8_t ao_log_format = AO_LOG_FORMAT_TELESCIENCE; + +static uint8_t +ao_log_csum(__xdata uint8_t *b) __reentrant +{ + uint8_t sum = 0x5a; + uint8_t i; + + for (i = 0; i < sizeof (struct ao_log_telescience); i++) + sum += *b++; + return -sum; +} + +static uint8_t +ao_log_telescience_write(void) +{ + uint8_t wrote = 0; + + ao_log_store.csum = 0; + ao_log_store.csum = ao_log_csum((__xdata uint8_t *) &ao_log_store); + ao_mutex_get(&ao_log_mutex); { + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + (__xdata uint8_t *) &ao_log_store, + sizeof (struct ao_log_telescience)); + ao_log_current_pos += sizeof (struct ao_log_telescience); + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_valid(struct ao_log_telescience *log) +{ + uint8_t *d; + uint8_t i; + d = (uint8_t *) log; + for (i = 0; i < sizeof (struct ao_log_telescience); i++) + if (d[i] != 0xff) + return 1; + return 0; +} + +static uint8_t +ao_log_telescience_read(uint32_t pos) +{ + if (!ao_storage_read(pos, &ao_log_fetch, sizeof (struct ao_log_telescience))) + return 0; + return ao_log_valid(&ao_log_fetch); +} + +void +ao_log_start(void) +{ + if (!ao_log_running) { + ao_log_running = 1; + ao_wakeup(&ao_log_running); + } +} + +void +ao_log_stop(void) +{ + if (ao_log_running) { + ao_log_running = 0; + } +} + +void +ao_log_restart(void) +{ + /* Find end of data */ + ao_log_end_pos = ao_storage_config; + for (ao_log_current_pos = 0; + ao_log_current_pos < ao_storage_config; + ao_log_current_pos += ao_storage_block) + { + if (!ao_log_telescience_read(ao_log_current_pos)) + break; + } + if (ao_log_current_pos > 0) { + ao_log_current_pos -= ao_storage_block; + for (; ao_log_current_pos < ao_storage_config; + ao_log_current_pos += sizeof (struct ao_log_telescience)) + { + if (!ao_log_telescience_read(ao_log_current_pos)) + break; + } + } +} + +void +ao_log_telescience(void) +{ + ao_storage_setup(); + + /* This can take a while, so let the rest + * of the system finish booting before we start + */ + ao_delay(AO_SEC_TO_TICKS(10)); + + ao_log_restart(); + for (;;) { + while (!ao_log_running) + ao_sleep(&ao_log_running); + + ao_log_start_pos = ao_log_current_pos; + ao_log_store.type = AO_LOG_TELESCIENCE_START; + ao_log_store.tick = ao_time(); + ao_log_store.adc[0] = ao_companion_command.serial; + ao_log_store.adc[1] = ao_companion_command.flight; + ao_log_telescience_write(); + /* Write the whole contents of the ring to the log + * when starting up. + */ + ao_log_adc_pos = ao_adc_ring_next(ao_adc_head); + ao_log_store.type = AO_LOG_TELESCIENCE_DATA; + while (ao_log_running) { + /* Write samples to EEPROM */ + while (ao_log_adc_pos != ao_adc_head) { + ao_log_store.tick = ao_adc_ring[ao_log_adc_pos].tick; + memcpy(&ao_log_store.adc, (void *) ao_adc_ring[ao_log_adc_pos].adc, + AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); + ao_log_telescience_write(); + ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); + } + /* Wait for more ADC data to arrive */ + ao_sleep((void *) &ao_adc_head); + } + memset(&ao_log_store.adc, '\0', sizeof (ao_log_store.adc)); + } +} + +void +ao_log_set(void) +{ + printf("Logging currently %s\n", ao_log_running ? "on" : "off"); + ao_cmd_hex(); + if (ao_cmd_status == ao_cmd_success) { + if (ao_cmd_lex_i) { + printf("Logging from %ld to %ld\n", ao_log_current_pos, ao_log_end_pos); + ao_log_start(); + } else { + printf ("Log stopped at %ld\n", ao_log_current_pos); + ao_log_stop(); + } + } + ao_cmd_status = ao_cmd_success; +} + +void +ao_log_list(void) +{ + uint32_t pos; + uint32_t start = 0; + uint8_t flight = 0; + + for (pos = 0; ; pos += sizeof (struct ao_log_telescience)) { + if (pos >= ao_storage_config || + !ao_log_telescience_read(pos) || + ao_log_fetch.type == AO_LOG_TELESCIENCE_START) + { + if (pos != start) { + printf("flight %d start %x end %x\n", + flight, + (uint16_t) (start >> 8), + (uint16_t) ((pos + 0xff) >> 8)); flush(); + } + if (ao_log_fetch.type != AO_LOG_TELESCIENCE_START) + break; + start = pos; + flight++; + } + } + printf ("done\n"); +} + +void +ao_log_delete(void) +{ + uint32_t pos; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_cmd_lex_i != 1) { + ao_cmd_status = ao_cmd_syntax_error; + printf("No such flight: %d\n", ao_cmd_lex_i); + return; + } + ao_log_stop(); + for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) { + if (!ao_log_telescience_read(pos)) + break; + ao_storage_erase(pos); + } + ao_log_current_pos = ao_log_start_pos = 0; + if (pos == 0) + printf("No such flight: %d\n", ao_cmd_lex_i); + else + printf ("Erased\n"); +} + +static void +ao_log_query(void) +{ + printf("Logging enabled: %d\n", ao_log_running); + printf("Log start: %ld\n", ao_log_start_pos); + printf("Log cur: %ld\n", ao_log_current_pos); + printf("Log end: %ld\n", ao_log_end_pos); + printf("log data tick: %04x\n", ao_log_store.tick); + printf("TM data tick: %04x\n", ao_log_store.tm_tick); + printf("TM state: %d\n", ao_log_store.tm_state); + printf("TM serial: %d\n", ao_companion_command.serial); + printf("TM flight: %d\n", ao_companion_command.flight); +} + +const struct ao_cmds ao_log_cmds[] = { + { ao_log_set, "L <0 off, 1 on>\0Set logging mode" }, + { ao_log_list, "l\0List stored flight logs" }, + { ao_log_delete, "d 1\0Delete all stored flights" }, + { ao_log_query, "q\0Query log status" }, + { 0, NULL }, +}; + +void +ao_log_init(void) +{ + ao_log_running = 0; + + ao_cmd_register(&ao_log_cmds[0]); + + ao_add_task(&ao_log_task, ao_log_telescience, "log"); +} diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index 0668dad2..b6ff65cc 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -24,6 +24,10 @@ #if !HAS_BEEP #define ao_beep(x) #endif +#if !LEDS_AVAILABLE +#define ao_led_on(x) +#define ao_led_off(x) +#endif static void ao_panic_delay(uint8_t n) diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index 4c8f4269..2e587f8e 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -30,7 +30,7 @@ #define COMPANION_SELECT() do { ao_spi_get_bit(COMPANION_CS); ao_spi_slow(); } while (0) #define COMPANION_DESELECT() do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS); } while (0) -static __xdata struct ao_companion_command ao_companion_command; +__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]; diff --git a/src/drivers/ao_lcd.c b/src/drivers/ao_lcd.c new file mode 100644 index 00000000..5bc89bbd --- /dev/null +++ b/src/drivers/ao_lcd.c @@ -0,0 +1,281 @@ +/* + * 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 LCD_PORT PORTB +#define LCD_DDR DDRB + +#define PIN_RS 4 +#define PIN_E 5 +#define PIN_RW 6 + +void +ao_lcd_set_bits(uint8_t bits) +{ +#if 0 + printf("\tLCD data %x RS %d R/W %d E %d\n", + bits & 0xf, + (bits & (1 << PIN_RS)) ? 1 : 0, + (bits & (1 << PIN_RW)) ? 1 : 0, + (bits & (1 << PIN_E)) ? 1 : 0); +#endif + LCD_PORT = bits; +#if 0 + ao_delay(1); + if (bits & (1 << PIN_RW)) + printf("\tLCD input %x\n", PINB); +#endif +} + +uint8_t +ao_lcd_get_nibble(uint8_t rs) +{ + uint8_t data = (rs ? (1 << PIN_RS) : 0) | (1 << PIN_RW); + uint8_t n; + + DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + ao_lcd_set_bits(data); + ao_lcd_set_bits(data | (1 << PIN_E)); + n = PINB & 0xf; + ao_lcd_set_bits(data); + return n; +} + +uint8_t +ao_lcd_get_status(void) +{ + uint8_t high, low; + uint8_t data; + + high = ao_lcd_get_nibble(0); + low = ao_lcd_get_nibble(0); + data = (high << 4) | low; + printf ("\tLCD status %02x\n", data); + return data; +} + +uint8_t +ao_lcd_get_data(void) +{ + uint8_t high, low; + uint8_t data; + + high = ao_lcd_get_nibble(1); + low = ao_lcd_get_nibble(1); + data = (high << 4) | low; + printf ("\tLCD data %02x\n", data); + return data; +} + +void +ao_lcd_wait_idle(void) +{ + uint8_t status; + uint8_t count = 0; + + do { + status = ao_lcd_get_status(); + count++; + if (count > 100) { + printf("idle timeout\n"); + break; + } + } while (0); /* status & 0x80); */ +} + +void +ao_lcd_send_nibble(uint8_t rs, uint8_t data) +{ + data = (data & 0xf) | (rs ? (1 << PIN_RS) : 0); + DDRB = (0xf) | (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + ao_lcd_set_bits(data); + ao_lcd_set_bits(data | (1 << PIN_E)); + ao_lcd_set_bits(data); +} + +static uint16_t ao_lcd_time = 3; + +void +ao_lcd_delay(void) +{ + volatile uint16_t count; + + for (count = 0; count < ao_lcd_time; count++) + ; +} + +void +ao_lcd_send_ins(uint8_t data) +{ +// printf("send ins %02x\n", data); +// ao_lcd_wait_idle(); +// ao_delay(1); + ao_lcd_delay(); + ao_lcd_send_nibble(0, data >> 4); + ao_lcd_send_nibble(0, data & 0xf); +} + +void +ao_lcd_send_data(uint8_t data) +{ +// printf ("send data %02x\n", data); +// ao_lcd_wait_idle(); + ao_lcd_delay(); + ao_lcd_send_nibble(1, data >> 4); + ao_lcd_send_nibble(1, data & 0x0f); +} + +void +ao_lcd_send_string(char *string) +{ + uint8_t c; + + while ((c = (uint8_t) *string++)) + ao_lcd_send_data(c); +} + +#define AO_LCD_POWER_CONTROL 0x54 + +void +ao_lcd_contrast_set(uint8_t contrast) +{ + ao_lcd_send_ins(AO_LCD_POWER_CONTROL | ((contrast >> 4) & 0x3)); + ao_lcd_send_ins(0x70 | (contrast & 0xf)); +} + +void +ao_lcd_clear(void) +{ + ao_lcd_send_ins(0x01); + ao_delay(1); + /* Entry mode */ + ao_lcd_send_ins(0x04 | 0x02); +} + +void +ao_lcd_start(void) +{ + /* get to 4bit mode */ + ao_lcd_send_nibble(0, 0x3); + ao_lcd_send_nibble(0, 0x3); + ao_lcd_send_nibble(0, 0x3); + ao_lcd_send_nibble(0, 0x2); + + /* function set */ + ao_lcd_send_ins(0x28); + /* function set, instruction table 1 */ + ao_lcd_send_ins(0x29); + + /* freq set */ + ao_lcd_send_ins(0x14); + + /* Power/icon/contrast control*/ + ao_lcd_send_ins(AO_LCD_POWER_CONTROL); + + /* Follower control */ + ao_lcd_send_ins(0x6d); + ao_delay(AO_MS_TO_TICKS(200)); + + /* contrast set */ + ao_lcd_contrast_set(0x18); + + /* Display on */ + ao_lcd_send_ins(0x08 | 0x04); + + /* Clear */ + ao_lcd_clear(); + +} + +void +ao_lcd_contrast(void) +{ + ao_cmd_hex(); + if (ao_cmd_status == ao_cmd_success) { + printf("setting contrast to %02x\n", ao_cmd_lex_i); + ao_lcd_contrast_set(ao_cmd_lex_i & 0x3f); + } +} + +static uint8_t +ao_cmd_hex_nibble(void) +{ + if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') + return ao_cmd_lex_c - '0'; + if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f') + return ao_cmd_lex_c - ('a' - 10); + if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F') + return ao_cmd_lex_c - ('A' - 10); + ao_cmd_status = ao_cmd_syntax_error; + return 0; +} + +void +ao_lcd_string(void) +{ + uint8_t col = 0; + uint8_t c; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_lcd_send_ins(0x80 | (ao_cmd_lex_i ? 0x40 : 0x00)); + ao_cmd_white(); + while (ao_cmd_lex_c != '\n') { + c = ao_cmd_lex_c; + if (c == '\\') { + ao_cmd_lex(); + c = ao_cmd_hex_nibble() << 4; + ao_cmd_lex(); + c |= ao_cmd_hex_nibble(); + } + ao_lcd_send_data(c); + ao_cmd_lex(); + col++; + } + while (col < 16) { + ao_lcd_send_data(' '); + col++; + } +} + +void +ao_lcd_delay_set(void) +{ + ao_cmd_decimal(); + if (ao_cmd_status == ao_cmd_success) { + printf("setting LCD delay to %d\n", ao_cmd_lex_i); + ao_lcd_time = ao_cmd_lex_i; + } +} + +__code struct ao_cmds ao_lcd_cmds[] = { + { ao_lcd_start, "S\0Start LCD" }, + { ao_lcd_contrast, "C \0Set LCD contrast" }, + { ao_lcd_string, "s \0Send string to LCD" }, + { ao_lcd_delay_set, "t \0Set LCD delay" }, + { 0, NULL }, +}; + +void +ao_lcd_init(void) +{ + DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + PORTB = 0; + ao_cmd_register(&ao_lcd_cmds[0]); +} diff --git a/src/drivers/ao_m25.c b/src/drivers/ao_m25.c index d7208273..28cb1dd7 100644 --- a/src/drivers/ao_m25.c +++ b/src/drivers/ao_m25.c @@ -376,5 +376,7 @@ ao_storage_device_init(void) /* Set up chip select wires */ SPI_CS_PORT |= M25_CS_MASK; /* raise all CS pins */ SPI_CS_DIR |= M25_CS_MASK; /* set CS pins as outputs */ +#ifdef SPI_CS_SEL SPI_CS_SEL &= ~M25_CS_MASK; /* set CS pins as GPIO */ +#endif } diff --git a/src/product/ao_telescience.c b/src/product/ao_telescience.c new file mode 100644 index 00000000..4dec3a18 --- /dev/null +++ b/src/product/ao_telescience.c @@ -0,0 +1,39 @@ +/* + * 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" + +int +main(void) +{ + ao_clock_init(); + + PORTE |= (1 << 6); + DDRE |= (1 << 6); + + ao_avr_stdio_init(); + ao_timer_init(); + ao_cmd_init(); + ao_spi_init(); + ao_spi_slave_init(); + ao_storage_init(); + ao_usb_init(); + ao_adc_init(); + ao_log_init(); + ao_start_scheduler(); + return 0; +} diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile new file mode 100644 index 00000000..3ccbb787 --- /dev/null +++ b/src/telescience-v0.1/Makefile @@ -0,0 +1,109 @@ +# +# AltOS build +# +# +vpath % ..:../core:../product:../drivers:../avr +vpath ao-make-product.5c ../util + +MCU=atmega32u4 +DUDECPUTYPE=m32u4 +#PROGRAMMER=stk500v2 -P usb +PROGRAMMER=usbtiny +LOADCMD=avrdude +LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: +CC=avr-gcc +OBJCOPY=avr-objcopy + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_usb.h \ + ao_pins.h \ + altitude.h + +# +# Common AltOS sources +# +TELESCIENCE_STORAGE= \ + ao_m25.c \ + ao_spi_usart.c \ + ao_storage.c \ + +ALTOS_SRC = \ + ao_cmd.c \ + ao_mutex.c \ + ao_panic.c \ + ao_product.c \ + ao_stdio.c \ + ao_task.c \ + ao_timer.c \ + ao_led.c \ + ao_avr_stdio.c \ + ao_romconfig.c \ + ao_usb_avr.c \ + ao_adc_avr.c \ + ao_spi_slave.c \ + ao_log_telescience.c \ + $(TELESCIENCE_STORAGE) + +PRODUCT=TeleScience-v0.1 +MCU=atmega32u4 +PRODUCT_DEF=-DTELESCIENCE +IDPRODUCT=0x0011 +CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I.. +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR + +NICKLE=nickle + +PROG=telescience-v0.1 + +SRC=$(ALTOS_SRC) ao_telescience.c +OBJ=$(SRC:.c=.o) + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: $(PROG) + +CHECK=sh ../util/check-avr-mem + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) + $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1) + +$(PROG).hex: $(PROG) + avr-size $(PROG) + $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ + + +load: $(PROG).hex + $(LOADCMD) $(LOADARG)$(PROG).hex + +../altitude.h: make-altitude + nickle $< > $@ + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.rel: ao_product.c ao_product.h + $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean: clean + +clean: + rm -f $(OBJ) + rm -f ao_product.h + +install: + +uninstall: + +$(OBJ): ao.h ao_product.h ao_usb.h diff --git a/src/util/check-avr-mem b/src/util/check-avr-mem new file mode 100644 index 00000000..c73edbd1 --- /dev/null +++ b/src/util/check-avr-mem @@ -0,0 +1,9 @@ +#!/bin/sh +nm "$@" | +grep ' N _end' | +awk '{ iram = strtonum("0x" $1) % 0x10000; +if ( iram > 0xaff) { + printf ("%d bytes of ram more than %d available\n", iram, 0xaff); + exit(1); +} else + exit(0); }' -- cgit v1.2.3 From 1c46c419704f661064d200432eb7efeeb11b3859 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 26 Aug 2011 20:46:47 -0700 Subject: altos: re-order ao_task to match single-arch code This is just for testing to make the new build match the old build exactly. Signed-off-by: Keith Packard --- src/core/ao.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index 05f056fd..c926c001 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -37,9 +37,9 @@ struct ao_task { __xdata void *wchan; /* current wait channel (NULL if running) */ uint16_t alarm; /* abort ao_sleep time */ + ao_arch_task_members /* any architecture-specific fields */ uint8_t task_id; /* unique id */ __code char *name; /* task name */ - ao_arch_task_members /* any architecture-specific fields */ uint8_t stack[AO_STACK_SIZE]; /* saved stack */ }; -- cgit v1.2.3 From b10fbbf0830053a39e4640a53598b1c027615c63 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 1 Aug 2011 22:44:13 -0700 Subject: altos: Add 'send all baro' compile-time option This option creates a new packet type that delivers full sensor-rate barometer telemetry data to allow for off-line analysis of flight algorithms using all of the data, rather than the slower rate provided either over telemetry or stored in the eeprom file. Define AO_SEND_ALL_BARO and this will get built in. Perhaps this could be a run-time option... Signed-off-by: Keith Packard --- src/core/ao.h | 31 +++++++++++++++++++++++++++++++ src/core/ao_telemetry.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index c926c001..0cff0436 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1118,6 +1118,30 @@ struct ao_telemetry_companion { /* 32 */ }; +/* #define AO_SEND_ALL_BARO */ + +#define AO_TELEMETRY_BARO 0x80 + +/* + * This packet allows the full sampling rate baro + * data to be captured over the RF link so that the + * flight software can be tested using 'real' data. + * + * Along with this telemetry packet, the flight + * code is modified to send full-rate telemetry all the time + * and never send an RDF tone; this ensure that the full radio + * link is available. + */ +struct ao_telemetry_baro { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t samples; /* 5 number samples */ + + int16_t baro[12]; /* 6 samples */ + /* 32 */ +}; + union ao_telemetry_all { struct ao_telemetry_generic generic; struct ao_telemetry_sensor sensor; @@ -1125,6 +1149,7 @@ union ao_telemetry_all { struct ao_telemetry_location location; struct ao_telemetry_satellite satellite; struct ao_telemetry_companion companion; + struct ao_telemetry_baro baro; }; /* @@ -1258,9 +1283,15 @@ struct ao_telemetry_raw_recv { /* Set delay between telemetry reports (0 to disable) */ +#ifdef AO_SEND_ALL_BARO +#define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(100) +#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100) +#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(100) +#else #define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) #define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100) #define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000) +#endif void ao_telemetry_set_interval(uint16_t interval); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index c7338a58..de669ce1 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -94,6 +94,30 @@ ao_send_sensor(void) ao_radio_send(&telemetry, sizeof (telemetry)); } +static uint8_t ao_baro_sample; + +#ifdef AO_SEND_ALL_BARO +static void +ao_send_baro(void) +{ + uint8_t sample = ao_sample_adc; + uint8_t samples = (sample - ao_baro_sample) & (AO_ADC_RING - 1); + + if (samples > 12) { + ao_baro_sample = (ao_baro_sample + (samples - 12)) & (AO_ADC_RING - 1); + samples = 12; + } + telemetry.generic.tick = ao_adc_ring[sample].tick; + telemetry.generic.type = AO_TELEMETRY_BARO; + telemetry.baro.samples = samples; + for (sample = 0; sample < samples; sample++) { + telemetry.baro.baro[sample] = ao_adc_ring[ao_baro_sample].pres; + ao_baro_sample = ao_adc_ring_next(ao_baro_sample); + } + ao_radio_send(&telemetry, sizeof (telemetry)); +} +#endif + static void ao_send_configuration(void) { @@ -193,6 +217,9 @@ ao_telemetry(void) while (ao_telemetry_interval) { +#ifdef AO_SEND_ALL_BARO + ao_send_baro(); +#endif ao_send_sensor(); #if HAS_COMPANION if (ao_companion_running) @@ -203,12 +230,14 @@ ao_telemetry(void) ao_send_location(); ao_send_satellite(); #endif +#ifndef AO_SEND_ALL_BARO if (ao_rdf && (int16_t) (ao_time() - ao_rdf_time) >= 0) { ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; ao_radio_rdf(AO_RDF_LENGTH_MS); } +#endif time += ao_telemetry_interval; delay = time - ao_time(); if (delay > 0) -- cgit v1.2.3 From f145be3fc4ee94fdb5c1e2406b6c11d38bdbbd9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 13 Jul 2011 20:01:47 -0700 Subject: altos: Start telelaunch product Looks a lot like TM, but without the flight code. Signed-off-by: Keith Packard --- src/Makefile | 3 ++- src/cc1111/ao_adc.c | 4 ++++ src/cc1111/ao_pins.h | 29 +++++++++++++++++++++++++++++ src/core/ao_config.c | 8 +++++--- src/telelaunch-v0.1/.gitignore | 2 ++ src/telelaunch-v0.1/.sdcdbrc | 1 + src/telelaunch-v0.1/Makefile | 1 + src/telelaunch-v0.1/Makefile.defs | 11 +++++++++++ 8 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 src/telelaunch-v0.1/.gitignore create mode 100644 src/telelaunch-v0.1/.sdcdbrc create mode 100644 src/telelaunch-v0.1/Makefile create mode 100644 src/telelaunch-v0.1/Makefile.defs (limited to 'src/core') diff --git a/src/Makefile b/src/Makefile index caa91e83..9ef5ae0a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -18,6 +18,7 @@ SUBDIRS=\ telemini-v1.0 telenano-v0.1 \ telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ + telelaunch-v0.1 \ tidongle test telescience-v0.1 all: all-local all-recursive @@ -50,4 +51,4 @@ ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c sh $< kalman > $@ clean-local: - rm -f altitude.h ao_kalman.h \ No newline at end of file + rm -f altitude.h ao_kalman.h diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 786dfd11..6aa6e018 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -41,7 +41,11 @@ ao_adc_poll(void) void ao_adc_get(__xdata struct ao_adc *packet) { +#if HAS_FLIGHT uint8_t i = ao_adc_ring_prev(ao_sample_adc); +#else + uint8_t i = ao_adc_ring_prev(ao_adc_head); +#endif memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); } diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 4ac6a84b..19ea0cfd 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -302,6 +302,35 @@ #define HAS_MONITOR 1 #endif +#if defined(TELELAUNCH_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 0 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_DBG 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 1 + #define HAS_ACCEL_REF 0 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + #if DBG_ON_P1 #define DBG_CLOCK (1 << 4) /* mi0 */ diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 0c10e608..ec2b61f6 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -47,7 +47,9 @@ _ao_config_put(void) ao_storage_setup(); ao_storage_erase(ao_storage_config); ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config)); +#if HAS_FLIGHT ao_log_write_erase(0); +#endif ao_storage_flush(); } @@ -301,7 +303,7 @@ ao_config_radio_cal_set(void) __reentrant _ao_config_edit_finish(); } -#if HAS_EEPROM +#if HAS_EEPROM && HAS_FLIGHT void ao_config_log_show(void) __reentrant { @@ -329,7 +331,7 @@ ao_config_log_set(void) __reentrant _ao_config_edit_finish(); } } -#endif /* HAS_EEPROM */ +#endif /* HAS_EEPROM && HAS_FLIGHT */ #if HAS_IGNITE void @@ -448,7 +450,7 @@ __code struct ao_config_var ao_config_vars[] = { #endif /* HAS_ACCEL */ { "f \0Radio calib (cal = rf/(xtal/2^16))", ao_config_radio_cal_set, ao_config_radio_cal_show }, -#if HAS_EEPROM +#if HAS_EEPROM && HAS_FLIGHT { "l \0Flight log size in kB", ao_config_log_set, ao_config_log_show }, #endif diff --git a/src/telelaunch-v0.1/.gitignore b/src/telelaunch-v0.1/.gitignore new file mode 100644 index 00000000..d25d7ad9 --- /dev/null +++ b/src/telelaunch-v0.1/.gitignore @@ -0,0 +1,2 @@ +telemetrum-v0.1-sky* +ao_product.h diff --git a/src/telelaunch-v0.1/.sdcdbrc b/src/telelaunch-v0.1/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telelaunch-v0.1/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telelaunch-v0.1/Makefile b/src/telelaunch-v0.1/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telelaunch-v0.1/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telelaunch-v0.1/Makefile.defs b/src/telelaunch-v0.1/Makefile.defs new file mode 100644 index 00000000..0c7efb52 --- /dev/null +++ b/src/telelaunch-v0.1/Makefile.defs @@ -0,0 +1,11 @@ +PROG = telelaunch-v0.1-$(VERSION).ihx + +SRC = \ + $(TLAUNCH_BASE_SRC) \ + $(SPI_DRIVER_SRC) \ + $(EE_DRIVER_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleLaunch-v0.1 +PRODUCT_DEF=-DTELELAUNCH_V_0_1 +IDPRODUCT=0x000f -- cgit v1.2.3 From a731d240f802d37524ce84c3c6acf22bcda4d522 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jul 2011 18:51:33 -0700 Subject: altos: Start work on AES and raw radio interfaces. We probably don't want this raw radio interface, but it's a start. Signed-off-by: Keith Packard --- src/ao_aes.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/ao_radio_cmac.c | 100 +++++++++++++++++++++++++++++++++++++++++ src/cc1111/ao_pins.h | 4 ++ src/cc1111/cc1111.h | 24 +++++++++- src/core/ao.h | 26 +++++++++++ 5 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 src/ao_aes.c create mode 100644 src/ao_radio_cmac.c (limited to 'src/core') diff --git a/src/ao_aes.c b/src/ao_aes.c new file mode 100644 index 00000000..649eda06 --- /dev/null +++ b/src/ao_aes.c @@ -0,0 +1,122 @@ +/* + * 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" + +__xdata uint8_t ao_aes_mutex; +__xdata uint8_t ao_aes_done; +__xdata uint8_t ao_aes_dma_in, ao_aes_dma_out; +__xdata uint8_t ao_aes_dma_in_done, ao_aes_dma_out_done; +__pdata enum ao_aes_mode ao_aes_current_mode; + +void +ao_aes_isr(void) __interrupt 4 +{ + S0CON = 0; + if (ENCCCS & ENCCCS_RDY) { + ao_aes_done = 1; + ao_wakeup(&ao_aes_done); + } +} + +void +ao_aes_set_mode(enum ao_aes_mode mode) +{ + ao_aes_current_mode = mode; +} + +void +ao_aes_set_key(__xdata uint8_t *in) +{ + ao_dma_set_transfer(ao_aes_dma_in, + in, + &ENCDIXADDR, + 7, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_ENC_DW, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_LOW); + ao_aes_done = 0; + ENCCCS = ENCCCS_MODE_CBC_MAC | + ENCCCS_CMD_LOAD_KEY | + ENCCCS_START; + while (!ao_aes_done) + ao_sleep(&ao_aes_done); +} + +void +ao_aes_run(__xdata uint8_t *in, + __xdata uint8_t *out) +{ + uint8_t b; + if (in) { + ao_dma_set_transfer(ao_aes_dma_in, + in, + &ENCDIXADDR, + 7, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_ENC_DW, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_LOW); + } + if (out) { + ao_dma_set_transfer(ao_aes_dma_out, + &ENCDOXADDR, + out, + 7, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_ENC_UP, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_1 | + DMA_CFG1_PRIORITY_LOW); + } + switch (ao_aes_current_mode) { + case ao_aes_mode_cbc_mac: + if (out) + b = (ENCCCS_MODE_CBC | + ENCCCS_CMD_ENCRYPT | + ENCCCS_START); + else + b = (ENCCCS_MODE_CBC_MAC | + ENCCCS_CMD_ENCRYPT | + ENCCCS_START); + break; + default: + return; + } + ao_aes_done = 0; + ENCCCS = b; + if (out) + while (!ao_aes_dma_out_done) + ao_sleep(&ao_aes_dma_out_done); + else + while (!ao_aes_done) + ao_sleep(&ao_aes_done); +} + +void +ao_aes_init(void) +{ + ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done); + ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done); + ENCIE = 1; +} diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c new file mode 100644 index 00000000..4b118d02 --- /dev/null +++ b/src/ao_radio_cmac.c @@ -0,0 +1,100 @@ +/* + * 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 AO_CMAC_KEY_LEN 16 +#define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) + +static __xdata uint8_t cmac_key[AO_CMAC_KEY_LEN]; +static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN]; + +static uint8_t +getnibble(void) +{ + __pdata 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_radio_cmac_key(void) __reentrant +{ + uint8_t i; + + for (i = 0; i < AO_CMAC_KEY_LEN; i++) { + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + cmac_key[i] = ao_cmd_lex_i; + } +} + +static void +ao_radio_cmac_send(void) __reentrant +{ + uint8_t i, b; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_cmd_lex_i > AO_CMAC_MAX_LEN || ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + for (i = 0; i < ao_cmd_lex_i; i++) { + b = getnibble() << 4; + b |= getnibble(); + if (ao_cmd_status != ao_cmd_success) + return; + cmac_data[i] = b; + } + ao_mutex_get(&ao_aes_mutex); + ao_aes_set_mode(ao_aes_mode_cbc_mac); + ao_aes_set_key(cmac_key); + for (i = 0; i < ao_cmd_lex_i; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < ao_cmd_lex_i) + ao_aes_run(&cmac_data[i], NULL); + else + ao_aes_run(&cmac_data[i], &cmac_data[ao_cmd_lex_i]); + } + ao_mutex_put(&ao_aes_mutex); + ao_set_monitor(0); + ao_radio_send(cmac_data, ao_cmd_lex_i + AO_CMAC_KEY_LEN); +} + +__code struct ao_cmds ao_radio_cmac_cmds[] = { + { ao_radio_cmac_key, "k ...\0Set AES-CMAC key." }, + { ao_radio_cmac_send, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, + { ao_radio_cmac_recv, "S \0Receive AES-CMAC packet. Timeout in ms" }, + { 0, NULL }, +}; + +void +ao_radio_cmac_init(void) +{ + ao_cmd_register(&ao_radio_cmac_cmds[0]); + +} diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 19ea0cfd..9e9b3bf6 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -108,6 +108,7 @@ #define SPI_CS_ON_P0 0 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_AES 1 #endif #if defined(TELEMINI_V_1_0) @@ -212,6 +213,7 @@ #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_AES 1 #endif #if defined(TIDONGLE) @@ -235,6 +237,7 @@ #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_AES 1 #endif #if defined(TELEBT_V_0_0) @@ -300,6 +303,7 @@ #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P1_7 #define HAS_MONITOR 1 + #define HAS_AES 1 #endif #if defined(TELELAUNCH_V_0_1) diff --git a/src/cc1111/cc1111.h b/src/cc1111/cc1111.h index e52aa79f..11ea8bbb 100644 --- a/src/cc1111/cc1111.h +++ b/src/cc1111/cc1111.h @@ -768,7 +768,7 @@ struct cc_dma_channel { # define DMA_CFG0_TRIGGER_ADC_CH7 28 # define DMA_CFG0_TRIGGER_I2STX 28 # define DMA_CFG0_TRIGGER_ENC_DW 29 -# define DMA_CFG0_TRIGGER_DNC_UP 30 +# define DMA_CFG0_TRIGGER_ENC_UP 30 # define DMA_CFG1_SRCINC_MASK (3 << 6) # define DMA_CFG1_SRCINC_0 (0 << 6) @@ -1303,4 +1303,26 @@ __xdata __at (0xdf3c) uint8_t RF_PKTSTATUS; __xdata __at (0xdf3d) uint8_t RF_VCO_VC_DAC; #define RF_VCO_VC_DAC_OFF 0x3d +/* AES engine */ + +__sfr at 0xB1 ENCDI; +__sfr at 0xB2 ENCDO; +__xdata at (0xDFB1) volatile uint8_t ENCDIXADDR; +__xdata at (0xDFB2) volatile uint8_t ENCDOXADDR; + +__sfr at 0xB3 ENCCCS; + +#define ENCCCS_MODE_CBC (0 << 4) +#define ENCCCS_MODE_CFB (1 << 4) +#define ENCCCS_MODE_OFB (2 << 4) +#define ENCCCS_MODE_CTR (3 << 4) +#define ENCCCS_MODE_ECB (4 << 4) +#define ENCCCS_MODE_CBC_MAC (5 << 4) +#define ENCCCS_RDY (1 << 3) +#define ENCCCS_CMD_ENCRYPT (0 << 1) +#define ENCCCS_CMD_DECRYPT (1 << 1) +#define ENCCCS_CMD_LOAD_KEY (2 << 1) +#define ENCCCS_CMD_LOAD_IV (3 << 1) +#define ENCCCS_START (1 << 0) + #endif diff --git a/src/core/ao.h b/src/core/ao.h index 0cff0436..0275cad1 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1629,4 +1629,30 @@ ao_companion_init(void); void ao_lcd_init(void); +/* ao_aes.c */ + +__xdata uint8_t ao_aes_mutex; + +enum ao_aes_mode { + ao_aes_mode_cbc_mac +}; + +#if HAS_AES +void +ao_aes_isr(void) __interrupt 4; +#endif + +void +ao_aes_set_mode(enum ao_aes_mode mode); + +void +ao_aes_set_key(__xdata uint8_t *in); + +void +ao_aes_run(__xdata uint8_t *in, + __xdata uint8_t *out); + +void +ao_aes_init(void); + #endif /* _AO_H_ */ -- cgit v1.2.3 From bd0bf00081bb24af5cd67a9351b0b0c1a041d0d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 14:25:01 -0700 Subject: altos: More work on AES bits Signed-off-by: Keith Packard --- src/ao_radio_cmac.c | 9 +++++++++ src/core/ao.h | 4 ++++ src/telelaunch-v0.1/Makefile.defs | 1 + 3 files changed, 14 insertions(+) (limited to 'src/core') diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index 4b118d02..9b406a21 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -22,6 +22,7 @@ static __xdata uint8_t cmac_key[AO_CMAC_KEY_LEN]; 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) @@ -85,6 +86,14 @@ ao_radio_cmac_send(void) __reentrant ao_radio_send(cmac_data, ao_cmd_lex_i + AO_CMAC_KEY_LEN); } +static void +ao_radio_cmac_recv(void) __reentrant +{ + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; +} + __code struct ao_cmds ao_radio_cmac_cmds[] = { { ao_radio_cmac_key, "k ...\0Set AES-CMAC key." }, { ao_radio_cmac_send, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, diff --git a/src/core/ao.h b/src/core/ao.h index 0275cad1..2394d401 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1655,4 +1655,8 @@ ao_aes_run(__xdata uint8_t *in, void ao_aes_init(void); +/* ao_launch.c */ +void +ao_launch_init(void); + #endif /* _AO_H_ */ diff --git a/src/telelaunch-v0.1/Makefile.defs b/src/telelaunch-v0.1/Makefile.defs index 0c7efb52..e4934ffa 100644 --- a/src/telelaunch-v0.1/Makefile.defs +++ b/src/telelaunch-v0.1/Makefile.defs @@ -4,6 +4,7 @@ SRC = \ $(TLAUNCH_BASE_SRC) \ $(SPI_DRIVER_SRC) \ $(EE_DRIVER_SRC) \ + ao_launch.c \ $(DBG_SRC) PRODUCT=TeleLaunch-v0.1 -- cgit v1.2.3 From 776df9ce2e7b4fa5cedda326988e66c614299af4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 20 Jul 2011 23:46:04 -0700 Subject: altos: Get AES CBC-MAC packet transfers running This just has simple command-line based packet transfers for testing. This also adds special ao_telelaunch bits where the launch control code will live. Signed-off-by: Keith Packard --- src/ao_aes.c | 48 +++++++++++++++------ src/ao_launch.c | 59 +++++++++++++++++++++++++ src/ao_radio_cmac.c | 90 +++++++++++++++++++++++++++++++-------- src/ao_telelaunch.c | 47 ++++++++++++++++++++ src/cc1111/ao_pins.h | 4 +- src/core/ao.h | 12 ++++++ src/product/ao_telebt.c | 4 ++ src/product/ao_teledongle.c | 2 + src/teledongle-v0.1/.sdcdbrc | 1 + src/telelaunch-v0.1/Makefile.defs | 2 + 10 files changed, 237 insertions(+), 32 deletions(-) create mode 100644 src/ao_launch.c create mode 100644 src/ao_telelaunch.c create mode 100644 src/teledongle-v0.1/.sdcdbrc (limited to 'src/core') diff --git a/src/ao_aes.c b/src/ao_aes.c index 649eda06..d50fecfb 100644 --- a/src/ao_aes.c +++ b/src/ao_aes.c @@ -17,6 +17,10 @@ #include "ao.h" +#if !HAS_AES +#error Must define HAS_AES 1 +#endif + __xdata uint8_t ao_aes_mutex; __xdata uint8_t ao_aes_done; __xdata uint8_t ao_aes_dma_in, ao_aes_dma_out; @@ -45,21 +49,32 @@ ao_aes_set_key(__xdata uint8_t *in) ao_dma_set_transfer(ao_aes_dma_in, in, &ENCDIXADDR, - 7, + AO_AES_LEN, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | DMA_CFG0_TRIGGER_ENC_DW, DMA_CFG1_SRCINC_1 | DMA_CFG1_DESTINC_0 | DMA_CFG1_PRIORITY_LOW); + ao_dma_start(ao_aes_dma_in); ao_aes_done = 0; ENCCCS = ENCCCS_MODE_CBC_MAC | - ENCCCS_CMD_LOAD_KEY | - ENCCCS_START; - while (!ao_aes_done) + ENCCCS_CMD_LOAD_KEY; + ENCCCS |= ENCCCS_START; + __critical while (!ao_aes_done) ao_sleep(&ao_aes_done); } +void +ao_aes_zero_iv(void) +{ + uint8_t b; + + ENCCCS = ENCCCS_MODE_CBC_MAC | ENCCCS_CMD_LOAD_IV | ENCCCS_START; + for (b = 0; b < AO_AES_LEN; b++) + ENCDI = 0; +} + void ao_aes_run(__xdata uint8_t *in, __xdata uint8_t *out) @@ -69,7 +84,7 @@ ao_aes_run(__xdata uint8_t *in, ao_dma_set_transfer(ao_aes_dma_in, in, &ENCDIXADDR, - 7, + AO_AES_LEN, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | DMA_CFG0_TRIGGER_ENC_DW, @@ -81,7 +96,7 @@ ao_aes_run(__xdata uint8_t *in, ao_dma_set_transfer(ao_aes_dma_out, &ENCDOXADDR, out, - 7, + AO_AES_LEN, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | DMA_CFG0_TRIGGER_ENC_UP, @@ -93,24 +108,28 @@ ao_aes_run(__xdata uint8_t *in, case ao_aes_mode_cbc_mac: if (out) b = (ENCCCS_MODE_CBC | - ENCCCS_CMD_ENCRYPT | - ENCCCS_START); + ENCCCS_CMD_ENCRYPT); else b = (ENCCCS_MODE_CBC_MAC | - ENCCCS_CMD_ENCRYPT | - ENCCCS_START); + ENCCCS_CMD_ENCRYPT); break; default: return; } ao_aes_done = 0; - ENCCCS = b; + if (in) + ao_dma_start(ao_aes_dma_in); if (out) - while (!ao_aes_dma_out_done) + ao_dma_start(ao_aes_dma_out); + ENCCCS = b; + ENCCCS |= ENCCCS_START; + if (out) { + __critical while (!ao_aes_dma_out_done) ao_sleep(&ao_aes_dma_out_done); - else - while (!ao_aes_done) + } else { + __critical while (!ao_aes_done) ao_sleep(&ao_aes_done); + } } void @@ -118,5 +137,6 @@ ao_aes_init(void) { ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done); ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done); + S0CON = 0; ENCIE = 1; } diff --git a/src/ao_launch.c b/src/ao_launch.c new file mode 100644 index 00000000..4870869e --- /dev/null +++ b/src/ao_launch.c @@ -0,0 +1,59 @@ +/* + * 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" + +static void +ao_launch(void) +{ + enum ao_igniter_status arm_status, ignite_status; + + ao_led_off(AO_LED_RED); + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + for (;;) { + arm_status = ao_igniter_status(ao_igniter_drogue); + + switch (arm_status) { + case ao_igniter_unknown: + break; + case ao_igniter_active: + case ao_igniter_open: + break; + case ao_igniter_ready: + ignite_status = ao_igniter_status(ao_igniter_main); + switch (ignite_status) { + case ao_igniter_unknown: + /* some kind of failure signal here */ + break; + case ao_igniter_active: + break; + case ao_igniter_open: + break; + } + break; + } + ao_delay(AO_SEC_TO_TICKS(1)); + } +} + +static __xdata struct ao_task ao_launch_task; + +void +ao_launch_init(void) +{ + ao_add_task(&ao_launch_task, ao_launch, "launch status"); +} diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index 9b406a21..7648a2f5 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -40,62 +40,119 @@ getnibble(void) return 0; } +static uint8_t +getbyte(void) +{ + uint8_t b; + b = getnibble() << 4; + b |= getnibble(); + return b; +} + static void ao_radio_cmac_key(void) __reentrant { uint8_t i; for (i = 0; i < AO_CMAC_KEY_LEN; i++) { - ao_cmd_hex(); + cmac_key[i] = getbyte(); if (ao_cmd_status != ao_cmd_success) return; - cmac_key[i] = ao_cmd_lex_i; } } static void ao_radio_cmac_send(void) __reentrant { - uint8_t i, b; + uint8_t i; + uint8_t len; - ao_cmd_hex(); + ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - if (ao_cmd_lex_i > AO_CMAC_MAX_LEN || ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) { + if (ao_cmd_lex_i < AO_CMAC_KEY_LEN || + ao_cmd_lex_i > AO_CMAC_MAX_LEN || + ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) + { ao_cmd_status = ao_cmd_syntax_error; return; } - for (i = 0; i < ao_cmd_lex_i; i++) { - b = getnibble() << 4; - b |= getnibble(); + flush(); + len = ao_cmd_lex_i; + for (i = 0; i < len; i++) { + cmac_data[i] = getbyte(); if (ao_cmd_status != ao_cmd_success) return; - cmac_data[i] = b; } ao_mutex_get(&ao_aes_mutex); ao_aes_set_mode(ao_aes_mode_cbc_mac); ao_aes_set_key(cmac_key); - for (i = 0; i < ao_cmd_lex_i; i += AO_CMAC_KEY_LEN) { - if (i + AO_CMAC_KEY_LEN < ao_cmd_lex_i) + 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[ao_cmd_lex_i]); + ao_aes_run(&cmac_data[i], &cmac_data[len]); } ao_mutex_put(&ao_aes_mutex); +#if HAS_MONITOR ao_set_monitor(0); - ao_radio_send(cmac_data, ao_cmd_lex_i + AO_CMAC_KEY_LEN); +#endif + printf("send:"); + for (i = 0; i < len + AO_CMAC_KEY_LEN; i++) + printf(" %02x", cmac_data[i]); + printf("\n"); flush(); + ao_radio_send(cmac_data, len + AO_CMAC_KEY_LEN); } static void ao_radio_cmac_recv(void) __reentrant { - ao_cmd_hex(); + uint8_t len, i; + uint16_t timeout; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_cmd_lex_i < AO_CMAC_KEY_LEN || + ao_cmd_lex_i > AO_CMAC_MAX_LEN || + ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) + { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + len = ao_cmd_lex_i; + ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; + timeout = ao_cmd_lex_i; +#if HAS_MONITOR + ao_set_monitor(0); +#endif + if (timeout) + ao_alarm(timeout); + if (!ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2)) { + printf("timeout\n"); + return; + } + ao_mutex_get(&ao_aes_mutex); + ao_aes_set_mode(ao_aes_mode_cbc_mac); + ao_aes_set_key(cmac_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]); + } + printf ("PACKET "); + for (i = 0; i < len + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN; i++) + printf("%02x", cmac_data[i]); + printf ("\n"); } -__code struct ao_cmds ao_radio_cmac_cmds[] = { - { ao_radio_cmac_key, "k ...\0Set AES-CMAC key." }, +static __code struct ao_cmds ao_radio_cmac_cmds[] = { + { ao_radio_cmac_key, "k\0Set AES-CMAC key. 16 key bytes follow on next line" }, { ao_radio_cmac_send, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, { ao_radio_cmac_recv, "S \0Receive AES-CMAC packet. Timeout in ms" }, { 0, NULL }, @@ -105,5 +162,4 @@ void ao_radio_cmac_init(void) { ao_cmd_register(&ao_radio_cmac_cmds[0]); - } diff --git a/src/ao_telelaunch.c b/src/ao_telelaunch.c new file mode 100644 index 00000000..b5404710 --- /dev/null +++ b/src/ao_telelaunch.c @@ -0,0 +1,47 @@ +/* + * 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" +#include "ao_pins.h" + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + ao_timer_init(); + ao_adc_init(); + ao_beep_init(); + ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); + ao_usb_init(); + ao_radio_init(); + ao_igniter_init(); +#if HAS_DBG + ao_dbg_init(); +#endif + ao_aes_init(); + ao_radio_cmac_init(); + ao_launch_init(); + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 9e9b3bf6..819dc7df 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -267,6 +267,7 @@ #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P2_1 #define HAS_MONITOR 1 + #define HAS_AES 1 #endif #if defined(TELEBT_V_0_1) @@ -322,7 +323,7 @@ #define IGNITE_ON_P2 1 #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 + #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 #define AO_LED_GREEN 1 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) @@ -333,6 +334,7 @@ #define HAS_ACCEL 0 #define HAS_IGNITE 1 #define HAS_MONITOR 0 + #define HAS_AES 1 #endif #if DBG_ON_P1 diff --git a/src/core/ao.h b/src/core/ao.h index 2394d401..2898852b 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1633,6 +1633,10 @@ ao_lcd_init(void); __xdata uint8_t ao_aes_mutex; +/* AES keys and blocks are 128 bits */ + +#define AO_AES_LEN 16 + enum ao_aes_mode { ao_aes_mode_cbc_mac }; @@ -1648,6 +1652,9 @@ ao_aes_set_mode(enum ao_aes_mode mode); void ao_aes_set_key(__xdata uint8_t *in); +void +ao_aes_zero_iv(void); + void ao_aes_run(__xdata uint8_t *in, __xdata uint8_t *out); @@ -1655,6 +1662,11 @@ ao_aes_run(__xdata uint8_t *in, void ao_aes_init(void); +/* ao_radio_cmac.c */ + +void +ao_radio_cmac_init(void); + /* ao_launch.c */ void ao_launch_init(void); diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 85565172..5bbbf71b 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -44,6 +44,10 @@ main(void) ao_btm_init(); #if HAS_DBG ao_dbg_init(); +#endif +#if HAS_AES + ao_aes_init(); + ao_radio_cmac_init(); #endif ao_config_init(); ao_start_scheduler(); diff --git a/src/product/ao_teledongle.c b/src/product/ao_teledongle.c index 008b200a..b8be9f45 100644 --- a/src/product/ao_teledongle.c +++ b/src/product/ao_teledongle.c @@ -35,6 +35,8 @@ main(void) #if HAS_DBG ao_dbg_init(); #endif + ao_aes_init(); + ao_radio_cmac_init(); ao_config_init(); ao_start_scheduler(); } diff --git a/src/teledongle-v0.1/.sdcdbrc b/src/teledongle-v0.1/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/teledongle-v0.1/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telelaunch-v0.1/Makefile.defs b/src/telelaunch-v0.1/Makefile.defs index e4934ffa..56f5730b 100644 --- a/src/telelaunch-v0.1/Makefile.defs +++ b/src/telelaunch-v0.1/Makefile.defs @@ -5,6 +5,8 @@ SRC = \ $(SPI_DRIVER_SRC) \ $(EE_DRIVER_SRC) \ ao_launch.c \ + ao_aes.c \ + ao_radio_cmac.c \ $(DBG_SRC) PRODUCT=TeleLaunch-v0.1 -- cgit v1.2.3 From 4299b5a36a2f6f9f7bbbc3a1b935dd2357c1fb0f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jul 2011 20:04:05 -0700 Subject: altos: Implement remote launch protocol Uses the radio_cmac module to provide secure communication. Keeps igniter closed for 500ms. Provides remote status for arming and ignition. Signed-off-by: Keith Packard --- src/ao_launch.c | 170 +++++++++++++++++++++++--- src/ao_radio_cmac.c | 278 ++++++++++++++++++++++++++++++------------ src/ao_telelaunch.c | 1 - src/cc1111/ao_ignite.c | 6 - src/cc1111/ao_packet_master.c | 6 +- src/cc1111/ao_timer.c | 1 + src/core/ao.h | 59 ++++++++- src/core/ao_cmd.c | 44 +++++-- src/core/ao_config.c | 36 ++++++ src/core/ao_task.c | 7 +- 10 files changed, 497 insertions(+), 111 deletions(-) (limited to 'src/core') diff --git a/src/ao_launch.c b/src/ao_launch.c index 4870869e..6c154719 100644 --- a/src/ao_launch.c +++ b/src/ao_launch.c @@ -17,43 +17,183 @@ #include "ao.h" +__xdata uint16_t ao_launch_ignite; + +static void +ao_launch_run(void) +{ + for (;;) { + while (!ao_launch_ignite) + ao_sleep(&ao_launch_ignite); + while (ao_launch_ignite) { + ao_launch_ignite = 0; + + ao_ignition[ao_igniter_drogue].firing = 1; + ao_ignition[ao_igniter_main].firing = 1; + AO_IGNITER_DROGUE = 1; + ao_delay(AO_MS_TO_TICKS(500)); + AO_IGNITER_DROGUE = 0; + ao_ignition[ao_igniter_drogue].firing = 0; + ao_ignition[ao_igniter_main].firing = 0; + } + } +} + +static void +ao_launch_status(void) +{ + uint8_t i; + for (;;) { + ao_delay(AO_SEC_TO_TICKS(1)); + 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)); + } + } + } +} + +static __pdata uint8_t ao_launch_armed; +static __pdata uint16_t ao_launch_arm_time; + static void ao_launch(void) { - enum ao_igniter_status arm_status, ignite_status; + static __xdata struct ao_launch_command command; + static __xdata struct ao_launch_query query; + int16_t time_difference; ao_led_off(AO_LED_RED); ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); for (;;) { - arm_status = ao_igniter_status(ao_igniter_drogue); + if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) + continue; + + printf ("tick %d serial %d cmd %d channel %d\n", + command.tick, command.serial, command.cmd, command.channel); + + if (command.serial != ao_serial_number) { + printf ("serial number mismatch\n"); + continue; + } - switch (arm_status) { - case ao_igniter_unknown: + switch (command.cmd) { + case AO_LAUNCH_QUERY: + if (command.channel == 0) { + query.valid = 1; + query.arm_status = ao_igniter_status(ao_igniter_drogue); + query.igniter_status = ao_igniter_status(ao_igniter_main); + } else { + query.valid = 0; + } + query.tick = ao_time(); + query.serial = ao_serial_number; + query.channel = command.channel; + printf ("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_igniter_active: - case ao_igniter_open: + case AO_LAUNCH_ARM: + if (command.channel != 0) + break; + time_difference = command.tick - ao_time(); + printf ("arm tick %d local tick %d\n", command.tick, ao_time()); + if (time_difference < 0) + time_difference = -time_difference; + if (time_difference > 10) { + printf ("time difference too large %d\n", time_difference); + break; + } + printf ("armed\n"); + ao_launch_armed = 1; + ao_launch_arm_time = ao_time(); break; - case ao_igniter_ready: - ignite_status = ao_igniter_status(ao_igniter_main); - switch (ignite_status) { - case ao_igniter_unknown: - /* some kind of failure signal here */ + case AO_LAUNCH_FIRE: + if (command.channel != 0) break; - case ao_igniter_active: + if (!ao_launch_armed) { + printf ("not armed\n"); break; - case ao_igniter_open: + } + if ((uint16_t) (ao_launch_arm_time - ao_time()) > AO_SEC_TO_TICKS(20)) { + printf ("late launch arm_time %d time %d\n", + ao_launch_arm_time, ao_time()); + break; + } + time_difference = command.tick - ao_time(); + if (time_difference < 0) + time_difference = -time_difference; + if (time_difference > 10) { + printf ("time different too large %d\n", time_difference); break; } + printf ("ignite\n"); + ao_launch_ignite = 1; + ao_wakeup(&ao_launch_ignite); break; } - ao_delay(AO_SEC_TO_TICKS(1)); } } +void +ao_launch_test(void) +{ + 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"); + } +} + +void +ao_launch_manual(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + ao_cmd_white(); + ao_launch_ignite = 1; + ao_wakeup(&ao_launch_ignite); +} + static __xdata struct ao_task ao_launch_task; +static __xdata struct ao_task ao_launch_ignite_task; +static __xdata struct ao_task ao_launch_status_task; + +__code struct ao_cmds ao_launch_cmds[] = { + { ao_launch_test, "t\0Test launch continuity" }, + { ao_launch_manual, "i \0Fire igniter. is doit with D&I" }, + { 0, NULL } +}; void ao_launch_init(void) { - ao_add_task(&ao_launch_task, ao_launch, "launch status"); + AO_IGNITER_DROGUE = 0; + AO_IGNITER_MAIN = 0; + AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; + ao_cmd_register(&ao_launch_cmds[0]); + ao_add_task(&ao_launch_task, ao_launch, "launch listener"); + ao_add_task(&ao_launch_ignite_task, ao_launch_run, "launch igniter"); + ao_add_task(&ao_launch_status_task, ao_launch_status, "launch status"); } diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index 7648a2f5..9694b5b3 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -17,27 +17,24 @@ #include "ao.h" -#define AO_CMAC_KEY_LEN 16 +#define AO_CMAC_KEY_LEN AO_AES_LEN #define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) -static __xdata uint8_t cmac_key[AO_CMAC_KEY_LEN]; +static __xdata uint8_t ao_radio_cmac_mutex; 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) { - __pdata 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; + 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 @@ -49,20 +46,137 @@ getbyte(void) return b; } +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 -ao_radio_cmac_key(void) __reentrant +radio_cmac_send(uint8_t len) __reentrant { uint8_t i; - for (i = 0; i < AO_CMAC_KEY_LEN; i++) { - cmac_key[i] = getbyte(); - if (ao_cmd_status != ao_cmd_success) - return; + len = round_len(len); + /* Make sure the AES key is loaded */ + ao_config_get(); + +#if HAS_MONITOR + ao_set_monitor(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_set_monitor(0); +#endif + if (timeout) + ao_alarm(timeout); + + i = ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2); + ao_clear_alarm(); + + if (!i) + return AO_RADIO_CMAC_TIMEOUT; + + if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & PKT_APPEND_STATUS_1_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); + memcpy(cmac_data, packet, len); + radio_cmac_send(len); + 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); + i = radio_cmac_recv(len, timeout); + if (i == AO_RADIO_CMAC_OK) + memcpy(packet, cmac_data, len); + ao_mutex_put(&ao_radio_cmac_mutex); + return i; } static void -ao_radio_cmac_send(void) __reentrant +radio_cmac_send_cmd(void) __reentrant { uint8_t i; uint8_t len; @@ -70,43 +184,25 @@ ao_radio_cmac_send(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - if (ao_cmd_lex_i < AO_CMAC_KEY_LEN || - ao_cmd_lex_i > AO_CMAC_MAX_LEN || - ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) - { + 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; } - ao_mutex_get(&ao_aes_mutex); - ao_aes_set_mode(ao_aes_mode_cbc_mac); - ao_aes_set_key(cmac_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); -#if HAS_MONITOR - ao_set_monitor(0); -#endif - printf("send:"); - for (i = 0; i < len + AO_CMAC_KEY_LEN; i++) - printf(" %02x", cmac_data[i]); - printf("\n"); flush(); - ao_radio_send(cmac_data, len + AO_CMAC_KEY_LEN); + radio_cmac_send(len); + ao_mutex_put(&ao_radio_cmac_mutex); } static void -ao_radio_cmac_recv(void) __reentrant +radio_cmac_recv_cmd(void) __reentrant { uint8_t len, i; uint16_t timeout; @@ -114,47 +210,79 @@ ao_radio_cmac_recv(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - if (ao_cmd_lex_i < AO_CMAC_KEY_LEN || - ao_cmd_lex_i > AO_CMAC_MAX_LEN || - ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) - { - ao_cmd_status = ao_cmd_syntax_error; - return; - } len = ao_cmd_lex_i; ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - timeout = ao_cmd_lex_i; -#if HAS_MONITOR - ao_set_monitor(0); -#endif - if (timeout) - ao_alarm(timeout); - if (!ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2)) { - printf("timeout\n"); + 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 ("\n"); + } else + printf ("ERROR %d\n", i); + ao_mutex_put(&ao_radio_cmac_mutex); +} + +static void +launch_report_cmd(void) __reentrant +{ + static __xdata struct ao_launch_command command; + static __xdata struct ao_launch_query query; + uint8_t channel; + uint16_t serial; + uint8_t i; + + ao_cmd_decimal(); + serial = ao_cmd_lex_i; + ao_cmd_decimal(); + channel = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) return; + flush(); + for (i = 0; i < 10; i++) { + printf ("."); flush(); + command.tick = 0; + command.serial = serial; + command.cmd = AO_LAUNCH_QUERY; + command.channel = channel; + ao_radio_cmac_send(&command, sizeof (command)); + switch (ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500))) { + case AO_RADIO_CMAC_OK: + printf("\n"); + switch (query.arm_status) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + switch (query.igniter_status) { + default: + printf("unknown status\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; + } + default: + printf("Disarmed\n"); + } + return; + default: + continue; + } } - ao_mutex_get(&ao_aes_mutex); - ao_aes_set_mode(ao_aes_mode_cbc_mac); - ao_aes_set_key(cmac_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]); - } - printf ("PACKET "); - for (i = 0; i < len + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN; i++) - printf("%02x", cmac_data[i]); - printf ("\n"); + printf ("Timeout\n"); } static __code struct ao_cmds ao_radio_cmac_cmds[] = { - { ao_radio_cmac_key, "k\0Set AES-CMAC key. 16 key bytes follow on next line" }, - { ao_radio_cmac_send, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, - { ao_radio_cmac_recv, "S \0Receive AES-CMAC packet. Timeout in ms" }, + { 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" }, { 0, NULL }, }; diff --git a/src/ao_telelaunch.c b/src/ao_telelaunch.c index b5404710..506431de 100644 --- a/src/ao_telelaunch.c +++ b/src/ao_telelaunch.c @@ -35,7 +35,6 @@ main(void) ao_storage_init(); ao_usb_init(); ao_radio_init(); - ao_igniter_init(); #if HAS_DBG ao_dbg_init(); #endif diff --git a/src/cc1111/ao_ignite.c b/src/cc1111/ao_ignite.c index 5238beb4..0fd2b4bf 100644 --- a/src/cc1111/ao_ignite.c +++ b/src/cc1111/ao_ignite.c @@ -39,12 +39,6 @@ #define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) #define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) -struct ao_ignition { - uint8_t request; - uint8_t fired; - uint8_t firing; -}; - __xdata struct ao_ignition ao_ignition[2]; void diff --git a/src/cc1111/ao_packet_master.c b/src/cc1111/ao_packet_master.c index b0fdf5a8..0d0be30e 100644 --- a/src/cc1111/ao_packet_master.c +++ b/src/cc1111/ao_packet_master.c @@ -80,13 +80,16 @@ ao_packet_master(void) ao_packet_master_time = ao_time(); ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; while (ao_packet_enable) { + uint8_t r; memcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); ao_packet_send(); if (ao_tx_packet.len) ao_packet_master_busy(); ao_packet_master_check_busy(); ao_alarm(ao_packet_master_delay); - if (ao_packet_recv()) { + r = ao_packet_recv(); + ao_clear_alarm(); + if (r) { /* if we can transmit data, do so */ if (ao_packet_tx_used && ao_tx_packet.len == 0) continue; @@ -95,6 +98,7 @@ ao_packet_master(void) ao_packet_master_sleeping = 1; ao_alarm(ao_packet_master_delay); ao_sleep(&ao_packet_master_sleeping); + ao_clear_alarm(); ao_packet_master_sleeping = 0; } } diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c index c977fbc8..aadee71e 100644 --- a/src/cc1111/ao_timer.c +++ b/src/cc1111/ao_timer.c @@ -31,6 +31,7 @@ ao_delay(uint16_t ticks) { ao_alarm(ticks); ao_sleep(&ao_forever); + ao_clear_alarm(); } #define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ diff --git a/src/core/ao.h b/src/core/ao.h index 2898852b..a5bbb6f1 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -68,6 +68,10 @@ ao_wakeup(__xdata void *wchan); void ao_alarm(uint16_t delay); +/* Clear any pending alarm */ +void +ao_clear_alarm(void); + /* Yield the processor to another task */ void ao_yield(void) ao_arch_naked_declare; @@ -342,6 +346,12 @@ ao_cmd_put16(uint16_t v); void ao_cmd_white(void); +int8_t +ao_cmd_hexchar(char c); + +void +ao_cmd_hexbyte(void); + void ao_cmd_hex(void); @@ -1417,6 +1427,14 @@ enum ao_igniter_status { ao_igniter_open, /* open circuit detected */ }; +struct ao_ignition { + uint8_t request; + uint8_t fired; + uint8_t firing; +}; + +extern __xdata struct ao_ignition ao_ignition[2]; + enum ao_igniter_status ao_igniter_status(enum ao_igniter igniter); @@ -1431,7 +1449,8 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 8 +#define AO_CONFIG_MINOR 9 +#define AO_AES_LEN 16 struct ao_config { uint8_t major; @@ -1448,6 +1467,7 @@ struct ao_config { uint8_t pad_orientation; /* minor version 6 */ uint32_t radio_setting; /* minor version 7 */ uint8_t radio_enable; /* minor version 8 */ + uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */ }; #define AO_IGNITE_MODE_DUAL 0 @@ -1635,8 +1655,6 @@ __xdata uint8_t ao_aes_mutex; /* AES keys and blocks are 128 bits */ -#define AO_AES_LEN 16 - enum ao_aes_mode { ao_aes_mode_cbc_mac }; @@ -1664,10 +1682,45 @@ 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); /* ao_launch.c */ + +struct ao_launch_command { + uint16_t tick; + uint16_t serial; + uint8_t cmd; + uint8_t channel; + uint16_t unused; +}; + +#define AO_LAUNCH_QUERY 1 + +struct ao_launch_query { + uint16_t tick; + uint16_t serial; + uint8_t channel; + uint8_t valid; + uint8_t arm_status; + uint8_t igniter_status; +}; + +#define AO_LAUNCH_ARM 2 +#define AO_LAUNCH_FIRE 3 + void ao_launch_init(void); diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 7663d875..9e14c221 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -22,7 +22,7 @@ __pdata uint32_t ao_cmd_lex_u32; __pdata char ao_cmd_lex_c; __pdata enum ao_cmd_status ao_cmd_status; -#define CMD_LEN 32 +#define CMD_LEN 48 static __xdata char cmd_line[CMD_LEN]; static __pdata uint8_t cmd_len; @@ -128,22 +128,48 @@ ao_cmd_white(void) ao_cmd_lex(); } +int8_t +ao_cmd_hexchar(char c) +{ + 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); + return -1; +} + +void +ao_cmd_hexbyte(void) +{ + uint8_t i; + int8_t n; + + ao_cmd_lex_i = 0; + ao_cmd_white(); + for (i = 0; i < 2; i++) { + n = ao_cmd_hexchar(ao_cmd_lex_c); + if (n < 0) { + ao_cmd_status = ao_cmd_syntax_error; + break; + } + ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n; + ao_cmd_lex(); + } +} + void ao_cmd_hex(void) { __pdata uint8_t r = ao_cmd_lex_error; - uint8_t n; + int8_t n; ao_cmd_lex_i = 0; ao_cmd_white(); for(;;) { - if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') - n = (ao_cmd_lex_c - '0'); - else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f') - n = (ao_cmd_lex_c - 'a' + 10); - else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F') - n = (ao_cmd_lex_c - 'A' + 10); - else + n = ao_cmd_hexchar(ao_cmd_lex_c); + if (n < 0) break; ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n; r = ao_cmd_success; diff --git a/src/core/ao_config.c b/src/core/ao_config.c index ec2b61f6..7f999feb 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -74,11 +74,14 @@ _ao_config_get(void) if (ao_config.major != AO_CONFIG_MAJOR) { ao_config.major = AO_CONFIG_MAJOR; ao_config.minor = 0; + + /* Version 0 stuff */ ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); + ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { /* Fixups for minor version 1 */ @@ -104,6 +107,8 @@ _ao_config_get(void) ao_config.radio_setting = ao_config.radio_cal; if (ao_config.minor < 8) ao_config.radio_enable = TRUE; + if (ao_config.minor < 9) + memset(&ao_config.aes_key, '\0', AO_AES_LEN); ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -414,6 +419,33 @@ ao_config_radio_enable_set(void) __reentrant _ao_config_edit_finish(); } +#if HAS_AES +void +ao_config_key_show(void) __reentrant +{ + uint8_t i; + printf("AES key: "); + for (i = 0; i < AO_AES_LEN; i++) + printf ("%02x", ao_config.aes_key[i]); + printf("\n"); +} + +void +ao_config_key_set(void) __reentrant +{ + uint8_t i; + + _ao_config_edit_start(); + for (i = 0; i < AO_AES_LEN; i++) { + ao_cmd_hexbyte(); + if (ao_cmd_status != ao_cmd_success) + break; + ao_config.aes_key[i] = ao_cmd_lex_i; + } + _ao_config_edit_finish(); +} +#endif + struct ao_config_var { __code char *str; void (*set)(void) __reentrant; @@ -461,6 +493,10 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_ACCEL { "o <0 antenna up, 1 antenna down>\0Set pad orientation", ao_config_pad_orientation_set,ao_config_pad_orientation_show }, +#endif +#if HAS_AES + { "k <32 hex digits>\0Set AES encryption key", + ao_config_key_set, ao_config_key_show }, #endif { "s\0Show", ao_config_show, 0 }, diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 32826114..a19a6a6f 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -107,7 +107,6 @@ ao_sleep(__xdata void *wchan) ao_cur_task->wchan = wchan; ); ao_yield(); - ao_cur_task->alarm = 0; if (ao_cur_task->wchan) { ao_cur_task->wchan = NULL; return 1; @@ -135,6 +134,12 @@ ao_alarm(uint16_t delay) ao_cur_task->alarm = 1; } +void +ao_clear_alarm(void) +{ + ao_cur_task->alarm = 0; +} + void ao_exit(void) { -- cgit v1.2.3 From bc1b94df4d6b92e794ec93d9c1682ae5f61efa61 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jul 2011 22:25:45 -0700 Subject: altos: Finish up primitive telelaunch protocol This adds two commands to teledongle, one to query and one to actually fire the igniter. These will (eventually) want to be replaced with something nicer. Signed-off-by: Keith Packard --- src/ao_launch.c | 44 +++++++++++++--------- src/ao_radio_cmac.c | 101 ++++++++++++++++++++++++++++++++++++++++++--------- src/core/ao_config.c | 2 +- 3 files changed, 111 insertions(+), 36 deletions(-) (limited to 'src/core') diff --git a/src/ao_launch.c b/src/ao_launch.c index 6c154719..35afbda8 100644 --- a/src/ao_launch.c +++ b/src/ao_launch.c @@ -19,6 +19,12 @@ __xdata uint16_t ao_launch_ignite; +#if 0 +#define PRINTD(...) printf(__VA_ARGS__) +#else +#define PRINTD(...) +#endif + static void ao_launch_run(void) { @@ -71,19 +77,20 @@ ao_launch(void) ao_led_off(AO_LED_RED); ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); for (;;) { + flush(); if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) continue; - printf ("tick %d serial %d cmd %d channel %d\n", + PRINTD ("tick %d serial %d cmd %d channel %d\n", command.tick, command.serial, command.cmd, command.channel); - if (command.serial != ao_serial_number) { - printf ("serial number mismatch\n"); - continue; - } - switch (command.cmd) { case AO_LAUNCH_QUERY: + if (command.serial != ao_serial_number) { + PRINTD ("serial number mismatch\n"); + break; + } + if (command.channel == 0) { query.valid = 1; query.arm_status = ao_igniter_status(ao_igniter_drogue); @@ -94,35 +101,38 @@ ao_launch(void) query.tick = ao_time(); query.serial = ao_serial_number; query.channel = command.channel; - printf ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", + 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_ARM: + if (command.serial != ao_serial_number) { + PRINTD ("serial number mismatch\n"); + break; + } + if (command.channel != 0) break; time_difference = command.tick - ao_time(); - printf ("arm tick %d local tick %d\n", 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) { - printf ("time difference too large %d\n", time_difference); + PRINTD ("time difference too large %d\n", time_difference); break; } - printf ("armed\n"); + PRINTD ("armed\n"); ao_launch_armed = 1; ao_launch_arm_time = ao_time(); break; case AO_LAUNCH_FIRE: - if (command.channel != 0) - break; if (!ao_launch_armed) { - printf ("not armed\n"); + PRINTD ("not armed\n"); break; } - if ((uint16_t) (ao_launch_arm_time - ao_time()) > AO_SEC_TO_TICKS(20)) { - printf ("late launch arm_time %d time %d\n", + if ((uint16_t) (ao_time() - ao_launch_arm_time) > AO_SEC_TO_TICKS(20)) { + PRINTD ("late launch arm_time %d time %d\n", ao_launch_arm_time, ao_time()); break; } @@ -130,10 +140,10 @@ ao_launch(void) if (time_difference < 0) time_difference = -time_difference; if (time_difference > 10) { - printf ("time different too large %d\n", time_difference); + PRINTD ("time different too large %d\n", time_difference); break; } - printf ("ignite\n"); + PRINTD ("ignite\n"); ao_launch_ignite = 1; ao_wakeup(&ao_launch_ignite); break; diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index 9694b5b3..c2757b16 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -227,14 +227,37 @@ 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 int8_t +launch_query(uint16_t serial, uint8_t channel) +{ + uint8_t i; + int8_t r = AO_RADIO_CMAC_OK; + + for (i = 0; i < 10; i++) { + printf ("."); flush(); + command.tick = ao_time(); + command.serial = serial; + command.cmd = AO_LAUNCH_QUERY; + command.channel = 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; + } + printf("\n"); flush(); + return r; +} + static void launch_report_cmd(void) __reentrant { - static __xdata struct ao_launch_command command; - static __xdata struct ao_launch_query query; uint8_t channel; uint16_t serial; - uint8_t i; + int8_t r; ao_cmd_decimal(); serial = ao_cmd_lex_i; @@ -242,17 +265,10 @@ launch_report_cmd(void) __reentrant channel = ao_cmd_lex_i; if (ao_cmd_status != ao_cmd_success) return; - flush(); - for (i = 0; i < 10; i++) { - printf ("."); flush(); - command.tick = 0; - command.serial = serial; - command.cmd = AO_LAUNCH_QUERY; - command.channel = channel; - ao_radio_cmac_send(&command, sizeof (command)); - switch (ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500))) { - case AO_RADIO_CMAC_OK: - printf("\n"); + r = launch_query(serial, channel); + switch (r) { + case AO_RADIO_CMAC_OK: + if (query.valid) { switch (query.arm_status) { case ao_igniter_ready: case ao_igniter_active: @@ -268,21 +284,70 @@ launch_report_cmd(void) __reentrant printf("igniter bad\n"); break; } + break; default: printf("Disarmed\n"); } - return; - default: - continue; + } else { + printf("Invalid channel %d\n", channel); } + break; + default: + printf("Error %d\n", r); + break; + } +} + +static void +launch_fire_cmd(void) __reentrant +{ + static __xdata struct ao_launch_command command; + uint8_t channel; + uint16_t serial; + uint8_t secs; + uint8_t i; + int8_t r; + uint16_t tick_offset; + + ao_cmd_decimal(); + serial = ao_cmd_lex_i; + ao_cmd_decimal(); + channel = ao_cmd_lex_i; + ao_cmd_decimal(); + secs = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + tick_offset = ao_time(); + r = launch_query(serial, channel); + tick_offset -= query.tick; + + for (i = 0; i < 4; i++) { + printf("arm %d\n", i); flush(); + command.tick = ao_time() - tick_offset; + command.serial = serial; + command.cmd = AO_LAUNCH_ARM; + command.channel = channel; + ao_radio_cmac_send(&command, sizeof (command)); + } + secs = secs * 10 - 5; + if (secs > 100) + secs = 100; + for (i = 0; i < secs; i++) { + printf("fire %d\n", i); flush(); + command.tick = ao_time() - tick_offset; + command.serial = serial; + command.cmd = AO_LAUNCH_FIRE; + command.channel = 0; + ao_radio_cmac_send(&command, sizeof (command)); + ao_delay(AO_MS_TO_TICKS(100)); } - printf ("Timeout\n"); } 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" }, { 0, NULL }, }; diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 7f999feb..28854ab5 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -108,7 +108,7 @@ _ao_config_get(void) if (ao_config.minor < 8) ao_config.radio_enable = TRUE; if (ao_config.minor < 9) - memset(&ao_config.aes_key, '\0', AO_AES_LEN); + memset(&ao_config.aes_key, 0, AO_AES_LEN); ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } -- cgit v1.2.3 From 8a1cbef0e316e38c80b71d3bac15641fe56e0a99 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 13:27:28 -0700 Subject: altos: Add HAS_LOG for products that log to eeprom Some products have eeprom for config, but none for logging (like telelaunch) Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 2 +- src/core/ao_config.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 9e14c221..d0a46633 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -237,7 +237,7 @@ version(void) printf("manufacturer %s\n", ao_manufacturer); printf("product %s\n", ao_product); printf("serial-number %u\n", ao_serial_number); -#if HAS_EEPROM +#if HAS_LOG printf("log-format %u\n", ao_log_format); #endif printf("software-version %s\n", ao_version); diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 28854ab5..a653bed2 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -308,7 +308,7 @@ ao_config_radio_cal_set(void) __reentrant _ao_config_edit_finish(); } -#if HAS_EEPROM && HAS_FLIGHT +#if HAS_LOG void ao_config_log_show(void) __reentrant { @@ -336,7 +336,7 @@ ao_config_log_set(void) __reentrant _ao_config_edit_finish(); } } -#endif /* HAS_EEPROM && HAS_FLIGHT */ +#endif /* HAS_LOG */ #if HAS_IGNITE void @@ -482,7 +482,7 @@ __code struct ao_config_var ao_config_vars[] = { #endif /* HAS_ACCEL */ { "f \0Radio calib (cal = rf/(xtal/2^16))", ao_config_radio_cal_set, ao_config_radio_cal_show }, -#if HAS_EEPROM && HAS_FLIGHT +#if HAS_LOG { "l \0Flight log size in kB", ao_config_log_set, ao_config_log_show }, #endif -- cgit v1.2.3 From b33a92e372327158ab21c1bb2d091c58761efe10 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 15:19:43 -0700 Subject: altos: Share log code between telescience and telebt. Add telebt log Telescience and telebt both log data in 32-byte chunks, so share some code which manages that between the two products. Add simple telemetry logging to telebt. Signed-off-by: Keith Packard --- src/avr/ao_spi_slave.c | 14 +-- src/core/ao.h | 97 +++++++++++++++---- src/core/ao_log_telem.c | 48 +++++++++- src/core/ao_log_telescience.c | 211 ++++++------------------------------------ src/core/ao_monitor.c | 10 +- src/product/ao_telebt.c | 3 + src/product/ao_telescience.c | 2 +- src/telebt-v0.1/Makefile | 1 + src/telescience-v0.1/Makefile | 1 + 9 files changed, 164 insertions(+), 223 deletions(-) (limited to 'src/core') diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c index 4dde09f3..e4d866a8 100644 --- a/src/avr/ao_spi_slave.c +++ b/src/avr/ao_spi_slave.c @@ -74,9 +74,9 @@ static uint8_t ao_spi_slave_recv(void) return 0; } - ao_log_store.tm_tick = ao_companion_command.tick; - if (ao_log_store.tm_state != ao_companion_command.flight_state) { - ao_log_store.tm_state = ao_companion_command.flight_state; + ao_log_single_write_data.telescience.tm_tick = ao_companion_command.tick; + if (ao_log_single_write_data.telescience.tm_state != ao_companion_command.flight_state) { + ao_log_single_write_data.telescience.tm_state = ao_companion_command.flight_state; return 1; } return 0; @@ -93,11 +93,11 @@ ISR(PCINT0_vect) cli(); changed = ao_spi_slave_recv(); sei(); - if (changed && ao_flight_boost <= ao_log_store.tm_state) { - if (ao_log_store.tm_state < ao_flight_landed) - ao_log_start(); + if (changed && ao_flight_boost <= ao_log_single_write_data.telescience.tm_state) { + if (ao_log_single_write_data.telescience.tm_state < ao_flight_landed) + ao_log_single_start(); else - ao_log_stop(); + ao_log_single_stop(); } } } else { diff --git a/src/core/ao.h b/src/core/ao.h index a5bbb6f1..8b978272 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -505,23 +505,6 @@ extern __pdata uint32_t ao_log_start_pos; extern __xdata uint8_t ao_log_running; extern __pdata enum flight_state ao_log_state; -#define AO_LOG_TELESCIENCE_START ((uint8_t) 's') -#define AO_LOG_TELESCIENCE_DATA ((uint8_t) 'd') - -#define AO_LOG_TELESCIENCE_NUM_ADC 12 - -struct ao_log_telescience { - uint8_t type; - uint8_t csum; - uint16_t tick; - uint16_t tm_tick; - uint8_t tm_state; - uint8_t unused; - uint16_t adc[AO_LOG_TELESCIENCE_NUM_ADC]; -}; - -extern struct ao_log_telescience ao_log_store; - /* required functions from the underlying log system */ #define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ @@ -1365,6 +1348,20 @@ ao_radio_init(void); extern const char const * const ao_state_names[]; +#define AO_MONITOR_RING 8 + +union ao_monitor { + struct ao_telemetry_raw_recv raw; + struct ao_telemetry_orig_recv orig; + struct ao_telemetry_tiny_recv tiny; +}; + +extern __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; + +#define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) + +extern __data uint8_t ao_monitor_head; + void ao_monitor(void); @@ -1724,4 +1721,70 @@ struct ao_launch_query { void ao_launch_init(void); +/* + * ao_log_single.c + */ + +#define AO_LOG_TELESCIENCE_START ((uint8_t) 's') +#define AO_LOG_TELESCIENCE_DATA ((uint8_t) 'd') + +#define AO_LOG_TELESCIENCE_NUM_ADC 12 + +struct ao_log_telescience { + uint8_t type; + uint8_t csum; + uint16_t tick; + uint16_t tm_tick; + uint8_t tm_state; + uint8_t unused; + uint16_t adc[AO_LOG_TELESCIENCE_NUM_ADC]; +}; + +#define AO_LOG_SINGLE_SIZE 32 + +union ao_log_single { + struct ao_log_telescience telescience; + union ao_telemetry_all telemetry; + uint8_t bytes[AO_LOG_SINGLE_SIZE]; +}; + +extern __xdata union ao_log_single ao_log_single_write_data; +extern __xdata union ao_log_single ao_log_single_read_data; + +void +ao_log_single_extra_query(void); + +void +ao_log_single_list(void); + +void +ao_log_single_main(void); + +uint8_t +ao_log_single_write(void); + +uint8_t +ao_log_single_read(uint32_t pos); + +void +ao_log_single_start(void); + +void +ao_log_single_stop(void); + +void +ao_log_single_restart(void); + +void +ao_log_single_set(void); + +void +ao_log_single_delete(void); + +void +ao_log_single_init(void); + +void +ao_log_single(void); + #endif /* _AO_H_ */ diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 1b472efe..34abe879 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -17,14 +17,52 @@ #include "ao.h" +__code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRY; + +static __data uint8_t ao_log_monitor_pos; + +void +ao_log_single(void) +{ + ao_storage_setup(); + + /* This can take a while, so let the rest + * of the system finish booting before we start + */ + ao_delay(AO_SEC_TO_TICKS(2)); + + ao_log_single_restart(); + for (;;) { + while (!ao_log_running) + ao_sleep(&ao_log_running); + + ao_log_monitor_pos = ao_monitor_head; + while (ao_log_running) { + /* Write samples to EEPROM */ + while (ao_log_monitor_pos != ao_monitor_head) { + memcpy(&ao_log_single_write_data.telemetry, + &ao_monitor_ring[ao_log_monitor_pos], + AO_LOG_SINGLE_SIZE); + ao_log_single_write(); + ao_log_monitor_pos = ao_monitor_ring_next(ao_log_monitor_pos); + } + /* Wait for more ADC data to arrive */ + ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + } + } +} + void -ao_log_write_erase(uint8_t pos) +ao_log_single_list(void) { - (void) pos; + if (ao_log_current_pos != 0) + printf("flight 1 start %x end %x\n", + 0, + (uint16_t) ((ao_log_current_pos + 0xff) >> 8)); + printf ("done\n"); } -uint8_t -ao_log_present(void) +void +ao_log_single_extra_query(void) { - return 0; } diff --git a/src/core/ao_log_telescience.c b/src/core/ao_log_telescience.c index aac780fa..31eda381 100644 --- a/src/core/ao_log_telescience.c +++ b/src/core/ao_log_telescience.c @@ -18,119 +18,25 @@ #include "ao.h" #include "ao_product.h" -static struct ao_task ao_log_task; -//static struct ao_task ao_spi_task; - -uint8_t ao_log_running; -uint8_t ao_log_mutex; -uint32_t ao_log_start_pos; -uint32_t ao_log_end_pos; -uint32_t ao_log_current_pos; - -#define AO_LOG_TELESCIENCE_START ((uint8_t) 's') -#define AO_LOG_TELESCIENCE_DATA ((uint8_t) 'd') - -struct ao_log_telescience ao_log_store; -struct ao_log_telescience ao_log_fetch; - static uint8_t ao_log_adc_pos; __code uint8_t ao_log_format = AO_LOG_FORMAT_TELESCIENCE; -static uint8_t -ao_log_csum(__xdata uint8_t *b) __reentrant +static void +ao_log_telescience_csum(void) __reentrant { + __xdata uint8_t *b = ao_log_single_write_data.bytes; uint8_t sum = 0x5a; uint8_t i; + ao_log_single_write_data.telescience.csum = 0; for (i = 0; i < sizeof (struct ao_log_telescience); i++) sum += *b++; - return -sum; -} - -static uint8_t -ao_log_telescience_write(void) -{ - uint8_t wrote = 0; - - ao_log_store.csum = 0; - ao_log_store.csum = ao_log_csum((__xdata uint8_t *) &ao_log_store); - ao_mutex_get(&ao_log_mutex); { - if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) - ao_log_stop(); - if (ao_log_running) { - wrote = 1; - ao_storage_write(ao_log_current_pos, - (__xdata uint8_t *) &ao_log_store, - sizeof (struct ao_log_telescience)); - ao_log_current_pos += sizeof (struct ao_log_telescience); - } - } ao_mutex_put(&ao_log_mutex); - return wrote; -} - -static uint8_t -ao_log_valid(struct ao_log_telescience *log) -{ - uint8_t *d; - uint8_t i; - d = (uint8_t *) log; - for (i = 0; i < sizeof (struct ao_log_telescience); i++) - if (d[i] != 0xff) - return 1; - return 0; -} - -static uint8_t -ao_log_telescience_read(uint32_t pos) -{ - if (!ao_storage_read(pos, &ao_log_fetch, sizeof (struct ao_log_telescience))) - return 0; - return ao_log_valid(&ao_log_fetch); -} - -void -ao_log_start(void) -{ - if (!ao_log_running) { - ao_log_running = 1; - ao_wakeup(&ao_log_running); - } -} - -void -ao_log_stop(void) -{ - if (ao_log_running) { - ao_log_running = 0; - } -} - -void -ao_log_restart(void) -{ - /* Find end of data */ - ao_log_end_pos = ao_storage_config; - for (ao_log_current_pos = 0; - ao_log_current_pos < ao_storage_config; - ao_log_current_pos += ao_storage_block) - { - if (!ao_log_telescience_read(ao_log_current_pos)) - break; - } - if (ao_log_current_pos > 0) { - ao_log_current_pos -= ao_storage_block; - for (; ao_log_current_pos < ao_storage_config; - ao_log_current_pos += sizeof (struct ao_log_telescience)) - { - if (!ao_log_telescience_read(ao_log_current_pos)) - break; - } - } + ao_log_single_write_data.telescience.csum = -sum; } void -ao_log_telescience(void) +ao_log_single(void) { ao_storage_setup(); @@ -139,57 +45,42 @@ ao_log_telescience(void) */ ao_delay(AO_SEC_TO_TICKS(10)); - ao_log_restart(); + ao_log_single_restart(); for (;;) { while (!ao_log_running) ao_sleep(&ao_log_running); ao_log_start_pos = ao_log_current_pos; - ao_log_store.type = AO_LOG_TELESCIENCE_START; - ao_log_store.tick = ao_time(); - ao_log_store.adc[0] = ao_companion_command.serial; - ao_log_store.adc[1] = ao_companion_command.flight; - ao_log_telescience_write(); + ao_log_single_write_data.telescience.type = AO_LOG_TELESCIENCE_START; + ao_log_single_write_data.telescience.tick = ao_time(); + ao_log_single_write_data.telescience.adc[0] = ao_companion_command.serial; + ao_log_single_write_data.telescience.adc[1] = ao_companion_command.flight; + ao_log_telescience_csum(); + ao_log_single_write(); /* Write the whole contents of the ring to the log * when starting up. */ ao_log_adc_pos = ao_adc_ring_next(ao_adc_head); - ao_log_store.type = AO_LOG_TELESCIENCE_DATA; + ao_log_single_write_data.telescience.type = AO_LOG_TELESCIENCE_DATA; while (ao_log_running) { /* Write samples to EEPROM */ while (ao_log_adc_pos != ao_adc_head) { - ao_log_store.tick = ao_adc_ring[ao_log_adc_pos].tick; - memcpy(&ao_log_store.adc, (void *) ao_adc_ring[ao_log_adc_pos].adc, + ao_log_single_write_data.telescience.tick = ao_adc_ring[ao_log_adc_pos].tick; + memcpy(&ao_log_single_write_data.telescience.adc, (void *) ao_adc_ring[ao_log_adc_pos].adc, AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); - ao_log_telescience_write(); + ao_log_telescience_csum(); + ao_log_single_write(); ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); } /* Wait for more ADC data to arrive */ ao_sleep((void *) &ao_adc_head); } - memset(&ao_log_store.adc, '\0', sizeof (ao_log_store.adc)); + memset(&ao_log_single_write_data.telescience.adc, '\0', sizeof (ao_log_single_write_data.telescience.adc)); } } void -ao_log_set(void) -{ - printf("Logging currently %s\n", ao_log_running ? "on" : "off"); - ao_cmd_hex(); - if (ao_cmd_status == ao_cmd_success) { - if (ao_cmd_lex_i) { - printf("Logging from %ld to %ld\n", ao_log_current_pos, ao_log_end_pos); - ao_log_start(); - } else { - printf ("Log stopped at %ld\n", ao_log_current_pos); - ao_log_stop(); - } - } - ao_cmd_status = ao_cmd_success; -} - -void -ao_log_list(void) +ao_log_single_list(void) { uint32_t pos; uint32_t start = 0; @@ -197,8 +88,8 @@ ao_log_list(void) for (pos = 0; ; pos += sizeof (struct ao_log_telescience)) { if (pos >= ao_storage_config || - !ao_log_telescience_read(pos) || - ao_log_fetch.type == AO_LOG_TELESCIENCE_START) + !ao_log_single_read(pos) || + ao_log_single_read_data.telescience.type == AO_LOG_TELESCIENCE_START) { if (pos != start) { printf("flight %d start %x end %x\n", @@ -206,7 +97,7 @@ ao_log_list(void) (uint16_t) (start >> 8), (uint16_t) ((pos + 0xff) >> 8)); flush(); } - if (ao_log_fetch.type != AO_LOG_TELESCIENCE_START) + if (ao_log_single_read_data.telescience.type != AO_LOG_TELESCIENCE_START) break; start = pos; flight++; @@ -216,59 +107,11 @@ ao_log_list(void) } void -ao_log_delete(void) +ao_log_single_extra_query(void) { - uint32_t pos; - - ao_cmd_hex(); - if (ao_cmd_status != ao_cmd_success) - return; - if (ao_cmd_lex_i != 1) { - ao_cmd_status = ao_cmd_syntax_error; - printf("No such flight: %d\n", ao_cmd_lex_i); - return; - } - ao_log_stop(); - for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) { - if (!ao_log_telescience_read(pos)) - break; - ao_storage_erase(pos); - } - ao_log_current_pos = ao_log_start_pos = 0; - if (pos == 0) - printf("No such flight: %d\n", ao_cmd_lex_i); - else - printf ("Erased\n"); -} - -static void -ao_log_query(void) -{ - printf("Logging enabled: %d\n", ao_log_running); - printf("Log start: %ld\n", ao_log_start_pos); - printf("Log cur: %ld\n", ao_log_current_pos); - printf("Log end: %ld\n", ao_log_end_pos); - printf("log data tick: %04x\n", ao_log_store.tick); - printf("TM data tick: %04x\n", ao_log_store.tm_tick); - printf("TM state: %d\n", ao_log_store.tm_state); + printf("log data tick: %04x\n", ao_log_single_write_data.telescience.tick); + printf("TM data tick: %04x\n", ao_log_single_write_data.telescience.tm_tick); + printf("TM state: %d\n", ao_log_single_write_data.telescience.tm_state); printf("TM serial: %d\n", ao_companion_command.serial); printf("TM flight: %d\n", ao_companion_command.flight); } - -const struct ao_cmds ao_log_cmds[] = { - { ao_log_set, "L <0 off, 1 on>\0Set logging mode" }, - { ao_log_list, "l\0List stored flight logs" }, - { ao_log_delete, "d 1\0Delete all stored flights" }, - { ao_log_query, "q\0Query log status" }, - { 0, NULL }, -}; - -void -ao_log_init(void) -{ - ao_log_running = 0; - - ao_cmd_register(&ao_log_cmds[0]); - - ao_add_task(&ao_log_task, ao_log_telescience, "log"); -} diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 69eb58e8..6f2d9dbb 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -25,15 +25,7 @@ __xdata uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; -#define AO_MONITOR_RING 8 - -__xdata union ao_monitor { - struct ao_telemetry_raw_recv raw; - struct ao_telemetry_orig_recv orig; - struct ao_telemetry_tiny_recv tiny; -} ao_monitor_ring[AO_MONITOR_RING]; - -#define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) +__xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; __data uint8_t ao_monitor_head; diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 5bbbf71b..cb23f391 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -42,6 +42,9 @@ main(void) ao_radio_init(); ao_packet_master_init(); ao_btm_init(); +#if HAS_LOG + ao_log_single_init(); +#endif #if HAS_DBG ao_dbg_init(); #endif diff --git a/src/product/ao_telescience.c b/src/product/ao_telescience.c index 4dec3a18..45b6d40e 100644 --- a/src/product/ao_telescience.c +++ b/src/product/ao_telescience.c @@ -33,7 +33,7 @@ main(void) ao_storage_init(); ao_usb_init(); ao_adc_init(); - ao_log_init(); + ao_log_single_init(); ao_start_scheduler(); return 0; } diff --git a/src/telebt-v0.1/Makefile b/src/telebt-v0.1/Makefile index a34e8912..01fbaf52 100644 --- a/src/telebt-v0.1/Makefile +++ b/src/telebt-v0.1/Makefile @@ -10,6 +10,7 @@ TELEBT_INC = \ TELEBT_SRC = \ ao_beep.c \ + ao_log_single.c \ ao_log_telem.c \ ao_spi.c \ ao_storage.c \ diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index 3ccbb787..282829e7 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -46,6 +46,7 @@ ALTOS_SRC = \ ao_usb_avr.c \ ao_adc_avr.c \ ao_spi_slave.c \ + ao_log_single.c \ ao_log_telescience.c \ $(TELESCIENCE_STORAGE) -- cgit v1.2.3 From e53557373e539d591a03d02db146b27d08c7eba3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:18:29 -0700 Subject: altos: Start logging telemetry data right at boot time Anything logging telemetry data should just start logging packets as soon as they boot. Signed-off-by: Keith Packard --- src/core/ao_log_telem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 34abe879..af0e8e6b 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -31,6 +31,7 @@ ao_log_single(void) */ ao_delay(AO_SEC_TO_TICKS(2)); + ao_log_running = 1; ao_log_single_restart(); for (;;) { while (!ao_log_running) @@ -46,7 +47,7 @@ ao_log_single(void) ao_log_single_write(); ao_log_monitor_pos = ao_monitor_ring_next(ao_log_monitor_pos); } - /* Wait for more ADC data to arrive */ + /* Wait for more telemetry data to arrive */ ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); } } -- cgit v1.2.3 From 27835686648e14b030f6f7ec1fc0c0fd1c387ea4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:38:12 -0700 Subject: altos: Add RSSI blinking to new-style telemetry code Pull the RSSI data out locally and set the RSSI led blinking when using the variable-length TELEM output mechanism. Signed-off-by: Keith Packard --- src/core/ao_monitor.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/core') diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 6f2d9dbb..c167b861 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -228,6 +228,10 @@ ao_monitor_put(void) printf("%02x", byte); } printf("%02x\n", sum); + if (recv_raw.packet[ao_monitoring + 1] & PKT_APPEND_STATUS_1_CRC_OK) { + rssi = ((int16_t) recv_raw.packet[ao_monitoring] >> 1) - 74; + ao_rssi_set(rssi); + } break; } ao_usb_flush(); -- cgit v1.2.3 From cff737c290347b61ba16584880c2f4c436b95042 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:40:40 -0700 Subject: altos: Remove RSSI reporting from telebt Telebt uses one LED for bluetooth connection and the other for telem packet reception leaving none for RSSI. Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 11 +++++++++++ src/core/ao_monitor.c | 6 ++++++ src/product/Makefile.telebt | 1 - src/product/ao_telebt.c | 3 +-- 4 files changed, 18 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 91719b54..57de67b2 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -111,6 +111,7 @@ #define SPI_CS_ON_P0 0 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_RSSI 1 #define HAS_AES 1 #endif @@ -220,6 +221,7 @@ #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_RSSI 1 #define HAS_AES 1 #endif @@ -245,6 +247,7 @@ #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_RSSI 1 #define HAS_AES 1 #endif @@ -276,6 +279,7 @@ #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P2_1 #define HAS_MONITOR 1 + #define HAS_RSSI 0 #define HAS_AES 1 #endif @@ -314,6 +318,7 @@ #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P1_7 #define HAS_MONITOR 1 + #define HAS_RSSI 0 #define HAS_AES 1 #endif @@ -456,6 +461,12 @@ #error Please define HAS_MONITOR #endif +#if HAS_MONITOR +#ifndef HAS_RSSI +#error Please define HAS_RSSI +#endif +#endif + #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index c167b861..aaa6bb8b 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -151,7 +151,9 @@ ao_monitor_put(void) ao_gps_print(&recv_orig.telemetry_orig.gps); ao_gps_tracking_print(&recv_orig.telemetry_orig.gps_tracking); putchar('\n'); +#if HAS_RSSI ao_rssi_set(rssi); +#endif } else { printf("CRC INVALID RSSI %3d\n", rssi); } @@ -214,7 +216,9 @@ ao_monitor_put(void) recv_tiny.telemetry_tiny.flight_vel, recv_tiny.telemetry_tiny.flight_pres); #endif +#if HAS_RSSI ao_rssi_set(rssi); +#endif } else { printf("CRC INVALID RSSI %3d\n", rssi); } @@ -228,10 +232,12 @@ ao_monitor_put(void) printf("%02x", byte); } printf("%02x\n", sum); +#if HAS_RSSI if (recv_raw.packet[ao_monitoring + 1] & PKT_APPEND_STATUS_1_CRC_OK) { rssi = ((int16_t) recv_raw.packet[ao_monitoring] >> 1) - 74; ao_rssi_set(rssi); } +#endif break; } ao_usb_flush(); diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index ff0e1502..46c87db0 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -26,7 +26,6 @@ CORE_SRC = \ ao_monitor.c \ ao_mutex.c \ ao_panic.c \ - ao_rssi.c \ ao_state.c \ ao_stdio.c \ ao_task.c diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index cb23f391..9154f4be 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -37,8 +37,7 @@ main(void) ao_storage_init(); #endif ao_usb_init(); - ao_monitor_init(AO_LED_GREEN, TRUE); - ao_rssi_init(AO_LED_RED); + ao_monitor_init(AO_LED_RED, TRUE); ao_radio_init(); ao_packet_master_init(); ao_btm_init(); -- cgit v1.2.3 From 7c6a3195dec6ac68f5d7b3f883ccc2c316384e76 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:42:25 -0700 Subject: altos: Blink on telem packet receive instead of toggle Toggling the LED was too confusing; just blink for 100ms each time a packet comes in. Signed-off-by: Keith Packard --- src/core/ao_monitor.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index aaa6bb8b..382af8a2 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -55,7 +55,15 @@ ao_monitor_get(void) continue; ao_monitor_head = ao_monitor_ring_next(ao_monitor_head); ao_wakeup(DATA_TO_XDATA(&ao_monitor_head)); - ao_led_toggle(ao_monitor_led); + } +} + +void +ao_monitor_blink(void) +{ + for (;;) { + ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + ao_led_for(ao_monitor_led, AO_MS_TO_TICKS(100)); } } @@ -246,6 +254,7 @@ ao_monitor_put(void) __xdata struct ao_task ao_monitor_get_task; __xdata struct ao_task ao_monitor_put_task; +__xdata struct ao_task ao_monitor_blink_task; void ao_set_monitor(uint8_t monitoring) @@ -276,4 +285,6 @@ ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant ao_cmd_register(&ao_monitor_cmds[0]); ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); + if (ao_monitor_led) + ao_add_task(&ao_monitor_blink_task, ao_monitor_blink, "monitor_blink"); } -- cgit v1.2.3 From 8eaa1c4697a3cfc2406e1adadc3094f7f712341a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:43:32 -0700 Subject: altos: Add pragma to eliminate unreachable code warning on SDCC This pragma was removed as GCC doesn't support it; make it conditional on SDCC so that we eliminate a warning message. Signed-off-by: Keith Packard --- src/core/ao_panic.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/core') diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index b6ff65cc..244917a8 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -58,6 +58,9 @@ ao_panic(uint8_t reason) ao_beep(AO_BEEP_OFF); ao_panic_delay(2); +#ifdef SDCC +#pragma disable_warning 126 +#endif for (n = 0; n < reason; n++) { ao_led_on(AO_LED_RED); ao_beep(AO_BEEP_MID); -- cgit v1.2.3 From 9b9568a637ffdbc67225271005f2b996ee08a0df Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 16:39:41 -0700 Subject: altos: add 'report' to telebt This beeps out flight state changes and max altitude at landing, just like the altimeter. Signed-off-by: Keith Packard --- src/core/ao.h | 1 + src/core/ao_log_telem.c | 25 ++++++++++++++++++++++++- src/core/ao_monitor.c | 6 +++--- src/drivers/ao_btm.c | 4 ---- src/product/Makefile.telebt | 1 + src/product/ao_telebt.c | 3 ++- 6 files changed, 31 insertions(+), 9 deletions(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index 8b978272..f2e40fc6 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1360,6 +1360,7 @@ extern __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; #define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) +extern __data uint8_t ao_monitoring; extern __data uint8_t ao_monitor_head; void diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index af0e8e6b..9afa13b2 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -19,8 +19,29 @@ __code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRY; -static __data uint8_t ao_log_monitor_pos; +static __data uint8_t ao_log_monitor_pos; +__pdata enum ao_flight_state ao_flight_state; +__pdata int16_t ao_max_height; /* max of ao_height */ +static void +ao_log_telem_track() { + if (ao_monitoring == sizeof (union ao_telemetry_all)) { + switch (ao_log_single_write_data.telemetry.generic.type) { + case AO_TELEMETRY_SENSOR_TELEMETRUM: + case AO_TELEMETRY_SENSOR_TELEMINI: + case AO_TELEMETRY_SENSOR_TELENANO: + if (ao_log_single_write_data.telemetry.sensor.height > ao_max_height) { + ao_max_height = ao_log_single_write_data.telemetry.sensor.height; + } + if (ao_log_single_write_data.telemetry.sensor.state != ao_flight_state) { + ao_flight_state = ao_log_single_write_data.telemetry.sensor.state; + if (ao_flight_state == ao_flight_pad) + ao_max_height = 0; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + } + } +} void ao_log_single(void) { @@ -33,6 +54,7 @@ ao_log_single(void) ao_log_running = 1; ao_log_single_restart(); + ao_flight_state = ao_flight_startup; for (;;) { while (!ao_log_running) ao_sleep(&ao_log_running); @@ -46,6 +68,7 @@ ao_log_single(void) AO_LOG_SINGLE_SIZE); ao_log_single_write(); ao_log_monitor_pos = ao_monitor_ring_next(ao_log_monitor_pos); + ao_log_telem_track(); } /* Wait for more telemetry data to arrive */ ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 382af8a2..56d7604d 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -22,7 +22,7 @@ #error Must define HAS_MONITOR to 1 #endif -__xdata uint8_t ao_monitoring; +__data uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; @@ -37,7 +37,7 @@ ao_monitor_get(void) for (;;) { switch (ao_monitoring) { case 0: - ao_sleep(&ao_monitoring); + ao_sleep(DATA_TO_XDATA(&ao_monitoring)); continue; case AO_MONITORING_ORIG: size = sizeof (struct ao_telemetry_orig_recv); @@ -262,7 +262,7 @@ ao_set_monitor(uint8_t monitoring) if (ao_monitoring) ao_radio_recv_abort(); ao_monitoring = monitoring; - ao_wakeup(&ao_monitoring); + ao_wakeup(DATA_TO_XDATA(&ao_monitoring)); } static void diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index e70e3048..5eb78815 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -249,10 +249,6 @@ ao_btm(void) */ ao_delay(AO_SEC_TO_TICKS(3)); -#if HAS_BEEP - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); -#endif - /* * The first time we connect, the BTM-180 comes up at 19200 baud. * After that, it will remember and come up at 57600 baud. So, see diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index 46c87db0..04dd044e 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -26,6 +26,7 @@ CORE_SRC = \ ao_monitor.c \ ao_mutex.c \ ao_panic.c \ + ao_report.c \ ao_state.c \ ao_stdio.c \ ao_task.c diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 9154f4be..6fe18a4d 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -37,7 +37,8 @@ main(void) ao_storage_init(); #endif ao_usb_init(); - ao_monitor_init(AO_LED_RED, TRUE); + ao_monitor_init(AO_LED_RED, sizeof (union ao_telemetry_all)); + ao_report_init(); ao_radio_init(); ao_packet_master_init(); ao_btm_init(); -- cgit v1.2.3 From 122c4101164d598e655fa9ad8473053d30ff4212 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 16:55:55 -0700 Subject: altos: Report continuity in telebt Report continuity values from remote altimeter Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 6 ++++++ src/core/ao_log_telem.c | 29 +++++++++++++++++++++++++++++ src/core/ao_report.c | 6 ++++-- src/product/Makefile.telebt | 1 - src/product/ao_telebt.c | 2 ++ src/telebt-v0.1/Makefile | 1 + 6 files changed, 42 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 57de67b2..723f1500 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -274,6 +274,7 @@ #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 #define HAS_IGNITE 0 + #define HAS_IGNITE_REPORT 1 #define BT_LINK_ON_P2 1 #define BT_LINK_ON_P1 0 #define BT_LINK_PIN_INDEX 7 @@ -313,6 +314,7 @@ #define M25_MAX_CHIPS 1 #define HAS_ACCEL 0 #define HAS_IGNITE 0 + #define HAS_IGNITE_REPORT 1 #define BT_LINK_ON_P2 0 #define BT_LINK_ON_P1 1 #define BT_LINK_PIN_INDEX 7 @@ -449,6 +451,10 @@ #error Please define HAS_IGNITE #endif +#if HAS_IGNITE +#define HAS_IGNITE_REPORT 1 +#endif + #ifndef PACKET_HAS_MASTER #error Please define PACKET_HAS_MASTER #endif diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 9afa13b2..193c11f3 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -22,6 +22,7 @@ __code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRY; static __data uint8_t ao_log_monitor_pos; __pdata enum ao_flight_state ao_flight_state; __pdata int16_t ao_max_height; /* max of ao_height */ +__pdata int16_t sense_d, sense_m; static void ao_log_telem_track() { @@ -29,6 +30,9 @@ ao_log_telem_track() { switch (ao_log_single_write_data.telemetry.generic.type) { case AO_TELEMETRY_SENSOR_TELEMETRUM: case AO_TELEMETRY_SENSOR_TELEMINI: + sense_d = ao_log_single_write_data.telemetry.sensor.sense_d; + sense_m = ao_log_single_write_data.telemetry.sensor.sense_m; + /* fall through ... */ case AO_TELEMETRY_SENSOR_TELENANO: if (ao_log_single_write_data.telemetry.sensor.height > ao_max_height) { ao_max_height = ao_log_single_write_data.telemetry.sensor.height; @@ -42,6 +46,31 @@ ao_log_telem_track() { } } } + +enum ao_igniter_status +ao_igniter_status(enum ao_igniter igniter) +{ + int16_t value; + + switch (igniter) { + case ao_igniter_drogue: + value = sense_d; + break; + case ao_igniter_main: + value = sense_m; + break; + default: + value = 0; + break; + } + if (value < AO_IGNITER_OPEN) + return ao_igniter_open; + else if (value > AO_IGNITER_CLOSED) + return ao_igniter_ready; + else + return ao_igniter_unknown; +} + void ao_log_single(void) { diff --git a/src/core/ao_report.c b/src/core/ao_report.c index 3cf558e1..e0355d96 100644 --- a/src/core/ao_report.c +++ b/src/core/ao_report.c @@ -109,7 +109,7 @@ ao_report_altitude(void) } } -#if HAS_IGNITE +#if HAS_IGNITE_REPORT static uint8_t ao_report_igniter_ready(enum ao_igniter igniter) { @@ -133,6 +133,7 @@ ao_report_continuity(void) __reentrant low(AO_MS_TO_TICKS(20)); } } +#if HAS_LOG if (ao_log_full()) { pause(AO_MS_TO_TICKS(100)); c = 2; @@ -143,6 +144,7 @@ ao_report_continuity(void) __reentrant mid(AO_MS_TO_TICKS(100)); } } +#endif c = 50; while (c-- && ao_flight_state == ao_flight_pad) pause(AO_MS_TO_TICKS(100)); @@ -157,7 +159,7 @@ ao_report(void) if (ao_flight_state == ao_flight_landed) ao_report_altitude(); ao_report_beep(); -#if HAS_IGNITE +#if HAS_IGNITE_REPORT if (ao_flight_state == ao_flight_idle) ao_report_continuity(); while (ao_flight_state == ao_flight_pad) diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index 04dd044e..46c87db0 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -26,7 +26,6 @@ CORE_SRC = \ ao_monitor.c \ ao_mutex.c \ ao_panic.c \ - ao_report.c \ ao_state.c \ ao_stdio.c \ ao_task.c diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 6fe18a4d..9e409db7 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -38,7 +38,9 @@ main(void) #endif ao_usb_init(); ao_monitor_init(AO_LED_RED, sizeof (union ao_telemetry_all)); +#if HAS_LOG ao_report_init(); +#endif ao_radio_init(); ao_packet_master_init(); ao_btm_init(); diff --git a/src/telebt-v0.1/Makefile b/src/telebt-v0.1/Makefile index 01fbaf52..90cd3cac 100644 --- a/src/telebt-v0.1/Makefile +++ b/src/telebt-v0.1/Makefile @@ -12,6 +12,7 @@ TELEBT_SRC = \ ao_beep.c \ ao_log_single.c \ ao_log_telem.c \ + ao_report.c \ ao_spi.c \ ao_storage.c \ ao_m25.c -- cgit v1.2.3 From e66fd72664aae7c000dce9c528803e28e7918fdf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 17:03:26 -0700 Subject: altos: don't beep igniter continuity for telenano Without any igniters, it's not nice to annoy people. Signed-off-by: Keith Packard --- src/core/ao.h | 2 ++ src/core/ao_log_telem.c | 10 ++++++++-- src/core/ao_report.c | 18 +++++++++++++----- 3 files changed, 23 insertions(+), 7 deletions(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index f2e40fc6..a541d8ac 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1436,6 +1436,8 @@ extern __xdata struct ao_ignition ao_ignition[2]; enum ao_igniter_status ao_igniter_status(enum ao_igniter igniter); +extern __pdata uint8_t ao_igniter_present; + void ao_ignite_set_pins(void); diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 193c11f3..096ad919 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -23,6 +23,7 @@ static __data uint8_t ao_log_monitor_pos; __pdata enum ao_flight_state ao_flight_state; __pdata int16_t ao_max_height; /* max of ao_height */ __pdata int16_t sense_d, sense_m; +__pdata uint8_t ao_igniter_present; static void ao_log_telem_track() { @@ -30,10 +31,15 @@ ao_log_telem_track() { switch (ao_log_single_write_data.telemetry.generic.type) { case AO_TELEMETRY_SENSOR_TELEMETRUM: case AO_TELEMETRY_SENSOR_TELEMINI: - sense_d = ao_log_single_write_data.telemetry.sensor.sense_d; - sense_m = ao_log_single_write_data.telemetry.sensor.sense_m; /* fall through ... */ case AO_TELEMETRY_SENSOR_TELENANO: + if (ao_log_single_write_data.telemetry.generic.type == AO_TELEMETRY_SENSOR_TELENANO) { + ao_igniter_present = 0; + } else { + sense_d = ao_log_single_write_data.telemetry.sensor.sense_d; + sense_m = ao_log_single_write_data.telemetry.sensor.sense_m; + ao_igniter_present = 1; + } if (ao_log_single_write_data.telemetry.sensor.height > ao_max_height) { ao_max_height = ao_log_single_write_data.telemetry.sensor.height; } diff --git a/src/core/ao_report.c b/src/core/ao_report.c index e0355d96..70f0b49d 100644 --- a/src/core/ao_report.c +++ b/src/core/ao_report.c @@ -119,7 +119,13 @@ ao_report_igniter_ready(enum ao_igniter igniter) static void ao_report_continuity(void) __reentrant { - uint8_t c = (ao_report_igniter_ready(ao_igniter_drogue) | + uint8_t c; + +#if !HAS_IGNITE + if (!ao_igniter_present) + return; +#endif + c = (ao_report_igniter_ready(ao_igniter_drogue) | (ao_report_igniter_ready(ao_igniter_main) << 1)); if (c) { while (c--) { @@ -145,9 +151,6 @@ ao_report_continuity(void) __reentrant } } #endif - c = 50; - while (c-- && ao_flight_state == ao_flight_pad) - pause(AO_MS_TO_TICKS(100)); } #endif @@ -162,8 +165,13 @@ ao_report(void) #if HAS_IGNITE_REPORT if (ao_flight_state == ao_flight_idle) ao_report_continuity(); - while (ao_flight_state == ao_flight_pad) + while (ao_flight_state == ao_flight_pad) { + uint8_t c; ao_report_continuity(); + c = 50; + while (c-- && ao_flight_state == ao_flight_pad) + pause(AO_MS_TO_TICKS(100)); + } #endif __critical { while (ao_report_state == ao_flight_state) -- cgit v1.2.3 From abf17522c206b465375b73a004a6d67bfa714ba3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 11:36:11 -0700 Subject: altos: SPI slave code is now per-product We can't write general purpose SPI slave code as we must eliminate any latency because the SPI ports have no buffering. Signed-off-by: Keith Packard --- src/avr/ao_pins.h | 7 +++ src/avr/ao_spi_slave.c | 99 +++++++++++++++--------------------------- src/core/ao.h | 13 +++++- src/drivers/ao_science_slave.c | 62 ++++++++++++++++++++++++++ src/telescience-v0.1/Makefile | 1 + 5 files changed, 118 insertions(+), 64 deletions(-) create mode 100644 src/drivers/ao_science_slave.c (limited to 'src/core') diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 56435f18..88f03829 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -52,6 +52,13 @@ #define SPI_CS_DIR DDRE #define M25_CS_MASK (1 << PORTE6) #define M25_MAX_CHIPS 1 + + #define SPI_SLAVE_CS_PORT PORTB + #define SPI_SLAVE_CS_PIN PINB + #define SPI_SLAVE_CS_PIN_NO PINB0 + + #define SPI_SLAVE_PIN_0_3 1 + #define SPI_SLAVE_PIN_2_5 0 #endif #endif /* _AO_PINS_H_ */ diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c index e4d866a8..76f574c6 100644 --- a/src/avr/ao_spi_slave.c +++ b/src/avr/ao_spi_slave.c @@ -16,18 +16,8 @@ */ #include "ao.h" -#include "ao_product.h" -struct ao_companion_command ao_companion_command; - -static const struct ao_companion_setup ao_telescience_setup = { - .board_id = AO_idProduct_NUMBER, - .board_id_inverse = ~AO_idProduct_NUMBER, - .update_period = 50, - .channels = AO_LOG_TELESCIENCE_NUM_ADC, -}; - -static uint8_t +uint8_t ao_spi_read(uint8_t *buf, uint8_t len) { while (len--) { @@ -39,7 +29,7 @@ ao_spi_read(uint8_t *buf, uint8_t len) return 1; } -static void +void ao_spi_write(uint8_t *buf, uint8_t len) { while (len--) { @@ -52,66 +42,38 @@ ao_spi_write(uint8_t *buf, uint8_t len) (void) SPDR; } -static uint8_t ao_spi_slave_recv(void) -{ - if (!ao_spi_read((uint8_t *) &ao_companion_command, - sizeof (ao_companion_command))) - return 0; - - /* Figure out the outbound data */ - switch (ao_companion_command.command) { - case AO_COMPANION_SETUP: - ao_spi_write((uint8_t *) &ao_telescience_setup, - sizeof (ao_telescience_setup)); - break; - case AO_COMPANION_FETCH: - ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, - AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); - break; - case AO_COMPANION_NOTIFY: - break; - default: - return 0; - } - - ao_log_single_write_data.telescience.tm_tick = ao_companion_command.tick; - if (ao_log_single_write_data.telescience.tm_state != ao_companion_command.flight_state) { - ao_log_single_write_data.telescience.tm_state = ao_companion_command.flight_state; - return 1; - } - return 0; -} - static uint8_t ao_spi_slave_running; ISR(PCINT0_vect) { - if ((PINB & (1 << PINB0)) == 0) { + cli(); +#if SPI_SLAVE_PIN_0_3 + if ((PINB & (1 << PORTB0)) == 0) +#endif +#if SPI_SLAVE_PIN_2_5 + if ((PINB & (1 << PORTB2)) == 0) +#endif + { if (!ao_spi_slave_running) { - uint8_t changed; ao_spi_slave_running = 1; - cli(); - changed = ao_spi_slave_recv(); - sei(); - if (changed && ao_flight_boost <= ao_log_single_write_data.telescience.tm_state) { - if (ao_log_single_write_data.telescience.tm_state < ao_flight_landed) - ao_log_single_start(); - else - ao_log_single_stop(); - } + ao_spi_slave(); } } else { ao_spi_slave_running = 0; } -} - -void ao_spi_slave_debug(void) { - printf ("slave running %d\n", ao_spi_slave_running); + sei(); } void ao_spi_slave_init(void) { + /* We'd like to have a pull-up on SS so that disconnecting the + * TM would cause any SPI transaction to abort. However, when + * I tried that, SPI transactions would spontaneously abort, + * making me assume that we needed a less aggressive pull-up + * than is offered inside the AVR + */ +#if SPI_SLAVE_PIN_0_3 PCMSK0 |= (1 << PCINT0); /* Enable PCINT0 pin change */ PCICR |= (1 << PCIE0); /* Enable pin change interrupt */ @@ -121,17 +83,28 @@ ao_spi_slave_init(void) (0 << 1) | /* SCK, input */ (0 << 0)); /* SS, input */ - /* We'd like to have a pull-up on SS so that disconnecting the - * TM would cause any SPI transaction to abort. However, when - * I tried that, SPI transactions would spontaneously abort, - * making me assume that we needed a less aggressive pull-up - * than is offered inside the AVR - */ PORTB = ((PORTB & 0xf0) | (1 << 3) | /* MISO, output */ (0 << 2) | /* MOSI, no pull-up */ (0 << 1) | /* SCK, no pull-up */ (0 << 0)); /* SS, no pull-up */ +#endif +#if SPI_SLAVE_PIN_2_5 + PCMSK0 |= (1 << PCINT2); /* Enable PCINT2 pin change */ + PCICR |= (1 << PCIE0); /* Enable pin change interrupt */ + + DDRB = ((DDRB & 0xf0) | + (0 << 5) | /* SCK, input */ + (1 << 4) | /* MISO, output */ + (0 << 3) | /* MOSI, input */ + (0 << 2)); /* SS, input */ + + PORTB = ((PORTB & 0xf0) | + (0 << 5) | /* SCK, no pull-up */ + (1 << 4) | /* MISO, output */ + (0 << 3) | /* MOSI, no pull-up */ + (0 << 2)); /* SS, no pull-up */ +#endif SPCR = (0 << SPIE) | /* Disable SPI interrupts */ (1 << SPE) | /* Enable SPI */ diff --git a/src/core/ao.h b/src/core/ao.h index a541d8ac..1d5769cb 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -974,12 +974,23 @@ ao_spi_init(void); * ao_spi_slave.c */ +uint8_t +ao_spi_read(uint8_t *buf, uint8_t len); + void -ao_spi_slave_debug(void); +ao_spi_write(uint8_t *buf, uint8_t len); void ao_spi_slave_init(void); +/* This must be defined by the product; it will get called when chip + * select goes low, at which point it should use ao_spi_read and + * ao_spi_write to deal with the request + */ + +void +ao_spi_slave(void); + /* * ao_telemetry.c */ diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c new file mode 100644 index 00000000..e902318f --- /dev/null +++ b/src/drivers/ao_science_slave.c @@ -0,0 +1,62 @@ +/* + * 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" +#include "ao_product.h" + +struct ao_companion_command ao_companion_command; + +static const struct ao_companion_setup ao_telescience_setup = { + .board_id = AO_idProduct_NUMBER, + .board_id_inverse = ~AO_idProduct_NUMBER, + .update_period = 50, + .channels = AO_LOG_TELESCIENCE_NUM_ADC, +}; + +void ao_spi_slave(void) +{ + if (!ao_spi_read((uint8_t *) &ao_companion_command, + sizeof (ao_companion_command))) + return; + + /* Figure out the outbound data */ + switch (ao_companion_command.command) { + case AO_COMPANION_SETUP: + ao_spi_write((uint8_t *) &ao_telescience_setup, + sizeof (ao_telescience_setup)); + break; + case AO_COMPANION_FETCH: + ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); + break; + case AO_COMPANION_NOTIFY: + break; + default: + return; + } + + ao_log_single_write_data.telescience.tm_tick = ao_companion_command.tick; + if (ao_log_single_write_data.telescience.tm_state != ao_companion_command.flight_state) { + ao_log_single_write_data.telescience.tm_state = ao_companion_command.flight_state; + if (ao_flight_boost <= ao_log_single_write_data.telescience.tm_state) { + if (ao_log_single_write_data.telescience.tm_state < ao_flight_landed) + ao_log_single_start(); + else + ao_log_single_stop(); + } + } +} diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index 28620242..a6797cbe 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -46,6 +46,7 @@ ALTOS_SRC = \ ao_romconfig.c \ ao_usb_avr.c \ ao_adc_avr.c \ + ao_science_slave.c \ ao_spi_slave.c \ ao_log_single.c \ ao_log_telescience.c \ -- cgit v1.2.3 From c8a00bb9ccdf0d4257f037c2bf996ce5e6b0b0c0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 11:39:24 -0700 Subject: altos: Pre-compute RDF packet len at compile time Instead of computing the RDF packet len at run time, which takes a pile of code space. Signed-off-by: Keith Packard --- src/cc1111/ao_radio.c | 14 +------------- src/core/ao.h | 12 +++++++++++- src/core/ao_telemetry.c | 2 +- 3 files changed, 13 insertions(+), 15 deletions(-) (limited to 'src/core') diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 00816b33..75f241d4 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -367,21 +367,9 @@ ao_radio_recv_abort(void) __xdata ao_radio_rdf_value = 0x55; void -ao_radio_rdf(int ms) +ao_radio_rdf(uint8_t pkt_len) { uint8_t i; - uint8_t pkt_len; - - /* - * Compute the packet length as follows: - * - * 2000 bps (for a 1kHz tone) - * so, for 'ms' milliseconds, we need - * 2 * ms bits, or ms / 4 bytes - */ - if (ms > (255 * 4)) - ms = 255 * 4; - pkt_len = ms >> 2; ao_radio_abort = 0; ao_radio_get(pkt_len); diff --git a/src/core/ao.h b/src/core/ao.h index 1d5769cb..c28c4549 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1341,8 +1341,18 @@ ao_radio_recv(__xdata void *data, uint8_t size) __reentrant; void ao_radio_recv_abort(void); +/* + * Compute the packet length as follows: + * + * 2000 bps (for a 1kHz tone) + * so, for 'ms' milliseconds, we need + * 2 * ms bits, or ms / 4 bytes + */ + +#define AO_MS_TO_RDF_LEN(ms) ((ms) > 255 * 4 ? 255 : ((ms) >> 2)) + void -ao_radio_rdf(int ms); +ao_radio_rdf(uint8_t pkt_len); void ao_radio_rdf_abort(void); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index de669ce1..c2707e7d 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -235,7 +235,7 @@ ao_telemetry(void) (int16_t) (ao_time() - ao_rdf_time) >= 0) { ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; - ao_radio_rdf(AO_RDF_LENGTH_MS); + ao_radio_rdf(AO_MS_TO_RDF_LEN(AO_RDF_LENGTH_MS)); } #endif time += ao_telemetry_interval; -- cgit v1.2.3 From 0820f5c6dfe067590f36e8201a4049719dcf3d7c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 11:40:56 -0700 Subject: altos: Support staging by going back to boost as needed Detect additional motor burns by looking for high positive acceleration in coast or fast modes. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 85c1825b..a5cf7468 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -34,7 +34,7 @@ /* Main flight thread. */ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ -__pdata uint16_t ao_launch_tick; /* time of launch detect */ +__pdata uint16_t ao_boost_tick; /* time of launch detect */ /* * track min/max data over a long interval to detect @@ -151,7 +151,7 @@ ao_flight(void) ) { ao_flight_state = ao_flight_boost; - ao_launch_tick = ao_sample_tick; + ao_boost_tick = ao_sample_tick; /* start logging data */ ao_log_start(); @@ -184,7 +184,7 @@ ao_flight(void) * (15 seconds) has past. */ if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || - (int16_t) (ao_sample_tick - ao_launch_tick) > BOOST_TICKS_MAX) + (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX) { #if HAS_ACCEL ao_flight_state = ao_flight_fast; @@ -205,7 +205,8 @@ ao_flight(void) { ao_flight_state = ao_flight_coast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } + } else + goto check_re_boost; break; #endif case ao_flight_coast: @@ -237,6 +238,16 @@ ao_flight(void) ao_flight_state = ao_flight_drogue; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } +#if HAS_ACCEL + else { + check_re_boost: + if (ao_accel > AO_MSS_TO_ACCEL(20)) { + ao_boost_tick = ao_sample_tick; + ao_flight_state = ao_flight_boost; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + } +#endif break; case ao_flight_drogue: -- cgit v1.2.3 From 7a02d4bace05cc829522933b9df6b82a9e17336f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 11:30:43 -0700 Subject: altos: Add TelePyro v0.1 support Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/avr/ao_adc_avr.c | 21 ++++++++- src/avr/ao_pins.h | 24 +++++++++++ src/core/ao.h | 6 +++ src/drivers/ao_pyro_slave.c | 51 ++++++++++++++++++++++ src/product/ao_telepyro.c | 36 ++++++++++++++++ src/telepyro-v0.1/Makefile | 101 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 238 insertions(+), 3 deletions(-) create mode 100644 src/drivers/ao_pyro_slave.c create mode 100644 src/product/ao_telepyro.c create mode 100644 src/telepyro-v0.1/Makefile (limited to 'src/core') diff --git a/src/Makefile b/src/Makefile index 9ef5ae0a..91d3f035 100644 --- a/src/Makefile +++ b/src/Makefile @@ -19,7 +19,7 @@ SUBDIRS=\ telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ telelaunch-v0.1 \ - tidongle test telescience-v0.1 + tidongle test telescience-v0.1 telepyro-v0.1 all: all-local all-recursive diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 5afced74..9f45acaf 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -20,6 +20,7 @@ volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; volatile __data uint8_t ao_adc_head; +#ifdef TELESCIENCE const uint8_t adc_channels[AO_LOG_TELESCIENCE_NUM_ADC] = { 0x00, 0x01, @@ -34,6 +35,22 @@ const uint8_t adc_channels[AO_LOG_TELESCIENCE_NUM_ADC] = { 0x24, 0x25, }; +#endif + +#ifdef TELEPYRO +const uint8_t adc_channels[AO_TELEPYRO_NUM_ADC] = { + 0x00, /* ADC0 v_batt */ + 0x04, /* ADC4 sense_a */ + 0x05, /* ADC5 sense_b */ + 0x06, /* ADC6 sense_c */ + 0x07, /* ADC7 sense_d */ + 0x23, /* ADC11 sense_e */ + 0x22, /* ADC10 sense_f */ + 0x21, /* ADC9 sense_g */ +}; +#endif + +#define NUM_ADC (sizeof (adc_channels) / sizeof (adc_channels[0])) static uint8_t ao_adc_channel; @@ -75,7 +92,7 @@ ISR(ADC_vect) value = ADCL; value |= (ADCH << 8); ao_adc_ring[ao_adc_head].adc[ao_adc_channel] = value; - if (++ao_adc_channel < AO_TELESCIENCE_NUM_ADC) + if (++ao_adc_channel < NUM_ADC) ao_adc_start(); else { ADCSRA = ADCSRA_INIT; @@ -108,7 +125,7 @@ ao_adc_dump(void) __reentrant uint8_t i; ao_adc_get(&packet); printf("tick: %5u", packet.tick); - for (i = 0; i < AO_TELESCIENCE_NUM_ADC; i++) + for (i = 0; i < NUM_ADC; i++) printf (" %2d: %5u", i, packet.adc[i]); printf ("\n"); } diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 88f03829..6b72530b 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -61,4 +61,28 @@ #define SPI_SLAVE_PIN_2_5 0 #endif +#ifdef TELEPYRO + #define LEDS_AVAILABLE 0 + #define HAS_USB 1 + #define HAS_LOG 0 + #define TEENSY 0 + #define USE_SERIAL_STDIN 1 + #define HAS_SERIAL_1 1 + #define HAS_USB 1 + #define HAS_ADC 1 + #define PACKET_HAS_SLAVE 0 + #define HAS_BEEP 0 + + #define AVR_VCC_5V 0 + #define AVR_VCC_3V3 1 + #define AVR_CLOCK 8000000UL + + #define SPI_SLAVE_CS_PORT PORTB + #define SPI_SLAVE_CS_PIN PINB + #define SPI_SLAVE_CS_PIN_NO PINB0 + + #define SPI_SLAVE_PIN_0_3 1 + #define SPI_SLAVE_PIN_2_5 0 +#endif + #endif /* _AO_PINS_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index c28c4549..04610fea 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1811,4 +1811,10 @@ ao_log_single_init(void); void ao_log_single(void); +/* + * ao_pyro_slave.c + */ + +#define AO_TELEPYRO_NUM_ADC 9 + #endif /* _AO_H_ */ diff --git a/src/drivers/ao_pyro_slave.c b/src/drivers/ao_pyro_slave.c new file mode 100644 index 00000000..e6c73a3c --- /dev/null +++ b/src/drivers/ao_pyro_slave.c @@ -0,0 +1,51 @@ +/* + * 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" +#include "ao_product.h" + +struct ao_companion_command ao_companion_command; + +static const struct ao_companion_setup ao_telepyro_setup = { + .board_id = AO_idProduct_NUMBER, + .board_id_inverse = ~AO_idProduct_NUMBER, + .update_period = 50, + .channels = AO_TELEPYRO_NUM_ADC, +}; + +void ao_spi_slave(void) +{ + if (!ao_spi_read((uint8_t *) &ao_companion_command, + sizeof (ao_companion_command))) + return; + + /* Figure out the outbound data */ + switch (ao_companion_command.command) { + case AO_COMPANION_SETUP: + ao_spi_write((uint8_t *) &ao_telepyro_setup, + sizeof (ao_telepyro_setup)); + break; + case AO_COMPANION_FETCH: + ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + AO_TELEPYRO_NUM_ADC * sizeof (uint16_t)); + break; + case AO_COMPANION_NOTIFY: + break; + default: + return; + } +} diff --git a/src/product/ao_telepyro.c b/src/product/ao_telepyro.c new file mode 100644 index 00000000..a2b8f83c --- /dev/null +++ b/src/product/ao_telepyro.c @@ -0,0 +1,36 @@ +/* + * 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" + +int +main(void) +{ + ao_clock_init(); + + PORTE |= (1 << 6); + DDRE |= (1 << 6); + + ao_avr_stdio_init(); + ao_timer_init(); + ao_cmd_init(); + ao_spi_slave_init(); + ao_usb_init(); + ao_adc_init(); + ao_start_scheduler(); + return 0; +} diff --git a/src/telepyro-v0.1/Makefile b/src/telepyro-v0.1/Makefile new file mode 100644 index 00000000..2f664fcb --- /dev/null +++ b/src/telepyro-v0.1/Makefile @@ -0,0 +1,101 @@ +# +# AltOS build +# +# +vpath % ..:../core:../product:../drivers:../avr +vpath ao-make-product.5c ../util + +MCU=atmega32u4 +DUDECPUTYPE=m32u4 +#PROGRAMMER=stk500v2 -P usb +PROGRAMMER=usbtiny +LOADCMD=avrdude +LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: +CC=avr-gcc +OBJCOPY=avr-objcopy + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_usb.h \ + ao_pins.h \ + altitude.h + +ALTOS_SRC = \ + ao_clock.c \ + ao_cmd.c \ + ao_mutex.c \ + ao_panic.c \ + ao_product.c \ + ao_stdio.c \ + ao_task.c \ + ao_timer.c \ + ao_led.c \ + ao_avr_stdio.c \ + ao_romconfig.c \ + ao_usb_avr.c \ + ao_adc_avr.c \ + ao_pyro_slave.c \ + ao_spi_slave.c + +PRODUCT=TelePyro-v0.1 +MCU=atmega32u4 +PRODUCT_DEF=-DTELEPYRO +IDPRODUCT=0x0011 +CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I.. +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR + +NICKLE=nickle + +PROG=telepyro-v0.1 + +SRC=$(ALTOS_SRC) ao_telepyro.c +OBJ=$(SRC:.c=.o) + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: $(PROG) + +CHECK=sh ../util/check-avr-mem + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) + $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1) + +$(PROG).hex: $(PROG) + avr-size $(PROG) + $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ + + +load: $(PROG).hex + $(LOADCMD) $(LOADARG)$(PROG).hex + +../altitude.h: make-altitude + nickle $< > $@ + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.rel: ao_product.c ao_product.h + $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean: clean + +clean: + rm -f $(OBJ) + rm -f ao_product.h + +install: + +uninstall: + +$(OBJ): ao.h ao_product.h ao_usb.h -- cgit v1.2.3 From 16aa67fc77b82a9d051f205037b27a5384e3e3b7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 14:24:30 -0700 Subject: altos: missing ao_log_single.c Neglected to add this file. Signed-off-by: Keith Packard --- src/core/ao_log_single.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 src/core/ao_log_single.c (limited to 'src/core') diff --git a/src/core/ao_log_single.c b/src/core/ao_log_single.c new file mode 100644 index 00000000..9e90bd82 --- /dev/null +++ b/src/core/ao_log_single.c @@ -0,0 +1,198 @@ +/* + * 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. + */ + +/* + * ao_log_single.c + * + * Stores a sequence of fixed-size (32 byte) chunks + * without splitting memory up into separate flights + */ + +#include "ao.h" +#include "ao_product.h" + +static __xdata struct ao_task ao_log_single_task; + +__xdata uint8_t ao_log_running; +__xdata uint8_t ao_log_mutex; +__pdata uint32_t ao_log_start_pos; +__pdata uint32_t ao_log_end_pos; +__pdata uint32_t ao_log_current_pos; + +__xdata union ao_log_single ao_log_single_write_data; +__xdata union ao_log_single ao_log_single_read_data; + +uint8_t +ao_log_single_write(void) +{ + uint8_t wrote = 0; + + ao_mutex_get(&ao_log_mutex); { + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_single_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + &ao_log_single_write_data, + AO_LOG_SINGLE_SIZE); + ao_log_current_pos += AO_LOG_SINGLE_SIZE; + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_single_valid(void) +{ + __xdata uint8_t *d = ao_log_single_read_data.bytes; + uint8_t i; + for (i = 0; i < AO_LOG_SINGLE_SIZE; i++) + if (*d++ != 0xff) + return 1; + return 0; +} + +uint8_t +ao_log_single_read(uint32_t pos) +{ + if (!ao_storage_read(pos, &ao_log_single_read_data, AO_LOG_SINGLE_SIZE)) + return 0; + return ao_log_single_valid(); +} + +void +ao_log_single_start(void) +{ + if (!ao_log_running) { + ao_log_running = 1; + ao_wakeup(&ao_log_running); + } +} + +void +ao_log_single_stop(void) +{ + if (ao_log_running) { + ao_log_running = 0; + } +} + +void +ao_log_single_restart(void) +{ + /* Find end of data */ + ao_log_end_pos = ao_storage_config; + for (ao_log_current_pos = 0; + ao_log_current_pos < ao_storage_config; + ao_log_current_pos += ao_storage_block) + { + if (!ao_log_single_read(ao_log_current_pos)) + break; + } + if (ao_log_current_pos > 0) { + ao_log_current_pos -= ao_storage_block; + for (; ao_log_current_pos < ao_storage_config; + ao_log_current_pos += sizeof (struct ao_log_telescience)) + { + if (!ao_log_single_read(ao_log_current_pos)) + break; + } + } +} + +void +ao_log_single_set(void) +{ + printf("Logging currently %s\n", ao_log_running ? "on" : "off"); + ao_cmd_hex(); + if (ao_cmd_status == ao_cmd_success) { + if (ao_cmd_lex_i) { + printf("Logging from %ld to %ld\n", ao_log_current_pos, ao_log_end_pos); + ao_log_single_start(); + } else { + printf ("Log stopped at %ld\n", ao_log_current_pos); + ao_log_single_stop(); + } + } + ao_cmd_status = ao_cmd_success; +} + +void +ao_log_single_delete(void) +{ + uint32_t pos; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_cmd_lex_i != 1) { + ao_cmd_status = ao_cmd_syntax_error; + printf("No such flight: %d\n", ao_cmd_lex_i); + return; + } + ao_log_single_stop(); + for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) { + if (!ao_log_single_read(pos)) + break; + ao_storage_erase(pos); + } + ao_log_current_pos = ao_log_start_pos = 0; + if (pos == 0) + printf("No such flight: %d\n", ao_cmd_lex_i); + else + printf ("Erased\n"); +} + +uint8_t +ao_log_full(void) +{ + return ao_log_current_pos >= ao_log_end_pos; +} + +uint8_t +ao_log_present(void) +{ + return ao_log_single_read(0); +} + +static void +ao_log_single_query(void) +{ + printf("Logging enabled: %d\n", ao_log_running); + printf("Log start: %ld\n", ao_log_start_pos); + printf("Log cur: %ld\n", ao_log_current_pos); + printf("Log end: %ld\n", ao_log_end_pos); + ao_log_single_extra_query(); +} + +const struct ao_cmds ao_log_single_cmds[] = { + { ao_log_single_set, "L <0 off, 1 on>\0Set logging mode" }, + { ao_log_single_list, "l\0List stored flight logs" }, + { ao_log_single_delete, "d 1\0Delete all stored flights" }, + { ao_log_single_query, "q\0Query log status" }, + { 0, NULL }, +}; + +void +ao_log_single_init(void) +{ + ao_log_running = 0; + + ao_cmd_register(&ao_log_single_cmds[0]); + + ao_add_task(&ao_log_single_task, ao_log_single, "log"); +} -- cgit v1.2.3 From 258b75498916183ed250d3abb3282fe3d843e7a1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Oct 2011 09:53:09 -0600 Subject: altos: Write xdata versions of memory functions These are significantly smaller than the general pointer versions from libc on the cc1111. Signed-off-by: Keith Packard Conflicts: src/Makefile.proto src/cc1111/ao_adc.c src/cc1111/ao_packet_master.c src/core/ao.h Fix up the new makefiles --- src/cc1111/ao_adc.c | 2 +- src/cc1111/ao_arch.h | 17 +++++++++++++++++ src/cc1111/ao_intflash.c | 2 +- src/cc1111/ao_packet.c | 4 ++-- src/cc1111/ao_packet_master.c | 2 +- src/cc1111/ao_packet_slave.c | 2 +- src/core/ao.h | 6 ++++++ src/core/ao_cmd.c | 4 ++-- src/core/ao_config.c | 11 ++++++----- src/core/ao_ee_fake.c | 2 +- src/core/ao_gps_report.c | 4 ++-- src/core/ao_host.h | 4 ++++ src/core/ao_monitor.c | 4 ++-- src/core/ao_telemetry.c | 10 +++++----- src/drivers/ao_25lc1024.c | 6 +++--- src/drivers/ao_at45db161d.c | 6 +++--- src/drivers/ao_gps_skytraq.c | 4 ++-- src/product/Makefile.telebt | 1 + src/product/Makefile.teledongle | 1 + src/product/Makefile.telelaunch | 1 + src/product/Makefile.telemetrum | 1 + src/product/Makefile.telemini | 1 + src/product/Makefile.telenano | 1 + src/test/ao_flight_test.c | 8 ++++++-- src/tidongle/Makefile | 1 + 25 files changed, 72 insertions(+), 33 deletions(-) (limited to 'src/core') diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 6aa6e018..1688eceb 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -46,7 +46,7 @@ ao_adc_get(__xdata struct ao_adc *packet) #else uint8_t i = ao_adc_ring_prev(ao_adc_head); #endif - memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); + ao_xmemcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); } void diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 8a41791f..02e36189 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -204,4 +204,21 @@ struct ao_adc { #define AO_ADC_RING 32 +/* ao_string.c */ + +void +_ao_xmemcpy(__xdata uint8_t *dst, __xdata uint8_t *src, uint8_t count); + +#define ao_xmemcpy(d,s,c) _ao_xmemcpy((__xdata uint8_t *) (d), (__xdata uint8_t *) (s), (c)) + +void +_ao_xmemset(__xdata uint8_t *dst, uint8_t value, uint8_t count); + +#define ao_xmemset(d,v,c) _ao_xmemset((__xdata uint8_t *) (d), (v), (c)) + +int8_t +_ao_xmemcmp(__xdata uint8_t *a, __xdata uint8_t *b, uint8_t count); + +#define ao_xmemcmp(d,s,c) _ao_xmemcmp((__xdata uint8_t *) (d), (__xdata uint8_t *) (s), (c)) + #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_intflash.c b/src/cc1111/ao_intflash.c index d76d954e..632e2a85 100644 --- a/src/cc1111/ao_intflash.c +++ b/src/cc1111/ao_intflash.c @@ -180,7 +180,7 @@ ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant { if (pos >= ao_storage_total || pos + len > ao_storage_total) return 0; - memcpy(d, ao_intflash+pos, len); + ao_xmemcpy(d, ao_intflash+pos, len); return 1; } diff --git a/src/cc1111/ao_packet.c b/src/cc1111/ao_packet.c index f627e02b..37ba92e0 100644 --- a/src/cc1111/ao_packet.c +++ b/src/cc1111/ao_packet.c @@ -35,7 +35,7 @@ ao_packet_send(void) ao_led_on(AO_LED_RED); /* If any tx data is pending then copy it into the tx packet */ if (ao_packet_tx_used && ao_tx_packet.len == 0) { - memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); + ao_xmemcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); ao_tx_packet.len = ao_packet_tx_used; ao_tx_packet.seq++; ao_packet_tx_used = 0; @@ -80,7 +80,7 @@ ao_packet_recv(void) /* Copy data to the receive data buffer and set up the * offsets */ - memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); + ao_xmemcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); ao_packet_rx_used = 0; ao_packet_rx_len = ao_rx_packet.packet.len; diff --git a/src/cc1111/ao_packet_master.c b/src/cc1111/ao_packet_master.c index 0d0be30e..ab19f979 100644 --- a/src/cc1111/ao_packet_master.c +++ b/src/cc1111/ao_packet_master.c @@ -81,7 +81,7 @@ ao_packet_master(void) ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; while (ao_packet_enable) { uint8_t r; - memcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); + ao_xmemcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); ao_packet_send(); if (ao_tx_packet.len) ao_packet_master_busy(); diff --git a/src/cc1111/ao_packet_slave.c b/src/cc1111/ao_packet_slave.c index d7cafa68..fd5d443e 100644 --- a/src/cc1111/ao_packet_slave.c +++ b/src/cc1111/ao_packet_slave.c @@ -24,7 +24,7 @@ ao_packet_slave(void) ao_tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { if (ao_packet_recv()) { - memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); + ao_xmemcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); #if HAS_FLIGHT ao_flight_force_idle = TRUE; #endif diff --git a/src/core/ao.h b/src/core/ao.h index 04610fea..c0474729 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1817,4 +1817,10 @@ ao_log_single(void); #define AO_TELEPYRO_NUM_ADC 9 +#ifndef ao_xmemcpy +#define ao_xmemcpy(d,s,c) memcpy(d,s,c) +#define ao_xmemset(d,v,c) memset(d,v,c) +#define ao_xmemcmp(d,s,c) memcmp(d,s,c) +#endif + #endif /* _AO_H_ */ diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 2b64b8ca..0c902f6b 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -265,8 +265,8 @@ help(void) cs = ao_cmds[cmds]; for (cmd = 0; cs[cmd].func; cmd++) printf("%-45s %s\n", - cs[cmd].help, - cs[cmd].help+1+strlen(cs[cmd].help)); + cs[cmd].help, + cs[cmd].help+1+strlen(cs[cmd].help)); } } diff --git a/src/core/ao_config.c b/src/core/ao_config.c index a653bed2..08cc79b1 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -78,8 +78,8 @@ _ao_config_get(void) /* Version 0 stuff */ ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; - memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); - memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, + ao_xmemset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); + ao_xmemcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config_dirty = 1; } @@ -148,7 +148,7 @@ ao_config_callsign_set(void) __reentrant uint8_t c; static __xdata char callsign[AO_MAX_CALLSIGN + 1]; - memset(callsign, '\0', sizeof callsign); + ao_xmemset(callsign, '\0', sizeof callsign); ao_cmd_white(); c = 0; while (ao_cmd_lex_c != '\n') { @@ -161,7 +161,7 @@ ao_config_callsign_set(void) __reentrant if (ao_cmd_status != ao_cmd_success) return; _ao_config_edit_start(); - memcpy(&ao_config.callsign, &callsign, + ao_xmemcpy(&ao_config.callsign, &callsign, AO_MAX_CALLSIGN + 1); _ao_config_edit_finish(); } @@ -535,7 +535,8 @@ ao_config_help(void) __reentrant for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) printf("%-20s %s\n", ao_config_vars[cmd].str, - ao_config_vars[cmd].str+1+strlen(ao_config_vars[cmd].str)); + ao_config_vars[cmd].str+1+ + strlen(ao_config_vars[cmd].str)); } static void diff --git a/src/core/ao_ee_fake.c b/src/core/ao_ee_fake.c index b0c1d61e..7fcfcab0 100644 --- a/src/core/ao_ee_fake.c +++ b/src/core/ao_ee_fake.c @@ -32,6 +32,6 @@ ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant uint8_t ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant { - memset(buf, '\0', len); + ao_xmemset(buf, '\0', len); return 1; } diff --git a/src/core/ao_gps_report.c b/src/core/ao_gps_report.c index e57f8744..c52ef621 100644 --- a/src/core/ao_gps_report.c +++ b/src/core/ao_gps_report.c @@ -27,7 +27,7 @@ ao_gps_report(void) for (;;) { ao_sleep(&ao_gps_data); ao_mutex_get(&ao_gps_mutex); - memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); + ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); ao_mutex_put(&ao_gps_mutex); if (!(gps_data.flags & AO_GPS_VALID)) @@ -72,7 +72,7 @@ ao_gps_tracking_report(void) ao_sleep(&ao_gps_tracking_data); ao_mutex_get(&ao_gps_mutex); gps_log.tick = ao_gps_tick; - memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); + ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); if (!(n = gps_tracking_data.channels)) diff --git a/src/core/ao_host.h b/src/core/ao_host.h index 65c25fe5..f2b2f0c9 100644 --- a/src/core/ao_host.h +++ b/src/core/ao_host.h @@ -125,3 +125,7 @@ struct ao_config { #define ao_config_get() struct ao_config ao_config = { 250, 16000 }; + +#define ao_xmemcpy(d,s,c) memcpy(d,s,c) +#define ao_xmemset(d,v,c) memset(d,v,c) +#define ao_xmemcmp(d,s,c) memcmp(d,s,c) diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 56d7604d..1a8bb52a 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -94,7 +94,7 @@ ao_monitor_put(void) /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ rssi = (int16_t) (recv_orig.rssi >> 1) - 74; - memcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN); + ao_xmemcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN); if (state > ao_flight_invalid) state = ao_flight_invalid; if (recv_orig.status & PKT_APPEND_STATUS_1_CRC_OK) { @@ -171,7 +171,7 @@ ao_monitor_put(void) /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ rssi = (int16_t) (recv_tiny.rssi >> 1) - 74; - memcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN); + ao_xmemcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN); if (state > ao_flight_invalid) state = ao_flight_invalid; if (recv_tiny.status & PKT_APPEND_STATUS_1_CRC_OK) { diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 26e4e2a0..95e53917 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -131,10 +131,10 @@ ao_send_configuration(void) telemetry.configuration.apogee_delay = ao_config.apogee_delay; telemetry.configuration.main_deploy = ao_config.main_deploy; telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10; - memcpy (telemetry.configuration.callsign, + ao_xmemcpy (telemetry.configuration.callsign, ao_config.callsign, AO_MAX_CALLSIGN); - memcpy (telemetry.configuration.version, + ao_xmemcpy (telemetry.configuration.version, ao_version, AO_MAX_VERSION); ao_radio_send(&telemetry, sizeof (telemetry)); @@ -150,7 +150,7 @@ ao_send_location(void) { telemetry.generic.type = AO_TELEMETRY_LOCATION; ao_mutex_get(&ao_gps_mutex); - memcpy(&telemetry.location.flags, + ao_xmemcpy(&telemetry.location.flags, &ao_gps_data.flags, 26); ao_mutex_put(&ao_gps_mutex); @@ -167,7 +167,7 @@ ao_send_satellite(void) telemetry.generic.type = AO_TELEMETRY_SATELLITE; ao_mutex_get(&ao_gps_mutex); telemetry.satellite.channels = ao_gps_tracking_data.channels; - memcpy(&telemetry.satellite.sats, + ao_xmemcpy(&telemetry.satellite.sats, &ao_gps_tracking_data.sats, AO_MAX_GPS_TRACKING * sizeof (struct ao_telemetry_satellite_info)); ao_mutex_put(&ao_gps_mutex); @@ -187,7 +187,7 @@ ao_send_companion(void) 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_xmemcpy(&telemetry.companion.companion_data, ao_companion_data, ao_companion_setup.channels * 2); ao_mutex_put(&ao_companion_mutex); diff --git a/src/drivers/ao_25lc1024.c b/src/drivers/ao_25lc1024.c index 738f8ce6..2d047a44 100644 --- a/src/drivers/ao_25lc1024.c +++ b/src/drivers/ao_25lc1024.c @@ -167,7 +167,7 @@ ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentra ao_ee_flush_internal(); ao_ee_block = block; } - memcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len); + ao_xmemcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len); ao_ee_block_dirty = 1; } ao_mutex_put(&ao_ee_mutex); return 1; @@ -181,7 +181,7 @@ ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentran /* Transfer the data */ ao_mutex_get(&ao_ee_mutex); { ao_ee_fill(block); - memcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len); + ao_xmemcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len); } ao_mutex_put(&ao_ee_mutex); return 1; } @@ -200,7 +200,7 @@ ao_storage_erase(uint32_t pos) __reentrant ao_mutex_get(&ao_ee_mutex); { ao_ee_flush_internal(); ao_ee_block = (uint16_t) (pos >> EE_BLOCK_SHIFT); - memset(ao_ee_data, 0xff, EE_BLOCK_SIZE); + ao_xmemset(ao_ee_data, 0xff, EE_BLOCK_SIZE); ao_ee_block_dirty = 1; } ao_mutex_put(&ao_ee_mutex); return 1; diff --git a/src/drivers/ao_at45db161d.c b/src/drivers/ao_at45db161d.c index aee9877a..6cd689e5 100644 --- a/src/drivers/ao_at45db161d.c +++ b/src/drivers/ao_at45db161d.c @@ -245,7 +245,7 @@ ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentra ao_flash_flush_internal(); ao_flash_block = block; } - memcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), + ao_xmemcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), buf, len); ao_flash_block_dirty = 1; @@ -261,7 +261,7 @@ ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentran /* Transfer the data */ ao_mutex_get(&ao_flash_mutex); { ao_flash_fill(block); - memcpy(buf, + ao_xmemcpy(buf, ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), len); } ao_mutex_put(&ao_flash_mutex); @@ -282,7 +282,7 @@ ao_storage_erase(uint32_t pos) __reentrant ao_mutex_get(&ao_flash_mutex); { ao_flash_flush_internal(); ao_flash_block = (uint16_t) (pos >> ao_flash_block_shift); - memset(ao_flash_data, 0xff, ao_flash_block_size); + ao_xmemset(ao_flash_data, 0xff, ao_flash_block_size); ao_flash_block_dirty = 1; } ao_mutex_put(&ao_flash_mutex); return 1; diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 7ac26946..6e65d651 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -265,7 +265,7 @@ ao_nmea_gga() if (!ao_gps_error) { ao_mutex_get(&ao_gps_mutex); ao_gps_tick = ao_gps_next_tick; - memcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data)); + ao_xmemcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data)); ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_data); } @@ -327,7 +327,7 @@ ao_nmea_gsv(void) ao_gps_tracking_next.channels = 0; else if (done) { ao_mutex_get(&ao_gps_mutex); - memcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, + ao_xmemcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, sizeof(ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_tracking_data); diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index 46c87db0..8f7c7429 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -41,6 +41,7 @@ CC1111_SRC = \ ao_radio_cmac.c \ ao_romconfig.c \ ao_serial.c \ + ao_string.c \ ao_timer.c \ ao_usb.c \ _bp.c diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index 56182b84..c1b422c0 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -43,6 +43,7 @@ CC1111_SRC = \ ao_radio.c \ ao_radio_cmac.c \ ao_romconfig.c \ + ao_string.c \ ao_timer.c \ ao_usb.c \ _bp.c diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 5da42e46..b40f61a2 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -45,6 +45,7 @@ CC1111_SRC = \ ao_romconfig.c \ ao_serial.c \ ao_spi.c \ + ao_string.c \ ao_timer.c \ ao_usb.c \ _bp.c diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index 2759ac52..4f4195a9 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -54,6 +54,7 @@ CC1111_SRC = \ ao_radio.c \ ao_romconfig.c \ ao_serial.c \ + ao_string.c \ ao_spi.c \ ao_timer.c \ ao_usb.c \ diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 7f251897..9f90b01f 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -45,6 +45,7 @@ CC1111_SRC = \ ao_packet_slave.c \ ao_radio.c \ ao_romconfig.c \ + ao_string.c \ ao_timer.c \ _bp.c diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index c47e95ff..eff3ea97 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -44,6 +44,7 @@ CC1111_SRC = \ ao_packet_slave.c \ ao_radio.c \ ao_romconfig.c \ + ao_string.c \ ao_timer.c \ _bp.c diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 56733c89..921d44e7 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -173,6 +173,10 @@ struct ao_cmds { const char *help; }; +#define ao_xmemcpy(d,s,c) memcpy(d,s,c) +#define ao_xmemset(d,v,c) memset(d,v,c) +#define ao_xmemcmp(d,s,c) memcmp(d,s,c) + #include "ao_convert.c" struct ao_config { @@ -542,7 +546,7 @@ ao_sleep(void *wchan) ao_flight_started = 1; } } else if (nword == 2 && strcmp(words[0], "TELEM") == 0) { - char *hex = words[1]; + __xdata char *hex = words[1]; char elt[3]; int i, len; uint8_t sum; @@ -574,7 +578,7 @@ ao_sleep(void *wchan) continue; } if (len == 36) { - memcpy(&telem, bytes + 1, 32); + ao_xmemcpy(&telem, bytes + 1, 32); tick = telem.generic.tick; switch (telem.generic.type) { case AO_TELEMETRY_SENSOR_TELEMETRUM: diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index 057e420b..58b9d735 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -38,6 +38,7 @@ CC1111_SRC = \ ao_radio.c \ ao_radio_cmac.c \ ao_romconfig.c \ + ao_string.c \ ao_timer.c \ ao_usb.c \ _bp.c -- cgit v1.2.3 From 6a7363b3ba99310bd44c9b66f6f5159e46762be4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 8 Oct 2011 11:51:05 -0600 Subject: altos: Ignore ejection bumps when doing boost re-detect An ejection charge looks an awful lot like an extra (really small) motor burn. Ignore them by averaging the acceleration during fast/coast using a /64 exponential decay filter. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 433efeae..5e194638 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -40,9 +40,11 @@ __pdata uint16_t ao_boost_tick; /* time of launch detect */ * track min/max data over a long interval to detect * resting */ -__pdata uint16_t ao_interval_end; -__pdata int16_t ao_interval_min_height; -__pdata int16_t ao_interval_max_height; +static __data uint16_t ao_interval_end; +static __data int16_t ao_interval_min_height; +static __data int16_t ao_interval_max_height; +static __data int16_t ao_coast_avg_accel; + __pdata uint8_t ao_flight_force_idle; /* We also have a clock, which can be used to sanity check things in @@ -197,6 +199,7 @@ ao_flight(void) { #if HAS_ACCEL ao_flight_state = ao_flight_fast; + ao_coast_avg_accel = ao_accel; #else ao_flight_state = ao_flight_coast; #endif @@ -250,7 +253,8 @@ ao_flight(void) #if HAS_ACCEL else { check_re_boost: - if (ao_accel > AO_MSS_TO_ACCEL(20)) { + ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); + if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) { ao_boost_tick = ao_sample_tick; ao_flight_state = ao_flight_boost; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); -- cgit v1.2.3 From 636b7b368e67346b0796cd84fbfd71e10966d61f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Oct 2011 10:21:56 -0600 Subject: altos: Respond to telemetry rate changes immediately Instead of waiting for the previous telemetry interval to expire, immediately switch to the new telemetry rate. This will provide more telemetry data early in the boost. Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 95e53917..d909bea5 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -240,8 +240,11 @@ ao_telemetry(void) #endif time += ao_telemetry_interval; delay = time - ao_time(); - if (delay > 0) - ao_delay(delay); + if (delay > 0) { + ao_alarm(delay); + ao_sleep(&telemetry); + ao_clear_alarm(); + } else time = ao_time(); } -- cgit v1.2.3 From ac0bebc44bc657b303db4c41fa0c9624f3df9f4f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 18:11:56 -0600 Subject: altos: Make HAS_STORAGE_DEBUG define consistent This allows products to include the 'w' command for testing flash writing as needed. Signed-off-by: Keith Packard --- src/core/ao_storage.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c index 6ffca0e5..ff4747d0 100644 --- a/src/core/ao_storage.c +++ b/src/core/ao_storage.c @@ -103,7 +103,7 @@ ao_storage_dump(void) __reentrant } } -#if 0 +#if HAS_STORAGE_DEBUG /* not enough space for this today */ @@ -160,6 +160,7 @@ ao_storage_zapall(void) __reentrant void ao_storage_info(void) __reentrant { + ao_storage_setup(); printf("Storage size: %ld\n", ao_storage_total); printf("Storage erase unit: %ld\n", ao_storage_block); ao_storage_device_info(); @@ -168,7 +169,7 @@ ao_storage_info(void) __reentrant __code struct ao_cmds ao_storage_cmds[] = { { ao_storage_info, "f\0Show storage" }, { ao_storage_dump, "e \0Dump flash" }, -#ifdef HAS_STORAGE_DBG +#if HAS_STORAGE_DEBUG { ao_storage_store, "w ...\0Write data to flash" }, #endif { ao_storage_zap, "z \0Erase " }, -- cgit v1.2.3 From 47c2c0b79dc516d2566ae149605b7d70ef2dca98 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 20:58:04 -0600 Subject: Bump to 1.0.9.3 TeleScience and TelePyro now work. Signed-off-by: Keith Packard --- configure.ac | 2 +- src/avr/ao_spi_slave.c | 4 ++-- src/avr/ao_usb_avr.c | 3 --- src/core/ao.h | 4 ++-- src/drivers/ao_pyro_slave.c | 12 ++++++------ src/drivers/ao_science_slave.c | 12 ++++++------ 6 files changed, 17 insertions(+), 20 deletions(-) (limited to 'src/core') diff --git a/configure.ac b/configure.ac index 57d2f196..19db6d27 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 1.0.9.2) +AC_INIT([altos], 1.0.9.3) AC_CONFIG_SRCDIR([src/core/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c index 3aa0b97f..b742d29a 100644 --- a/src/avr/ao_spi_slave.c +++ b/src/avr/ao_spi_slave.c @@ -18,7 +18,7 @@ #include "ao.h" uint8_t -ao_spi_read(uint8_t *buf, uint8_t len) +ao_spi_slave_recv(uint8_t *buf, uint8_t len) { while (len--) { while (!(SPSR & (1 << SPIF))) @@ -30,7 +30,7 @@ ao_spi_read(uint8_t *buf, uint8_t len) } void -ao_spi_write(uint8_t *buf, uint8_t len) +ao_spi_slave_send(uint8_t *buf, uint8_t len) { while (len--) { SPDR = *buf++; diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c index 74bdea23..fc8899d8 100644 --- a/src/avr/ao_usb_avr.c +++ b/src/avr/ao_usb_avr.c @@ -303,9 +303,6 @@ ao_usb_ep0_setup(void) } break; case AO_USB_RECIP_INTERFACE: -#ifndef AVR - #pragma disable_warning 110 -#endif debug ("Interface setup packet\n"); switch(ao_usb_setup.request) { case AO_USB_REQ_GET_STATUS: diff --git a/src/core/ao.h b/src/core/ao.h index c0474729..94526bc3 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -975,10 +975,10 @@ ao_spi_init(void); */ uint8_t -ao_spi_read(uint8_t *buf, uint8_t len); +ao_spi_slave_recv(uint8_t *buf, uint8_t len); void -ao_spi_write(uint8_t *buf, uint8_t len); +ao_spi_slave_send(uint8_t *buf, uint8_t len); void ao_spi_slave_init(void); diff --git a/src/drivers/ao_pyro_slave.c b/src/drivers/ao_pyro_slave.c index e6c73a3c..5ef42b5a 100644 --- a/src/drivers/ao_pyro_slave.c +++ b/src/drivers/ao_pyro_slave.c @@ -29,19 +29,19 @@ static const struct ao_companion_setup ao_telepyro_setup = { void ao_spi_slave(void) { - if (!ao_spi_read((uint8_t *) &ao_companion_command, - sizeof (ao_companion_command))) + if (!ao_spi_slave_recv((uint8_t *) &ao_companion_command, + sizeof (ao_companion_command))) return; /* Figure out the outbound data */ switch (ao_companion_command.command) { case AO_COMPANION_SETUP: - ao_spi_write((uint8_t *) &ao_telepyro_setup, - sizeof (ao_telepyro_setup)); + ao_spi_slave_send((uint8_t *) &ao_telepyro_setup, + sizeof (ao_telepyro_setup)); break; case AO_COMPANION_FETCH: - ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, - AO_TELEPYRO_NUM_ADC * sizeof (uint16_t)); + ao_spi_slave_send((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + AO_TELEPYRO_NUM_ADC * sizeof (uint16_t)); break; case AO_COMPANION_NOTIFY: break; diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c index 78941255..1ebb1480 100644 --- a/src/drivers/ao_science_slave.c +++ b/src/drivers/ao_science_slave.c @@ -29,19 +29,19 @@ static const struct ao_companion_setup ao_telescience_setup = { void ao_spi_slave(void) { - if (!ao_spi_read((uint8_t *) &ao_companion_command, - sizeof (ao_companion_command))) + if (!ao_spi_slave_recv((uint8_t *) &ao_companion_command, + sizeof (ao_companion_command))) return; /* Figure out the outbound data */ switch (ao_companion_command.command) { case AO_COMPANION_SETUP: - ao_spi_write((uint8_t *) &ao_telescience_setup, - sizeof (ao_telescience_setup)); + ao_spi_slave_send((uint8_t *) &ao_telescience_setup, + sizeof (ao_telescience_setup)); break; case AO_COMPANION_FETCH: - ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, - AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); + ao_spi_slave_send((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); break; case AO_COMPANION_NOTIFY: break; -- cgit v1.2.3 From badda0d910c56135401dce9adc9e6abebdba2ad7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 23:28:02 -0600 Subject: altos: Split out arch-specific bits of LCD driver The arch-specific section just puts a single nibble to the device. Signed-off-by: Keith Packard --- src/avr/ao_lcd_port.c | 74 ++++++++++++++++++++++++ src/cc1111/ao_lcd_port.c | 41 ++++++++++++++ src/cc1111/ao_packet.c | 4 ++ src/core/ao.h | 28 ++++++++++ src/core/ao_monitor.c | 13 ++++- src/drivers/ao_lcd.c | 142 ++++++++++------------------------------------- 6 files changed, 186 insertions(+), 116 deletions(-) create mode 100644 src/avr/ao_lcd_port.c create mode 100644 src/cc1111/ao_lcd_port.c (limited to 'src/core') diff --git a/src/avr/ao_lcd_port.c b/src/avr/ao_lcd_port.c new file mode 100644 index 00000000..b1e8aa17 --- /dev/null +++ b/src/avr/ao_lcd_port.c @@ -0,0 +1,74 @@ +/* + * 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 LCD_PORT PORTB +#define LCD_DDR DDRB + +#define PIN_RS 4 +#define PIN_E 5 +#define PIN_RW 6 + +static void +ao_lcd_port_set_bits(uint8_t bits) +{ +#if 0 + printf("\tLCD data %x RS %d R/W %d E %d\n", + bits & 0xf, + (bits & (1 << PIN_RS)) ? 1 : 0, + (bits & (1 << PIN_RW)) ? 1 : 0, + (bits & (1 << PIN_E)) ? 1 : 0); +#endif + LCD_PORT = bits; +#if 0 + ao_delay(1); + if (bits & (1 << PIN_RW)) + printf("\tLCD input %x\n", PINB); +#endif +} + +uint8_t +ao_lcd_port_get_nibble(uint8_t rs) +{ + uint8_t data = (rs ? (1 << PIN_RS) : 0) | (1 << PIN_RW); + uint8_t n; + + DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + ao_lcd_port_set_bits(data); + ao_lcd_port_set_bits(data | (1 << PIN_E)); + n = PINB & 0xf; + ao_lcd_port_set_bits(data); + return n; +} + +void +ao_lcd_port_put_nibble(uint8_t rs, uint8_t data) +{ + data = (data & 0xf) | (rs ? (1 << PIN_RS) : 0); + DDRB = (0xf) | (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + ao_lcd_port_set_bits(data); + ao_lcd_port_set_bits(data | (1 << PIN_E)); + ao_lcd_port_set_bits(data); +} + +void +ao_lcd_port_init(void) +{ + DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + PORTB = 0; +} diff --git a/src/cc1111/ao_lcd_port.c b/src/cc1111/ao_lcd_port.c new file mode 100644 index 00000000..324cc3d3 --- /dev/null +++ b/src/cc1111/ao_lcd_port.c @@ -0,0 +1,41 @@ +/* + * 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" + +void +ao_lcd_port_put_nibble(uint8_t rs, uint8_t nibble) +{ + P0 = (P0 & 0xf0) | (nibble & 0x0f); + P1_1 = rs; + P1_0 = 1; + ao_delay(1); + P1_0 = 0; + ao_delay(1); +} + +void +ao_lcd_port_init(void) +{ + /* LCD_E and LCD_RS are GPIO outputs */ + P1DIR |= 0x03; + P1SEL &= ~0x03; + + /* LCD D4-D7 are GPIO outputs */ + P0DIR |= 0x0f; + P0SEL &= ~0x0f; +} diff --git a/src/cc1111/ao_packet.c b/src/cc1111/ao_packet.c index 37ba92e0..f502d67c 100644 --- a/src/cc1111/ao_packet.c +++ b/src/cc1111/ao_packet.c @@ -32,7 +32,9 @@ __xdata uint8_t ao_packet_master_sleeping; void ao_packet_send(void) { +#ifdef AO_LED_RED ao_led_on(AO_LED_RED); +#endif /* If any tx data is pending then copy it into the tx packet */ if (ao_packet_tx_used && ao_tx_packet.len == 0) { ao_xmemcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); @@ -42,7 +44,9 @@ ao_packet_send(void) ao_wakeup(&tx_data); } ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet)); +#ifdef AO_LED_RED ao_led_off(AO_LED_RED); +#endif } uint8_t diff --git a/src/core/ao.h b/src/core/ao.h index 94526bc3..c800f1fc 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1667,9 +1667,37 @@ ao_companion_init(void); /* ao_lcd.c */ +void +ao_lcd_putchar(uint8_t data); + +void +ao_lcd_putstring(char *string); + +void +ao_lcd_contrast_set(uint8_t contrast); + +void +ao_lcd_clear(void); + +#define AO_LCD_ADDR(row,col) ((row << 6) | (col)) + +void +ao_lcd_goto(uint8_t addr); + +void +ao_lcd_start(void); + void ao_lcd_init(void); +/* ao_lcd_port.c */ + +void +ao_lcd_port_put_nibble(uint8_t rs, uint8_t data); + +void +ao_lcd_port_init(void); + /* ao_aes.c */ __xdata uint8_t ao_aes_mutex; diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 1a8bb52a..5a6f61dd 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -22,6 +22,10 @@ #error Must define HAS_MONITOR to 1 #endif +#ifndef LEGACY_MONITOR +#error Must define LEGACY_MONITOR +#endif + __data uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; @@ -39,12 +43,14 @@ ao_monitor_get(void) case 0: ao_sleep(DATA_TO_XDATA(&ao_monitoring)); continue; +#if LEGACY_MONITOR case AO_MONITORING_ORIG: size = sizeof (struct ao_telemetry_orig_recv); break; case AO_MONITORING_TINY: size = sizeof (struct ao_telemetry_tiny_recv); break; +#endif default: if (ao_monitoring > AO_MAX_TELEMETRY) ao_monitoring = AO_MAX_TELEMETRY; @@ -70,12 +76,13 @@ ao_monitor_blink(void) void ao_monitor_put(void) { +#if LEGACY_MONITOR __xdata char callsign[AO_MAX_CALLSIGN+1]; - + int16_t rssi; +#endif uint8_t ao_monitor_tail; uint8_t state; uint8_t sum, byte; - int16_t rssi; __xdata union ao_monitor *m; #define recv_raw ((m->raw)) @@ -89,6 +96,7 @@ ao_monitor_put(void) m = &ao_monitor_ring[ao_monitor_tail]; ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail); switch (ao_monitoring) { +#if LEGACY_MONITOR case AO_MONITORING_ORIG: state = recv_orig.telemetry_orig.flight_state; @@ -231,6 +239,7 @@ ao_monitor_put(void) printf("CRC INVALID RSSI %3d\n", rssi); } break; +#endif /* LEGACY_MONITOR */ default: printf ("TELEM %02x", ao_monitoring + 2); sum = 0x5a; diff --git a/src/drivers/ao_lcd.c b/src/drivers/ao_lcd.c index 5bc89bbd..e62247ae 100644 --- a/src/drivers/ao_lcd.c +++ b/src/drivers/ao_lcd.c @@ -17,100 +17,9 @@ #include "ao.h" -#define LCD_PORT PORTB -#define LCD_DDR DDRB - -#define PIN_RS 4 -#define PIN_E 5 -#define PIN_RW 6 - -void -ao_lcd_set_bits(uint8_t bits) -{ -#if 0 - printf("\tLCD data %x RS %d R/W %d E %d\n", - bits & 0xf, - (bits & (1 << PIN_RS)) ? 1 : 0, - (bits & (1 << PIN_RW)) ? 1 : 0, - (bits & (1 << PIN_E)) ? 1 : 0); -#endif - LCD_PORT = bits; -#if 0 - ao_delay(1); - if (bits & (1 << PIN_RW)) - printf("\tLCD input %x\n", PINB); -#endif -} - -uint8_t -ao_lcd_get_nibble(uint8_t rs) -{ - uint8_t data = (rs ? (1 << PIN_RS) : 0) | (1 << PIN_RW); - uint8_t n; - - DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); - ao_lcd_set_bits(data); - ao_lcd_set_bits(data | (1 << PIN_E)); - n = PINB & 0xf; - ao_lcd_set_bits(data); - return n; -} - -uint8_t -ao_lcd_get_status(void) -{ - uint8_t high, low; - uint8_t data; - - high = ao_lcd_get_nibble(0); - low = ao_lcd_get_nibble(0); - data = (high << 4) | low; - printf ("\tLCD status %02x\n", data); - return data; -} - -uint8_t -ao_lcd_get_data(void) -{ - uint8_t high, low; - uint8_t data; - - high = ao_lcd_get_nibble(1); - low = ao_lcd_get_nibble(1); - data = (high << 4) | low; - printf ("\tLCD data %02x\n", data); - return data; -} - -void -ao_lcd_wait_idle(void) -{ - uint8_t status; - uint8_t count = 0; - - do { - status = ao_lcd_get_status(); - count++; - if (count > 100) { - printf("idle timeout\n"); - break; - } - } while (0); /* status & 0x80); */ -} - -void -ao_lcd_send_nibble(uint8_t rs, uint8_t data) -{ - data = (data & 0xf) | (rs ? (1 << PIN_RS) : 0); - DDRB = (0xf) | (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); - ao_lcd_set_bits(data); - ao_lcd_set_bits(data | (1 << PIN_E)); - ao_lcd_set_bits(data); -} - static uint16_t ao_lcd_time = 3; -void +static void ao_lcd_delay(void) { volatile uint16_t count; @@ -119,34 +28,34 @@ ao_lcd_delay(void) ; } -void -ao_lcd_send_ins(uint8_t data) +static void +ao_lcd_send_ins(uint8_t ins) { -// printf("send ins %02x\n", data); +// printf("send ins %02x\n", ins); // ao_lcd_wait_idle(); // ao_delay(1); ao_lcd_delay(); - ao_lcd_send_nibble(0, data >> 4); - ao_lcd_send_nibble(0, data & 0xf); + ao_lcd_port_put_nibble(0, ins >> 4); + ao_lcd_port_put_nibble(0, ins & 0xf); } void -ao_lcd_send_data(uint8_t data) +ao_lcd_put_byte(uint8_t c) { -// printf ("send data %02x\n", data); +// printf ("send data %02x\n", c); // ao_lcd_wait_idle(); ao_lcd_delay(); - ao_lcd_send_nibble(1, data >> 4); - ao_lcd_send_nibble(1, data & 0x0f); + ao_lcd_port_put_nibble(1, c >> 4); + ao_lcd_port_put_nibble(1, c & 0x0f); } void -ao_lcd_send_string(char *string) +ao_lcd_putstring(char *string) { - uint8_t c; + char c; while ((c = (uint8_t) *string++)) - ao_lcd_send_data(c); + ao_lcd_put_byte((uint8_t) c); } #define AO_LCD_POWER_CONTROL 0x54 @@ -167,14 +76,21 @@ ao_lcd_clear(void) ao_lcd_send_ins(0x04 | 0x02); } +void +ao_lcd_goto(uint8_t addr) +{ + ao_lcd_send_ins(0x80 | addr); + ao_lcd_send_ins(0x04 | 0x02); +} + void ao_lcd_start(void) { /* get to 4bit mode */ - ao_lcd_send_nibble(0, 0x3); - ao_lcd_send_nibble(0, 0x3); - ao_lcd_send_nibble(0, 0x3); - ao_lcd_send_nibble(0, 0x2); + ao_lcd_port_put_nibble(0, 0x3); + ao_lcd_port_put_nibble(0, 0x3); + ao_lcd_port_put_nibble(0, 0x3); + ao_lcd_port_put_nibble(0, 0x2); /* function set */ ao_lcd_send_ins(0x28); @@ -199,7 +115,6 @@ ao_lcd_start(void) /* Clear */ ao_lcd_clear(); - } void @@ -229,7 +144,7 @@ void ao_lcd_string(void) { uint8_t col = 0; - uint8_t c; + char c; ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) @@ -244,12 +159,12 @@ ao_lcd_string(void) ao_cmd_lex(); c |= ao_cmd_hex_nibble(); } - ao_lcd_send_data(c); + ao_lcd_put_byte(c); ao_cmd_lex(); col++; } while (col < 16) { - ao_lcd_send_data(' '); + ao_lcd_put_byte(' '); col++; } } @@ -275,7 +190,6 @@ __code struct ao_cmds ao_lcd_cmds[] = { void ao_lcd_init(void) { - DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); - PORTB = 0; + ao_lcd_port_init(); ao_cmd_register(&ao_lcd_cmds[0]); } -- cgit v1.2.3 From eb61f7aa2c8b692bd892b85e782f249187c80e5c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 21 Oct 2011 11:30:43 -0700 Subject: altos: Add teleballoon-v1.1 directory This is an alternate firmware load for telemetrum v1.1. Signed-off-by: Keith Packard --- src/core/ao_log_big.c | 2 + src/core/ao_telemetry.c | 2 +- src/teleballoon-v1.1/.gitignore | 2 + src/teleballoon-v1.1/Makefile | 122 +++++++++++++++++++ src/teleballoon-v1.1/ao_balloon.c | 155 ++++++++++++++++++++++++ src/teleballoon-v1.1/ao_pins.h | 220 ++++++++++++++++++++++++++++++++++ src/teleballoon-v1.1/ao_teleballoon.c | 77 ++++++++++++ 7 files changed, 579 insertions(+), 1 deletion(-) create mode 100644 src/teleballoon-v1.1/.gitignore create mode 100644 src/teleballoon-v1.1/Makefile create mode 100644 src/teleballoon-v1.1/ao_balloon.c create mode 100644 src/teleballoon-v1.1/ao_pins.h create mode 100644 src/teleballoon-v1.1/ao_teleballoon.c (limited to 'src/core') diff --git a/src/core/ao_log_big.c b/src/core/ao_log_big.c index 74d94c4b..43b3aa0c 100644 --- a/src/core/ao_log_big.c +++ b/src/core/ao_log_big.c @@ -65,9 +65,11 @@ static __data uint8_t ao_log_adc_pos; /* a hack to make sure that ao_log_records fill the eeprom block in even units */ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; +#ifndef AO_SENSOR_INTERVAL_ASCENT #define AO_SENSOR_INTERVAL_ASCENT 1 #define AO_SENSOR_INTERVAL_DESCENT 10 #define AO_OTHER_INTERVAL 32 +#endif void ao_log(void) diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index d909bea5..e66598d1 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -35,7 +35,7 @@ static __pdata uint16_t ao_rdf_time; #define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) #define AO_RDF_LENGTH_MS 500 -#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) +#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) #define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM #endif diff --git a/src/teleballoon-v1.1/.gitignore b/src/teleballoon-v1.1/.gitignore new file mode 100644 index 00000000..21b236c0 --- /dev/null +++ b/src/teleballoon-v1.1/.gitignore @@ -0,0 +1,2 @@ +teleballoon-* +ao_product.h diff --git a/src/teleballoon-v1.1/Makefile b/src/teleballoon-v1.1/Makefile new file mode 100644 index 00000000..89471cf4 --- /dev/null +++ b/src/teleballoon-v1.1/Makefile @@ -0,0 +1,122 @@ +# +# TeleBalloon build file +# +# The various telemetrum versions differ only +# in which flash and GPS drivers are included, +# so the per-board makefiles simply define +# TM_VER, TM_DEF, TM_INC and TM_SRC and include +# this file + +TELEBALLOON_VER=1.1 +TELEBALLOON_DEF=1_1 + +TELEBALLOON_INC = + +TELEBALLOON_SRC = \ + ao_companion.c \ + ao_gps_skytraq.c \ + ao_m25.c + +vpath %.c ..:../core:../cc1111:../drivers:../product:. +vpath %.h ..:../core:../cc1111:../drivers:../product:. +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + altitude.h \ + ao_kalman.h \ + ao_product.h \ + $(TELEBALLOON_INC) + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_convert.c \ + ao_gps_report.c \ + ao_mutex.c \ + ao_panic.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c \ + ao_balloon.c \ + ao_sample.c \ + ao_kalman.c \ + ao_log.c \ + ao_log_big.c \ + ao_report.c \ + ao_telemetry.c + +CC1111_SRC = \ + ao_adc.c \ + ao_beep.c \ + ao_dbg.c \ + ao_dma.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_slave.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_string.c \ + ao_spi.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = \ + $(TELEBALLOON_SRC) + +PRODUCT_SRC = \ + ao_teleballoon.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = teleballoon-v$(TELEBALLOON_VER)-$(VERSION).ihx +PRODUCT=TeleBalloon-v$(TELEBALLOON_VER) +PRODUCT_DEF=-DTELEBALLOON_V_$(TELEBALLOON_DEF) +IDPRODUCT=0x000b + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: + diff --git a/src/teleballoon-v1.1/ao_balloon.c b/src/teleballoon-v1.1/ao_balloon.c new file mode 100644 index 00000000..08a3ae1e --- /dev/null +++ b/src/teleballoon-v1.1/ao_balloon.c @@ -0,0 +1,155 @@ +/* + * Copyright © 2009 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_FLIGHT_TEST +#include "ao.h" +#endif + +#ifndef HAS_ACCEL +#error Please define HAS_ACCEL +#endif + +#ifndef HAS_GPS +#error Please define HAS_GPS +#endif + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ + +__pdata uint8_t ao_flight_force_idle; + +void +ao_flight(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + for (;;) { + + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + + /* Check to see what mode we should go to. + * - Invalid mode if accel cal appears to be out + * - pad mode if we're upright, + * - idle mode otherwise + */ +#if HAS_ACCEL + if (ao_config.accel_plus_g == 0 || + ao_config.accel_minus_g == 0 || + ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) + { + /* Detected an accel value outside -1.5g to 1.5g + * (or uncalibrated values), so we go into invalid mode + */ + ao_flight_state = ao_flight_invalid; + + /* Turn on packet system in invalid mode on TeleMetrum */ + ao_packet_slave_start(); + } else +#endif + if (!ao_flight_force_idle +#if HAS_ACCEL + && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP +#endif + ) + { + /* Set pad mode - we can fly! */ + ao_flight_state = ao_flight_pad; +#if HAS_USB + /* Disable the USB controller in flight mode + * to save power + */ + ao_usb_disable(); +#endif + +#if !HAS_ACCEL + /* Disable packet mode in pad state on TeleMini */ + ao_packet_slave_stop(); +#endif + + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_BALLOON); + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } else { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + +#if HAS_ACCEL + /* Turn on packet system in idle mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + + break; + case ao_flight_pad: + + /* pad to coast: + * + * barometer: > 20m vertical motion + */ + if (ao_height > AO_M_TO_HEIGHT(20)) + { + ao_flight_state = ao_flight_drogue; + + /* start logging data */ + ao_log_start(); + +#if HAS_GPS + /* Record current GPS position by waking up GPS log tasks */ + ao_wakeup(&ao_gps_data); + ao_wakeup(&ao_gps_tracking_data); +#endif + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_drogue: + break; + + } + } +} + +static __xdata struct ao_task flight_task; + +void +ao_flight_init(void) +{ + ao_flight_state = ao_flight_startup; + ao_add_task(&flight_task, ao_flight, "flight"); +} diff --git a/src/teleballoon-v1.1/ao_pins.h b/src/teleballoon-v1.1/ao_pins.h new file mode 100644 index 00000000..a96c6f2b --- /dev/null +++ b/src/teleballoon-v1.1/ao_pins.h @@ -0,0 +1,220 @@ +/* + * Copyright © 2010 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_PINS_H_ +#define _AO_PINS_H_ + +#if defined(TELEBALLOON_V_1_1) + + #define AO_SENSOR_INTERVAL_ASCENT AO_MS_TO_TICKS(1000) + #define AO_SENSOR_INTERVAL_DESCENT AO_MS_TO_TICKS(1000) + #define AO_OTHER_INTERVAL AO_MS_TO_TICKS(1000) + #define AO_TELEMETRY_INTERVAL_BALLOON AO_MS_TO_TICKS(1000) + + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define HAS_LOG 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #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 + #define HAS_ACCEL_REF 1 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 1 + #define HAS_IGNITE 0 + #define HAS_MONITOR 0 +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#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 + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#ifndef HAS_LOG +#error Please define HAS_LOG +#endif + +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + +#if HAS_IGNITE +#define HAS_IGNITE_REPORT 1 +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif + +#if HAS_MONITOR +#ifndef HAS_RSSI +#error Please define HAS_RSSI +#endif +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC + +#if HAS_ACCEL +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif +#else +#define HAS_ACCEL_REF 0 +#endif + +#endif /* HAS_ADC */ + +#if IGNITE_ON_P2 +#define AO_IGNITER_DROGUE P2_3 +#define AO_IGNITER_MAIN P2_4 +#define AO_IGNITER_DIR P2DIR +#define AO_IGNITER_DROGUE_BIT (1 << 3) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +#if IGNITE_ON_P0 +#define AO_IGNITER_DROGUE P0_5 +#define AO_IGNITER_MAIN P0_4 +#define AO_IGNITER_DIR P0DIR +#define AO_IGNITER_DROGUE_BIT (1 << 5) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +/* test these values with real igniters */ +#define AO_IGNITER_OPEN 1000 +#define AO_IGNITER_CLOSED 7000 +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) + +#endif /* _AO_PINS_H_ */ diff --git a/src/teleballoon-v1.1/ao_teleballoon.c b/src/teleballoon-v1.1/ao_teleballoon.c new file mode 100644 index 00000000..a48e21d2 --- /dev/null +++ b/src/teleballoon-v1.1/ao_teleballoon.c @@ -0,0 +1,77 @@ +/* + * Copyright © 2009 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" +#include "ao_pins.h" + +void +ao_ignite_set_pins(void) +{ + AO_IGNITER_DROGUE = 0; + AO_IGNITER_MAIN = 0; + AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; +} + +void +main(void) +{ + /* + * Reduce the transient on the ignite pins at startup by + * pulling the pins low as soon as possible at power up + */ + ao_ignite_set_pins(); + + ao_clock_init(); + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + /* A hack -- look at the SPI clock pin, if it's sitting at + * ground, then we force the computer to idle mode instead of + * flight mode + */ + if (P1_3 == 0) { + ao_flight_force_idle = 1; + while (P1_3 == 0) + ; + } + ao_timer_init(); + ao_adc_init(); + ao_beep_init(); + ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); + ao_flight_init(); + ao_log_init(); + ao_report_init(); + ao_usb_init(); + ao_serial_init(); + ao_gps_init(); + ao_gps_report_init(); + ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(FALSE); +#if HAS_DBG + ao_dbg_init(); +#endif +#if HAS_COMPANION + ao_companion_init(); +#endif + ao_config_init(); + ao_start_scheduler(); +} -- cgit v1.2.3 From 7e7a10c06a0486e9f869e361e46f2c98db9897b0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Oct 2011 14:08:59 -0700 Subject: altos: Add button driver and sample user Hook up the teleterra buttons and have them beep Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 15 ++++++++ src/cc1111/ao_button.c | 86 ++++++++++++++++++++++++++++++++++++++++++ src/cc1111/ao_usb.c | 3 ++ src/core/ao.h | 7 ++++ src/product/ao_teleterra_0_2.c | 1 + src/product/ao_terraui.c | 45 ++++++++++++++++++++++ src/teleterra-v0.2/Makefile | 4 +- src/teleterra-v0.2/ao_pins.h | 4 ++ 8 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 src/cc1111/ao_button.c create mode 100644 src/product/ao_terraui.c (limited to 'src/core') diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 02e36189..23589e66 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -204,6 +204,21 @@ struct ao_adc { #define AO_ADC_RING 32 +/* ao_button.c */ +void +ao_p2_isr(void); + +void +ao_button_init(void); + +#if HAS_BUTTON_P0 +void +ao_p0_isr(void) ao_arch_interrupt(13); +#endif + +char +ao_button_get(void) __critical; + /* ao_string.c */ void diff --git a/src/cc1111/ao_button.c b/src/cc1111/ao_button.c new file mode 100644 index 00000000..547d71ac --- /dev/null +++ b/src/cc1111/ao_button.c @@ -0,0 +1,86 @@ +/* + * 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" + +volatile __xdata struct ao_fifo ao_button_fifo; + +#define BUTTON_1_PIN (P0_4) +#define BUTTON_1_MASK (1 << 4) /* P0_4 */ + +#define BUTTON_2_PIN (P2_3) +#define BUTTON_2_MASK (1 << 3) /* P2_3 */ + +#define BUTTON_3_PIN (P2_4) +#define BUTTON_3_MASK (1 << 4) /* P2_4 */ + +static void +ao_button_insert(char n) +{ + ao_fifo_insert(ao_button_fifo, n); + ao_wakeup(&ao_button_fifo); +} + +char +ao_button_get(void) __critical +{ + char b; + + while (ao_fifo_empty(ao_button_fifo)) + ao_sleep(&ao_button_fifo); + ao_fifo_remove(ao_button_fifo, b); + return b; +} + +void +ao_p2_isr(void) +{ + if (P2IFG & BUTTON_2_MASK) + ao_button_insert(2); + if (P2IFG & BUTTON_3_MASK) + ao_button_insert(3); + P2IFG = 0; +} + +void +ao_p0_isr(void) ao_arch_interrupt(13) +{ + P0IF = 0; + if (P0IFG & BUTTON_1_MASK) + ao_button_insert(1); + P0IFG = 0; +} + +void +ao_button_init(void) +{ + /* Pins are configured as inputs with pull-up by default */ + + /* Enable interrupts for P2_0 - P2_4 + * Enable interrupts for P0_4 - P0_7 + * Set P2 interrupts to falling edge + * Set P0 interrupts to falling edge + */ + + PICTL |= PICTL_P2IEN | PICTL_P0IENH | PICTL_P2ICON | PICTL_P0ICON; + + /* Enable interrupts for P0 inputs */ + IEN1 |= IEN1_P0IE; + + /* Enable interrupts for P2 inputs */ + IEN2 |= IEN2_P2IE; +} diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c index 08cb7390..35c9ac20 100644 --- a/src/cc1111/ao_usb.c +++ b/src/cc1111/ao_usb.c @@ -62,6 +62,9 @@ ao_usb_isr(void) __interrupt 6 ao_btm_isr(); #endif #endif +#if HAS_P2_ISR + ao_p2_isr(); +#endif } struct ao_usb_setup { diff --git a/src/core/ao.h b/src/core/ao.h index c800f1fc..43d4e0e3 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1851,4 +1851,11 @@ ao_log_single(void); #define ao_xmemcmp(d,s,c) memcmp(d,s,c) #endif +/* + * ao_terraui.c + */ + +void +ao_terraui_init(void); + #endif /* _AO_H_ */ diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index 05085860..b38f2907 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -37,5 +37,6 @@ main(void) ao_radio_init(); ao_config_init(); ao_lcd_init(); + ao_terraui_init(); ao_start_scheduler(); } diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c new file mode 100644 index 00000000..3885db4e --- /dev/null +++ b/src/product/ao_terraui.c @@ -0,0 +1,45 @@ +/* + * 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" + +static void +ao_terraui(void) +{ + for (;;) { + char b = ao_button_get(); + switch (b) { + case 1: + ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(200)); + break; + case 2: + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + break; + case 3: + ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(200)); + break; + } + } +} + +__xdata static struct ao_task ao_terraui_task; + +void +ao_terraui_init(void) +{ + ao_add_task(&ao_terraui_task, ao_terraui, "ui"); +} diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index eda67a2a..8e4569a9 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -33,6 +33,7 @@ CORE_SRC = \ CC1111_SRC = \ ao_beep.c \ + ao_button.c \ ao_dbg.c \ ao_dma.c \ ao_led.c \ @@ -54,7 +55,8 @@ DRIVER_SRC = \ ao_gps_skytraq.c PRODUCT_SRC = \ - ao_teleterra_0_2.c + ao_teleterra_0_2.c \ + ao_terraui.c SRC = \ $(CORE_SRC) \ diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 671d3876..7b6f08b2 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -53,6 +53,10 @@ #define SPI_CS_ON_P0 0 #define M25_CS_MASK 0x04 #define M25_MAX_CHIPS 1 + + #define HAS_P2_ISR 1 + #define HAS_BUTTON_P0 1 + #define HAS_BUTTON_P2 1 #endif #if DBG_ON_P1 -- cgit v1.2.3 From f70553106707e3496d07eecb83f0c0a1acad7f77 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Oct 2011 14:51:32 -0700 Subject: altos: Add battery voltage sampling driver For devices without a full ADC compliment, this just samples the battery pin and converts to mV. Signed-off-by: Keith Packard --- src/cc1111/ao_battery.c | 60 ++++++++++++++++++++++++++++++++++++++++++ src/core/ao.h | 15 +++++++++++ src/product/ao_teleterra_0_2.c | 1 + src/teleterra-v0.2/Makefile | 1 + src/teleterra-v0.2/ao_pins.h | 2 ++ 5 files changed, 79 insertions(+) create mode 100644 src/cc1111/ao_battery.c (limited to 'src/core') diff --git a/src/cc1111/ao_battery.c b/src/cc1111/ao_battery.c new file mode 100644 index 00000000..070f682f --- /dev/null +++ b/src/cc1111/ao_battery.c @@ -0,0 +1,60 @@ +/* + * 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" +static __data union { + uint8_t d[2]; + int16_t v; +} ao_battery_value; + +void +ao_battery_isr(void) ao_arch_interrupt(1) +{ + ao_battery_value.d[0] = ADCL; + ao_battery_value.d[1] = ADCH; + ao_wakeup(DATA_TO_XDATA(&ao_battery_value)); +} + +uint16_t +ao_battery_get(void) +{ + ao_arch_critical( + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | BATTERY_PIN; + ao_sleep(DATA_TO_XDATA(&ao_battery_value)); + ); + return (uint16_t) ((int32_t) ao_battery_value.v * (int32_t) 3333 >> 15); +} + +static void +ao_battery_show(void) +{ + printf("Battery: %u mV\n", ao_battery_get()); +} + +__code struct ao_cmds ao_battery_cmds[] = { + { ao_battery_show, "B\0Show battery voltage" }, + { 0, NULL }, +}; + +void +ao_battery_init(void) +{ + ADCCFG = (1 << BATTERY_PIN); + ADCIF = 0; + IEN0 |= IEN0_ADCIE; + ao_cmd_register(&ao_battery_cmds[0]); +} diff --git a/src/core/ao.h b/src/core/ao.h index 43d4e0e3..558d0e38 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1858,4 +1858,19 @@ ao_log_single(void); void ao_terraui_init(void); +/* + * ao_battery.c + */ + +#ifdef BATTERY_PIN +void +ao_battery_isr(void) ao_arch_interrupt(1); + +uint16_t +ao_battery_get(void); + +void +ao_battery_init(void); +#endif /* BATTERY_PIN */ + #endif /* _AO_H_ */ diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index b38f2907..3272970f 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -38,5 +38,6 @@ main(void) ao_config_init(); ao_lcd_init(); ao_terraui_init(); + ao_battery_init(); ao_start_scheduler(); } diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 8e4569a9..36f523a3 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -32,6 +32,7 @@ CORE_SRC = \ ao_task.c CC1111_SRC = \ + ao_battery.c \ ao_beep.c \ ao_button.c \ ao_dbg.c \ diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 7b6f08b2..36f3c199 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -57,6 +57,8 @@ #define HAS_P2_ISR 1 #define HAS_BUTTON_P0 1 #define HAS_BUTTON_P2 1 + + #define BATTERY_PIN 5 #endif #if DBG_ON_P1 -- cgit v1.2.3 From da330c5975b9f565d059ef8084dfdacc20f34246 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 26 Oct 2011 22:49:11 -0700 Subject: altos: Bring up basic TeleTerra v0.2 UI Lots of fun stuff here -- multiple panes of information. Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 14 +- src/cc1111/ao_button.c | 115 ++++++--- src/cc1111/ao_lcd_port.c | 13 +- src/core/ao.h | 24 +- src/core/ao_monitor.c | 10 +- src/core/ao_sqrt.c | 46 ++++ src/drivers/ao_lcd.c | 12 +- src/product/Makefile.telemetrum | 6 +- src/product/ao_teleterra_0_2.c | 3 +- src/product/ao_terraui.c | 497 +++++++++++++++++++++++++++++++++++++- src/telelaunch-v0.1/.gitignore | 2 +- src/telemetrum-v0.1-sirf/Makefile | 1 + src/telemetrum-v0.1-sky/Makefile | 1 + src/teleterra-v0.2/.gitignore | 2 + src/teleterra-v0.2/.sdcdbrc | 1 + src/teleterra-v0.2/Makefile | 1 + src/teleterra-v0.2/ao_pins.h | 14 +- 17 files changed, 710 insertions(+), 52 deletions(-) create mode 100644 src/core/ao_sqrt.c create mode 100644 src/teleterra-v0.2/.gitignore create mode 100644 src/teleterra-v0.2/.sdcdbrc (limited to 'src/core') diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 23589e66..f0f0daae 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -205,17 +205,23 @@ struct ao_adc { #define AO_ADC_RING 32 /* ao_button.c */ +#ifdef HAS_BUTTON void -ao_p2_isr(void); +ao_p0_isr(void) ao_arch_interrupt(13); void -ao_button_init(void); +ao_p1_isr(void) ao_arch_interrupt(15); -#if HAS_BUTTON_P0 void -ao_p0_isr(void) ao_arch_interrupt(13); +ao_p2_isr(void); + +#define HAS_P2_ISR 1 + #endif +void +ao_button_init(void); + char ao_button_get(void) __critical; diff --git a/src/cc1111/ao_button.c b/src/cc1111/ao_button.c index 3516d559..77a8dde8 100644 --- a/src/cc1111/ao_button.c +++ b/src/cc1111/ao_button.c @@ -19,14 +19,22 @@ volatile __xdata struct ao_fifo ao_button_fifo; -#define BUTTON_1_PIN (P0_4) -#define BUTTON_1_MASK (1 << 4) /* P0_4 */ +static __code struct { + uint8_t mask; + uint8_t reg; +} ao_buttons[] = { +#ifdef BUTTON_1_MASK + { BUTTON_1_MASK, BUTTON_1_REG }, +#endif +#ifdef BUTTON_2_MASK + { BUTTON_2_MASK, BUTTON_2_REG }, +#endif +#ifdef BUTTON_3_MASK + { BUTTON_3_MASK, BUTTON_3_REG }, +#endif +}; -#define BUTTON_2_PIN (P2_3) -#define BUTTON_2_MASK (1 << 3) /* P2_3 */ - -#define BUTTON_3_PIN (P2_4) -#define BUTTON_3_MASK (1 << 4) /* P2_4 */ +#define NUM_BUTTONS ((sizeof ao_buttons) / sizeof (ao_buttons[0])) static void ao_button_insert(char n) @@ -35,52 +43,101 @@ ao_button_insert(char n) ao_wakeup(&ao_button_fifo); } +static void +ao_button_isr(uint8_t flag, uint8_t reg) +{ + uint8_t b; + + for (b = 0; b < NUM_BUTTONS; b++) + if (ao_buttons[b].reg == reg && (ao_buttons[b].mask & flag)) + ao_button_insert(b + 1); +} + +static uint8_t +ao_button_mask(uint8_t reg) +{ + uint8_t b; + uint8_t mask = 0; + + for (b = 0; b < NUM_BUTTONS; b++) + if (ao_buttons[b].reg == reg) + mask |= ao_buttons[b].mask; + return mask; +} + char ao_button_get(void) __critical { char b; while (ao_fifo_empty(ao_button_fifo)) - ao_sleep(&ao_button_fifo); + if (ao_sleep(&ao_button_fifo)) + return 0; ao_fifo_remove(ao_button_fifo, b); return b; } void -ao_p2_isr(void) +ao_p0_isr(void) ao_arch_interrupt(13) { - if (P2IFG & BUTTON_2_MASK) - ao_button_insert(2); - if (P2IFG & BUTTON_3_MASK) - ao_button_insert(3); - P2IFG = 0; + P0IF = 0; + ao_button_isr(P0IFG, 0); + P0IFG = 0; } void -ao_p0_isr(void) ao_arch_interrupt(13) +ao_p1_isr(void) ao_arch_interrupt(15) { - P0IF = 0; - if (P0IFG & BUTTON_1_MASK) - ao_button_insert(1); - P0IFG = 0; + P1IF = 0; + ao_button_isr(P1IFG, 1); + P1IFG = 0; +} + +/* Shared with USB */ +void +ao_p2_isr(void) +{ + ao_button_isr(P2IFG, 2); + P2IFG = 0; } void ao_button_init(void) { + uint8_t mask; + /* Pins are configured as inputs with pull-up by default */ - /* Enable interrupts for P2_0 - P2_4 - * Enable interrupts for P0_4 - P0_7 - * Set P2 interrupts to falling edge - * Set P0 interrupts to falling edge - */ - /* Enable interrupts for P0 inputs */ - IEN1 |= IEN1_P0IE; + mask = ao_button_mask(0); + if (mask) { + if (mask & 0x0f) + PICTL |= PICTL_P0IENL; + if (mask & 0xf0) + PICTL |= PICTL_P0IENH; + P0IFG = 0; + P0IF = 0; + IEN1 |= IEN1_P0IE; + PICTL |= PICTL_P0ICON; + } - /* Enable interrupts for P2 inputs */ - IEN2 |= IEN2_P2IE; + /* Enable interrupts for P1 inputs */ + mask = ao_button_mask(1); + if (mask) { + P1IEN |= mask; + P1IFG = 0; + P1IF = 0; + IEN2 |= IEN2_P1IE; + PICTL |= PICTL_P1ICON; + } - PICTL |= PICTL_P2IEN | PICTL_P0IENH | PICTL_P2ICON | PICTL_P0ICON; + /* Enable interrupts for P2 inputs */ + mask = ao_button_mask(2); + if (mask) { + PICTL |= PICTL_P2IEN; + P2IFG = 0; + P2IF = 0; + IEN2 |= IEN2_P2IE; + PICTL |= PICTL_P2ICON; + } } diff --git a/src/cc1111/ao_lcd_port.c b/src/cc1111/ao_lcd_port.c index 324cc3d3..e61b1a60 100644 --- a/src/cc1111/ao_lcd_port.c +++ b/src/cc1111/ao_lcd_port.c @@ -17,15 +17,24 @@ #include "ao.h" +static void +ao_lcd_port_delay(void) +{ + uint8_t i; + + for (i = 0; i < 100; i++) + ao_arch_nop(); +} + void ao_lcd_port_put_nibble(uint8_t rs, uint8_t nibble) { P0 = (P0 & 0xf0) | (nibble & 0x0f); P1_1 = rs; P1_0 = 1; - ao_delay(1); + ao_lcd_port_delay(); P1_0 = 0; - ao_delay(1); + ao_lcd_port_delay(); } void diff --git a/src/core/ao.h b/src/core/ao.h index 558d0e38..9b8d3270 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -996,7 +996,11 @@ ao_spi_slave(void); */ #define AO_MAX_CALLSIGN 8 #define AO_MAX_VERSION 8 +#if LEGACY_MONITOR #define AO_MAX_TELEMETRY 128 +#else +#define AO_MAX_TELEMETRY 32 +#endif struct ao_telemetry_generic { uint16_t serial; /* 0 */ @@ -1156,6 +1160,12 @@ union ao_telemetry_all { struct ao_telemetry_baro baro; }; +struct ao_telemetry_all_recv { + union ao_telemetry_all telemetry; + int8_t rssi; + uint8_t status; +}; + /* * ao_gps.c */ @@ -1372,9 +1382,10 @@ extern const char const * const ao_state_names[]; #define AO_MONITOR_RING 8 union ao_monitor { - struct ao_telemetry_raw_recv raw; - struct ao_telemetry_orig_recv orig; - struct ao_telemetry_tiny_recv tiny; + struct ao_telemetry_raw_recv raw; + struct ao_telemetry_all_recv all; + struct ao_telemetry_orig_recv orig; + struct ao_telemetry_tiny_recv tiny; }; extern __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; @@ -1873,4 +1884,11 @@ void ao_battery_init(void); #endif /* BATTERY_PIN */ +/* + * ao_sqrt.c + */ + +uint32_t +ao_sqrt(uint32_t op); + #endif /* _AO_H_ */ diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 5a6f61dd..f7795fe4 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -26,6 +26,10 @@ #error Must define LEGACY_MONITOR #endif +#ifndef HAS_MONITOR_PUT +#define HAS_MONIOTOR_PUT 1 +#endif + __data uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; @@ -73,6 +77,7 @@ ao_monitor_blink(void) } } +#if HAS_MONITOR_PUT void ao_monitor_put(void) { @@ -260,9 +265,10 @@ ao_monitor_put(void) ao_usb_flush(); } } +__xdata struct ao_task ao_monitor_put_task; +#endif __xdata struct ao_task ao_monitor_get_task; -__xdata struct ao_task ao_monitor_put_task; __xdata struct ao_task ao_monitor_blink_task; void @@ -293,7 +299,9 @@ ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant ao_monitoring = monitoring; ao_cmd_register(&ao_monitor_cmds[0]); ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); +#if HAS_MONITOR_PUT ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); +#endif if (ao_monitor_led) ao_add_task(&ao_monitor_blink_task, ao_monitor_blink, "monitor_blink"); } diff --git a/src/core/ao_sqrt.c b/src/core/ao_sqrt.c new file mode 100644 index 00000000..09c2e319 --- /dev/null +++ b/src/core/ao_sqrt.c @@ -0,0 +1,46 @@ +/* + * 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" + +/* Adapted from int_sqrt.c in the linux kernel, which is licensed GPLv2 */ +/** + * int_sqrt - rough approximation to sqrt + * @x: integer of which to calculate the sqrt + * + * A very rough approximation to the sqrt() function. + */ + +uint32_t +ao_sqrt(uint32_t op) +{ + uint32_t res = 0; + uint32_t one = 1UL << (sizeof (one) * 8 - 2); + + while (one > op) + one >>= 2; + + while (one != 0) { + if (op >= res + one) { + op = op - (res + one); + res = res + 2 * one; + } + res /= 2; + one /= 4; + } + return res; +} diff --git a/src/drivers/ao_lcd.c b/src/drivers/ao_lcd.c index e62247ae..8745b3f6 100644 --- a/src/drivers/ao_lcd.c +++ b/src/drivers/ao_lcd.c @@ -19,6 +19,8 @@ static uint16_t ao_lcd_time = 3; +static __xdata uint8_t ao_lcd_mutex; + static void ao_lcd_delay(void) { @@ -39,7 +41,7 @@ ao_lcd_send_ins(uint8_t ins) ao_lcd_port_put_nibble(0, ins & 0xf); } -void +static void ao_lcd_put_byte(uint8_t c) { // printf ("send data %02x\n", c); @@ -54,8 +56,10 @@ ao_lcd_putstring(char *string) { char c; + ao_mutex_get(&ao_lcd_mutex); while ((c = (uint8_t) *string++)) ao_lcd_put_byte((uint8_t) c); + ao_mutex_put(&ao_lcd_mutex); } #define AO_LCD_POWER_CONTROL 0x54 @@ -63,24 +67,30 @@ ao_lcd_putstring(char *string) void ao_lcd_contrast_set(uint8_t contrast) { + ao_mutex_get(&ao_lcd_mutex); ao_lcd_send_ins(AO_LCD_POWER_CONTROL | ((contrast >> 4) & 0x3)); ao_lcd_send_ins(0x70 | (contrast & 0xf)); + ao_mutex_put(&ao_lcd_mutex); } void ao_lcd_clear(void) { + ao_mutex_get(&ao_lcd_mutex); ao_lcd_send_ins(0x01); ao_delay(1); /* Entry mode */ ao_lcd_send_ins(0x04 | 0x02); + ao_mutex_put(&ao_lcd_mutex); } void ao_lcd_goto(uint8_t addr) { + ao_mutex_get(&ao_lcd_mutex); ao_lcd_send_ins(0x80 | addr); ao_lcd_send_ins(0x04 | 0x02); + ao_mutex_put(&ao_lcd_mutex); } void diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index 4f4195a9..40fc6bc2 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -7,8 +7,8 @@ # TM_VER, TM_DEF, TM_INC and TM_SRC and include # this file -vpath %.c ..:../core:../cc1111:../drivers:../product -vpath %.h ..:../core:../cc1111:../drivers:../product +vpath %.c .:..:../core:../cc1111:../drivers:../product +vpath %.h .:..:../core:../cc1111:../drivers:../product vpath ao-make-product.5c ../util ifndef VERSION @@ -72,7 +72,7 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = telemetrum-v$(TM_VER)-$(VERSION).ihx +PROG = telemetrum-v$(TM_VER)-$(VERSION)$(TM_EXTRA).ihx PRODUCT=TeleMetrum-v$(TM_VER) PRODUCT_DEF=-DTELEMETRUM_V_$(TM_DEF) IDPRODUCT=0x000b diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index 3272970f..6ce29894 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -31,13 +31,14 @@ main(void) ao_usb_init(); ao_serial_init(); ao_gps_init(); - ao_monitor_init(0, TRUE); + ao_monitor_init(0, sizeof (struct ao_telemetry_generic)); ao_report_init(); ao_log_single_init(); ao_radio_init(); ao_config_init(); ao_lcd_init(); ao_terraui_init(); + ao_button_init(); ao_battery_init(); ao_start_scheduler(); } diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 3885db4e..cfbfb1fb 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -16,21 +16,450 @@ */ #include "ao.h" +#include + +static __xdata struct ao_telemetry_sensor ao_tel_sensor; +static __xdata struct ao_telemetry_location ao_tel_location; +static __xdata struct ao_telemetry_configuration ao_tel_config; +static __xdata int16_t ao_tel_max_speed; +static __xdata int16_t ao_tel_max_height; +static int8_t ao_tel_rssi; + +static __xdata char ao_lcd_line[17]; +static __xdata char ao_state_name[] = "SIPBFCDMLI"; + +static void +ao_terraui_line(uint8_t addr) +{ + ao_lcd_goto(addr); + ao_lcd_putstring(ao_lcd_line); +} + +#define ao_terraui_state() (ao_state_name[ao_tel_sensor.state]) + +static char +ao_terraui_igniter(int16_t sense) +{ + if (sense < AO_IGNITER_OPEN) + return '-'; + if (sense > AO_IGNITER_CLOSED) + return '+'; + return '?'; +} + +static char +ao_terraui_battery(void) +{ + if (ao_tel_sensor.v_batt > 25558) + return '+'; + return '-'; +} + +static char +ao_terraui_gps(void) +{ + if (ao_tel_location.flags & (1 << 4)) { + if ((ao_tel_location.flags & 0xf) >= 4) + return '+'; + } + return '-'; +} + +static char +ao_terraui_local_gps(void) +{ + if (ao_gps_data.flags & (1 << 4)) { + if ((ao_gps_data.flags & 0xf) >= 4) + return '+'; + } + return '-'; +} + +static char +ao_terraui_logging(void) +{ + if (ao_tel_config.flight != 0) + return '+'; + return '-'; +} + +static __code char ao_progress[4] = { '\011', '\012', '\014', '\013' }; + +static uint8_t ao_telem_progress; +static uint8_t ao_gps_progress; + +static void +ao_terraui_info(void) +{ + sprintf(ao_lcd_line, "S %4d %7.7s %c", + ao_tel_sensor.serial, + ao_tel_config.callsign, + ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "F %4d RSSI%4d%c", + ao_tel_config.flight, + ao_tel_rssi, + ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static void +ao_terraui_pad(void) +{ + sprintf(ao_lcd_line, "B%c A%c M%c L%c G%c %c", + ao_terraui_battery(), + ao_terraui_igniter(ao_tel_sensor.sense_d), + ao_terraui_igniter(ao_tel_sensor.sense_m), + ao_terraui_logging(), + ao_terraui_gps(), + ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "SAT %2d RSSI%4d%c", + ao_tel_location.flags & 0xf, + ao_tel_rssi, + ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static void +ao_terraui_ascent(void) +{ + sprintf(ao_lcd_line, "S %5d S\011%5d%c", + ao_tel_sensor.speed >> 4, + ao_tel_max_speed >> 4, + ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "H %5d H\011%5d%c", + ao_tel_sensor.height >> 4, + ao_tel_max_height >> 4, + ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static int16_t mag(int32_t d) +{ + if (d < 0) + d = -d; + if (d > 0x7fff) + d = 0x7fff; + return d; +} + +static uint32_t +dist(int32_t d) +{ + int32_t m; + + if (d < 0) + d = -d; + + m = 1000000; + while (d >= (2147483647 / 111198)) { + d /= 10; + m /= 10; + } + return (d * 111198) / m; +} + +static __code uint8_t cos_table[] = { + 0, /* 0 */ + 0, /* 1 */ + 0, /* 2 */ + 255, /* 3 */ + 254, /* 4 */ + 253, /* 5 */ + 252, /* 6 */ + 251, /* 7 */ + 249, /* 8 */ + 247, /* 9 */ + 245, /* 10 */ + 243, /* 11 */ + 240, /* 12 */ + 238, /* 13 */ + 235, /* 14 */ + 232, /* 15 */ + 228, /* 16 */ + 225, /* 17 */ + 221, /* 18 */ + 217, /* 19 */ + 213, /* 20 */ + 209, /* 21 */ + 205, /* 22 */ + 200, /* 23 */ + 195, /* 24 */ + 190, /* 25 */ + 185, /* 26 */ + 180, /* 27 */ + 175, /* 28 */ + 169, /* 29 */ + 163, /* 30 */ + 158, /* 31 */ + 152, /* 32 */ + 145, /* 33 */ + 139, /* 34 */ + 133, /* 35 */ + 126, /* 36 */ + 120, /* 37 */ + 113, /* 38 */ + 106, /* 39 */ + 100, /* 40 */ + 93, /* 41 */ + 86, /* 42 */ + 79, /* 43 */ + 71, /* 44 */ + 64, /* 45 */ + 57, /* 46 */ + 49, /* 47 */ + 42, /* 48 */ + 35, /* 49 */ + 27, /* 50 */ + 20, /* 51 */ + 12, /* 52 */ + 5, /* 53 */ + 1, /* 54 */ +}; + +static __code uint8_t tan_table[] = { + 0, /* 0 */ + 4, /* 1 */ + 9, /* 2 */ + 13, /* 3 */ + 18, /* 4 */ + 22, /* 5 */ + 27, /* 6 */ + 31, /* 7 */ + 36, /* 8 */ + 41, /* 9 */ + 45, /* 10 */ + 50, /* 11 */ + 54, /* 12 */ + 59, /* 13 */ + 64, /* 14 */ + 69, /* 15 */ + 73, /* 16 */ + 78, /* 17 */ + 83, /* 18 */ + 88, /* 19 */ + 93, /* 20 */ + 98, /* 21 */ + 103, /* 22 */ + 109, /* 23 */ + 114, /* 24 */ + 119, /* 25 */ + 125, /* 26 */ + 130, /* 27 */ + 136, /* 28 */ + 142, /* 29 */ + 148, /* 30 */ + 154, /* 31 */ + 160, /* 32 */ + 166, /* 33 */ + 173, /* 34 */ + 179, /* 35 */ + 186, /* 36 */ + 193, /* 37 */ + 200, /* 38 */ + 207, /* 39 */ + 215, /* 40 */ + 223, /* 41 */ + 231, /* 42 */ + 239, /* 43 */ + 247, /* 44 */ +}; + +int16_t ao_atan2(int32_t dy, int32_t dx) __reentrant +{ + int8_t m = 1; + int16_t a = 0; + uint8_t r; + int8_t t; + + if (dx == 0) { + if (dy > 0) + return 90; + if (dy < 0) + return -90; + return 0; + } + + if (dx < 0) { + a = 180; + m = -m; + dx = -dx; + } + + if (dy < 0) { + m = -m; + a = -a; + dy = -dy; + } + + if (dy > dx) { + int t; + + t = dy; dy = dx; dx = t; + a = a + m * 90; + m = -m; + } + + r = ((dy << 8) + (dx >> 1)) / dx; + for (t = 0; t < 44; t++) + if (tan_table[t] >= r) + break; + return t * m + a; +} + +static __pdata uint32_t lon_dist, lat_dist; +static __pdata uint32_t ground_dist, range; +static __pdata int16_t bearing, elevation; + +static void +ao_terraui_lat_dist(void) +{ + lat_dist = dist (ao_tel_location.latitude - ao_gps_data.latitude); +} + +static void +ao_terraui_lon_dist(void) +{ + uint8_t c = cos_table[ao_gps_data.latitude >> 24]; + lon_dist = dist(ao_tel_location.longitude - ao_gps_data.longitude); + if (c) + lon_dist = ((uint32_t) lon_dist * c) >> 8; +} + +static void +ao_terraui_compute(void) +{ + ao_terraui_lat_dist(); + ao_terraui_lon_dist(); + ground_dist = ao_sqrt (lat_dist * lat_dist + lon_dist * lon_dist); + range = ao_sqrt(ground_dist * ground_dist + ao_tel_sensor.height * ao_tel_sensor.height); + bearing = ao_atan2(lat_dist, lon_dist); + elevation = ao_atan2(ao_tel_sensor.height, ground_dist); +} + +static void +ao_terraui_descent(void) +{ + ao_terraui_compute(); + sprintf(ao_lcd_line, "\007 %4d \005 %3d %c", + bearing, elevation, + ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "H:%5d S:%5d%c", + ao_tel_sensor.height, ao_tel_sensor.speed >> 4, + ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static void +ao_terraui_coord(int32_t c, char plus, char minus, char extra) __reentrant +{ + uint16_t d; + uint8_t m; + uint16_t f; + + if (c < 0) { + plus = minus; + c = -c; + } + d = c / 10000000; + c = c % 10000000; + c = c * 60; + m = c / 10000000; + c = c % 10000000; + f = (c + 500) / 1000; + sprintf(ao_lcd_line, "%c %3d\362 %2d.%04d\"%c", + plus, d, m, f, extra); +} + +static void +ao_terraui_remote(void) +{ + ao_terraui_coord(ao_tel_location.latitude, 'N', 'S', ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + ao_terraui_coord(ao_tel_location.longitude, 'E', 'W', ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static void +ao_terraui_local(void) __reentrant +{ + ao_terraui_coord(ao_gps_data.latitude, 'n', 's', + ao_terraui_local_gps()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + ao_terraui_coord(ao_gps_data.longitude, 'e', 'w', ao_progress[ao_gps_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static void +ao_terraui_config(void) +{ + +} + +enum ao_page { + ao_page_info, + ao_page_pad, + ao_page_ascent, + ao_page_descent, + ao_page_remote, + ao_page_local, +}; static void ao_terraui(void) { + enum ao_page cur_page = ao_page_info; + + ao_lcd_start(); for (;;) { - char b = ao_button_get(); + char b; + switch (cur_page) { + case ao_page_info: + ao_terraui_info(); + break; + case ao_page_pad: + ao_terraui_pad(); + break; + case ao_page_ascent: + ao_terraui_ascent(); + break; + case ao_page_descent: + ao_terraui_descent(); + break; + case ao_page_remote: + ao_terraui_remote(); + break; + case ao_page_local: + ao_terraui_local(); + break; + } + + ao_alarm(AO_SEC_TO_TICKS(1)); + b = ao_button_get(); + ao_clear_alarm(); + switch (b) { + case 0: + break; case 1: - ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(200)); + if (cur_page == ao_page_local) + cur_page = ao_page_info; + else + cur_page++; + ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(50)); break; case 2: - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(200)); break; case 3: - ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(200)); + if (cur_page == ao_page_info) + cur_page = ao_page_local; + else + cur_page--; + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); break; } } @@ -38,8 +467,68 @@ ao_terraui(void) __xdata static struct ao_task ao_terraui_task; +static void +ao_terramonitor(void) +{ + uint8_t monitor; + + monitor = ao_monitor_head; + for (monitor = ao_monitor_head;; + monitor = ao_monitor_ring_next(monitor)) + { + while (monitor == ao_monitor_head) + ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + if (ao_monitoring != sizeof (union ao_telemetry_all)) + continue; + if (!(ao_monitor_ring[monitor].all.status & PKT_APPEND_STATUS_1_CRC_OK)) + continue; + ao_tel_rssi = (ao_monitor_ring[monitor].all.rssi >> 1) - 74; + switch (ao_monitor_ring[monitor].all.telemetry.generic.type) { + case AO_TELEMETRY_SENSOR_TELEMETRUM: + case AO_TELEMETRY_SENSOR_TELEMINI: + case AO_TELEMETRY_SENSOR_TELENANO: + ao_xmemcpy(&ao_tel_sensor, &ao_monitor_ring[monitor], sizeof (ao_tel_sensor)); + if (ao_tel_sensor.state < ao_flight_boost) { + ao_tel_max_speed = 0; + ao_tel_max_height = 0; + } else { + if (ao_tel_sensor.speed > ao_tel_max_speed) + ao_tel_max_speed = ao_tel_sensor.speed; + if (ao_tel_sensor.height > ao_tel_max_height) + ao_tel_max_height = ao_tel_sensor.height; + } + ao_telem_progress = (ao_telem_progress + 1) & 0x3; + break; + case AO_TELEMETRY_LOCATION: + ao_xmemcpy(&ao_tel_location, &ao_monitor_ring[monitor], sizeof (ao_tel_location)); + break; + case AO_TELEMETRY_CONFIGURATION: + ao_xmemcpy(&ao_tel_config, &ao_monitor_ring[monitor], sizeof (ao_tel_config)); + } + } +} + +__xdata static struct ao_task ao_terramonitor_task; + +static void +ao_terragps(void) +{ + uint16_t gps_tick = ao_gps_progress; + + for (;;) { + while (ao_gps_tick == gps_tick) + ao_sleep(&ao_gps_data); + gps_tick = ao_gps_tick; + ao_gps_progress = (ao_gps_progress + 1) & 3; + } +} + +__xdata static struct ao_task ao_terragps_task; + void ao_terraui_init(void) { ao_add_task(&ao_terraui_task, ao_terraui, "ui"); + ao_add_task(&ao_terramonitor_task, ao_terramonitor, "monitor"); + ao_add_task(&ao_terragps_task, ao_terragps, "gps"); } diff --git a/src/telelaunch-v0.1/.gitignore b/src/telelaunch-v0.1/.gitignore index d25d7ad9..e2cf954c 100644 --- a/src/telelaunch-v0.1/.gitignore +++ b/src/telelaunch-v0.1/.gitignore @@ -1,2 +1,2 @@ -telemetrum-v0.1-sky* +telelaunch* ao_product.h diff --git a/src/telemetrum-v0.1-sirf/Makefile b/src/telemetrum-v0.1-sirf/Makefile index 00cdc9c5..d138b5ef 100644 --- a/src/telemetrum-v0.1-sirf/Makefile +++ b/src/telemetrum-v0.1-sirf/Makefile @@ -4,6 +4,7 @@ TM_VER=0.1 TM_DEF=0_1 +TM_EXTRA=-sirf TM_INC = \ ao_25lc1024.h diff --git a/src/telemetrum-v0.1-sky/Makefile b/src/telemetrum-v0.1-sky/Makefile index e3c61db6..69cd3461 100644 --- a/src/telemetrum-v0.1-sky/Makefile +++ b/src/telemetrum-v0.1-sky/Makefile @@ -4,6 +4,7 @@ TM_VER=0.1 TM_DEF=0_1 +TM_EXTRA=-sky TM_INC = \ ao_25lc1024.h diff --git a/src/teleterra-v0.2/.gitignore b/src/teleterra-v0.2/.gitignore new file mode 100644 index 00000000..9daebc3e --- /dev/null +++ b/src/teleterra-v0.2/.gitignore @@ -0,0 +1,2 @@ +teleterra-v0.2* +ao_product.h diff --git a/src/teleterra-v0.2/.sdcdbrc b/src/teleterra-v0.2/.sdcdbrc new file mode 100644 index 00000000..fbe9a599 --- /dev/null +++ b/src/teleterra-v0.2/.sdcdbrc @@ -0,0 +1 @@ +--directory=../cc1111:../product:../core:../drivers:. diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 36f523a3..583805f6 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -26,6 +26,7 @@ CORE_SRC = \ ao_panic.c \ ao_report.c \ ao_rssi.c \ + ao_sqrt.c \ ao_state.c \ ao_stdio.c \ ao_storage.c \ diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 36f3c199..9c35b06a 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -45,6 +45,7 @@ #define HAS_ACCEL 0 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_MONITOR_PUT 0 #define LEGACY_MONITOR 0 #define HAS_RSSI 0 #define HAS_AES 0 @@ -54,11 +55,18 @@ #define M25_CS_MASK 0x04 #define M25_MAX_CHIPS 1 - #define HAS_P2_ISR 1 - #define HAS_BUTTON_P0 1 - #define HAS_BUTTON_P2 1 + #define HAS_BUTTON 1 + #define BUTTON_1_REG 0 + #define BUTTON_1_MASK (1 << 4) /* P0_4 */ + + #define BUTTON_2_REG 2 + #define BUTTON_2_MASK (1 << 3) /* P2_3 */ + + #define BUTTON_3_REG 2 + #define BUTTON_3_MASK (1 << 4) /* P2_4 */ #define BATTERY_PIN 5 + #endif #if DBG_ON_P1 -- cgit v1.2.3 From b132eefc5f63412bb4a98a4bb72b9055e40d5d42 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 11 Nov 2011 22:30:17 -0800 Subject: altos: Make ao_xmem funcs require __xdata void * instead of casting Having an explicit cast in the ao_xmem wrapper macros caused the compiler to generate garbage values for pdata addresses, making the upper byte 0x00 instead of the required 0xf0. Removing the casts from the ao_xmem macros exposed this problem, so a new PDATA_TO_XDATA macros was added, along with a CODE_TO_XDATA macro which serve to cast pointers, with suitable address modifications, so that things work again. Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 18 ++++++++++++------ src/cc1111/ao_string.c | 23 +++++++++++++++-------- src/core/ao.h | 6 ++++++ src/core/ao_config.c | 2 +- src/core/ao_host.h | 4 ++++ src/core/ao_telemetry.c | 8 ++++---- src/drivers/ao_gps_skytraq.c | 5 ++--- 7 files changed, 44 insertions(+), 22 deletions(-) (limited to 'src/core') diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index f0f0daae..001165fa 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -27,6 +27,12 @@ /* Convert a __data pointer into an __xdata pointer */ #define DATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xff00)) +/* Code and xdata use the same address space */ +#define CODE_TO_XDATA(a) ((__xdata void *) ((uint16_t) (a))) + +/* Pdata lives at the start of xdata */ +#define PDATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xf000)) + /* Stack runs from above the allocated __data space to 0xfe, which avoids * writing to 0xff as that triggers the stack overflow indicator */ @@ -228,18 +234,18 @@ ao_button_get(void) __critical; /* ao_string.c */ void -_ao_xmemcpy(__xdata uint8_t *dst, __xdata uint8_t *src, uint8_t count); +_ao_xmemcpy(__xdata void *dst, __xdata void *src, uint8_t count); -#define ao_xmemcpy(d,s,c) _ao_xmemcpy((__xdata uint8_t *) (d), (__xdata uint8_t *) (s), (c)) +#define ao_xmemcpy(d,s,c) _ao_xmemcpy(d,s,c) void -_ao_xmemset(__xdata uint8_t *dst, uint8_t value, uint8_t count); +_ao_xmemset(__xdata void *dst, uint8_t value, uint8_t count); -#define ao_xmemset(d,v,c) _ao_xmemset((__xdata uint8_t *) (d), (v), (c)) +#define ao_xmemset(d,v,c) _ao_xmemset(d,v,c) int8_t -_ao_xmemcmp(__xdata uint8_t *a, __xdata uint8_t *b, uint8_t count); +_ao_xmemcmp(__xdata void *a, __xdata void *b, uint8_t count); -#define ao_xmemcmp(d,s,c) _ao_xmemcmp((__xdata uint8_t *) (d), (__xdata uint8_t *) (s), (c)) +#define ao_xmemcmp(d,s,c) _ao_xmemcmp((d), (s), (c)) #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_string.c b/src/cc1111/ao_string.c index daa5c14b..3a07e47e 100644 --- a/src/cc1111/ao_string.c +++ b/src/cc1111/ao_string.c @@ -18,26 +18,33 @@ #include "ao.h" void -_ao_xmemcpy(__xdata uint8_t *dst, __xdata uint8_t *src, uint8_t count) +_ao_xmemcpy(__xdata void *dst, __xdata void *src, uint8_t count) { - while (count--) - *dst++ = *src++; + while (count--) { + *(__xdata uint8_t *) dst = *(__xdata uint8_t *) src; + dst = (__xdata uint8_t *) dst + 1; + src = (__xdata uint8_t *) src + 1; + } } void -_ao_xmemset(__xdata uint8_t *dst, uint8_t v, uint8_t count) +_ao_xmemset(__xdata void *dst, uint8_t v, uint8_t count) { - while (count--) - *dst++ = v; + while (count--) { + *(__xdata uint8_t *) dst = v; + dst = (__xdata uint8_t *) dst + 1; + } } int8_t -_ao_xmemcmp(__xdata uint8_t *a, __xdata uint8_t *b, uint8_t count) +_ao_xmemcmp(__xdata void *a, __xdata void *b, uint8_t count) { while (count--) { - int8_t d = *a++ - *b++; + int8_t d = *(__xdata int8_t *) a - *(__xdata int8_t *) b; if (d) return d; + a = (__xdata int8_t *) a + 1; + b = (__xdata int8_t *) b + 1; } return 0; } diff --git a/src/core/ao.h b/src/core/ao.h index 9b8d3270..cbe2f8dc 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -32,6 +32,12 @@ #ifndef DATA_TO_XDATA #define DATA_TO_XDATA(a) (a) #endif +#ifndef PDATA_TO_XDATA +#define PDATA_TO_XDATA(a) (a) +#endif +#ifndef CODE_TO_XDATA +#define CODE_TO_XDATA(a) (a) +#endif /* An AltOS task */ struct ao_task { diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 08cc79b1..f0a576ee 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -79,7 +79,7 @@ _ao_config_get(void) ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; ao_xmemset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); - ao_xmemcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, + ao_xmemcpy(&ao_config.callsign, CODE_TO_XDATA(AO_CONFIG_DEFAULT_CALLSIGN), sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config_dirty = 1; } diff --git a/src/core/ao_host.h b/src/core/ao_host.h index f2b2f0c9..6eb752c9 100644 --- a/src/core/ao_host.h +++ b/src/core/ao_host.h @@ -46,6 +46,10 @@ struct ao_adc { #define __code #define __reentrant +#define DATA_TO_XDATA(a) (a) +#define PDATA_TO_XDATA(a) (a) +#define CODE_TO_XDATA(a) (a) + enum ao_flight_state { ao_flight_startup = 0, ao_flight_idle = 1, diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index e66598d1..c68f1589 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -132,11 +132,11 @@ ao_send_configuration(void) telemetry.configuration.main_deploy = ao_config.main_deploy; telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10; ao_xmemcpy (telemetry.configuration.callsign, - ao_config.callsign, - AO_MAX_CALLSIGN); + ao_config.callsign, + AO_MAX_CALLSIGN); ao_xmemcpy (telemetry.configuration.version, - ao_version, - AO_MAX_VERSION); + CODE_TO_XDATA(ao_version), + AO_MAX_VERSION); ao_radio_send(&telemetry, sizeof (telemetry)); ao_telemetry_config_cur = ao_telemetry_config_max; } diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 1d457a1f..62909606 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -285,7 +285,7 @@ ao_nmea_gga(void) if (!ao_gps_error) { ao_mutex_get(&ao_gps_mutex); ao_gps_tick = ao_gps_next_tick; - ao_xmemcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data)); + ao_xmemcpy(&ao_gps_data, PDATA_TO_XDATA(&ao_gps_next), sizeof (ao_gps_data)); ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_data); } @@ -343,8 +343,7 @@ ao_nmea_gsv(void) ao_gps_tracking_next.channels = 0; else if (done) { ao_mutex_get(&ao_gps_mutex); - ao_xmemcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, - sizeof(ao_gps_tracking_data)); + ao_xmemcpy(&ao_gps_tracking_data, PDATA_TO_XDATA(&ao_gps_tracking_next), sizeof(ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_tracking_data); } -- cgit v1.2.3 From 5972c642f0de0789e90268bfa19ef8b51c06eebc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:44:36 -0800 Subject: altos: Handle internal and external telem monitoring requests Record separate internal vs external monitoring state, allowing both to happen at the same time, and when either is turned off, the other keeps working. This also adds disable/enable so that other radio users can temporarily take over the radio; monitoring will resume when the other radio user is finished. Signed-off-by: Keith Packard --- src/ao_radio_cmac.c | 4 +- src/cc1111/ao_packet_master.c | 5 +- src/cc1111/ao_pins.h | 5 ++ src/cc1111/ao_radio.c | 5 +- src/core/ao.h | 11 ++- src/core/ao_log_telem.c | 2 + src/core/ao_monitor.c | 151 ++++++++++++++++++----------------------- src/product/ao_telebt.c | 2 +- src/product/ao_teledongle.c | 2 +- src/product/ao_teleterra_0_2.c | 2 +- src/product/ao_tidongle.c | 2 +- src/teleterra-v0.2/ao_pins.h | 3 +- 12 files changed, 96 insertions(+), 98 deletions(-) (limited to 'src/core') diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index 41fbbe1f..e263f0db 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -78,7 +78,7 @@ radio_cmac_send(uint8_t len) __reentrant ao_config_get(); #if HAS_MONITOR - ao_set_monitor(0); + ao_monitor_set(0); #endif ao_mutex_get(&ao_aes_mutex); @@ -107,7 +107,7 @@ radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant len = round_len(len); #if HAS_MONITOR - ao_set_monitor(0); + ao_monitor_set(0); #endif if (timeout) ao_alarm(timeout); diff --git a/src/cc1111/ao_packet_master.c b/src/cc1111/ao_packet_master.c index ab19f979..66f94288 100644 --- a/src/cc1111/ao_packet_master.c +++ b/src/cc1111/ao_packet_master.c @@ -114,7 +114,7 @@ ao_packet_forward(void) __reentrant flush(); #if HAS_MONITOR - ao_set_monitor(0); + ao_monitor_disable(); #endif ao_add_task(&ao_packet_task, ao_packet_master, "master"); ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); @@ -132,6 +132,9 @@ ao_packet_forward(void) __reentrant ao_wakeup(&ao_stdin_ready); ao_delay(AO_MS_TO_TICKS(10)); } +#if HAS_MONITOR + ao_monitor_enable(); +#endif } diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 7c5b4574..2b6232a4 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -107,6 +107,7 @@ #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 1 #define AO_LED_GREEN 2 + #define AO_MONITOR_LED AO_LED_GREEN #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 @@ -218,6 +219,7 @@ #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 #define AO_LED_GREEN 1 + #define AO_MONITOR_LED AO_LED_GREEN #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 0 #define SPI_CS_ON_P0 1 @@ -245,6 +247,7 @@ #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 + #define AO_MONITOR_LED AO_LED_RED #define LEDS_AVAILABLE (AO_LED_RED) #define SPI_CS_ON_P1 0 #define SPI_CS_ON_P0 1 @@ -274,6 +277,7 @@ #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 #define AO_LED_GREEN 1 + #define AO_MONITOR_LED AO_LED_RED #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 @@ -312,6 +316,7 @@ #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 1 #define AO_LED_GREEN 2 + #define AO_MONITOR_LED AO_LED_RED #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 75f241d4..ee506f89 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -421,7 +421,7 @@ ao_radio_test(void) mode++; if ((mode & 2) && !radio_on) { #if HAS_MONITOR - ao_set_monitor(0); + ao_monitor_disable(); #endif #if PACKET_HAS_SLAVE ao_packet_slave_stop(); @@ -439,6 +439,9 @@ ao_radio_test(void) ao_radio_idle(); ao_radio_put(); radio_on = 0; +#if HAS_MONITOR + ao_monitor_enable(); +#endif } } diff --git a/src/core/ao.h b/src/core/ao.h index cbe2f8dc..f57398ce 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1406,13 +1406,18 @@ ao_monitor(void); #define AO_MONITORING_OFF 0 #define AO_MONITORING_ORIG 1 -#define AO_MONITORING_TINY 2 void -ao_set_monitor(uint8_t monitoring); +ao_monitor_set(uint8_t monitoring); void -ao_monitor_init(uint8_t led, uint8_t monitoring) __reentrant; +ao_monitor_disable(void); + +void +ao_monitor_enable(void); + +void +ao_monitor_init(void) __reentrant; /* * ao_stdio.c diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 096ad919..9e1b06d3 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -90,6 +90,8 @@ ao_log_single(void) ao_log_running = 1; ao_log_single_restart(); ao_flight_state = ao_flight_startup; + ao_monitor_set(sizeof(struct ao_telemetry_generic)); + for (;;) { while (!ao_log_running) ao_sleep(&ao_log_running); diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index f7795fe4..7960208e 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -30,13 +30,35 @@ #define HAS_MONIOTOR_PUT 1 #endif +#ifndef AO_MONITOR_LED +#error Must define AO_MONITOR_LED +#endif + __data uint8_t ao_monitoring; -__pdata uint8_t ao_monitor_led; +static __data uint8_t ao_monitor_disabled; +static __data uint8_t ao_internal_monitoring; +static __data uint8_t ao_external_monitoring; __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; __data uint8_t ao_monitor_head; +static void +_ao_monitor_adjust(void) +{ + if (ao_monitoring) + ao_radio_recv_abort(); + if (ao_monitor_disabled) + ao_monitoring = 0; + else { + if (ao_external_monitoring) + ao_monitoring = ao_external_monitoring; + else + ao_monitoring = ao_internal_monitoring; + } + ao_wakeup(DATA_TO_XDATA(&ao_monitoring)); +} + void ao_monitor_get(void) { @@ -51,9 +73,6 @@ ao_monitor_get(void) case AO_MONITORING_ORIG: size = sizeof (struct ao_telemetry_orig_recv); break; - case AO_MONITORING_TINY: - size = sizeof (struct ao_telemetry_tiny_recv); - break; #endif default: if (ao_monitoring > AO_MAX_TELEMETRY) @@ -68,16 +87,21 @@ ao_monitor_get(void) } } +#if AO_MONITOR_LED +__xdata struct ao_task ao_monitor_blink_task; + void ao_monitor_blink(void) { for (;;) { ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); - ao_led_for(ao_monitor_led, AO_MS_TO_TICKS(100)); + ao_led_for(AO_MONITOR_LED, AO_MS_TO_TICKS(100)); } } +#endif #if HAS_MONITOR_PUT + void ao_monitor_put(void) { @@ -96,11 +120,15 @@ ao_monitor_put(void) ao_monitor_tail = ao_monitor_head; for (;;) { - while (ao_monitor_tail == ao_monitor_head) + while (!ao_external_monitoring) + ao_sleep(DATA_TO_XDATA(&ao_external_monitoring)); + while (ao_monitor_tail == ao_monitor_head && ao_external_monitoring) ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); m = &ao_monitor_ring[ao_monitor_tail]; ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail); switch (ao_monitoring) { + case 0: + break; #if LEGACY_MONITOR case AO_MONITORING_ORIG: state = recv_orig.telemetry_orig.flight_state; @@ -172,71 +200,6 @@ ao_monitor_put(void) ao_gps_print(&recv_orig.telemetry_orig.gps); ao_gps_tracking_print(&recv_orig.telemetry_orig.gps_tracking); putchar('\n'); -#if HAS_RSSI - ao_rssi_set(rssi); -#endif - } else { - printf("CRC INVALID RSSI %3d\n", rssi); - } - break; - case AO_MONITORING_TINY: - state = recv_tiny.telemetry_tiny.flight_state; - - /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ - rssi = (int16_t) (recv_tiny.rssi >> 1) - 74; - ao_xmemcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN); - if (state > ao_flight_invalid) - state = ao_flight_invalid; - if (recv_tiny.status & PKT_APPEND_STATUS_1_CRC_OK) { - /* General header fields */ - printf(AO_TELEM_VERSION " %d " - AO_TELEM_CALL " %s " - AO_TELEM_SERIAL " %d " - AO_TELEM_FLIGHT " %d " - AO_TELEM_RSSI " %d " - AO_TELEM_STATE " %s " - AO_TELEM_TICK " %d ", - AO_TELEMETRY_VERSION, - callsign, - recv_tiny.telemetry_tiny.serial, - recv_tiny.telemetry_tiny.flight, - rssi, - ao_state_names[state], - recv_tiny.telemetry_tiny.adc.tick); - - /* Raw sensor values */ - printf(AO_TELEM_RAW_BARO " %d " - AO_TELEM_RAW_THERMO " %d " - AO_TELEM_RAW_BATT " %d " - AO_TELEM_RAW_DROGUE " %d " - AO_TELEM_RAW_MAIN " %d ", - recv_tiny.telemetry_tiny.adc.pres, - recv_tiny.telemetry_tiny.adc.temp, - recv_tiny.telemetry_tiny.adc.v_batt, - recv_tiny.telemetry_tiny.adc.sense_d, - recv_tiny.telemetry_tiny.adc.sense_m); - - /* Sensor calibration values */ - printf(AO_TELEM_CAL_BARO_GROUND " %d ", - recv_tiny.telemetry_tiny.ground_pres); - -#if 1 - /* Kalman state values */ - printf(AO_TELEM_KALMAN_HEIGHT " %d " - AO_TELEM_KALMAN_SPEED " %d " - AO_TELEM_KALMAN_ACCEL " %d\n", - recv_tiny.telemetry_tiny.height, - recv_tiny.telemetry_tiny.speed, - recv_tiny.telemetry_tiny.accel); -#else - /* Ad-hoc flight values */ - printf(AO_TELEM_ADHOC_ACCEL " %d " - AO_TELEM_ADHOC_SPEED " %ld " - AO_TELEM_ADHOC_BARO " %d\n", - recv_tiny.telemetry_tiny.flight_accel, - recv_tiny.telemetry_tiny.flight_vel, - recv_tiny.telemetry_tiny.flight_pres); -#endif #if HAS_RSSI ao_rssi_set(rssi); #endif @@ -265,43 +228,59 @@ ao_monitor_put(void) ao_usb_flush(); } } + __xdata struct ao_task ao_monitor_put_task; #endif __xdata struct ao_task ao_monitor_get_task; -__xdata struct ao_task ao_monitor_blink_task; void -ao_set_monitor(uint8_t monitoring) +ao_monitor_set(uint8_t monitoring) { - if (ao_monitoring) - ao_radio_recv_abort(); - ao_monitoring = monitoring; - ao_wakeup(DATA_TO_XDATA(&ao_monitoring)); + ao_internal_monitoring = monitoring; + _ao_monitor_adjust(); } +void +ao_monitor_disable(void) +{ + ++ao_monitor_disabled; + _ao_monitor_adjust(); +} + +void +ao_monitor_enable(void) +{ + --ao_monitor_disabled; + _ao_monitor_adjust(); +} + +#if HAS_MONITOR_PUT static void set_monitor(void) { ao_cmd_hex(); - ao_set_monitor(ao_cmd_lex_i); + ao_external_monitoring = ao_cmd_lex_i; + ao_wakeup(DATA_TO_XDATA(&ao_external_monitoring)); + ao_wakeup(DATA_TO_XDATA(&ao_monitor_head)); + _ao_monitor_adjust(); } __code struct ao_cmds ao_monitor_cmds[] = { - { set_monitor, "m <0 off, 1 full, 2 tiny>\0Enable/disable radio monitoring" }, + { set_monitor, "m <0 off, 1 old, 20 std>\0Enable/disable radio monitoring" }, { 0, NULL }, }; +#endif void -ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant +ao_monitor_init(void) __reentrant { - ao_monitor_led = monitor_led; - ao_monitoring = monitoring; - ao_cmd_register(&ao_monitor_cmds[0]); - ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); #if HAS_MONITOR_PUT + ao_cmd_register(&ao_monitor_cmds[0]); ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); #endif - if (ao_monitor_led) - ao_add_task(&ao_monitor_blink_task, ao_monitor_blink, "monitor_blink"); + ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); +#if AO_MONITOR_LED + ao_add_task(&ao_monitor_blink_task, ao_monitor_blink, "monitor_blink"); +#endif } diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index c4b40dfc..97c9d792 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -37,7 +37,7 @@ main(void) ao_storage_init(); #endif ao_usb_init(); - ao_monitor_init(AO_LED_RED, TRUE); + ao_monitor_init(); #if HAS_LOG ao_report_init(); #endif diff --git a/src/product/ao_teledongle.c b/src/product/ao_teledongle.c index b8be9f45..49b80500 100644 --- a/src/product/ao_teledongle.c +++ b/src/product/ao_teledongle.c @@ -28,7 +28,7 @@ main(void) ao_timer_init(); ao_cmd_init(); ao_usb_init(); - ao_monitor_init(AO_LED_GREEN, TRUE); + ao_monitor_init(); ao_rssi_init(AO_LED_RED); ao_radio_init(); ao_packet_master_init(); diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index 6ce29894..1a268c99 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -31,7 +31,7 @@ main(void) ao_usb_init(); ao_serial_init(); ao_gps_init(); - ao_monitor_init(0, sizeof (struct ao_telemetry_generic)); + ao_monitor_init(); ao_report_init(); ao_log_single_init(); ao_radio_init(); diff --git a/src/product/ao_tidongle.c b/src/product/ao_tidongle.c index 5adbb05c..a504a747 100644 --- a/src/product/ao_tidongle.c +++ b/src/product/ao_tidongle.c @@ -30,7 +30,7 @@ main(void) ao_timer_init(); ao_cmd_init(); ao_usb_init(); - ao_monitor_init(AO_LED_RED, TRUE); + ao_monitor_init(); ao_rssi_init(AO_LED_RED); ao_radio_init(); ao_dbg_init(); diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 9c35b06a..72ded004 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -39,13 +39,14 @@ #define HAS_COMPANION 0 + #define AO_MONITOR_LED 0 #define LEDS_AVAILABLE 0 #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL_REF 0 #define HAS_ACCEL 0 #define HAS_IGNITE 0 #define HAS_MONITOR 1 - #define HAS_MONITOR_PUT 0 + #define HAS_MONITOR_PUT 1 #define LEGACY_MONITOR 0 #define HAS_RSSI 0 #define HAS_AES 0 -- cgit v1.2.3 From 20282ef00afe70e3f3193f6f0200254cb2c33e93 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:47:08 -0800 Subject: altos: Set default flight log max to 127k on TM v0.1 The flash part on v0.1 boards is only 128kB. Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 1 + src/core/ao_config.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'src/core') diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 2b6232a4..ca85c39f 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -199,6 +199,7 @@ #define HAS_ACCEL 1 #define HAS_IGNITE 1 #define HAS_MONITOR 0 + #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 127 * (uint32_t) 1024) #endif #if defined(TELEDONGLE_V_0_1) diff --git a/src/core/ao_config.c b/src/core/ao_config.c index f0a576ee..921a2480 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -34,11 +34,13 @@ __xdata uint8_t ao_config_mutex; #error Please define USE_INTERNAL_FLASH #endif #endif +#ifndef AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX #if USE_INTERNAL_FLASH #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config #else #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024) #endif +#endif #if HAS_EEPROM static void -- cgit v1.2.3 From 2ba946fea29ff134ffaeaea9d7932f4bd4e953aa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:48:07 -0800 Subject: altos: Export 'ao_cmd_is_white' for use by other code This function tests the current input character. Signed-off-by: Keith Packard --- src/core/ao.h | 3 +++ src/core/ao_cmd.c | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index f57398ce..2139983c 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -349,6 +349,9 @@ ao_cmd_put8(uint8_t v); void ao_cmd_put16(uint16_t v); +uint8_t +ao_cmd_is_white(void); + void ao_cmd_white(void); diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 0c902f6b..14cb7569 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -121,10 +121,16 @@ ao_cmd_put8(uint8_t v) putnibble(v & 0xf); } +uint8_t +ao_cmd_is_white(void) +{ + return ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t'; +} + void ao_cmd_white(void) { - while (ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t') + while (ao_cmd_is_white()) ao_cmd_lex(); } -- cgit v1.2.3 From 75a8490a7bee2a2c7afd559b13f1d9c40c2aa08f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:49:17 -0800 Subject: altos: Add configurable set of channels for TT This adds the channel list for TT, which will be configured by AltosUI. Signed-off-by: Keith Packard --- src/core/ao.h | 17 ++++++++++++++- src/core/ao_config.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index 2139983c..3c1aa156 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1495,9 +1495,21 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 9 +#define AO_CONFIG_MINOR 10 #define AO_AES_LEN 16 +#if HAS_RADIO_CHANNELS +#define AO_CHANNEL_NAME_LEN 10 + +#define AO_NUM_CHANNELS 10 + +struct ao_radio_channel { + char name[AO_CHANNEL_NAME_LEN]; + uint32_t kHz; + uint32_t radio_setting; +}; +#endif + struct ao_config { uint8_t major; uint8_t minor; @@ -1514,6 +1526,9 @@ struct ao_config { uint32_t radio_setting; /* minor version 7 */ uint8_t radio_enable; /* minor version 8 */ uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */ +#if HAS_RADIO_CHANNELS + struct ao_radio_channel radio_channels[AO_NUM_CHANNELS]; /* minor version 10 */ +#endif }; #define AO_IGNITE_MODE_DUAL 0 diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 921a2480..86bbc473 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -111,6 +111,15 @@ _ao_config_get(void) ao_config.radio_enable = TRUE; if (ao_config.minor < 9) memset(&ao_config.aes_key, 0, AO_AES_LEN); +#if HAS_RADIO_CHANNELS + if (ao_config.minor < 10) { + ao_xmemset(&ao_config.radio_channels, '\0', sizeof (ao_config.radio_channels)); + ao_xmemcpy(&ao_config.radio_channels[0].name[0], + CODE_TO_XDATA("Channel 0"), sizeof("Channel 0")); + ao_config.radio_channels[0].kHz = 434550; + ao_config.radio_channels[0].radio_setting = ao_config.radio_cal; + } +#endif ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -448,6 +457,53 @@ ao_config_key_set(void) __reentrant } #endif +#if HAS_RADIO_CHANNELS +void +ao_config_radio_config_show(void) __reentrant +{ + uint8_t i; + for (i = 0; i < AO_NUM_CHANNELS; i++) + if (ao_config.radio_channels[i].name[0]) { + printf("%2d %-16.16s %ld %ld\n", + i, + ao_config.radio_channels[i].name, + ao_config.radio_channels[i].kHz, + ao_config.radio_channels[i].radio_setting); + } +} + +void +ao_config_radio_config_set(void) __reentrant +{ + __xdata struct ao_radio_channel * ch; + uint8_t i; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + if ((uint8_t) ao_cmd_lex_i >= AO_NUM_CHANNELS) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + ch = &ao_config.radio_channels[(uint8_t) ao_cmd_lex_i]; + _ao_config_edit_start(); + ao_cmd_white(); + i = 0; + while (ao_cmd_lex_c != '/' && ao_cmd_lex_c != '\n' && i < AO_CHANNEL_NAME_LEN) { + ch->name[i++] = ao_cmd_lex_c; + ao_cmd_lex(); + } + if (i < AO_CHANNEL_NAME_LEN) { + ch->name[i] = '\0'; + ao_cmd_lex(); + } + ao_cmd_decimal(); + ch->kHz = ao_cmd_lex_u32; + ao_cmd_decimal(); + ch->radio_setting = ao_cmd_lex_u32; + _ao_config_edit_finish(); +} +#endif + struct ao_config_var { __code char *str; void (*set)(void) __reentrant; @@ -499,6 +555,10 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_AES { "k <32 hex digits>\0Set AES encryption key", ao_config_key_set, ao_config_key_show }, +#endif +#if HAS_RADIO_CHANNELS + { "C / \0Set radio chan config", + ao_config_radio_config_set,ao_config_radio_config_show }, #endif { "s\0Show", ao_config_show, 0 }, -- cgit v1.2.3 From 430b439b9a5cc98b32273a233505de2c2f975c59 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:51:03 -0800 Subject: altosui: Add ao_lcd_cursor_on/off This shows or hides a blinking cursor on the LCD. Signed-off-by: Keith Packard --- src/core/ao.h | 6 ++++++ src/drivers/ao_lcd.c | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index 3c1aa156..8bd7a3d2 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1719,6 +1719,12 @@ ao_lcd_contrast_set(uint8_t contrast); void ao_lcd_clear(void); +void +ao_lcd_cursor_on(void); + +void +ao_lcd_cursor_off(void); + #define AO_LCD_ADDR(row,col) ((row << 6) | (col)) void diff --git a/src/drivers/ao_lcd.c b/src/drivers/ao_lcd.c index 8745b3f6..8ce32233 100644 --- a/src/drivers/ao_lcd.c +++ b/src/drivers/ao_lcd.c @@ -73,6 +73,22 @@ ao_lcd_contrast_set(uint8_t contrast) ao_mutex_put(&ao_lcd_mutex); } +void +ao_lcd_cursor_on(void) +{ + ao_mutex_get(&ao_lcd_mutex); + ao_lcd_send_ins(0x08 | 0x04 | 0x02 | 0x01); + ao_mutex_put(&ao_lcd_mutex); +} + +void +ao_lcd_cursor_off(void) +{ + ao_mutex_get(&ao_lcd_mutex); + ao_lcd_send_ins(0x08 | 0x04); + ao_mutex_put(&ao_lcd_mutex); +} + void ao_lcd_clear(void) { -- cgit v1.2.3 From d3dcb9451f40506abced72783966104645a73bc7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:52:02 -0800 Subject: altos: Allow TT/TBT reports to escape landed state The TM altitude reporting code kept beeping out state and altitude forever, which isn't very useful on TBT or TT. Signed-off-by: Keith Packard --- src/core/ao_report.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_report.c b/src/core/ao_report.c index 70f0b49d..7c928792 100644 --- a/src/core/ao_report.c +++ b/src/core/ao_report.c @@ -99,14 +99,10 @@ ao_report_altitude(void) agl /= 10; } while (agl); - for (;;) { - ao_report_beep(); - i = ndigits; - do - ao_report_digit(digits[--i]); - while (i != 0); - pause(AO_SEC_TO_TICKS(5)); - } + i = ndigits; + do + ao_report_digit(digits[--i]); + while (i != 0); } #if HAS_IGNITE_REPORT @@ -159,9 +155,14 @@ ao_report(void) { ao_report_state = ao_flight_state; for(;;) { - if (ao_flight_state == ao_flight_landed) - ao_report_altitude(); ao_report_beep(); + if (ao_flight_state == ao_flight_landed) { + ao_report_altitude(); +#if HAS_FLIGHT + ao_delay(AO_SEC_TO_TICKS(5)); + continue; +#endif + } #if HAS_IGNITE_REPORT if (ao_flight_state == ao_flight_idle) ao_report_continuity(); @@ -173,11 +174,10 @@ ao_report(void) pause(AO_MS_TO_TICKS(100)); } #endif - __critical { - while (ao_report_state == ao_flight_state) - ao_sleep(DATA_TO_XDATA(&ao_flight_state)); - ao_report_state = ao_flight_state; - } + + while (ao_report_state == ao_flight_state) + ao_sleep(DATA_TO_XDATA(&ao_flight_state)); + ao_report_state = ao_flight_state; } } -- cgit v1.2.3 From dbf7c0c59854e040b65f068069d80716f02fc1bc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 13 Nov 2011 23:03:22 -0800 Subject: altos: Fix pad orientation for pre-1.1 boards They use a different code path for accel as they don't have the VCC compensation code in place. Signed-off-by: Keith Packard --- src/core/ao_sample.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/core') diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c index b2b8e9f6..2bf9632f 100644 --- a/src/core/ao_sample.c +++ b/src/core/ao_sample.c @@ -182,6 +182,11 @@ ao_sample(void) if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) ao_sample_accel = 0x7fff - ao_sample_accel; ao_adc->accel = ao_sample_accel; +#else + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) { + ao_sample_accel = 0x7fff - ao_sample_accel; + ao_adc->accel = ao_sample_accel; + } #endif #endif -- cgit v1.2.3 From eff8611e3eb19853b06acfcd7e978c9046cd5f78 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Dec 2011 17:05:06 -0800 Subject: altos: Create TeleMetrum v1.2 directory The hardware is software-compatible with v1.1, but it's nice to have the right version number in all of the files. Signed-off-by: Keith Packard --- altosui/Makefile.am | 3 ++- altosui/altos-windows.nsi | 1 + doc/altusmetrum.xsl | 8 ++++---- src/Makefile | 2 +- src/cc1111/ao_pins.h | 37 +++++++++++++++++++++++++++++++++++++ src/core/ao_telemetry.c | 2 +- src/telemetrum-v1.2/.gitignore | 2 ++ src/telemetrum-v1.2/.sdcdbrc | 1 + src/telemetrum-v1.2/Makefile | 16 ++++++++++++++++ 9 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 src/telemetrum-v1.2/.gitignore create mode 100644 src/telemetrum-v1.2/.sdcdbrc create mode 100644 src/telemetrum-v1.2/Makefile (limited to 'src/core') diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 7cd383ac..fc024fff 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -171,7 +171,8 @@ FIRMWARE_TD=$(FIRMWARE_TD_0_2) FIRMWARE_TM_1_0=$(top_srcdir)/src/telemetrum-v1.0-$(VERSION).ihx FIRMWARE_TM_1_1=$(top_srcdir)/src/telemetrum-v1.1-$(VERSION).ihx -FIRMWARE_TM=$(FIRMWARE_TM_1_0) $(FIRMWARE_TM_1_1) +FIRMWARE_TM_1_2=$(top_srcdir)/src/telemetrum-v1.2-$(VERSION).ihx +FIRMWARE_TM=$(FIRMWARE_TM_1_0) $(FIRMWARE_TM_1_1) $(FIRMWARE_TM_1_2) FIRMWARE_TELEMINI_1_0=$(top_srcdir)/src/telemini-v1.0-$(VERSION).ihx FIRMWARE_TELEMINI=$(FIRMWARE_TELEMINI_1_0) diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi index cbcb389d..e5e01d79 100644 --- a/altosui/altos-windows.nsi +++ b/altosui/altos-windows.nsi @@ -112,6 +112,7 @@ Section "TeleMetrum and TeleDongle Firmware" File "../src/telemetrum-v1.0/telemetrum-v1.0-${VERSION}.ihx" File "../src/telemetrum-v1.1/telemetrum-v1.1-${VERSION}.ihx" + File "../src/telemetrum-v1.2/telemetrum-v1.2-${VERSION}.ihx" File "../src/telemini-v1.0/telemini-v1.0-${VERSION}.ihx" File "../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx" diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 606c8b99..5c18fec3 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -586,7 +586,7 @@ NAR #88757, TRA #12200
Maximum Flight Log - TeleMetrum version 1.1 has 2MB of on-board flash storage, + TeleMetrum version 1.1 and 1.2 have 2MB of on-board flash storage, enough to hold over 40 minutes of data at full data rate (100 samples/second). TeleMetrum 1.0 has 1MB of on-board storage. As data are stored at a reduced rate during descent @@ -602,7 +602,7 @@ NAR #88757, TRA #12200 All of the configuration data is also stored in the flash - memory, which consumes 64kB on TeleMetrum v1.1 and 256B on + memory, which consumes 64kB on TeleMetrum v1.1/v1.2 and 256B on TeleMetrum v1.0. This configuration space is not available for storing flight log data. @@ -619,7 +619,7 @@ NAR #88757, TRA #12200 The default size, 192kB, allows for 10 flights of storage on - TeleMetrum v1.1 and 5 flights on TeleMetrum v1.0. This + TeleMetrum v1.1/v1.2 and 5 flights on TeleMetrum v1.0. This ensures that you won't need to erase the memory before flying each time while still allowing more than sufficient storage for each flight. @@ -1842,7 +1842,7 @@ NAR #88757, TRA #12200 Select the image you want put on the TeleMetrum, which should have a - name in the form telemetrum-v1.1-1.0.0.ihx. It should be visible + name in the form telemetrum-v1.2-1.0.0.ihx. It should be visible in the default directory, if not you may have to poke around your system to find it. diff --git a/src/Makefile b/src/Makefile index 61b1a835..d3173254 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,7 +13,7 @@ vpath matrix.5c kalman include Version SUBDIRS=\ - telemetrum-v1.1 telemetrum-v1.0 \ + telemetrum-v1.2 telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ telemini-v1.0 telenano-v0.1 \ telebt-v0.0 telebt-v0.1 \ diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index ca85c39f..a18c74c8 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -89,6 +89,43 @@ #define HAS_MONITOR 0 #endif +#if defined(TELEMETRUM_V_1_2) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define HAS_LOG 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #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 + #define HAS_ACCEL_REF 1 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + #if defined(TELEDONGLE_V_0_2) #define HAS_FLIGHT 0 #define HAS_USB 1 diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index c68f1589..eb614b0f 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -35,7 +35,7 @@ static __pdata uint16_t ao_rdf_time; #define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) #define AO_RDF_LENGTH_MS 500 -#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) +#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) || defined(TELEMETRUM_V_1_2) #define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM #endif diff --git a/src/telemetrum-v1.2/.gitignore b/src/telemetrum-v1.2/.gitignore new file mode 100644 index 00000000..c2212151 --- /dev/null +++ b/src/telemetrum-v1.2/.gitignore @@ -0,0 +1,2 @@ +telemetrum-* +ao_product.h diff --git a/src/telemetrum-v1.2/.sdcdbrc b/src/telemetrum-v1.2/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telemetrum-v1.2/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telemetrum-v1.2/Makefile b/src/telemetrum-v1.2/Makefile new file mode 100644 index 00000000..4b650adf --- /dev/null +++ b/src/telemetrum-v1.2/Makefile @@ -0,0 +1,16 @@ +# +# AltOS build +# +# + +TM_VER=1.2 +TM_DEF=1_2 + +TM_INC = + +TM_SRC = \ + ao_companion.c \ + ao_gps_skytraq.c \ + ao_m25.c + +include ../product/Makefile.telemetrum -- cgit v1.2.3 From 614ab6a991258a5caad0ca12ae35d0288a5b7503 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Dec 2011 15:38:32 -0800 Subject: altos: Clean up for SDCC 3.1 - more keywords _asm -> __asm sbit -> __sbit remove variables named 'data' Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 14 ++++---- src/cc1111/cc1111.h | 100 +++++++++++++++++++++++++-------------------------- src/core/ao.h | 12 +++---- 3 files changed, 63 insertions(+), 63 deletions(-) (limited to 'src/core') diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index eb8ce9be..e6c27a1e 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -45,7 +45,7 @@ ao_delay(AO_SEC_TO_TICKS(2)); \ } while (0) -#define ao_arch_nop() _asm nop _endasm +#define ao_arch_nop() __asm nop __endasm #define ao_arch_interrupt(n) __interrupt n #define ao_arch_naked_declare __naked @@ -106,7 +106,7 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; /* Save current context */ #define ao_arch_save_regs() \ - _asm \ + __asm \ /* Push ACC first, as when restoring the context it must be restored \ * last (it is used to set the IE register). */ \ push ACC \ @@ -125,11 +125,11 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; push ar0 \ push ar1 \ push PSW \ - _endasm; \ + __endasm; \ PSW = 0; \ - _asm \ + __asm \ push _bp \ - _endasm + __endasm #define ao_arch_save_stack() { \ uint8_t stack_len; \ @@ -166,7 +166,7 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; *stack_ptr++ = *save_ptr++; \ while (--stack_len); \ \ - _asm \ + __asm \ pop _bp \ pop PSW \ pop ar1 \ @@ -193,7 +193,7 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; /* Finally pop off the ACC, which was the first register saved. */ \ pop ACC \ ret \ - _endasm; \ + __endasm; \ } #define ao_arch_critical(b) __critical { b } diff --git a/src/cc1111/cc1111.h b/src/cc1111/cc1111.h index 70e8c9c7..80d3fb70 100644 --- a/src/cc1111/cc1111.h +++ b/src/cc1111/cc1111.h @@ -42,14 +42,14 @@ __sfr __at 0xA8 IEN0; /* Interrupt Enable 0 Register */ -sbit __at 0xA8 RFTXRXIE; /* RF TX/RX done interrupt enable */ -sbit __at 0xA9 ADCIE; /* ADC interrupt enable */ -sbit __at 0xAA URX0IE; /* USART0 RX interrupt enable */ -sbit __at 0xAB URX1IE; /* USART1 RX interrupt enable (shared with I2S RX) */ -sbit __at 0xAB I2SRXIE; /* I2S RX interrupt enable (shared with USART1 RX) */ -sbit __at 0xAC ENCIE; /* AES encryption/decryption interrupt enable */ -sbit __at 0xAD STIE; /* Sleep Timer interrupt enable */ -sbit __at 0xAF EA; /* Enable All */ +__sbit __at 0xA8 RFTXRXIE; /* RF TX/RX done interrupt enable */ +__sbit __at 0xA9 ADCIE; /* ADC interrupt enable */ +__sbit __at 0xAA URX0IE; /* USART0 RX interrupt enable */ +__sbit __at 0xAB URX1IE; /* USART1 RX interrupt enable (shared with I2S RX) */ +__sbit __at 0xAB I2SRXIE; /* I2S RX interrupt enable (shared with USART1 RX) */ +__sbit __at 0xAC ENCIE; /* AES encryption/decryption interrupt enable */ +__sbit __at 0xAD STIE; /* Sleep Timer interrupt enable */ +__sbit __at 0xAF EA; /* Enable All */ #define IEN0_EA (1 << 7) #define IEN0_STIE (1 << 5) @@ -135,11 +135,11 @@ __sfr __at 0x87 PCON; /* Power Mode Control Register */ */ __sfr __at 0x88 TCON; /* CPU Interrupt Flag 1 */ -sbit __at 0x8F URX1IF; /* USART1 RX interrupt flag. Automatically cleared */ -sbit __at 0x8F I2SRXIF; /* I2S RX interrupt flag. Automatically cleared */ -sbit __at 0x8D ADCIF; /* ADC interrupt flag. Automatically cleared */ -sbit __at 0x8B URX0IF; /* USART0 RX interrupt flag. Automatically cleared */ -sbit __at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleared */ +__sbit __at 0x8F URX1IF; /* USART1 RX interrupt flag. Automatically cleared */ +__sbit __at 0x8F I2SRXIF; /* I2S RX interrupt flag. Automatically cleared */ +__sbit __at 0x8D ADCIF; /* ADC interrupt flag. Automatically cleared */ +__sbit __at 0x8B URX0IF; /* USART0 RX interrupt flag. Automatically cleared */ +__sbit __at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleared */ #define TCON_URX1IF (1 << 7) #define TCON_I2SRXIF (1 << 7) @@ -152,8 +152,8 @@ sbit __at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically clea */ __sfr __at 0x98 S0CON; /* CPU Interrupt Flag 2 */ -sbit __at 0x98 ENCIF_0; /* AES interrupt 0. */ -sbit __at 0x99 ENCIF_1; /* AES interrupt 1. */ +__sbit __at 0x98 ENCIF_0; /* AES interrupt 0. */ +__sbit __at 0x99 ENCIF_1; /* AES interrupt 1. */ #define S0CON_ENCIF_1 (1 << 1) #define S0CON_ENCIF_0 (1 << 0) @@ -171,13 +171,13 @@ __sfr __at 0x9B S1CON; /* CPU Interrupt Flag 3 */ */ __sfr __at 0xC0 IRCON; /* CPU Interrupt Flag 4 */ -sbit __at 0xC0 DMAIF; /* DMA complete interrupt flag */ -sbit __at 0xC1 T1IF; /* Timer 1 interrupt flag. Automatically cleared */ -sbit __at 0xC2 T2IF; /* Timer 2 interrupt flag. Automatically cleared */ -sbit __at 0xC3 T3IF; /* Timer 3 interrupt flag. Automatically cleared */ -sbit __at 0xC4 T4IF; /* Timer 4 interrupt flag. Automatically cleared */ -sbit __at 0xC5 P0IF; /* Port0 interrupt flag */ -sbit __at 0xC7 STIF; /* Sleep Timer interrupt flag */ +__sbit __at 0xC0 DMAIF; /* DMA complete interrupt flag */ +__sbit __at 0xC1 T1IF; /* Timer 1 interrupt flag. Automatically cleared */ +__sbit __at 0xC2 T2IF; /* Timer 2 interrupt flag. Automatically cleared */ +__sbit __at 0xC3 T3IF; /* Timer 3 interrupt flag. Automatically cleared */ +__sbit __at 0xC4 T4IF; /* Timer 4 interrupt flag. Automatically cleared */ +__sbit __at 0xC5 P0IF; /* Port0 interrupt flag */ +__sbit __at 0xC7 STIF; /* Sleep Timer interrupt flag */ #define IRCON_DMAIF (1 << 0) /* DMA complete interrupt flag */ #define IRCON_T1IF (1 << 1) /* Timer 1 interrupt flag. Automatically cleared */ @@ -192,13 +192,13 @@ sbit __at 0xC7 STIF; /* Sleep Timer interrupt flag */ */ __sfr __at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */ -sbit __at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ -sbit __at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ -sbit __at 0xE9 UTX0IF; /* USART0 TX interrupt flag */ -sbit __at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */ -sbit __at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */ -sbit __at 0xEB P1IF; /* Port1 interrupt flag */ -sbit __at 0xEC WDTIF; /* Watchdog timer interrupt flag */ +__sbit __at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ +__sbit __at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ +__sbit __at 0xE9 UTX0IF; /* USART0 TX interrupt flag */ +__sbit __at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */ +__sbit __at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */ +__sbit __at 0xEB P1IF; /* Port1 interrupt flag */ +__sbit __at 0xEC WDTIF; /* Watchdog timer interrupt flag */ #define IRCON2_USBIF (1 << 0) /* USB interrupt flag (shared with Port2) */ #define IRCON2_P2IF (1 << 0) /* Port2 interrupt flag (shared with USB) */ @@ -679,33 +679,33 @@ __sfr __at 0x8C PICTL; /* GPIO pins */ __sfr __at 0x80 P0; -sbit __at 0x80 P0_0; -sbit __at 0x81 P0_1; -sbit __at 0x82 P0_2; -sbit __at 0x83 P0_3; -sbit __at 0x84 P0_4; -sbit __at 0x85 P0_5; -sbit __at 0x86 P0_6; -sbit __at 0x87 P0_7; +__sbit __at 0x80 P0_0; +__sbit __at 0x81 P0_1; +__sbit __at 0x82 P0_2; +__sbit __at 0x83 P0_3; +__sbit __at 0x84 P0_4; +__sbit __at 0x85 P0_5; +__sbit __at 0x86 P0_6; +__sbit __at 0x87 P0_7; __sfr __at 0x90 P1; -sbit __at 0x90 P1_0; -sbit __at 0x91 P1_1; -sbit __at 0x92 P1_2; -sbit __at 0x93 P1_3; -sbit __at 0x94 P1_4; -sbit __at 0x95 P1_5; -sbit __at 0x96 P1_6; -sbit __at 0x97 P1_7; +__sbit __at 0x90 P1_0; +__sbit __at 0x91 P1_1; +__sbit __at 0x92 P1_2; +__sbit __at 0x93 P1_3; +__sbit __at 0x94 P1_4; +__sbit __at 0x95 P1_5; +__sbit __at 0x96 P1_6; +__sbit __at 0x97 P1_7; __sfr __at 0xa0 P2; -sbit __at 0xa0 P2_0; -sbit __at 0xa1 P2_1; -sbit __at 0xa2 P2_2; -sbit __at 0xa3 P2_3; -sbit __at 0xa4 P2_4; +__sbit __at 0xa0 P2_0; +__sbit __at 0xa1 P2_1; +__sbit __at 0xa2 P2_2; +__sbit __at 0xa3 P2_3; +__sbit __at 0xa4 P2_4; /* DMA controller */ struct cc_dma_channel { diff --git a/src/core/ao.h b/src/core/ao.h index 8bd7a3d2..1fbcf7df 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -376,7 +376,7 @@ struct ao_cmds { }; void -ao_cmd_register(__code struct ao_cmds *cmds); +ao_cmd_register(const __code struct ao_cmds *cmds); void ao_cmd_init(void); @@ -1352,10 +1352,10 @@ void ao_radio_set_packet(void); void -ao_radio_send(__xdata void *data, uint8_t size) __reentrant; +ao_radio_send(__xdata void *d, uint8_t size) __reentrant; uint8_t -ao_radio_recv(__xdata void *data, uint8_t size) __reentrant; +ao_radio_recv(__xdata void *d, uint8_t size) __reentrant; void ao_radio_recv_abort(void); @@ -1708,7 +1708,7 @@ ao_companion_init(void); /* ao_lcd.c */ void -ao_lcd_putchar(uint8_t data); +ao_lcd_putchar(uint8_t d); void ao_lcd_putstring(char *string); @@ -1739,14 +1739,14 @@ ao_lcd_init(void); /* ao_lcd_port.c */ void -ao_lcd_port_put_nibble(uint8_t rs, uint8_t data); +ao_lcd_port_put_nibble(uint8_t rs, uint8_t d); void ao_lcd_port_init(void); /* ao_aes.c */ -__xdata uint8_t ao_aes_mutex; +extern __xdata uint8_t ao_aes_mutex; /* AES keys and blocks are 128 bits */ -- cgit v1.2.3 From 7a42f2e0f145d2d520aed8e241fa39f7cb62b19f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jan 2012 20:41:15 -0800 Subject: altos: Add support for UART0 in async mode And copy bytes from it to stdout. Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 7 ++ src/cc1111/ao_serial.c | 5 +- src/cc1111/ao_serial0.c | 152 +++++++++++++++++++++++++++++++++++ src/core/ao.h | 29 +++++++ src/teleshield-v0.1/Makefile | 4 +- src/teleshield-v0.1/ao_ardu_serial.c | 38 +++++++++ src/teleshield-v0.1/ao_pins.h | 8 ++ src/teleshield-v0.1/ao_teleshield.c | 1 + 8 files changed, 239 insertions(+), 5 deletions(-) create mode 100644 src/cc1111/ao_serial0.c create mode 100644 src/teleshield-v0.1/ao_ardu_serial.c (limited to 'src/core') diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index e6c27a1e..360b35c8 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -251,4 +251,11 @@ _ao_xmemcmp(__xdata void *a, __xdata void *b, uint8_t count); #define ao_xmemcmp(d,s,c) _ao_xmemcmp((d), (s), (c)) +struct ao_serial_speed { + uint8_t baud; + uint8_t gcr; +}; + +extern const __code struct ao_serial_speed ao_serial_speeds[]; + #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c index 82370c64..4d5b9abd 100644 --- a/src/cc1111/ao_serial.c +++ b/src/cc1111/ao_serial.c @@ -91,10 +91,7 @@ ao_serial_drain(void) __critical ao_sleep(&ao_usart1_tx_fifo); } -static __code struct { - uint8_t baud; - uint8_t gcr; -} ao_serial_speeds[] = { +const __code struct ao_serial_speed ao_serial_speeds[] = { /* [AO_SERIAL_SPEED_4800] = */ { /* .baud = */ 163, /* .gcr = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB diff --git a/src/cc1111/ao_serial0.c b/src/cc1111/ao_serial0.c new file mode 100644 index 00000000..140721b1 --- /dev/null +++ b/src/cc1111/ao_serial0.c @@ -0,0 +1,152 @@ +/* + * Copyright © 2009 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" + +volatile __xdata struct ao_fifo ao_usart0_rx_fifo; +volatile __xdata struct ao_fifo ao_usart0_tx_fifo; + +void +ao_serial0_rx0_isr(void) __interrupt 2 +{ + if (!ao_fifo_full(ao_usart0_rx_fifo)) + ao_fifo_insert(ao_usart0_rx_fifo, U0DBUF); + ao_wakeup(&ao_usart0_rx_fifo); +} + +static __xdata uint8_t ao_serial0_tx0_started; + +static void +ao_serial0_tx0_start(void) +{ + if (!ao_fifo_empty(ao_usart0_tx_fifo) && + !ao_serial0_tx0_started) + { + ao_serial0_tx0_started = 1; + ao_fifo_remove(ao_usart0_tx_fifo, U0DBUF); + } +} + +void +ao_serial0_tx0_isr(void) __interrupt 7 +{ + UTX0IF = 0; + ao_serial0_tx0_started = 0; + ao_serial0_tx0_start(); + ao_wakeup(&ao_usart0_tx_fifo); +} + +char +ao_serial0_getchar(void) __critical +{ + char c; + while (ao_fifo_empty(ao_usart0_rx_fifo)) + ao_sleep(&ao_usart0_rx_fifo); + ao_fifo_remove(ao_usart0_rx_fifo, c); + return c; +} + +#if USE_SERIAL_STDIN +char +ao_serial0_pollchar(void) __critical +{ + char c; + if (ao_fifo_empty(ao_usart0_rx_fifo)) + return AO_READ_AGAIN; + ao_fifo_remove(ao_usart0_rx_fifo,c); + return c; +} +#endif + +void +ao_serial0_putchar(char c) __critical +{ + while (ao_fifo_full(ao_usart0_tx_fifo)) + ao_sleep(&ao_usart0_tx_fifo); + ao_fifo_insert(ao_usart0_tx_fifo, c); + ao_serial0_tx0_start(); +} + +void +ao_serial0_drain(void) __critical +{ + while (!ao_fifo_empty(ao_usart0_tx_fifo)) + ao_sleep(&ao_usart0_tx_fifo); +} + +void +ao_serial0_set_speed(uint8_t speed) +{ + ao_serial0_drain(); + if (speed > AO_SERIAL_SPEED_57600) + return; + U1UCR |= UxUCR_FLUSH; + U1BAUD = ao_serial_speeds[speed].baud; + U1GCR = ao_serial_speeds[speed].gcr; +} + +void +ao_serial0_init(void) +{ +#if HAS_SERIAL_0_ALT_1 + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_1; + + P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART0_USART1; + + /* Make the USART pins be controlled by the USART */ + P0SEL |= (1 << 2) | (1 << 3); +#if HAS_SERIAL_0_HW_FLOW + P0SEL |= (1 << 4) | (1 << 5); +#endif +#else + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; + + P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI0P1_MASK)) | + (P2SEL_PRI3P1_USART0 | P2SEL_PRI0P1_USART0); + + /* Make the USART pins be controlled by the USART */ + P1SEL |= (1 << 2) | (1 << 3); +#if HAS_SERIAL_0_HW_FLOW + P1SEL |= (1 << 5) | (1 << 4); +#endif +#endif + + /* UART mode with receiver enabled */ + U0CSR = (UxCSR_MODE_UART | UxCSR_RE); + + /* Pick a 9600 baud rate */ + ao_serial0_set_speed(AO_SERIAL_SPEED_9600); + + /* Reasonable serial parameters */ + U0UCR = (UxUCR_FLUSH | +#if HAS_SERIAL_0_HW_FLOW + UxUCR_FLOW_ENABLE | +#else + UxUCR_FLOW_DISABLE | +#endif + UxUCR_D9_EVEN_PARITY | + UxUCR_BIT9_8_BITS | + UxUCR_PARITY_DISABLE | + UxUCR_SPB_1_STOP_BIT | + UxUCR_STOP_HIGH | + UxUCR_START_LOW); + + IEN0 |= IEN0_URX0IE; + IEN2 |= IEN2_UTX0IE; +} diff --git a/src/core/ao.h b/src/core/ao.h index 1fbcf7df..494993f1 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -938,6 +938,35 @@ void ao_serial_init(void); #endif +#ifndef HAS_SERIAL_0 +#define HAS_SERIAL_0 0 +#endif + +#if HAS_SERIAL_0 +void +ao_serial0_rx0_isr(void) ao_arch_interrupt(2); + +void +ao_serial0_tx0_isr(void) ao_arch_interrupt(7); + +char +ao_serial0_getchar(void) __critical; + +void +ao_serial0_putchar(char c) __critical; + +void +ao_serial0_drain(void) __critical; + +void +ao_serial0_set_speed(uint8_t speed); + +void +ao_serial0_init(void); + +#endif + + /* * ao_spi.c */ diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile index b63a81d6..a21a6052 100644 --- a/src/teleshield-v0.1/Makefile +++ b/src/teleshield-v0.1/Makefile @@ -53,6 +53,7 @@ CC1111_SRC = \ ao_radio.c \ ao_romconfig.c \ ao_serial.c \ + ao_serial0.c \ ao_string.c \ ao_timer.c \ ao_usb.c \ @@ -62,7 +63,8 @@ DRIVER_SRC = \ $(TELESHIELD_SRC) PRODUCT_SRC = \ - ao_teleshield.c + ao_teleshield.c \ + ao_ardu_serial.c SRC = \ $(CORE_SRC) \ diff --git a/src/teleshield-v0.1/ao_ardu_serial.c b/src/teleshield-v0.1/ao_ardu_serial.c new file mode 100644 index 00000000..7d4dc0db --- /dev/null +++ b/src/teleshield-v0.1/ao_ardu_serial.c @@ -0,0 +1,38 @@ +/* + * 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" + +static void +ao_ardu_serial_recv(void) +{ + char c; + + for (;;) { + c = ao_serial0_getchar(); + putchar (c); + } +} + +static __xdata struct ao_task ao_ardu_serial_recv_task; + +void +ao_ardu_serial_init (void) +{ + ao_serial0_init(); + ao_add_task(&ao_ardu_serial_recv_task, ao_ardu_serial_recv, "recv"); +} diff --git a/src/teleshield-v0.1/ao_pins.h b/src/teleshield-v0.1/ao_pins.h index 1f659739..a907e2a5 100644 --- a/src/teleshield-v0.1/ao_pins.h +++ b/src/teleshield-v0.1/ao_pins.h @@ -27,6 +27,10 @@ #define HAS_SERIAL_1_ALT_2 0 #define HAS_SERIAL_1_HW_FLOW 1 #define USE_SERIAL_STDIN 1 + #define HAS_SERIAL_0 1 + #define HAS_SERIAL_0_ALT_1 0 + #define HAS_SERIAL_0_ALT_2 1 + #define HAS_SERIAL_0_HW_FLOW 0 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 @@ -214,4 +218,8 @@ #define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) #define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) +void +ao_ardu_serial_init (void); + + #endif /* _AO_PINS_H_ */ diff --git a/src/teleshield-v0.1/ao_teleshield.c b/src/teleshield-v0.1/ao_teleshield.c index 3e07a955..fd12ce7a 100644 --- a/src/teleshield-v0.1/ao_teleshield.c +++ b/src/teleshield-v0.1/ao_teleshield.c @@ -43,6 +43,7 @@ main(void) ao_aes_init(); ao_radio_cmac_init(); #endif + ao_ardu_serial_init(); ao_config_init(); ao_start_scheduler(); } -- cgit v1.2.3 From c6821ae734a7efaf2e069f6c5edf9605a9dbe125 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jan 2012 20:46:25 -0800 Subject: altos: flush stdout when fifo from arduino serial port is empty This avoids leaving bytes pending inside altos Signed-off-by: Keith Packard --- src/core/ao.h | 4 ++++ src/teleshield-v0.1/ao_ardu_serial.c | 2 ++ 2 files changed, 6 insertions(+) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index 494993f1..8c5335c4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -943,6 +943,10 @@ ao_serial_init(void); #endif #if HAS_SERIAL_0 + +extern volatile __xdata struct ao_fifo ao_usart0_rx_fifo; +extern volatile __xdata struct ao_fifo ao_usart0_tx_fifo; + void ao_serial0_rx0_isr(void) ao_arch_interrupt(2); diff --git a/src/teleshield-v0.1/ao_ardu_serial.c b/src/teleshield-v0.1/ao_ardu_serial.c index 7d4dc0db..7ff859af 100644 --- a/src/teleshield-v0.1/ao_ardu_serial.c +++ b/src/teleshield-v0.1/ao_ardu_serial.c @@ -23,6 +23,8 @@ ao_ardu_serial_recv(void) char c; for (;;) { + if (ao_fifo_empty(ao_usart0_rx_fifo)) + flush(); c = ao_serial0_getchar(); putchar (c); } -- cgit v1.2.3 From c1d12a117b36de7fe8dd992959b890bfd1163e81 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Mar 2012 23:35:35 -0700 Subject: Do radio settings solely by frequency Compute the radio setting needed based on the calibration value provided and the requested frequency. Signed-off-by: Keith Packard --- src/core/ao.h | 8 ++++- src/core/ao_cmd.c | 6 ++-- src/core/ao_config.c | 68 ++++++++++++++++++++++------------------- src/core/ao_freq.c | 52 +++++++++++++++++++++++++++++++ src/product/Makefile.telebt | 3 +- src/product/Makefile.teledongle | 3 +- src/product/Makefile.telelaunch | 3 +- src/product/Makefile.telemetrum | 3 +- src/product/Makefile.telemini | 3 +- src/product/Makefile.telenano | 3 +- src/product/ao_terraui.c | 2 +- src/teleshield-v0.1/Makefile | 3 +- src/teleterra-v0.2/Makefile | 3 +- src/tidongle/Makefile | 3 +- 14 files changed, 117 insertions(+), 46 deletions(-) create mode 100644 src/core/ao_freq.c (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index 8c5335c4..ce9a1f70 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1539,7 +1539,6 @@ ao_igniter_init(void); struct ao_radio_channel { char name[AO_CHANNEL_NAME_LEN]; uint32_t kHz; - uint32_t radio_setting; }; #endif @@ -1559,6 +1558,7 @@ struct ao_config { uint32_t radio_setting; /* minor version 7 */ uint8_t radio_enable; /* minor version 8 */ uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */ + uint32_t frequency; /* minor version 10 */ #if HAS_RADIO_CHANNELS struct ao_radio_channel radio_channels[AO_NUM_CHANNELS]; /* minor version 10 */ #endif @@ -1959,4 +1959,10 @@ ao_battery_init(void); uint32_t ao_sqrt(uint32_t op); +/* + * ao_freq.c + */ + +int32_t ao_freq_to_set(int32_t freq, int32_t cal); + #endif /* _AO_H_ */ diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 14cb7569..cde68b39 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -263,9 +263,9 @@ static __pdata uint8_t ao_ncmds; static void help(void) { - register uint8_t cmds; - register uint8_t cmd; - register __code struct ao_cmds * cs; + __pdata uint8_t cmds; + __pdata uint8_t cmd; + __code struct ao_cmds * __pdata cs; for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 86bbc473..6fcebe1e 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -64,6 +64,12 @@ ao_config_put(void) } #endif +static void +ao_config_set_radio(void) +{ + ao_config.radio_setting = ao_freq_to_set(ao_config.frequency, ao_config.radio_cal); +} + static void _ao_config_get(void) { @@ -105,24 +111,23 @@ _ao_config_get(void) ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; if (ao_config.minor < 6) ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; - if (ao_config.minor < 7) - ao_config.radio_setting = ao_config.radio_cal; if (ao_config.minor < 8) ao_config.radio_enable = TRUE; if (ao_config.minor < 9) memset(&ao_config.aes_key, 0, AO_AES_LEN); -#if HAS_RADIO_CHANNELS if (ao_config.minor < 10) { + ao_config.frequency = 434550; +#if HAS_RADIO_CHANNELS ao_xmemset(&ao_config.radio_channels, '\0', sizeof (ao_config.radio_channels)); ao_xmemcpy(&ao_config.radio_channels[0].name[0], CODE_TO_XDATA("Channel 0"), sizeof("Channel 0")); ao_config.radio_channels[0].kHz = 434550; - ao_config.radio_channels[0].radio_setting = ao_config.radio_cal; - } #endif + } ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } + ao_config_set_radio(); ao_config_loaded = 1; } @@ -196,6 +201,26 @@ ao_config_radio_channel_set(void) __reentrant ao_radio_recv_abort(); } +void +ao_config_frequency_show(void) __reentrant +{ + printf("Frequency: %ld\n", + ao_config.frequency); +} + +void +ao_config_frequency_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.frequency = ao_cmd_lex_u32; + ao_config_set_radio(); + _ao_config_edit_finish(); + ao_radio_recv_abort(); +} + #if HAS_ADC void @@ -315,7 +340,8 @@ ao_config_radio_cal_set(void) __reentrant if (ao_cmd_status != ao_cmd_success) return; _ao_config_edit_start(); - ao_config.radio_setting = ao_config.radio_cal = ao_cmd_lex_u32; + ao_config.radio_cal = ao_cmd_lex_u32; + ao_config_set_radio(); _ao_config_edit_finish(); } @@ -394,25 +420,6 @@ ao_config_pad_orientation_set(void) __reentrant } #endif -void -ao_config_radio_setting_show(void) __reentrant -{ - printf("Radio setting: %ld\n", ao_config.radio_setting); -} - -void -ao_config_radio_setting_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.radio_setting = ao_cmd_lex_u32; - ao_config.radio_channel = 0; - _ao_config_edit_finish(); - ao_radio_recv_abort(); -} - void ao_config_radio_enable_show(void) __reentrant { @@ -464,11 +471,10 @@ ao_config_radio_config_show(void) __reentrant uint8_t i; for (i = 0; i < AO_NUM_CHANNELS; i++) if (ao_config.radio_channels[i].name[0]) { - printf("%2d %-16.16s %ld %ld\n", + printf("%2d %-16.16s %ld\n", i, ao_config.radio_channels[i].name, - ao_config.radio_channels[i].kHz, - ao_config.radio_channels[i].radio_setting); + ao_config.radio_channels[i].kHz); } } @@ -498,8 +504,6 @@ ao_config_radio_config_set(void) __reentrant } ao_cmd_decimal(); ch->kHz = ao_cmd_lex_u32; - ao_cmd_decimal(); - ch->radio_setting = ao_cmd_lex_u32; _ao_config_edit_finish(); } #endif @@ -528,10 +532,10 @@ __code struct ao_config_var ao_config_vars[] = { #endif /* HAS_ADC */ { "r \0Radio channel (freq = 434.550 + chan * .1)", ao_config_radio_channel_set, ao_config_radio_channel_show }, + { "F \0Frequency (kHz)", + ao_config_frequency_set, ao_config_frequency_show }, { "c \0Callsign (8 char max)", ao_config_callsign_set, ao_config_callsign_show }, - { "R \0Radio freq control (freq = 434.550 * setting/cal)", - ao_config_radio_setting_set, ao_config_radio_setting_show }, { "e <0 disable, 1 enable>\0Enable telemetry and RDF", ao_config_radio_enable_set, ao_config_radio_enable_show }, #if HAS_ACCEL diff --git a/src/core/ao_freq.c b/src/core/ao_freq.c new file mode 100644 index 00000000..13bcb383 --- /dev/null +++ b/src/core/ao_freq.c @@ -0,0 +1,52 @@ +/* + * 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 + +/* + * The provided 'calibration' value is + * that needed to tune the radio to precisely 434550kHz. + * Use that to 'walk' to the target frequency by following + * a 'bresenham' line from 434550kHz to the target + * frequency, and updating the radio setting along the way + */ + +int32_t ao_freq_to_set(int32_t freq, int32_t cal) { + __pdata int32_t set = 0; + uint8_t neg = 0; + __pdata int32_t error = -434550 / 2; + + freq -= 434550; + if (freq < 0) { + neg = 1; + freq = -freq; + } + for (;;) { + if (freq == 0 && error <= 0) + break; + if (error > 0) { + error -= 434550; + set++; + } else { + error += cal; + freq--; + } + } + if (neg) + set = -set; + return cal + set; +} diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index ea18ff18..e53aa2c4 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -28,7 +28,8 @@ CORE_SRC = \ ao_panic.c \ ao_state.c \ ao_stdio.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_aes.c \ diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index cf33d1f1..27e7d24b 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -31,7 +31,8 @@ CORE_SRC = \ ao_rssi.c \ ao_state.c \ ao_stdio.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_aes.c \ diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 97764517..8aab50e0 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -27,7 +27,8 @@ CORE_SRC = \ ao_panic.c \ ao_stdio.c \ ao_storage.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_adc.c \ diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index 52c723ca..e4f55f88 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -40,7 +40,8 @@ CORE_SRC = \ ao_log.c \ ao_log_big.c \ ao_report.c \ - ao_telemetry.c + ao_telemetry.c \ + ao_freq.c CC1111_SRC = \ ao_adc.c \ diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 75beeae4..82ec42a2 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -33,7 +33,8 @@ CORE_SRC = \ ao_stdio.c \ ao_storage.c \ ao_task.c \ - ao_telemetry.c + ao_telemetry.c \ + ao_freq.c CC1111_SRC = \ ao_adc.c \ diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index b30ca789..cf27527c 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -33,7 +33,8 @@ CORE_SRC = \ ao_stdio.c \ ao_storage.c \ ao_task.c \ - ao_telemetry.c + ao_telemetry.c \ + ao_freq.c CC1111_SRC = \ ao_adc.c \ diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 05157cb1..9b40c42a 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -459,7 +459,7 @@ ao_terraui_config(void) __reentrant for (chan = 0; chan < AO_NUM_CHANNELS; chan++) - if (ao_config.radio_channels[chan].radio_setting == ao_config.radio_setting) + if (ao_config.radio_channels[chan].kHz == ao_config.frequency) break; if (chan == AO_NUM_CHANNELS) chan = 0; diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile index a21a6052..44780476 100644 --- a/src/teleshield-v0.1/Makefile +++ b/src/teleshield-v0.1/Makefile @@ -41,7 +41,8 @@ CORE_SRC = \ ao_state.c \ ao_storage.c \ ao_stdio.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_dbg.c \ diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 0747bfbf..4967d187 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -28,7 +28,8 @@ CORE_SRC = \ ao_sqrt.c \ ao_stdio.c \ ao_storage.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_battery.c \ diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index 698d612c..149b00c5 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -26,7 +26,8 @@ CORE_SRC = \ ao_rssi.c \ ao_state.c \ ao_stdio.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_aes.c \ -- cgit v1.2.3 From 7dd1d62676c1e605fe69a4c0acfe7638c6b79aa5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Mar 2012 18:19:05 -0700 Subject: altos: Optimize ao_freq_to_set a bit Reduces size from 327 bytes to 287 bytes Signed-off-by: Keith Packard --- src/core/ao_freq.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_freq.c b/src/core/ao_freq.c index 13bcb383..67b0b037 100644 --- a/src/core/ao_freq.c +++ b/src/core/ao_freq.c @@ -30,20 +30,18 @@ int32_t ao_freq_to_set(int32_t freq, int32_t cal) { uint8_t neg = 0; __pdata int32_t error = -434550 / 2; - freq -= 434550; - if (freq < 0) { + if ((freq -= 434550) < 0) { neg = 1; freq = -freq; } for (;;) { - if (freq == 0 && error <= 0) - break; if (error > 0) { error -= 434550; set++; } else { error += cal; - freq--; + if (--freq < 0) + break; } } if (neg) -- cgit v1.2.3 From b6c7ae2c1f8cba7351cd139c49322280d9d3af47 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Mar 2012 22:53:08 -0700 Subject: altos: Reset config version if it's too large as well Any future config values will get trashed if we down grade the firmware, so we must reset the firmware version whenever it gets written. Signed-off-by: Keith Packard --- src/core/ao_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 6fcebe1e..350ebcbe 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -91,7 +91,7 @@ _ao_config_get(void) sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config_dirty = 1; } - if (ao_config.minor < AO_CONFIG_MINOR) { + if (ao_config.minor != AO_CONFIG_MINOR) { /* Fixups for minor version 1 */ if (ao_config.minor < 1) ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; -- cgit v1.2.3 From d60862fce6ac27a97ad6337eea32a4b48645d158 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Mar 2012 00:38:37 -0700 Subject: altos: Make sure config values are loaded in 'c s' command ao_config_get may not have been called when ao_config_show is invoked by the user, so make sure the config values are loaded before showing uninitialized data. Signed-off-by: Keith Packard --- src/core/ao_config.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/core') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 350ebcbe..08e6deea 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -609,6 +609,7 @@ static void ao_config_show(void) __reentrant { uint8_t cmd; + ao_config_get(); printf("Config version: %d.%d\n", ao_config.major, ao_config.minor); for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) -- cgit v1.2.3 From 3c7d1f6cfffb43299041f2850a48177f4e9b83a5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 Feb 2012 23:26:03 +1300 Subject: 'stdin' is a special name in some compiler environments, don't use it. Switch to 'in' in the prototype for altos_serial_set_stdin. Signed-off-by: Keith Packard --- src/core/ao.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index ce9a1f70..ac51c270 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -917,7 +917,7 @@ char ao_serial_pollchar(void) __critical; void -ao_serial_set_stdin(uint8_t stdin); +ao_serial_set_stdin(uint8_t in); #endif void -- cgit v1.2.3 From 93481fd3d9305a107b88c8a64de4194a6d94dc0e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:05:46 -0700 Subject: Incorrect type in ao_task_info for wchan Would truncate 32-bit pointers on arm. Signed-off-by: Keith Packard --- src/core/ao_task.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao_task.c b/src/core/ao_task.c index a19a6a6f..d7d0e8a2 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -164,7 +164,7 @@ ao_task_info(void) task = ao_tasks[i]; printf("%12s: wchan %04x\n", task->name, - (int16_t) task->wchan); + (int) task->wchan); } } -- cgit v1.2.3 From 4bfce11873f34af9621c60f83a8355f85769f6d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:07:07 -0700 Subject: When debugging, send pre-init output to ao_debug_out Before tasking is running, send output to ao_debug_out to help debug system initialization. Signed-off-by: Keith Packard --- src/core/ao_stdio.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/core') diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index c0138a30..2967e705 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -30,6 +30,15 @@ __pdata int8_t ao_num_stdios; void putchar(char c) { +#if LOW_LEVEL_DEBUG + if (!ao_cur_task) { + extern void ao_debug_out(char c); + if (c == '\n') + ao_debug_out('\r'); + ao_debug_out(c); + return; + } +#endif if (c == '\n') (*ao_stdios[ao_cur_stdio].putchar)('\r'); (*ao_stdios[ao_cur_stdio].putchar)(c); -- cgit v1.2.3 From 1ca46760cf903860dccb4864578558a1abb6e0fa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:08:48 -0700 Subject: When debugging, send ao_panic message to ao_debug_out Use the low-level debug hooks to get the panic state sent to the serial port. Signed-off-by: Keith Packard --- src/core/ao_panic.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/core') diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index 244917a8..25dc145e 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -45,6 +45,10 @@ ao_panic(uint8_t reason) { uint8_t n; +#if LOW_LEVEL_DEBUG + ao_cur_task = NULL; + printf ("panic %d\n", reason); +#endif __critical for (;;) { ao_panic_delay(20); for (n = 0; n < 5; n++) { -- cgit v1.2.3 From 0cc01d378ae96325e429ad608b953661582939b0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:09:20 -0700 Subject: Add AO_PANIC_STACK Provide a panic code for stack overflow. Signed-off-by: Keith Packard --- src/core/ao.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index ac51c270..86a943a8 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -113,6 +113,7 @@ ao_start_scheduler(void); #define AO_PANIC_FLASH 9 /* Invalid flash part (or wrong blocksize) */ #define AO_PANIC_USB 10 /* Trying to send USB packet while busy */ #define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ +#define AO_PANIC_STACK 12 /* Stack overflow */ /* Stop the operating system, beeping and blinking the reason */ void -- cgit v1.2.3 From bf060b3e3ed655bbb8464f342d0a0b1745a06173 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:01:50 -0700 Subject: Allow for more than one serial port in core AltOS Signed-off-by: Keith Packard --- src/core/ao.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index 86a943a8..b2f3305f 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -899,7 +899,7 @@ ao_dbg_init(void); #error Please define HAS_SERIAL_1 #endif -#if HAS_SERIAL_1 +#if HAS_SERIAL_1 | HAS_SERIAL_2 | HAS_SERIAL_3 #ifndef USE_SERIAL_STDIN #error Please define USE_SERIAL_STDIN #endif -- cgit v1.2.3 From 25184baa36c20e3d661f94e642a33e8aae179d60 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:40:09 -0700 Subject: Allow for more than 8 LEDs Provide hook for architecture-specific LED mask (AO_LED_TYPE) Signed-off-by: Keith Packard --- src/core/ao.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index b2f3305f..c9f17dc0 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -258,29 +258,33 @@ ao_beep_init(void); #define AO_LED_NONE 0 +#ifndef AO_LED_TYPE +#define AO_LED_TYPE uint8_t +#endif + /* Turn on the specified LEDs */ void -ao_led_on(uint8_t colors); +ao_led_on(AO_LED_TYPE colors); /* Turn off the specified LEDs */ void -ao_led_off(uint8_t colors); +ao_led_off(AO_LED_TYPE colors); /* Set all of the LEDs to the specified state */ void -ao_led_set(uint8_t colors); +ao_led_set(AO_LED_TYPE colors); /* Toggle the specified LEDs */ void -ao_led_toggle(uint8_t colors); +ao_led_toggle(AO_LED_TYPE colors); /* Turn on the specified LEDs for the indicated interval */ void -ao_led_for(uint8_t colors, uint16_t ticks) __reentrant; +ao_led_for(AO_LED_TYPE colors, uint16_t ticks) __reentrant; /* Initialize the LEDs */ void -ao_led_init(uint8_t enable); +ao_led_init(AO_LED_TYPE enable); /* * ao_usb.c -- cgit v1.2.3 From 1f2b75518169c4f2da9762de46bf1d9a71a04d17 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Mar 2012 21:54:32 -0700 Subject: altos: Move cc1111 DMA engine interface to cc1111/ao_arch.h from ao.h It's hardware specific Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 36 ++++++++++++++++++++++++++++++++++++ src/core/ao.h | 36 ------------------------------------ 2 files changed, 36 insertions(+), 36 deletions(-) (limited to 'src/core') diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 360b35c8..847ac1a6 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -258,4 +258,40 @@ struct ao_serial_speed { extern const __code struct ao_serial_speed ao_serial_speeds[]; +/* + * ao_dma.c + */ + +/* Allocate a DMA channel. the 'done' parameter will be set when the + * dma is finished and will be used to wakeup any waiters + */ + +uint8_t +ao_dma_alloc(__xdata uint8_t * done); + +/* Setup a DMA channel */ +void +ao_dma_set_transfer(uint8_t id, + void __xdata *srcaddr, + void __xdata *dstaddr, + uint16_t count, + uint8_t cfg0, + uint8_t cfg1); + +/* Start a DMA channel */ +void +ao_dma_start(uint8_t id); + +/* Manually trigger a DMA channel */ +void +ao_dma_trigger(uint8_t id); + +/* Abort a running DMA transfer */ +void +ao_dma_abort(uint8_t id); + +/* DMA interrupt routine */ +void +ao_dma_isr(void) ao_arch_interrupt(8); + #endif /* _AO_ARCH_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index c9f17dc0..8263a529 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -394,42 +394,6 @@ uint8_t ao_cmd_filter(void); #endif -/* - * ao_dma.c - */ - -/* Allocate a DMA channel. the 'done' parameter will be set when the - * dma is finished and will be used to wakeup any waiters - */ - -uint8_t -ao_dma_alloc(__xdata uint8_t * done); - -/* Setup a DMA channel */ -void -ao_dma_set_transfer(uint8_t id, - void __xdata *srcaddr, - void __xdata *dstaddr, - uint16_t count, - uint8_t cfg0, - uint8_t cfg1); - -/* Start a DMA channel */ -void -ao_dma_start(uint8_t id); - -/* Manually trigger a DMA channel */ -void -ao_dma_trigger(uint8_t id); - -/* Abort a running DMA transfer */ -void -ao_dma_abort(uint8_t id); - -/* DMA interrupt routine */ -void -ao_dma_isr(void) ao_arch_interrupt(8); - /* * ao_mutex.c */ -- cgit v1.2.3 From cf1e4d60e1fcd75fa734365a2666ea8930938128 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Apr 2012 22:58:54 -0700 Subject: altos: Move SPI functions to architecture-specific location Some architecture specific stuff needs to use core altos code, so create new ao_arch_funcs.h files per architecture that get pulled in at the end of ao.h Signed-off-by: Keith Packard --- src/avr/ao_arch_funcs.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++ src/cc1111/ao_arch_funcs.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++ src/core/ao.h | 43 ++-------------------------------- src/stm/ao_arch_funcs.h | 35 ++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 41 deletions(-) create mode 100644 src/avr/ao_arch_funcs.h create mode 100644 src/cc1111/ao_arch_funcs.h create mode 100644 src/stm/ao_arch_funcs.h (limited to 'src/core') diff --git a/src/avr/ao_arch_funcs.h b/src/avr/ao_arch_funcs.h new file mode 100644 index 00000000..9ad14fbb --- /dev/null +++ b/src/avr/ao_arch_funcs.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. + */ + +/* + * 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; + +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_init(void); + diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h new file mode 100644 index 00000000..9ad14fbb --- /dev/null +++ b/src/cc1111/ao_arch_funcs.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. + */ + +/* + * 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; + +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_init(void); + diff --git a/src/core/ao.h b/src/core/ao.h index 8263a529..080cadb2 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -940,47 +940,6 @@ ao_serial0_init(void); #endif -/* - * 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; - -void -ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; - -void -ao_spi_init(void); - /* * ao_spi_slave.c */ @@ -1934,4 +1893,6 @@ ao_sqrt(uint32_t op); int32_t ao_freq_to_set(int32_t freq, int32_t cal); +#include + #endif /* _AO_H_ */ diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h new file mode 100644 index 00000000..9b68f19a --- /dev/null +++ b/src/stm/ao_arch_funcs.h @@ -0,0 +1,35 @@ +/* + * 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_ARCH_FUNCS_H_ +#define _AO_ARCH_FUNCS_H_ + +extern uint8_t ao_spi_mutex[STM_NUM_SPI]; + +static inline void ao_spi_get(uint8_t spi_index) { ao_mutex_get(&ao_spi_mutex[spi_index]); } +static inline void ao_spi_put(uint8_t spi_index) { ao_mutex_put(&ao_spi_mutex[spi_index]); } + +void +ao_spi_send(void *block, uint16_t len, uint8_t spi_index); + +void +ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); + +void +ao_spi_init(uint8_t spi_index); + +#endif /* _AO_ARCH_FUNCS_H_ */ -- cgit v1.2.3 From 9b12bc445fe482306e4587ad60c6d2daf65a60f3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Apr 2012 18:07:07 -0700 Subject: altos: Add DMA, SPI and MS5607 drivers Signed-off-by: Keith Packard --- src/core/ao.h | 7 ++ src/drivers/ao_ms5607.c | 164 ++++++++++++++++++++++++ src/drivers/ao_ms5607.h | 38 ++++++ src/megametrum-v0.1/Makefile | 7 +- src/megametrum-v0.1/ao_megametrum.c | 3 + src/megametrum-v0.1/ao_pins.h | 5 +- src/stm-demo/Makefile | 5 +- src/stm-demo/ao_demo.c | 79 +++++++++++- src/stm-demo/ao_pins.h | 5 + src/stm/ao_arch_funcs.h | 28 ++++- src/stm/ao_dma_stm.c | 99 +++++++++++++++ src/stm/ao_spi_stm.c | 240 ++++++++++++++++++++++++++++++++++++ src/stm/stm32l.h | 180 ++++++++++++++++++++++++++- 13 files changed, 847 insertions(+), 13 deletions(-) create mode 100644 src/drivers/ao_ms5607.c create mode 100644 src/drivers/ao_ms5607.h create mode 100644 src/stm/ao_dma_stm.c create mode 100644 src/stm/ao_spi_stm.c (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index 080cadb2..67efa437 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -114,6 +114,7 @@ ao_start_scheduler(void); #define AO_PANIC_USB 10 /* Trying to send USB packet while busy */ #define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ #define AO_PANIC_STACK 12 /* Stack overflow */ +#define AO_PANIC_SPI 13 /* SPI communication failure */ /* Stop the operating system, beeping and blinking the reason */ void @@ -1895,4 +1896,10 @@ int32_t ao_freq_to_set(int32_t freq, int32_t cal); #include +/* + * ao_ms5607.c + */ + +void ao_ms5607_init(void); + #endif /* _AO_H_ */ diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c new file mode 100644 index 00000000..970fea1e --- /dev/null +++ b/src/drivers/ao_ms5607.c @@ -0,0 +1,164 @@ +/* + * 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 "ao_ms5607.h" + +#define AO_MS5607_CS_GPIO stm_gpioc +#define AO_MS5607_CS 4 +#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) +#define AO_MS5607_SPI_INDEX (STM_SPI_INDEX(1)) + +struct ms5607_prom { + uint16_t reserved; + uint16_t sens; + uint16_t off; + uint16_t tcs; + uint16_t tco; + uint16_t tref; + uint16_t tempsens; + uint16_t crc; +}; + +static struct ms5607_prom ms5607_prom; + +static void +ao_ms5607_start(void) { + ao_spi_get(AO_MS5607_SPI_INDEX); + stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 0); +} + +static void +ao_ms5607_stop(void) { + stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); + ao_spi_put(AO_MS5607_SPI_INDEX); +} + +static void +ao_ms5607_reset(void) { + uint8_t cmd; + + cmd = AO_MS5607_RESET; + ao_ms5607_start(); + ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_ms5607_stop(); +} + +static uint16_t +ao_ms5607_prom_read(uint8_t addr) +{ + uint8_t cmd = AO_MS5607_PROM_READ(addr); + uint8_t d[2]; + + ao_ms5607_start(); + ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_spi_recv(d, 2, AO_MS5607_SPI_INDEX); + ao_ms5607_stop(); + return ((uint16_t) d[0] << 8) | (uint16_t) d[1]; +} + +static void +ao_ms5607_init_chip(void) { + uint8_t addr; + uint16_t *prom; + ao_ms5607_reset(); + prom = &ms5607_prom.reserved; + + for (addr = 0; addr <= 7; addr++) + prom[addr] = ao_ms5607_prom_read(addr); +} + +static uint32_t +ao_ms5607_convert(uint8_t cmd) { + uint8_t reply[3]; + uint8_t read; + + ao_ms5607_start(); + ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_ms5607_stop(); + + ao_delay(AO_MS_TO_TICKS(200)); + + ao_ms5607_start(); + read = AO_MS5607_ADC_READ; + ao_spi_send(&read, 1, AO_MS5607_SPI_INDEX); + ao_spi_recv(&reply, 3, AO_MS5607_SPI_INDEX); + ao_ms5607_stop(); + + return ((uint32_t) reply[0] << 16) | ((uint32_t) reply[1] << 8) | (uint32_t) reply[2]; +} + +static void +ao_ms5607_dump(void) +{ + uint8_t addr; + uint32_t d1, d2; + int32_t dT; + int32_t TEMP; + int64_t OFF; + int64_t SENS; + int32_t P; + + ao_ms5607_init_chip(); + printf ("reserved: %d\n", ms5607_prom.reserved); + printf ("sens: %d\n", ms5607_prom.sens); + printf ("off: %d\n", ms5607_prom.off); + printf ("tcs: %d\n", ms5607_prom.tcs); + printf ("tco: %d\n", ms5607_prom.tco); + printf ("tref: %d\n", ms5607_prom.tref); + printf ("tempsens: %d\n", ms5607_prom.tempsens); + printf ("crc: %d\n", ms5607_prom.crc); + d1 = ao_ms5607_convert(AO_MS5607_CONVERT_D1_4096); + printf ("Conversion D1: %d\n", d1); + d2 = ao_ms5607_convert(AO_MS5607_CONVERT_D2_4096); + printf ("Conversion D2: %d\n", d2); + + dT = d2 - ((int32_t) ms5607_prom.tref << 8); + + TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23); + + OFF = ((int64_t) ms5607_prom.off << 17) + (((int64_t) ms5607_prom.tco * dT) >> 6); + + SENS = ((int64_t) ms5607_prom.sens << 16) + (((int64_t) ms5607_prom.tcs * dT) >> 7); + + if (TEMP < 2000) { + int32_t T2 = ((int64_t) dT * (int64_t) dT) >> 31; + int32_t TEMPM = TEMP - 2000; + int64_t OFF2 = (61 * (int64_t) TEMPM * (int64_t) TEMPM) >> 4; + int64_t SENS2 = 2 * (int64_t) TEMPM * (int64_t) TEMPM; + } + + P = ((((int64_t) d1 * SENS) >> 21) - OFF) >> 15; + + printf ("Temperature: %d", TEMP); + printf ("Pressure %d\n", P); +} + +__code struct ao_cmds ao_ms5607_cmds[] = { + { ao_ms5607_dump, "p\0Display MS5607 data" }, + { 0, NULL }, +}; + +void +ao_ms5607_init(void) +{ + ao_cmd_register(&ao_ms5607_cmds[0]); + + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); + stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); + stm_moder_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, STM_MODER_OUTPUT); +} diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h new file mode 100644 index 00000000..6c245368 --- /dev/null +++ b/src/drivers/ao_ms5607.h @@ -0,0 +1,38 @@ +/* + * 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_MS5607_H_ +#define _AO_MS5607_H_ + +#define AO_MS5607_RESET 0x1e + +#define AO_MS5607_CONVERT_D1_256 0x40 +#define AO_MS5607_CONVERT_D1_512 0x42 +#define AO_MS5607_CONVERT_D1_1024 0x44 +#define AO_MS5607_CONVERT_D1_2048 0x46 +#define AO_MS5607_CONVERT_D1_4096 0x48 + +#define AO_MS5607_CONVERT_D2_256 0x50 +#define AO_MS5607_CONVERT_D2_512 0x52 +#define AO_MS5607_CONVERT_D2_1024 0x54 +#define AO_MS5607_CONVERT_D2_2048 0x56 +#define AO_MS5607_CONVERT_D2_4096 0x58 + +#define AO_MS5607_ADC_READ 0x00 +#define AO_MS5607_PROM_READ(ad) 0xA0 | ((ad) << 1) + +#endif /* _AO_MS5607_H_ */ diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 23160d9b..fbcb4a57 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -31,13 +31,16 @@ ALTOS_SRC = \ ao_serial_stm.c \ ao_gps_skytraq.c \ ao_cc1120.c \ - ao_freq.c + ao_freq.c \ + ao_dma_stm.c \ + ao_spi_stm.c \ + ao_ms5607.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -O0 -g PROG=megametrum-v0.1-$(VERSION).elf diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 6bf43cb1..0d88f4c1 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -29,6 +29,9 @@ main(void) ao_cmd_init(); ao_gps_init(); ao_config_init(); + ao_dma_init(); + ao_spi_init(); + ao_ms5607_init(); ao_start_scheduler(); return 0; diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index dadeb380..ee4510e6 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -42,10 +42,13 @@ #define HAS_BEEP 0 #define HAS_SPI_1 1 -#define SPI_1_PE13_PE14_PE15 1 +#define SPI_1_PA5_PA6_PA7 1 +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_PE13_PE14_PE15 0 #define HAS_SPI_2 1 #define SPI_2_PB13_PB14_PB15 1 +#define SPI_2_PD1_PD3_PD4 0 #define HAS_I2C_1 1 #define I2C_1_PB8_PB9 1 diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 366291c6..c1f49371 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -26,7 +26,10 @@ ALTOS_SRC = \ ao_timer.c \ ao_serial_stm.c \ ao_lcd_stm.c \ - ao_lcd_font.c + ao_lcd_font.c \ + ao_mutex.c \ + ao_dma_stm.c \ + ao_spi_stm.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 544f261f..54f7c8f2 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -50,6 +50,71 @@ void _lseek() { } void _exit () { } void _read () { } void _fstat() { } + +static void +ao_dma_test(void) { + static char src[20] = "hello, world"; + static char dst[20]; + + dst[0] = '\0'; + ao_dma_set_transfer(STM_DMA_INDEX(1), dst, src, 13, + (1 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_LOW << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (1 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + ao_dma_start(STM_DMA_INDEX(1)); + cli(); + while (!ao_dma_done[STM_DMA_INDEX(1)]) + ao_sleep(&ao_dma_done[STM_DMA_INDEX(1)]); + sei(); + printf ("copied %s\n", dst); +} + +static void +ao_spi_write(void) { + unsigned char data[] = { 0x55, 0xaa, 0xff, 0x00 }; + int i; + + for (i = 0; i < 10; i++) { + ao_spi_get(0); + stm_gpio_set(&stm_gpioc, 12, 0); + ao_spi_send(data, 1, 0); + stm_gpio_set(&stm_gpioc, 12, 1); + ao_spi_put(0); + printf("."); + flush(); + ao_delay(100); + } +} + +static void +ao_spi_read(void) { + unsigned char data[4]; + int i; + + for (i = 0; i < 10; i++) { + ao_spi_get(0); + stm_gpio_set(&stm_gpioc, 12, 0); + ao_spi_recv(data, 4, 0); + printf("."); + flush(); + stm_gpio_set(&stm_gpioc, 12, 1); + ao_spi_put(0); + ao_delay(100); + } +} + +__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" }, + { 0, NULL } +}; + int main(void) { @@ -57,11 +122,19 @@ main(void) ao_serial_init(); ao_timer_init(); + ao_dma_init(); ao_cmd_init(); - ao_lcd_stm_init(); - ao_lcd_font_init(); - ao_add_task(&demo_task, ao_demo, "demo"); +// ao_lcd_stm_init(); +// ao_lcd_font_init(); + ao_spi_init(); + + ao_cmd_register(&ao_demo_cmds[0]); + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); + stm_gpio_set(&stm_gpioc, 12, 1); + stm_moder_set(&stm_gpioc, 12, STM_MODER_OUTPUT); + stm_otyper_set(&stm_gpioc, 12, STM_OTYPER_PUSH_PULL); + ao_start_scheduler(); return 0; } diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 798a292e..09c88f90 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -34,6 +34,11 @@ #define SERIAL_3_PC10_PC11 0 #define SERIAL_3_PD8_PD9 1 +#define HAS_SPI_1 1 +#define SPI_1_PB3_PB4_PB5 1 + +#define HAS_SPI_2 0 + #define HAS_USB 0 #define HAS_BEEP 0 #define PACKET_HAS_SLAVE 0 diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 9b68f19a..29e3f42f 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -18,6 +18,8 @@ #ifndef _AO_ARCH_FUNCS_H_ #define _AO_ARCH_FUNCS_H_ +/* ao_spi_stm.c + */ extern uint8_t ao_spi_mutex[STM_NUM_SPI]; static inline void ao_spi_get(uint8_t spi_index) { ao_mutex_get(&ao_spi_mutex[spi_index]); } @@ -30,6 +32,30 @@ void ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); void -ao_spi_init(uint8_t spi_index); +ao_spi_init(void); + +/* ao_dma_stm.c + */ + +extern uint8_t ao_dma_done[STM_NUM_DMA]; + +void +ao_dma_set_transfer(uint8_t index, + volatile void *peripheral, + void *memory, + uint16_t count, + uint32_t ccr); + +void +ao_dma_start(uint8_t index); + +void +ao_dma_done_transfer(uint8_t index); + +void +ao_dma_abort(uint8_t index); + +void +ao_dma_init(void); #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c new file mode 100644 index 00000000..70b9e48a --- /dev/null +++ b/src/stm/ao_dma_stm.c @@ -0,0 +1,99 @@ +/* + * 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 "ao.h" + +#define NUM_DMA 7 + +struct ao_dma_config { + uint32_t isr; +}; + +uint8_t ao_dma_done[NUM_DMA]; + +static struct ao_dma_config ao_dma_config[NUM_DMA]; +static uint8_t ao_dma_mutex[NUM_DMA]; + +static void +ao_dma_isr(uint8_t index) { + /* Get channel interrupt bits */ + uint32_t isr = stm_dma.isr & (STM_DMA_ISR_MASK << + STM_DMA_ISR(index)); + + /* Ack them */ + stm_dma.ifcr = isr; + isr >>= STM_DMA_ISR(index); + ao_dma_config[index].isr |= isr; + ao_dma_done[index] = 1; + ao_wakeup(&ao_dma_done[index]); +} + +void stm_dma1_channel1_isr(void) { ao_dma_isr(STM_DMA_INDEX(1)); } +void stm_dma1_channel2_isr(void) { ao_dma_isr(STM_DMA_INDEX(2)); } +void stm_dma1_channel3_isr(void) { ao_dma_isr(STM_DMA_INDEX(3)); } +void stm_dma1_channel4_isr(void) { ao_dma_isr(STM_DMA_INDEX(4)); } +void stm_dma1_channel5_isr(void) { ao_dma_isr(STM_DMA_INDEX(5)); } +void stm_dma1_channel6_isr(void) { ao_dma_isr(STM_DMA_INDEX(6)); } +void stm_dma1_channel7_isr(void) { ao_dma_isr(STM_DMA_INDEX(7)); } + +void +ao_dma_set_transfer(uint8_t index, + volatile void *peripheral, + void *memory, + uint16_t count, + uint32_t ccr) +{ + ao_mutex_get(&ao_dma_mutex[index]); + stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE); + stm_dma.channel[index].cndtr = count; + stm_dma.channel[index].cpar = (uint32_t) peripheral; + stm_dma.channel[index].cmar = (uint32_t) memory; +} + +void +ao_dma_start(uint8_t index) +{ + ao_dma_done[index] = 0; + stm_dma.channel[index].ccr |= (1 << STM_DMA_CCR_EN); +} + +void +ao_dma_done_transfer(uint8_t index) +{ + stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); + ao_mutex_put(&ao_dma_mutex[index]); +} + +void +ao_dma_abort(uint8_t index) +{ + stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); +} + +void +ao_dma_init(void) +{ + int index; + + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); + + for (index = 0; index < STM_NUM_DMA; index++) { + stm_nvic_set_enable(STM_ISR_DMA1_CHANNEL1_POS + index); + stm_nvic_set_priority(STM_ISR_DMA1_CHANNEL1_POS + index, 4); + } + +} diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c new file mode 100644 index 00000000..da04302b --- /dev/null +++ b/src/stm/ao_spi_stm.c @@ -0,0 +1,240 @@ +/* + * 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 + +struct ao_spi_stm_info { + uint8_t miso_dma_index; + uint8_t mosi_dma_index; + struct stm_spi *stm_spi; +}; + +uint8_t ao_spi_mutex[STM_NUM_SPI]; + +static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = { + { + .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_RX), + .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_TX), + &stm_spi1 + }, + { + .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_RX), + .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_TX), + &stm_spi2 + } +}; + +static uint8_t spi_dev_null; + +void +ao_spi_send(void *block, uint16_t len, uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + block, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + /* Clear any stale data */ + (void) stm_spi->dr; + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + &spi_dev_null, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (1 << STM_SPI_CR2_RXDMAEN)); + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +} + +void +ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; +#if 0 + uint8_t *d = block; + + while (len--) { + stm_spi->dr = 0xff; + while (!(stm_spi->sr & (1 << STM_SPI_SR_RXNE))); + *d++ = stm_spi->dr; + } + while (stm_spi->sr & (1 << STM_SPI_SR_BSY)); +#else + uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + &spi_dev_null, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + /* Clear any stale data */ + (void) stm_spi->dr; + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + block, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (1 << STM_SPI_CR2_RXDMAEN)); + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +#endif +} + +static void +ao_spi_channel_init(uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + + stm_spi->cr1 = 0; + (void) stm_spi->sr; + stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | + (0 << STM_SPI_CR1_BIDIOE) | + (0 << STM_SPI_CR1_CRCEN) | + (0 << STM_SPI_CR1_CRCNEXT) | + (0 << STM_SPI_CR1_DFF) | + (0 << STM_SPI_CR1_RXONLY) | + (1 << STM_SPI_CR1_SSM) | + (1 << STM_SPI_CR1_SSI) | + (0 << STM_SPI_CR1_LSBFIRST) | + (1 << STM_SPI_CR1_SPE) | + (STM_SPI_CR1_BR_PCLK_4 << STM_SPI_CR1_BR) | + (1 << STM_SPI_CR1_MSTR) | + (0 << STM_SPI_CR1_CPOL) | + (0 << STM_SPI_CR1_CPHA)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (0 << STM_SPI_CR2_TXDMAEN) | + (0 << STM_SPI_CR2_RXDMAEN)); +} + +void +ao_spi_init(void) +{ +#if HAS_SPI_1 +# if SPI_1_PA5_PA6_PA7 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + stm_afr_set(&stm_gpioa, 5, STM_AFR_AF5); + stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5); + stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5); +# else +# if SPI_1_PB3_PB4_PB5 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5); +# else +# if SPI_1_PE13_PE14_PE15 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN); + stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5); + stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5); + stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5); +# else +# error "No SPI_1 port configuration specified" +# endif +# endif +# endif + + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); + + ao_spi_channel_init(0); + + stm_nvic_set_enable(STM_ISR_SPI1_POS); + stm_nvic_set_priority(STM_ISR_SPI1_POS, 3); +#endif + +#if HAS_SPI_2 +# if SPI_2_PB13_PB14_PB15 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + stm_afr_set(&stm_gpiob, 13, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5); +# else +# if SPI_2_PPD1_PD3_PD4 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); + stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5); + stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5); + stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5); +# else +# error "No SPI_2 port configuration specified" +# endif +# endif + + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); + + ao_spi_channel_init(1); + + stm_nvic_set_enable(STM_ISR_SPI2_POS); + stm_nvic_set_priority(STM_ISR_SPI2_POS, 3); +#endif +} diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 531a4fb9..b40ec0ee 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -159,6 +159,17 @@ stm_afr_get(struct stm_gpio *gpio, int pin) { } } +static inline void +stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) { + /* Use the bit set/reset register to do this atomically */ + gpio->bsrr = ((uint32_t) (value ^ 1) << (pin + 16)) | ((uint32_t) value << pin); +} + +static inline uint8_t +stm_gpio_isset(struct stm_gpio *gpio, int pin) { + return (gpio->idr >> pin) & 1; +} + extern struct stm_gpio stm_gpioa; extern struct stm_gpio stm_gpiob; extern struct stm_gpio stm_gpioc; @@ -238,11 +249,6 @@ extern struct stm_usart stm_usart3; #define STM_USART_CR3_IREN (1) /* IrDA mode enable */ #define STM_USART_CR3_EIE (0) /* Error interrupt enable */ -struct stm_spi { -}; - -extern struct stm_spi stm_spi1; - struct stm_tim { }; @@ -842,4 +848,168 @@ isr(tim7) #define STM_ISR_TIM6_POS 43 #define STM_ISR_TIM7_POS 44 +struct stm_dma_channel { + vuint32_t ccr; + vuint32_t cndtr; + vuint32_t cpar; + vuint32_t cmar; + vuint32_t reserved; +}; + +#define STM_NUM_DMA 7 + +struct stm_dma { + vuint32_t isr; + vuint32_t ifcr; + struct stm_dma_channel channel[STM_NUM_DMA]; +}; + +extern struct stm_dma stm_dma; + +/* DMA channels go from 1 to 7, instead of 0 to 6 (sigh) + */ + +#define STM_DMA_INDEX(channel) ((channel) - 1) + +#define STM_DMA_ISR(index) ((index) << 2) +#define STM_DMA_ISR_MASK 0xf +#define STM_DMA_ISR_TEIF 3 +#define STM_DMA_ISR_HTIF 2 +#define STM_DMA_ISR_TCIF 1 +#define STM_DMA_ISR_GIF 0 + +#define STM_DMA_IFCR(index) ((index) << 2) +#define STM_DMA_IFCR_MASK 0xf +#define STM_DMA_IFCR_CTEIF 3 +#define STM_DMA_IFCR_CHTIF 2 +#define STM_DMA_IFCR_CTCIF 1 +#define STM_DMA_IFCR_CGIF 0 + +#define STM_DMA_CCR_MEM2MEM (14) + +#define STM_DMA_CCR_PL (12) +#define STM_DMA_CCR_PL_LOW (0) +#define STM_DMA_CCR_PL_MEDIUM (1) +#define STM_DMA_CCR_PL_HIGH (2) +#define STM_DMA_CCR_PL_VERY_HIGH (3) +#define STM_DMA_CCR_PL_MASK (3) + +#define STM_DMA_CCR_MSIZE (10) +#define STM_DMA_CCR_MSIZE_8 (0) +#define STM_DMA_CCR_MSIZE_16 (1) +#define STM_DMA_CCR_MSIZE_32 (2) +#define STM_DMA_CCR_MSIZE_MASK (3) + +#define STM_DMA_CCR_PSIZE (8) +#define STM_DMA_CCR_PSIZE_8 (0) +#define STM_DMA_CCR_PSIZE_16 (1) +#define STM_DMA_CCR_PSIZE_32 (2) +#define STM_DMA_CCR_PSIZE_MASK (3) + +#define STM_DMA_CCR_MINC (7) +#define STM_DMA_CCR_PINC (6) +#define STM_DMA_CCR_CIRC (5) +#define STM_DMA_CCR_DIR (4) +#define STM_DMA_CCR_DIR_PER_TO_MEM 0 +#define STM_DMA_CCR_DIR_MEM_TO_PER 1 +#define STM_DMA_CCR_TEIE (3) +#define STM_DMA_CCR_HTIE (2) +#define STM_DMA_CCR_TCIE (1) +#define STM_DMA_CCR_EN (0) + +#define STM_DMA_CHANNEL_ADC1 1 +#define STM_DMA_CHANNEL_SPI1_RX 2 +#define STM_DMA_CHANNEL_SPI1_TX 3 +#define STM_DMA_CHANNEL_SPI2_RX 4 +#define STM_DMA_CHANNEL_SPI2_TX 5 +#define STM_DMA_CHANNEL_USART3_TX 2 +#define STM_DMA_CHANNEL_USART3_RX 3 +#define STM_DMA_CHANNEL_USART1_TX 4 +#define STM_DMA_CHANNEL_USART1_RX 5 +#define STM_DMA_CHANNEL_USART2_RX 6 +#define STM_DMA_CHANNEL_USART2_TX 7 +#define STM_DMA_CHANNEL_I2C2_TX 4 +#define STM_DMA_CHANNEL_I2C2_RX 5 +#define STM_DMA_CHANNEL_I2C1_RX 6 +#define STM_DMA_CHANNEL_I2C1_TX 7 +#define STM_DMA_CHANNEL_TIM2_CH3 1 +#define STM_DMA_CHANNEL_TIM2_UP 2 +#define STM_DMA_CHANNEL_TIM2_CH1 5 +#define STM_DMA_CHANNEL_TIM2_CH2 7 +#define STM_DMA_CHANNEL_TIM2_CH4 7 +#define STM_DMA_CHANNEL_TIM3_CH3 2 +#define STM_DMA_CHANNEL_TIM3_CH4 3 +#define STM_DMA_CHANNEL_TIM3_UP 3 +#define STM_DMA_CHANNEL_TIM3_CH1 6 +#define STM_DMA_CHANNEL_TIM3_TRIG 6 +#define STM_DMA_CHANNEL_TIM4_CH1 1 +#define STM_DMA_CHANNEL_TIM4_CH2 4 +#define STM_DMA_CHANNEL_TIM4_CH3 5 +#define STM_DMA_CHANNEL_TIM4_UP 7 +#define STM_DMA_CHANNEL_TIM6_UP_DA 2 +#define STM_DMA_CHANNEL_C_CHANNEL1 2 +#define STM_DMA_CHANNEL_TIM7_UP_DA 3 +#define STM_DMA_CHANNEL_C_CHANNEL2 3 + +/* + * Only spi channel 1 and 2 can use DMA + */ +#define STM_NUM_SPI 2 + +struct stm_spi { + vuint32_t cr1; + vuint32_t cr2; + vuint32_t sr; + vuint32_t dr; + vuint32_t crcpr; + vuint32_t rxcrcr; + vuint32_t txcrcr; +}; + +extern struct stm_spi stm_spi1, stm_spi2, stm_spi3; + +/* SPI channels go from 1 to 3, instead of 0 to 2 (sigh) + */ + +#define STM_SPI_INDEX(channel) ((channel) - 1) + +#define STM_SPI_CR1_BIDIMODE 15 +#define STM_SPI_CR1_BIDIOE 14 +#define STM_SPI_CR1_CRCEN 13 +#define STM_SPI_CR1_CRCNEXT 12 +#define STM_SPI_CR1_DFF 11 +#define STM_SPI_CR1_RXONLY 10 +#define STM_SPI_CR1_SSM 9 +#define STM_SPI_CR1_SSI 8 +#define STM_SPI_CR1_LSBFIRST 7 +#define STM_SPI_CR1_SPE 6 +#define STM_SPI_CR1_BR 3 +#define STM_SPI_CR1_BR_PCLK_2 0 +#define STM_SPI_CR1_BR_PCLK_4 1 +#define STM_SPI_CR1_BR_PCLK_8 2 +#define STM_SPI_CR1_BR_PCLK_16 3 +#define STM_SPI_CR1_BR_PCLK_32 4 +#define STM_SPI_CR1_BR_PCLK_64 5 +#define STM_SPI_CR1_BR_PCLK_128 6 +#define STM_SPI_CR1_BR_PCLK_256 7 +#define STM_SPI_CR1_BR_MASK 7 + +#define STM_SPI_CR1_MSTR 2 +#define STM_SPI_CR1_CPOL 1 +#define STM_SPI_CR1_CPHA 0 + +#define STM_SPI_CR2_TXEIE 7 +#define STM_SPI_CR2_RXNEIE 6 +#define STM_SPI_CR2_ERRIE 5 +#define STM_SPI_CR2_SSOE 2 +#define STM_SPI_CR2_TXDMAEN 1 +#define STM_SPI_CR2_RXDMAEN 0 + +#define STM_SPI_SR_BSY 7 +#define STM_SPI_SR_OVR 6 +#define STM_SPI_SR_MODF 5 +#define STM_SPI_SR_CRCERR 4 +#define STM_SPI_SR_TXE 1 +#define STM_SPI_SR_RXNE 0 + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From 41a8383ccd29351f3a88a374f9456d6efb71b9a0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:22:41 -0700 Subject: altos: Save memory in ao_cmd.c Shrink a couple of help strings move a variable in ao_cmd from data to pdata. Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index cde68b39..fdc70007 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -300,7 +300,7 @@ ao_cmd_register(__code struct ao_cmds *cmds) void ao_cmd(void) { - char c; + __pdata char c; uint8_t cmd, cmds; __code struct ao_cmds * __xdata cs; void (*__xdata func)(void); @@ -336,8 +336,8 @@ __xdata struct ao_task ao_cmd_task; __code struct ao_cmds ao_base_cmds[] = { { help, "?\0Help" }, - { ao_task_info, "T\0Show tasks" }, - { echo, "E <0 off, 1 on>\0Set echo mode" }, + { ao_task_info, "T\0Tasks" }, + { echo, "E <0 off, 1 on>\0Echo" }, { ao_reboot, "r eboot\0Reboot" }, { version, "v\0Version" }, { 0, NULL }, -- cgit v1.2.3 From 8405efb6ca68c8216413b94e7acbdf51af00554a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:23:55 -0700 Subject: altos: Save memory in ao_config.c Shorten help messages. Stop setting aes_key on products not using aes key. Signed-off-by: Keith Packard --- src/core/ao_config.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 08e6deea..1dafab8d 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -113,8 +113,10 @@ _ao_config_get(void) ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; if (ao_config.minor < 8) ao_config.radio_enable = TRUE; +#if HAS_AES if (ao_config.minor < 9) - memset(&ao_config.aes_key, 0, AO_AES_LEN); + ao_xmemset(&ao_config.aes_key, '\0', AO_AES_LEN); +#endif if (ao_config.minor < 10) { ao_config.frequency = 434550; #if HAS_RADIO_CHANNELS @@ -525,12 +527,12 @@ ao_config_write(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { #if HAS_ADC - { "m \0Main deploy (in meters)", + { "m \0Main deploy (m)", ao_config_main_deploy_set, ao_config_main_deploy_show, }, - { "d \0Apogee delay (in seconds)", + { "d \0Apogee delay (s)", ao_config_apogee_delay_set, ao_config_apogee_delay_show }, #endif /* HAS_ADC */ - { "r \0Radio channel (freq = 434.550 + chan * .1)", + { "r \0Radio channel", ao_config_radio_channel_set, ao_config_radio_channel_show }, { "F \0Frequency (kHz)", ao_config_frequency_set, ao_config_frequency_show }, @@ -545,7 +547,7 @@ __code struct ao_config_var ao_config_vars[] = { { "f \0Radio calib (cal = rf/(xtal/2^16))", ao_config_radio_cal_set, ao_config_radio_cal_show }, #if HAS_LOG - { "l \0Flight log size in kB", + { "l \0Flight log size (kB)", ao_config_log_set, ao_config_log_show }, #endif #if HAS_IGNITE @@ -637,7 +639,7 @@ ao_config_write(void) __reentrant #endif __code struct ao_cmds ao_config_cmds[] = { - { ao_config_set, "c \0Set config variable (? for help, s to show)" }, + { ao_config_set, "c \0Set config (? for help, s to show)" }, { 0, NULL }, }; -- cgit v1.2.3 From d0d0d20c20e5eeacbc9a1ec1c93141a2044830fb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:24:59 -0700 Subject: altos: Shorten help strings Save a bit of code space Signed-off-by: Keith Packard --- src/core/ao_log.c | 2 +- src/core/ao_log_single.c | 6 +++--- src/core/ao_monitor.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_log.c b/src/core/ao_log.c index 6d3ad535..db60707d 100644 --- a/src/core/ao_log.c +++ b/src/core/ao_log.c @@ -264,7 +264,7 @@ ao_log_delete(void) __reentrant } __code struct ao_cmds ao_log_cmds[] = { - { ao_log_list, "l\0List flight logs" }, + { ao_log_list, "l\0List logs" }, { ao_log_delete, "d \0Delete flight" }, { 0, NULL }, }; diff --git a/src/core/ao_log_single.c b/src/core/ao_log_single.c index 9e90bd82..3f6235a6 100644 --- a/src/core/ao_log_single.c +++ b/src/core/ao_log_single.c @@ -180,9 +180,9 @@ ao_log_single_query(void) } const struct ao_cmds ao_log_single_cmds[] = { - { ao_log_single_set, "L <0 off, 1 on>\0Set logging mode" }, - { ao_log_single_list, "l\0List stored flight logs" }, - { ao_log_single_delete, "d 1\0Delete all stored flights" }, + { ao_log_single_set, "L <0 off, 1 on>\0Set logging" }, + { ao_log_single_list, "l\0List stored logs" }, + { ao_log_single_delete, "d 1\0Delete all stored logs" }, { ao_log_single_query, "q\0Query log status" }, { 0, NULL }, }; diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 7960208e..830464d8 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -267,7 +267,7 @@ set_monitor(void) } __code struct ao_cmds ao_monitor_cmds[] = { - { set_monitor, "m <0 off, 1 old, 20 std>\0Enable/disable radio monitoring" }, + { set_monitor, "m <0 off, 1 old, 20 std>\0Set radio monitoring" }, { 0, NULL }, }; #endif -- cgit v1.2.3 From c7119405a3dd7128120374a2a001bc98ef523619 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:25:26 -0700 Subject: altos: Make ao_freq_to_set reentrant Save a bunch of data space this way. Signed-off-by: Keith Packard --- src/core/ao.h | 2 +- src/core/ao_freq.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index 67efa437..150c0817 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1892,7 +1892,7 @@ ao_sqrt(uint32_t op); * ao_freq.c */ -int32_t ao_freq_to_set(int32_t freq, int32_t cal); +int32_t ao_freq_to_set(int32_t freq, int32_t cal) __reentrant; #include diff --git a/src/core/ao_freq.c b/src/core/ao_freq.c index 67b0b037..12496f6f 100644 --- a/src/core/ao_freq.c +++ b/src/core/ao_freq.c @@ -25,10 +25,15 @@ * frequency, and updating the radio setting along the way */ -int32_t ao_freq_to_set(int32_t freq, int32_t cal) { - __pdata int32_t set = 0; - uint8_t neg = 0; - __pdata int32_t error = -434550 / 2; +int32_t ao_freq_to_set(int32_t freq, int32_t cal) __reentrant +{ + static __pdata int32_t set; + static __pdata uint8_t neg; + static __pdata int32_t error; + + set = 0; + neg = 0; + error = -434550 / 2; if ((freq -= 434550) < 0) { neg = 1; -- cgit v1.2.3 From a0a650a2be007b0436bd527d6c18f36eef6fbe2b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:25:50 -0700 Subject: altos: Force radio channel to zero when setting frequency Otherwise, the actual radio frequency will include the channel offset, which is not useful. Signed-off-by: Keith Packard --- src/core/ao_config.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/core') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 1dafab8d..2d3d2870 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -218,6 +218,7 @@ ao_config_frequency_set(void) __reentrant return; _ao_config_edit_start(); ao_config.frequency = ao_cmd_lex_u32; + ao_config.radio_channel = 0; ao_config_set_radio(); _ao_config_edit_finish(); ao_radio_recv_abort(); -- cgit v1.2.3 From 4700f63937786e8f6e9b4882363234a33eb54c46 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 01:01:06 -0700 Subject: altos: Make ao_config_set_radio public Allows other bits of code to reset the radio parameters. Signed-off-by: Keith Packard --- src/core/ao.h | 3 +++ src/core/ao_config.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index 150c0817..f7db3bf4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1510,6 +1510,9 @@ ao_config_get(void); void ao_config_put(void); +void +ao_config_set_radio(void); + void ao_config_init(void); diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 2d3d2870..32798f75 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -64,7 +64,7 @@ ao_config_put(void) } #endif -static void +void ao_config_set_radio(void) { ao_config.radio_setting = ao_freq_to_set(ao_config.frequency, ao_config.radio_cal); -- cgit v1.2.3 From f952f9c285e2718a433c8c720c9b5d9c369e7036 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 12 Apr 2012 14:50:12 -0700 Subject: altos: Start adding apogee lockout support Remove radio channel support too. Signed-off-by: Keith Packard --- src/cc1111/ao_radio.c | 2 +- src/core/ao.h | 20 ++------- src/core/ao_config.c | 112 ++++++++++++-------------------------------------- 3 files changed, 32 insertions(+), 102 deletions(-) (limited to 'src/core') diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index ee506f89..51ed369b 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -286,7 +286,7 @@ ao_radio_get(uint8_t len) ao_config_get(); ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); - RF_CHANNR = ao_config.radio_channel; + RF_CHANNR = 0; RF_FREQ2 = (uint8_t) (ao_config.radio_setting >> 16); RF_FREQ1 = (uint8_t) (ao_config.radio_setting >> 8); RF_FREQ0 = (uint8_t) (ao_config.radio_setting); diff --git a/src/core/ao.h b/src/core/ao.h index f7db3bf4..9a3b5829 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1457,26 +1457,16 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 10 -#define AO_AES_LEN 16 - -#if HAS_RADIO_CHANNELS -#define AO_CHANNEL_NAME_LEN 10 +#define AO_CONFIG_MINOR 11 -#define AO_NUM_CHANNELS 10 - -struct ao_radio_channel { - char name[AO_CHANNEL_NAME_LEN]; - uint32_t kHz; -}; -#endif +#define AO_AES_LEN 16 struct ao_config { uint8_t major; uint8_t minor; uint16_t main_deploy; int16_t accel_plus_g; /* changed for minor version 2 */ - uint8_t radio_channel; + uint8_t _legacy_radio_channel; char callsign[AO_MAX_CALLSIGN + 1]; uint8_t apogee_delay; /* minor version 1 */ int16_t accel_minus_g; /* minor version 2 */ @@ -1488,9 +1478,7 @@ struct ao_config { uint8_t radio_enable; /* minor version 8 */ uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */ uint32_t frequency; /* minor version 10 */ -#if HAS_RADIO_CHANNELS - struct ao_radio_channel radio_channels[AO_NUM_CHANNELS]; /* minor version 10 */ -#endif + uint16_t apogee_lockout; /* minor version 11 */ }; #define AO_IGNITE_MODE_DUAL 0 diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 32798f75..55fb8590 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -85,7 +85,6 @@ _ao_config_get(void) /* Version 0 stuff */ ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; - ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; ao_xmemset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); ao_xmemcpy(&ao_config.callsign, CODE_TO_XDATA(AO_CONFIG_DEFAULT_CALLSIGN), sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); @@ -113,19 +112,12 @@ _ao_config_get(void) ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; if (ao_config.minor < 8) ao_config.radio_enable = TRUE; -#if HAS_AES if (ao_config.minor < 9) ao_xmemset(&ao_config.aes_key, '\0', AO_AES_LEN); -#endif - if (ao_config.minor < 10) { + if (ao_config.minor < 10) ao_config.frequency = 434550; -#if HAS_RADIO_CHANNELS - ao_xmemset(&ao_config.radio_channels, '\0', sizeof (ao_config.radio_channels)); - ao_xmemcpy(&ao_config.radio_channels[0].name[0], - CODE_TO_XDATA("Channel 0"), sizeof("Channel 0")); - ao_config.radio_channels[0].kHz = 434550; -#endif - } + if (ao_config.minor < 11) + ao_config.apogee_lockout = 0; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -184,25 +176,6 @@ ao_config_callsign_set(void) __reentrant _ao_config_edit_finish(); } -void -ao_config_radio_channel_show(void) __reentrant -{ - printf("Radio channel: %d\n", - ao_config.radio_channel); -} - -void -ao_config_radio_channel_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.radio_channel = ao_cmd_lex_i; - _ao_config_edit_finish(); - ao_radio_recv_abort(); -} - void ao_config_frequency_show(void) __reentrant { @@ -218,13 +191,12 @@ ao_config_frequency_set(void) __reentrant return; _ao_config_edit_start(); ao_config.frequency = ao_cmd_lex_u32; - ao_config.radio_channel = 0; ao_config_set_radio(); _ao_config_edit_finish(); ao_radio_recv_abort(); } -#if HAS_ADC +#if HAS_FLIGHT void ao_config_main_deploy_show(void) __reentrant @@ -328,7 +300,25 @@ ao_config_apogee_delay_set(void) __reentrant _ao_config_edit_finish(); } -#endif /* HAS_ADC */ +void +ao_config_apogee_lockout_show(void) __reentrant +{ + printf ("Apogee lockout: %d seconds\n", + ao_config.apogee_lockout); +} + +void +ao_config_apogee_lockout_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.apogee_lockout = ao_cmd_lex_i; + _ao_config_edit_finish(); +} + +#endif /* HAS_FLIGHT */ void ao_config_radio_cal_show(void) __reentrant @@ -467,50 +457,6 @@ ao_config_key_set(void) __reentrant } #endif -#if HAS_RADIO_CHANNELS -void -ao_config_radio_config_show(void) __reentrant -{ - uint8_t i; - for (i = 0; i < AO_NUM_CHANNELS; i++) - if (ao_config.radio_channels[i].name[0]) { - printf("%2d %-16.16s %ld\n", - i, - ao_config.radio_channels[i].name, - ao_config.radio_channels[i].kHz); - } -} - -void -ao_config_radio_config_set(void) __reentrant -{ - __xdata struct ao_radio_channel * ch; - uint8_t i; - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - if ((uint8_t) ao_cmd_lex_i >= AO_NUM_CHANNELS) { - ao_cmd_status = ao_cmd_syntax_error; - return; - } - ch = &ao_config.radio_channels[(uint8_t) ao_cmd_lex_i]; - _ao_config_edit_start(); - ao_cmd_white(); - i = 0; - while (ao_cmd_lex_c != '/' && ao_cmd_lex_c != '\n' && i < AO_CHANNEL_NAME_LEN) { - ch->name[i++] = ao_cmd_lex_c; - ao_cmd_lex(); - } - if (i < AO_CHANNEL_NAME_LEN) { - ch->name[i] = '\0'; - ao_cmd_lex(); - } - ao_cmd_decimal(); - ch->kHz = ao_cmd_lex_u32; - _ao_config_edit_finish(); -} -#endif - struct ao_config_var { __code char *str; void (*set)(void) __reentrant; @@ -527,14 +473,14 @@ static void ao_config_write(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { -#if HAS_ADC +#if HAS_FLIGHT { "m \0Main deploy (m)", ao_config_main_deploy_set, ao_config_main_deploy_show, }, { "d \0Apogee delay (s)", ao_config_apogee_delay_set, ao_config_apogee_delay_show }, -#endif /* HAS_ADC */ - { "r \0Radio channel", - ao_config_radio_channel_set, ao_config_radio_channel_show }, + { "L \0Apogee detect lockout (s)", + ao_config_apogee_lockout_set, ao_config_apogee_lockout_show, }, +#endif /* HAS_FLIGHT */ { "F \0Frequency (kHz)", ao_config_frequency_set, ao_config_frequency_show }, { "c \0Callsign (8 char max)", @@ -562,10 +508,6 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_AES { "k <32 hex digits>\0Set AES encryption key", ao_config_key_set, ao_config_key_show }, -#endif -#if HAS_RADIO_CHANNELS - { "C / \0Set radio chan config", - ao_config_radio_config_set,ao_config_radio_config_show }, #endif { "s\0Show", ao_config_show, 0 }, -- cgit v1.2.3 From 040a6eb119451026e1ec7c3a6a8e76b439c632d5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 12 Apr 2012 14:51:07 -0700 Subject: altos: Massive product config cleanup Support multiple serial ports more cleanly Split out parts of ao.h into separate feature header files Signed-off-by: Keith Packard --- src/avr/ao_arch.h | 7 - src/avr/ao_pins.h | 15 +- src/avr/ao_serial_avr.c | 62 +-- src/avr/ao_usb.h | 100 ----- src/avr/ao_usb_avr.c | 6 +- src/cc1111/ao_arch.h | 30 ++ src/cc1111/ao_pins.h | 24 +- src/cc1111/ao_serial.c | 227 +++++++++-- src/cc1111/ao_serial0.c | 152 -------- src/cc1111/ao_usb.c | 6 +- src/cc1111/ao_usb.h | 100 ----- src/core/ao.h | 704 ++--------------------------------- src/core/ao_adc.h | 62 +++ src/core/ao_beep.h | 74 ++++ src/core/ao_dbg.h | 62 +++ src/core/ao_flight.h | 59 +++ src/core/ao_led.h | 55 +++ src/core/ao_log.h | 196 ++++++++++ src/core/ao_log_telem.c | 4 +- src/core/ao_product.c | 8 +- src/core/ao_report.c | 2 + src/core/ao_sample.h | 137 +++++++ src/core/ao_serial.h | 86 +++++ src/core/ao_stdio.c | 6 + src/core/ao_storage.c | 2 +- src/core/ao_storage.h | 84 +++++ src/core/ao_usb.h | 136 +++++++ src/drivers/ao_btm.c | 30 +- src/drivers/ao_gps_sirf.c | 36 +- src/drivers/ao_gps_skytraq.c | 6 +- src/drivers/ao_science_slave.c | 1 + src/megametrum-v0.1/ao_pins.h | 2 + src/product/ao_telebt.c | 2 + src/product/ao_terraui.c | 1 + src/stm/ao_arch.h | 2 - src/stm/ao_serial_stm.c | 2 +- src/stm/ao_usb.h | 101 ----- src/stm/ao_usb_stm.c | 6 +- src/teleballoon-v1.1/ao_pins.h | 5 - src/telepyro-v0.1/Makefile | 6 +- src/telescience-v0.1/Makefile | 9 +- src/teleshield-v0.1/Makefile | 1 - src/teleshield-v0.1/ao_ardu_serial.c | 3 +- src/teleshield-v0.1/ao_pins.h | 8 +- src/teleshield-v0.1/ao_teleshield.c | 3 + src/teleterra-v0.1/ao_pins.h | 5 - src/teleterra-v0.2/ao_pins.h | 5 - src/test/ao_gps_test.c | 6 +- src/test/ao_gps_test_skytraq.c | 6 +- 49 files changed, 1342 insertions(+), 1310 deletions(-) delete mode 100644 src/avr/ao_usb.h delete mode 100644 src/cc1111/ao_serial0.c delete mode 100644 src/cc1111/ao_usb.h create mode 100644 src/core/ao_adc.h create mode 100644 src/core/ao_beep.h create mode 100644 src/core/ao_dbg.h create mode 100644 src/core/ao_flight.h create mode 100644 src/core/ao_led.h create mode 100644 src/core/ao_log.h create mode 100644 src/core/ao_sample.h create mode 100644 src/core/ao_serial.h create mode 100644 src/core/ao_storage.h create mode 100644 src/core/ao_usb.h delete mode 100644 src/stm/ao_usb.h (limited to 'src/core') diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index b816279e..c775dab6 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -146,12 +146,5 @@ extern uint8_t ao_cpu_sleep_disable; #define AO_TELESCIENCE_NUM_ADC 12 -struct ao_adc { - uint16_t tick; /* tick when the sample was read */ - uint16_t adc[AO_TELESCIENCE_NUM_ADC]; /* samples */ -}; - -#define AO_ADC_RING 16 - #endif /* _AO_ARCH_H_ */ diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 6a63468f..f2b40fb4 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -21,7 +21,7 @@ #ifdef AVR_DEMO #define AO_LED_RED (1<<7) #define LEDS_AVAILABLE (AO_LED_RED) - #define USE_SERIAL_STDIN 1 + #define USE_SERIAL_1_STDIN 1 #define HAS_USB 1 #define PACKET_HAS_SLAVE 0 #define HAS_SERIAL_1 1 @@ -37,11 +37,11 @@ #define HAS_USB 1 #define HAS_LOG 1 #define TEENSY 0 - #define USE_SERIAL_STDIN 0 #define HAS_SERIAL_1 0 #define HAS_ADC 1 #define PACKET_HAS_SLAVE 0 #define HAS_BEEP 0 + #define HAS_EEPROM 1 #define HAS_STORAGE_DEBUG 0 #define AVR_VCC_5V 0 @@ -66,7 +66,7 @@ #define HAS_USB 1 #define HAS_LOG 0 #define TEENSY 0 - #define USE_SERIAL_STDIN 1 + #define USE_SERIAL_1_STDIN 1 #define HAS_SERIAL_1 1 #define HAS_USB 1 #define HAS_ADC 1 @@ -88,4 +88,13 @@ #define AO_M25_SPI_CS_PORT SPI_CS_PORT #define AO_M25_SPI_CS_MASK M25_CS_MASK +#define AO_TELESCIENCE_NUM_ADC 12 + +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + uint16_t adc[AO_TELESCIENCE_NUM_ADC]; /* samples */ +}; + +#define AO_ADC_RING 16 + #endif /* _AO_PINS_H_ */ diff --git a/src/avr/ao_serial_avr.c b/src/avr/ao_serial_avr.c index 6885c339..dcee246c 100644 --- a/src/avr/ao_serial_avr.c +++ b/src/avr/ao_serial_avr.c @@ -17,8 +17,8 @@ #include "ao.h" -__xdata struct ao_fifo ao_usart1_rx_fifo; -__xdata struct ao_fifo ao_usart1_tx_fifo; +__xdata struct ao_fifo ao_serial1_rx_fifo; +__xdata struct ao_fifo ao_serial1_tx_fifo; void ao_debug_out(char c) @@ -31,10 +31,10 @@ ao_debug_out(char c) ISR(USART1_RX_vect) { - if (!ao_fifo_full(ao_usart1_rx_fifo)) - ao_fifo_insert(ao_usart1_rx_fifo, UDR1); - ao_wakeup(&ao_usart1_rx_fifo); -#if USE_SERIAL_STDIN + if (!ao_fifo_full(ao_serial1_rx_fifo)) + ao_fifo_insert(ao_serial1_rx_fifo, UDR1); + ao_wakeup(&ao_serial1_rx_fifo); +#if USE_SERIAL_1_STDIN ao_wakeup(&ao_stdin_ready); #endif } @@ -42,68 +42,68 @@ ISR(USART1_RX_vect) static __xdata uint8_t ao_serial_tx1_started; static void -ao_serial_tx1_start(void) +ao_serial1_tx_start(void) { - if (!ao_fifo_empty(ao_usart1_tx_fifo) && + if (!ao_fifo_empty(ao_serial1_tx_fifo) && !ao_serial_tx1_started) { ao_serial_tx1_started = 1; - ao_fifo_remove(ao_usart1_tx_fifo, UDR1); + ao_fifo_remove(ao_serial1_tx_fifo, UDR1); } } ISR(USART1_UDRE_vect) { - ao_serial_tx1_started = 0; - ao_serial_tx1_start(); - ao_wakeup(&ao_usart1_tx_fifo); + ao_serial1_tx_started = 0; + ao_serial1_tx_start(); + ao_wakeup(&ao_serial1_tx_fifo); } char -ao_serial_getchar(void) __critical +ao_serial1_getchar(void) __critical { char c; cli(); - while (ao_fifo_empty(ao_usart1_rx_fifo)) - ao_sleep(&ao_usart1_rx_fifo); - ao_fifo_remove(ao_usart1_rx_fifo, c); + while (ao_fifo_empty(ao_serial1_rx_fifo)) + ao_sleep(&ao_serial1_rx_fifo); + ao_fifo_remove(ao_serial1_rx_fifo, c); sei(); return c; } -#if USE_SERIAL_STDIN +#if USE_SERIAL_1_STDIN char -ao_serial_pollchar(void) __critical +ao_serial1_pollchar(void) __critical { char c; cli(); - if (ao_fifo_empty(ao_usart1_rx_fifo)) { + if (ao_fifo_empty(ao_serial1_rx_fifo)) { sei(); return AO_READ_AGAIN; } - ao_fifo_remove(ao_usart1_rx_fifo,c); + ao_fifo_remove(ao_serial1_rx_fifo,c); sei(); return c; } #endif void -ao_serial_putchar(char c) __critical +ao_serial1_putchar(char c) __critical { cli(); - while (ao_fifo_full(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); - ao_fifo_insert(ao_usart1_tx_fifo, c); + while (ao_fifo_full(ao_serial1_tx_fifo)) + ao_sleep(&ao_serial1_tx_fifo); + ao_fifo_insert(ao_serial1_tx_fifo, c); ao_serial_tx1_start(); sei(); } void -ao_serial_drain(void) __critical +ao_serial1_drain(void) __critical { cli(); - while (!ao_fifo_empty(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); + while (!ao_fifo_empty(ao_serial1_tx_fifo)) + ao_sleep(&ao_serial1_tx_fifo); sei(); } @@ -125,7 +125,7 @@ static const struct { }; void -ao_serial_set_speed(uint8_t speed) +ao_serial1_set_speed(uint8_t speed) { ao_serial_drain(); if (speed > AO_SERIAL_SPEED_57600) @@ -154,9 +154,9 @@ ao_serial_init(void) (1 << TXEN1) | /* Enable transmitter */ (1 << RXCIE1) | /* Enable receive interrupts */ (1 << UDRIE1)); /* Enable transmit empty interrupts */ -#if USE_SERIAL_STDIN - ao_add_stdio(ao_serial_pollchar, - ao_serial_putchar, +#if USE_SERIAL_1_STDIN + ao_add_stdio(ao_serial1_pollchar, + ao_serial1_putchar, NULL); #endif } diff --git a/src/avr/ao_usb.h b/src/avr/ao_usb.h deleted file mode 100644 index 6633dafc..00000000 --- a/src/avr/ao_usb.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright © 2009 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_USB_H_ -#define _AO_USB_H_ - -#define AO_USB_SETUP_DIR_MASK (0x01 << 7) -#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) -#define AO_USB_SETUP_RECIP_MASK (0x1f) - -#define AO_USB_DIR_OUT 0 -#define AO_USB_DIR_IN (1 << 7) - -#define AO_USB_TYPE_STANDARD 0 -#define AO_USB_TYPE_CLASS (1 << 5) -#define AO_USB_TYPE_VENDOR (2 << 5) -#define AO_USB_TYPE_RESERVED (3 << 5) - -#define AO_USB_RECIP_DEVICE 0 -#define AO_USB_RECIP_INTERFACE 1 -#define AO_USB_RECIP_ENDPOINT 2 -#define AO_USB_RECIP_OTHER 3 - -/* standard requests */ -#define AO_USB_REQ_GET_STATUS 0x00 -#define AO_USB_REQ_CLEAR_FEATURE 0x01 -#define AO_USB_REQ_SET_FEATURE 0x03 -#define AO_USB_REQ_SET_ADDRESS 0x05 -#define AO_USB_REQ_GET_DESCRIPTOR 0x06 -#define AO_USB_REQ_SET_DESCRIPTOR 0x07 -#define AO_USB_REQ_GET_CONFIGURATION 0x08 -#define AO_USB_REQ_SET_CONFIGURATION 0x09 -#define AO_USB_REQ_GET_INTERFACE 0x0A -#define AO_USB_REQ_SET_INTERFACE 0x0B -#define AO_USB_REQ_SYNCH_FRAME 0x0C - -#define AO_USB_DESC_DEVICE 1 -#define AO_USB_DESC_CONFIGURATION 2 -#define AO_USB_DESC_STRING 3 -#define AO_USB_DESC_INTERFACE 4 -#define AO_USB_DESC_ENDPOINT 5 -#define AO_USB_DESC_DEVICE_QUALIFIER 6 -#define AO_USB_DESC_OTHER_SPEED 7 -#define AO_USB_DESC_INTERFACE_POWER 8 - -#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) -#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) - -#define AO_USB_CONTROL_EP 0 -#define AO_USB_INT_EP 1 -#define AO_USB_OUT_EP 4 -#define AO_USB_IN_EP 5 -#define AO_USB_CONTROL_SIZE 32 -/* - * Double buffer IN and OUT EPs, so each - * gets half of the available space - * - * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 - * byte sizes, so we'll use 64 for everything - */ -#define AO_USB_IN_SIZE 64 -#define AO_USB_OUT_SIZE 64 - -#define AO_USB_EP0_IDLE 0 -#define AO_USB_EP0_DATA_IN 1 -#define AO_USB_EP0_DATA_OUT 2 - -#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) - -/* CDC definitions */ -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 - -#define SET_LINE_CODING 0x20 -#define GET_LINE_CODING 0x21 -#define SET_CONTROL_LINE_STATE 0x22 - -/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ -struct ao_usb_line_coding { - uint32_t rate; - uint8_t char_format; - uint8_t parity; - uint8_t data_bits; -} ; - -#endif /* _AO_USB_H_ */ diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c index fc8899d8..23a27c73 100644 --- a/src/avr/ao_usb_avr.c +++ b/src/avr/ao_usb_avr.c @@ -330,17 +330,17 @@ ao_usb_ep0_setup(void) case AO_USB_TYPE_CLASS: debug ("Class setup packet\n"); switch (ao_usb_setup.request) { - case SET_LINE_CODING: + case AO_USB_SET_LINE_CODING: debug ("set line coding\n"); ao_usb_ep0_out_len = 7; ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding; break; - case GET_LINE_CODING: + case AO_USB_GET_LINE_CODING: debug ("get line coding\n"); ao_usb_ep0_in_len = 7; ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; break; - case SET_CONTROL_LINE_STATE: + case AO_USB_SET_CONTROL_LINE_STATE: break; } break; diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 847ac1a6..9d0643b4 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -294,4 +294,34 @@ ao_dma_abort(uint8_t id); void ao_dma_isr(void) ao_arch_interrupt(8); +/* ao_adc.c */ + +#if HAS_ADC +/* The A/D interrupt handler */ +void +ao_adc_isr(void) ao_arch_interrupt(1); +#endif + +#if HAS_USB +/* USB interrupt handler */ +void +ao_usb_isr(void) ao_arch_interrupt(6); +#endif + +#if HAS_SERIAL_0 +void +ao_serial0_rx_isr(void) ao_arch_interrupt(2); + +void +ao_serial0_tx_isr(void) ao_arch_interrupt(7); +#endif + +#if HAS_SERIAL_1 +void +ao_serial1_rx_isr(void) ao_arch_interrupt(3); + +void +ao_serial1_tx_isr(void) ao_arch_interrupt(14); +#endif + #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 5c0cb7df..4f6edd37 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -25,7 +25,6 @@ #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 1 - #define USE_SERIAL_STDIN 0 #define HAS_EEPROM 1 #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 @@ -58,7 +57,6 @@ #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 @@ -95,7 +93,6 @@ #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 @@ -131,7 +128,6 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 @@ -161,7 +157,6 @@ #define HAS_BEEP 0 #define HAS_GPS 0 #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 @@ -188,7 +183,6 @@ #define HAS_BEEP 0 #define HAS_GPS 0 #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 @@ -214,7 +208,6 @@ #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_DBG 0 #define HAS_EEPROM 1 @@ -244,7 +237,6 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 0 #define HAS_DBG 0 #define HAS_EEPROM 0 @@ -273,7 +265,6 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 @@ -301,7 +292,8 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 1 + #define USE_SERIAL_1_STDIN 1 + #define DELAY_SERIAL_1_STDIN 1 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 @@ -339,7 +331,8 @@ #define HAS_SERIAL_1_ALT_1 1 #define HAS_SERIAL_1_ALT_2 0 #define HAS_SERIAL_1_HW_FLOW 1 - #define USE_SERIAL_STDIN 1 + #define USE_SERIAL_1_STDIN 1 + #define DELAY_SERIAL_1_STDIN 1 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 1 @@ -379,7 +372,6 @@ #define HAS_BEEP 1 #define HAS_GPS 0 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_DBG 0 #define HAS_EEPROM 1 @@ -468,14 +460,6 @@ #error Please define IGNITE_ON_P0 #endif -#ifndef HAS_SERIAL_1 -#error Please define HAS_SERIAL_1 -#endif - -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c index 4d5b9abd..00c85ff3 100644 --- a/src/cc1111/ao_serial.c +++ b/src/cc1111/ao_serial.c @@ -17,78 +17,168 @@ #include "ao.h" -volatile __xdata struct ao_fifo ao_usart1_rx_fifo; -volatile __xdata struct ao_fifo ao_usart1_tx_fifo; +#if HAS_SERIAL_0 + +volatile __xdata struct ao_fifo ao_serial0_rx_fifo; +volatile __xdata struct ao_fifo ao_serial0_tx_fifo; + +void +ao_serial0_rx_isr(void) __interrupt 2 +{ + if (!ao_fifo_full(ao_serial0_rx_fifo)) + ao_fifo_insert(ao_serial0_rx_fifo, U0DBUF); + ao_wakeup(&ao_serial0_rx_fifo); +#if USE_SERIAL_0_STDIN + ao_wakeup(&ao_stdin_ready); +#endif +} + +static __xdata uint8_t ao_serial0_tx_started; + +static void +ao_serial0_tx_start(void) +{ + if (!ao_fifo_empty(ao_serial0_tx_fifo) && + !ao_serial0_tx_started) + { + ao_serial0_tx_started = 1; + ao_fifo_remove(ao_serial0_tx_fifo, U0DBUF); + } +} + +void +ao_serial0_tx_isr(void) __interrupt 7 +{ + UTX0IF = 0; + ao_serial0_tx_started = 0; + ao_serial0_tx_start(); + ao_wakeup(&ao_serial0_tx_fifo); +} + +char +ao_serial0_getchar(void) __critical +{ + char c; + while (ao_fifo_empty(ao_serial0_rx_fifo)) + ao_sleep(&ao_serial0_rx_fifo); + ao_fifo_remove(ao_serial0_rx_fifo, c); + return c; +} + +#if USE_SERIAL_0_STDIN +char +ao_serial0_pollchar(void) __critical +{ + char c; + if (ao_fifo_empty(ao_serial0_rx_fifo)) + return AO_READ_AGAIN; + ao_fifo_remove(ao_serial0_rx_fifo,c); + return c; +} +#endif + +void +ao_serial0_putchar(char c) __critical +{ + while (ao_fifo_full(ao_serial0_tx_fifo)) + ao_sleep(&ao_serial0_tx_fifo); + ao_fifo_insert(ao_serial0_tx_fifo, c); + ao_serial0_tx_start(); +} + +void +ao_serial0_drain(void) __critical +{ + while (!ao_fifo_empty(ao_serial0_tx_fifo)) + ao_sleep(&ao_serial0_tx_fifo); +} + +void +ao_serial0_set_speed(uint8_t speed) +{ + ao_serial0_drain(); + if (speed > AO_SERIAL_SPEED_57600) + return; + U0UCR |= UxUCR_FLUSH; + U0BAUD = ao_serial_speeds[speed].baud; + U0GCR = ao_serial_speeds[speed].gcr; +} +#endif /* HAS_SERIAL_0 */ + +#if HAS_SERIAL_1 + +volatile __xdata struct ao_fifo ao_serial1_rx_fifo; +volatile __xdata struct ao_fifo ao_serial1_tx_fifo; void -ao_serial_rx1_isr(void) __interrupt 3 +ao_serial1_rx_isr(void) __interrupt 3 { - if (!ao_fifo_full(ao_usart1_rx_fifo)) - ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF); - ao_wakeup(&ao_usart1_rx_fifo); -#if USE_SERIAL_STDIN + if (!ao_fifo_full(ao_serial1_rx_fifo)) + ao_fifo_insert(ao_serial1_rx_fifo, U1DBUF); + ao_wakeup(&ao_serial1_rx_fifo); +#if USE_SERIAL1_STDIN ao_wakeup(&ao_stdin_ready); #endif } -static __xdata uint8_t ao_serial_tx1_started; +static __xdata uint8_t ao_serial1_tx_started; static void -ao_serial_tx1_start(void) +ao_serial1_tx_start(void) { - if (!ao_fifo_empty(ao_usart1_tx_fifo) && - !ao_serial_tx1_started) + if (!ao_fifo_empty(ao_serial1_tx_fifo) && + !ao_serial1_tx_started) { - ao_serial_tx1_started = 1; - ao_fifo_remove(ao_usart1_tx_fifo, U1DBUF); + ao_serial1_tx_started = 1; + ao_fifo_remove(ao_serial1_tx_fifo, U1DBUF); } } void -ao_serial_tx1_isr(void) __interrupt 14 +ao_serial1_tx_isr(void) __interrupt 14 { UTX1IF = 0; - ao_serial_tx1_started = 0; - ao_serial_tx1_start(); - ao_wakeup(&ao_usart1_tx_fifo); + ao_serial1_tx_started = 0; + ao_serial1_tx_start(); + ao_wakeup(&ao_serial1_tx_fifo); } char -ao_serial_getchar(void) __critical +ao_serial1_getchar(void) __critical { char c; - while (ao_fifo_empty(ao_usart1_rx_fifo)) - ao_sleep(&ao_usart1_rx_fifo); - ao_fifo_remove(ao_usart1_rx_fifo, c); + while (ao_fifo_empty(ao_serial1_rx_fifo)) + ao_sleep(&ao_serial1_rx_fifo); + ao_fifo_remove(ao_serial1_rx_fifo, c); return c; } -#if USE_SERIAL_STDIN +#if USE_SERIAL_1_STDIN char -ao_serial_pollchar(void) __critical +ao_serial1_pollchar(void) __critical { char c; - if (ao_fifo_empty(ao_usart1_rx_fifo)) + if (ao_fifo_empty(ao_serial1_rx_fifo)) return AO_READ_AGAIN; - ao_fifo_remove(ao_usart1_rx_fifo,c); + ao_fifo_remove(ao_serial1_rx_fifo,c); return c; } #endif void -ao_serial_putchar(char c) __critical +ao_serial1_putchar(char c) __critical { - while (ao_fifo_full(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); - ao_fifo_insert(ao_usart1_tx_fifo, c); - ao_serial_tx1_start(); + while (ao_fifo_full(ao_serial1_tx_fifo)) + ao_sleep(&ao_serial1_tx_fifo); + ao_fifo_insert(ao_serial1_tx_fifo, c); + ao_serial1_tx_start(); } void -ao_serial_drain(void) __critical +ao_serial1_drain(void) __critical { - while (!ao_fifo_empty(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); + while (!ao_fifo_empty(ao_serial1_tx_fifo)) + ao_sleep(&ao_serial1_tx_fifo); } const __code struct ao_serial_speed ao_serial_speeds[] = { @@ -111,9 +201,9 @@ const __code struct ao_serial_speed ao_serial_speeds[] = { }; void -ao_serial_set_speed(uint8_t speed) +ao_serial1_set_speed(uint8_t speed) { - ao_serial_drain(); + ao_serial1_drain(); if (speed > AO_SERIAL_SPEED_57600) return; U1UCR |= UxUCR_FLUSH; @@ -121,9 +211,67 @@ ao_serial_set_speed(uint8_t speed) U1GCR = ao_serial_speeds[speed].gcr; } +#endif /* HAS_SERIAL_1 */ + void ao_serial_init(void) { +#if HAS_SERIAL_0 +#if HAS_SERIAL_0_ALT_1 + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_1; + + P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART0_USART1; + + /* Make the USART pins be controlled by the USART */ + P0SEL |= (1 << 2) | (1 << 3); +#if HAS_SERIAL_0_HW_FLOW + P0SEL |= (1 << 4) | (1 << 5); +#endif +#else + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; + + P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI0P1_MASK)) | + (P2SEL_PRI3P1_USART0 | P2SEL_PRI0P1_USART0); + + /* Make the USART pins be controlled by the USART */ + P1SEL |= (1 << 2) | (1 << 3); +#if HAS_SERIAL_0_HW_FLOW + P1SEL |= (1 << 5) | (1 << 4); +#endif +#endif + + /* UART mode with receiver enabled */ + U0CSR = (UxCSR_MODE_UART | UxCSR_RE); + + /* Pick a 9600 baud rate */ + ao_serial0_set_speed(AO_SERIAL_SPEED_9600); + + /* Reasonable serial parameters */ + U0UCR = (UxUCR_FLUSH | +#if HAS_SERIAL_0_HW_FLOW + UxUCR_FLOW_ENABLE | +#else + UxUCR_FLOW_DISABLE | +#endif + UxUCR_D9_EVEN_PARITY | + UxUCR_BIT9_8_BITS | + UxUCR_PARITY_DISABLE | + UxUCR_SPB_1_STOP_BIT | + UxUCR_STOP_HIGH | + UxUCR_START_LOW); + + IEN0 |= IEN0_URX0IE; + IEN2 |= IEN2_UTX0IE; +#if USE_SERIAL_0_STDIN && !DELAY_SERIAL_0_STDIN + ao_add_stdio(ao_serial0_pollchar, + ao_serial0_putchar, + NULL); +#endif +#endif /* HAS_SERIAL_0 */ + +#if HAS_SERIAL_1 #if HAS_SERIAL_1_ALT_1 /* Set up the USART pin assignment */ PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_1; @@ -151,7 +299,7 @@ ao_serial_init(void) U1CSR = (UxCSR_MODE_UART | UxCSR_RE); /* Pick a 4800 baud rate */ - ao_serial_set_speed(AO_SERIAL_SPEED_4800); + ao_serial1_set_speed(AO_SERIAL_SPEED_4800); /* Reasonable serial parameters */ U1UCR = (UxUCR_FLUSH | @@ -169,4 +317,11 @@ ao_serial_init(void) IEN0 |= IEN0_URX1IE; IEN2 |= IEN2_UTX1IE; + +#if USE_SERIAL_1_STDIN && !DELAY_SERIAL_1_STDIN + ao_add_stdio(ao_serial1_pollchar, + ao_serial1_putchar, + NULL); +#endif +#endif /* HAS_SERIAL_1 */ } diff --git a/src/cc1111/ao_serial0.c b/src/cc1111/ao_serial0.c deleted file mode 100644 index e8c1eb35..00000000 --- a/src/cc1111/ao_serial0.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright © 2009 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" - -volatile __xdata struct ao_fifo ao_usart0_rx_fifo; -volatile __xdata struct ao_fifo ao_usart0_tx_fifo; - -void -ao_serial0_rx0_isr(void) __interrupt 2 -{ - if (!ao_fifo_full(ao_usart0_rx_fifo)) - ao_fifo_insert(ao_usart0_rx_fifo, U0DBUF); - ao_wakeup(&ao_usart0_rx_fifo); -} - -static __xdata uint8_t ao_serial0_tx0_started; - -static void -ao_serial0_tx0_start(void) -{ - if (!ao_fifo_empty(ao_usart0_tx_fifo) && - !ao_serial0_tx0_started) - { - ao_serial0_tx0_started = 1; - ao_fifo_remove(ao_usart0_tx_fifo, U0DBUF); - } -} - -void -ao_serial0_tx0_isr(void) __interrupt 7 -{ - UTX0IF = 0; - ao_serial0_tx0_started = 0; - ao_serial0_tx0_start(); - ao_wakeup(&ao_usart0_tx_fifo); -} - -char -ao_serial0_getchar(void) __critical -{ - char c; - while (ao_fifo_empty(ao_usart0_rx_fifo)) - ao_sleep(&ao_usart0_rx_fifo); - ao_fifo_remove(ao_usart0_rx_fifo, c); - return c; -} - -#if USE_SERIAL_STDIN -char -ao_serial0_pollchar(void) __critical -{ - char c; - if (ao_fifo_empty(ao_usart0_rx_fifo)) - return AO_READ_AGAIN; - ao_fifo_remove(ao_usart0_rx_fifo,c); - return c; -} -#endif - -void -ao_serial0_putchar(char c) __critical -{ - while (ao_fifo_full(ao_usart0_tx_fifo)) - ao_sleep(&ao_usart0_tx_fifo); - ao_fifo_insert(ao_usart0_tx_fifo, c); - ao_serial0_tx0_start(); -} - -void -ao_serial0_drain(void) __critical -{ - while (!ao_fifo_empty(ao_usart0_tx_fifo)) - ao_sleep(&ao_usart0_tx_fifo); -} - -void -ao_serial0_set_speed(uint8_t speed) -{ - ao_serial0_drain(); - if (speed > AO_SERIAL_SPEED_57600) - return; - U0UCR |= UxUCR_FLUSH; - U0BAUD = ao_serial_speeds[speed].baud; - U0GCR = ao_serial_speeds[speed].gcr; -} - -void -ao_serial0_init(void) -{ -#if HAS_SERIAL_0_ALT_1 - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_1; - - P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART0_USART1; - - /* Make the USART pins be controlled by the USART */ - P0SEL |= (1 << 2) | (1 << 3); -#if HAS_SERIAL_0_HW_FLOW - P0SEL |= (1 << 4) | (1 << 5); -#endif -#else - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; - - P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI0P1_MASK)) | - (P2SEL_PRI3P1_USART0 | P2SEL_PRI0P1_USART0); - - /* Make the USART pins be controlled by the USART */ - P1SEL |= (1 << 2) | (1 << 3); -#if HAS_SERIAL_0_HW_FLOW - P1SEL |= (1 << 5) | (1 << 4); -#endif -#endif - - /* UART mode with receiver enabled */ - U0CSR = (UxCSR_MODE_UART | UxCSR_RE); - - /* Pick a 9600 baud rate */ - ao_serial0_set_speed(AO_SERIAL_SPEED_9600); - - /* Reasonable serial parameters */ - U0UCR = (UxUCR_FLUSH | -#if HAS_SERIAL_0_HW_FLOW - UxUCR_FLOW_ENABLE | -#else - UxUCR_FLOW_DISABLE | -#endif - UxUCR_D9_EVEN_PARITY | - UxUCR_BIT9_8_BITS | - UxUCR_PARITY_DISABLE | - UxUCR_SPB_1_STOP_BIT | - UxUCR_STOP_HIGH | - UxUCR_START_LOW); - - IEN0 |= IEN0_URX0IE; - IEN2 |= IEN2_UTX0IE; -} diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c index 35c9ac20..ce26e808 100644 --- a/src/cc1111/ao_usb.c +++ b/src/cc1111/ao_usb.c @@ -261,15 +261,15 @@ ao_usb_ep0_setup(void) break; case AO_USB_TYPE_CLASS: switch (ao_usb_setup.request) { - case SET_LINE_CODING: + case AO_USB_SET_LINE_CODING: ao_usb_ep0_out_len = 7; ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding; break; - case GET_LINE_CODING: + case AO_USB_GET_LINE_CODING: ao_usb_ep0_in_len = 7; ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; break; - case SET_CONTROL_LINE_STATE: + case AO_USB_SET_CONTROL_LINE_STATE: break; } break; diff --git a/src/cc1111/ao_usb.h b/src/cc1111/ao_usb.h deleted file mode 100644 index 6633dafc..00000000 --- a/src/cc1111/ao_usb.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright © 2009 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_USB_H_ -#define _AO_USB_H_ - -#define AO_USB_SETUP_DIR_MASK (0x01 << 7) -#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) -#define AO_USB_SETUP_RECIP_MASK (0x1f) - -#define AO_USB_DIR_OUT 0 -#define AO_USB_DIR_IN (1 << 7) - -#define AO_USB_TYPE_STANDARD 0 -#define AO_USB_TYPE_CLASS (1 << 5) -#define AO_USB_TYPE_VENDOR (2 << 5) -#define AO_USB_TYPE_RESERVED (3 << 5) - -#define AO_USB_RECIP_DEVICE 0 -#define AO_USB_RECIP_INTERFACE 1 -#define AO_USB_RECIP_ENDPOINT 2 -#define AO_USB_RECIP_OTHER 3 - -/* standard requests */ -#define AO_USB_REQ_GET_STATUS 0x00 -#define AO_USB_REQ_CLEAR_FEATURE 0x01 -#define AO_USB_REQ_SET_FEATURE 0x03 -#define AO_USB_REQ_SET_ADDRESS 0x05 -#define AO_USB_REQ_GET_DESCRIPTOR 0x06 -#define AO_USB_REQ_SET_DESCRIPTOR 0x07 -#define AO_USB_REQ_GET_CONFIGURATION 0x08 -#define AO_USB_REQ_SET_CONFIGURATION 0x09 -#define AO_USB_REQ_GET_INTERFACE 0x0A -#define AO_USB_REQ_SET_INTERFACE 0x0B -#define AO_USB_REQ_SYNCH_FRAME 0x0C - -#define AO_USB_DESC_DEVICE 1 -#define AO_USB_DESC_CONFIGURATION 2 -#define AO_USB_DESC_STRING 3 -#define AO_USB_DESC_INTERFACE 4 -#define AO_USB_DESC_ENDPOINT 5 -#define AO_USB_DESC_DEVICE_QUALIFIER 6 -#define AO_USB_DESC_OTHER_SPEED 7 -#define AO_USB_DESC_INTERFACE_POWER 8 - -#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) -#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) - -#define AO_USB_CONTROL_EP 0 -#define AO_USB_INT_EP 1 -#define AO_USB_OUT_EP 4 -#define AO_USB_IN_EP 5 -#define AO_USB_CONTROL_SIZE 32 -/* - * Double buffer IN and OUT EPs, so each - * gets half of the available space - * - * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 - * byte sizes, so we'll use 64 for everything - */ -#define AO_USB_IN_SIZE 64 -#define AO_USB_OUT_SIZE 64 - -#define AO_USB_EP0_IDLE 0 -#define AO_USB_EP0_DATA_IN 1 -#define AO_USB_EP0_DATA_OUT 2 - -#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) - -/* CDC definitions */ -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 - -#define SET_LINE_CODING 0x20 -#define GET_LINE_CODING 0x21 -#define SET_CONTROL_LINE_STATE 0x22 - -/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ -struct ao_usb_line_coding { - uint32_t rate; - uint8_t char_format; - uint8_t parity; - uint8_t data_bits; -} ; - -#endif /* _AO_USB_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 9a3b5829..28d0ba87 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -154,182 +154,14 @@ void ao_clock_init(void); /* - * One set of samples read from the A/D converter or telemetry - */ - -#if HAS_ADC - -/* - * ao_adc.c - */ - -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) - - -/* - * A/D data is stored in a ring, with the next sample to be written - * at ao_adc_head - */ -extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -extern volatile __data uint8_t ao_adc_head; -#if HAS_ACCEL_REF -extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; -#endif - -/* Trigger a conversion sequence (called from the timer interrupt) */ -void -ao_adc_poll(void); - -/* Suspend the current task until another A/D sample is converted */ -void -ao_adc_sleep(void); - -/* Get a copy of the last complete A/D sample set */ -void -ao_adc_get(__xdata struct ao_adc *packet); - -/* The A/D interrupt handler */ - -void -ao_adc_isr(void) ao_arch_interrupt(1); - -/* Initialize the A/D converter */ -void -ao_adc_init(void); - -#endif /* HAS_ADC */ - -/* - * ao_beep.c - */ - -/* - * Various pre-defined beep frequencies - * - * frequency = 1/2 (24e6/32) / beep - */ - -#define AO_BEEP_LOW 150 /* 2500Hz */ -#define AO_BEEP_MID 94 /* 3989Hz */ -#define AO_BEEP_HIGH 75 /* 5000Hz */ -#define AO_BEEP_OFF 0 /* off */ - -#define AO_BEEP_g 240 /* 1562.5Hz */ -#define AO_BEEP_gs 227 /* 1652Hz (1655Hz) */ -#define AO_BEEP_aa 214 /* 1752Hz (1754Hz) */ -#define AO_BEEP_bbf 202 /* 1856Hz (1858Hz) */ -#define AO_BEEP_bb 190 /* 1974Hz (1969Hz) */ -#define AO_BEEP_cc 180 /* 2083Hz (2086Hz) */ -#define AO_BEEP_ccs 170 /* 2205Hz (2210Hz) */ -#define AO_BEEP_dd 160 /* 2344Hz (2341Hz) */ -#define AO_BEEP_eef 151 /* 2483Hz (2480Hz) */ -#define AO_BEEP_ee 143 /* 2622Hz (2628Hz) */ -#define AO_BEEP_ff 135 /* 2778Hz (2784Hz) */ -#define AO_BEEP_ffs 127 /* 2953Hz (2950Hz) */ -#define AO_BEEP_gg 120 /* 3125Hz */ -#define AO_BEEP_ggs 113 /* 3319Hz (3311Hz) */ -#define AO_BEEP_aaa 107 /* 3504Hz (3508Hz) */ -#define AO_BEEP_bbbf 101 /* 3713Hz (3716Hz) */ -#define AO_BEEP_bbb 95 /* 3947Hz (3937Hz) */ -#define AO_BEEP_ccc 90 /* 4167Hz (4171Hz) */ -#define AO_BEEP_cccs 85 /* 4412Hz (4419Hz) */ -#define AO_BEEP_ddd 80 /* 4688Hz (4682Hz) */ -#define AO_BEEP_eeef 76 /* 4934Hz (4961Hz) */ -#define AO_BEEP_eee 71 /* 5282Hz (5256Hz) */ -#define AO_BEEP_fff 67 /* 5597Hz (5568Hz) */ -#define AO_BEEP_fffs 64 /* 5859Hz (5899Hz) */ -#define AO_BEEP_ggg 60 /* 6250Hz */ - -/* Set the beeper to the specified tone */ -void -ao_beep(uint8_t beep); - -/* Turn on the beeper for the specified time */ -void -ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant; - -/* Initialize the beeper */ -void -ao_beep_init(void); - -/* - * ao_led.c - */ - -#define AO_LED_NONE 0 - -#ifndef AO_LED_TYPE -#define AO_LED_TYPE uint8_t -#endif - -/* Turn on the specified LEDs */ -void -ao_led_on(AO_LED_TYPE colors); - -/* Turn off the specified LEDs */ -void -ao_led_off(AO_LED_TYPE colors); - -/* Set all of the LEDs to the specified state */ -void -ao_led_set(AO_LED_TYPE colors); - -/* Toggle the specified LEDs */ -void -ao_led_toggle(AO_LED_TYPE colors); - -/* Turn on the specified LEDs for the indicated interval */ -void -ao_led_for(AO_LED_TYPE colors, uint16_t ticks) __reentrant; - -/* Initialize the LEDs */ -void -ao_led_init(AO_LED_TYPE enable); - -/* - * ao_usb.c - */ - -/* Put one character to the USB output queue */ -void -ao_usb_putchar(char c); - -/* Get one character from the USB input queue */ -char -ao_usb_getchar(void); - -/* Poll for a charcter on the USB input queue. - * returns AO_READ_AGAIN if none are available + * ao_mutex.c */ -char -ao_usb_pollchar(void); - -/* Flush the USB output queue */ -void -ao_usb_flush(void); - -#if HAS_USB -/* USB interrupt handler */ -void -ao_usb_isr(void) ao_arch_interrupt(6); -#endif -/* Enable the USB controller */ void -ao_usb_enable(void); - -/* Disable the USB controller */ -void -ao_usb_disable(void); +ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant; -/* Initialize the USB system */ void -ao_usb_init(void); - -#if HAS_USB -extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; -#endif +ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant; /* * ao_cmd.c @@ -396,405 +228,36 @@ ao_cmd_filter(void); #endif /* - * ao_mutex.c - */ - -void -ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant; - -void -ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant; - -/* - * Storage interface, provided by one of the eeprom or flash - * drivers - */ - -/* Total bytes of available storage */ -extern __pdata uint32_t ao_storage_total; - -/* Block size - device is erased in these units. At least 256 bytes */ -extern __pdata uint32_t ao_storage_block; - -/* Byte offset of config block. Will be ao_storage_block bytes long */ -extern __pdata uint32_t ao_storage_config; - -/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -extern __pdata uint16_t ao_storage_unit; - -#define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) - -/* Initialize above values. Can only be called once the OS is running */ -void -ao_storage_setup(void) __reentrant; - -/* Write data. Returns 0 on failure, 1 on success */ -uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Read data. Returns 0 on failure, 1 on success */ -uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Erase a block of storage. This always clears ao_storage_block bytes */ -uint8_t -ao_storage_erase(uint32_t pos) __reentrant; - -/* Flush any pending writes to stable storage */ -void -ao_storage_flush(void) __reentrant; - -/* Initialize the storage code */ -void -ao_storage_init(void); - -/* - * Low-level functions wrapped by ao_storage.c - */ - -/* Read data within a storage unit */ -uint8_t -ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Write data within a storage unit */ -uint8_t -ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Initialize low-level device bits */ -void -ao_storage_device_init(void); - -/* Print out information about flash chips */ -void -ao_storage_device_info(void) __reentrant; - -/* - * ao_log.c - */ - -/* We record flight numbers in the first record of - * the log. Tasks may wait for this to be initialized - * by sleeping on this variable. - */ -extern __xdata uint16_t ao_flight_number; - -extern __pdata uint32_t ao_log_current_pos; -extern __pdata uint32_t ao_log_end_pos; -extern __pdata uint32_t ao_log_start_pos; -extern __xdata uint8_t ao_log_running; -extern __pdata enum flight_state ao_log_state; - -/* required functions from the underlying log system */ - -#define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ -#define AO_LOG_FORMAT_FULL 1 /* 8 byte typed log records */ -#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ -#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ -#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ -#define AO_LOG_FORMAT_NONE 127 /* No log at all */ - -extern __code uint8_t ao_log_format; - -/* Return the flight number from the given log slot, 0 if none */ -uint16_t -ao_log_flight(uint8_t slot); - -/* Flush the log */ -void -ao_log_flush(void); - -/* Logging thread main routine */ -void -ao_log(void); - -/* functions provided in ao_log.c */ - -/* Figure out the current flight number */ -void -ao_log_scan(void) __reentrant; - -/* Return the position of the start of the given log slot */ -uint32_t -ao_log_pos(uint8_t slot); - -/* Start logging to eeprom */ -void -ao_log_start(void); - -/* Stop logging */ -void -ao_log_stop(void); - -/* Initialize the logging system */ -void -ao_log_init(void); - -/* Write out the current flight number to the erase log */ -void -ao_log_write_erase(uint8_t pos); - -/* Returns true if there are any logs stored in eeprom */ -uint8_t -ao_log_present(void); - -/* Returns true if there is no more storage space available */ -uint8_t -ao_log_full(void); - -/* - * ao_log_big.c + * Various drivers */ - -/* - * The data log is recorded in the eeprom as a sequence - * of data packets. - * - * Each packet starts with a 4-byte header that has the - * packet type, the packet checksum and the tick count. Then - * they all contain 2 16 bit values which hold packet-specific - * data. - * - * For each flight, the first packet - * is FLIGHT packet, indicating the serial number of the - * device and a unique number marking the number of flights - * recorded by this device. - * - * During flight, data from the accelerometer and barometer - * are recorded in SENSOR packets, using the raw 16-bit values - * read from the A/D converter. - * - * Also during flight, but at a lower rate, the deployment - * sensors are recorded in DEPLOY packets. The goal here is to - * detect failure in the deployment circuits. - * - * STATE packets hold state transitions as the flight computer - * transitions through different stages of the flight. - */ -#define AO_LOG_FLIGHT 'F' -#define AO_LOG_SENSOR 'A' -#define AO_LOG_TEMP_VOLT 'T' -#define AO_LOG_DEPLOY 'D' -#define AO_LOG_STATE 'S' -#define AO_LOG_GPS_TIME 'G' -#define AO_LOG_GPS_LAT 'N' -#define AO_LOG_GPS_LON 'W' -#define AO_LOG_GPS_ALT 'H' -#define AO_LOG_GPS_SAT 'V' -#define AO_LOG_GPS_DATE 'Y' - -#define AO_LOG_POS_NONE (~0UL) - -struct ao_log_record { - char type; - uint8_t csum; - uint16_t tick; - union { - struct { - int16_t ground_accel; - uint16_t flight; - } flight; - struct { - int16_t accel; - int16_t pres; - } sensor; - struct { - int16_t temp; - int16_t v_batt; - } temp_volt; - struct { - int16_t drogue; - int16_t main; - } deploy; - struct { - uint16_t state; - uint16_t reason; - } state; - struct { - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t flags; - } gps_time; - int32_t gps_latitude; - int32_t gps_longitude; - struct { - int16_t altitude; - uint16_t unused; - } gps_altitude; - struct { - uint16_t svid; - uint8_t unused; - uint8_t c_n; - } gps_sat; - struct { - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t extra; - } gps_date; - struct { - uint16_t d0; - uint16_t d1; - } anon; - } u; -}; - -/* Write a record to the eeprom log */ -uint8_t -ao_log_data(__xdata struct ao_log_record *log) __reentrant; - -/* - * ao_flight.c - */ - -enum ao_flight_state { - ao_flight_startup = 0, - ao_flight_idle = 1, - ao_flight_pad = 2, - ao_flight_boost = 3, - ao_flight_fast = 4, - ao_flight_coast = 5, - ao_flight_drogue = 6, - ao_flight_main = 7, - ao_flight_landed = 8, - ao_flight_invalid = 9 -}; - -extern __pdata enum ao_flight_state ao_flight_state; - -extern __pdata uint16_t ao_launch_time; -extern __pdata uint8_t ao_flight_force_idle; - -/* Flight thread */ -void -ao_flight(void); - -/* Initialize flight thread */ -void -ao_flight_init(void); - -/* - * ao_flight_nano.c - */ - -void -ao_flight_nano_init(void); - -/* - * ao_sample.c - */ - -/* - * Barometer calibration - * - * We directly sample the barometer. The specs say: - * - * Pressure range: 15-115 kPa - * Voltage at 115kPa: 2.82 - * Output scale: 27mV/kPa - * - * If we want to detect launch with the barometer, we need - * a large enough bump to not be fooled by noise. At typical - * launch elevations (0-2000m), a 200Pa pressure change cooresponds - * to about a 20m elevation change. This is 5.4mV, or about 3LSB. - * As all of our calculations are done in 16 bits, we'll actually see a change - * of 16 times this though - * - * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa - */ - -/* Accelerometer calibration - * - * We're sampling the accelerometer through a resistor divider which - * consists of 5k and 10k resistors. This multiplies the values by 2/3. - * That goes into the cc1111 A/D converter, which is running at 11 bits - * of precision with the bits in the MSB of the 16 bit value. Only positive - * values are used, so values should range from 0-32752 for 0-3.3V. The - * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what - * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV, - * for a final computation of: - * - * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g - * - * Zero g was measured at 16000 (we would expect 16384). - * Note that this value is only require to tell if the - * rocket is standing upright. Once that is determined, - * the value of the accelerometer is averaged for 100 samples - * to find the resting accelerometer value, which is used - * for all further flight computations - */ - -#define GRAVITY 9.80665 - -/* - * Above this height, the baro sensor doesn't work - */ -#define AO_MAX_BARO_HEIGHT 12000 - -/* - * Above this speed, baro measurements are unreliable - */ -#define AO_MAX_BARO_SPEED 200 - -#define ACCEL_NOSE_UP (ao_accel_2g >> 2) - -/* - * Speed and acceleration are scaled by 16 to provide a bit more - * resolution while still having reasonable range. Note that this - * limits speed to 2047m/s (around mach 6) and acceleration to - * 2047m/s² (over 200g) - */ - -#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) -#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) -#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) - -extern __pdata uint16_t ao_sample_tick; /* time of last data */ -extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */ -extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */ -extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */ -extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ - -#if HAS_ACCEL -extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ +#if HAS_ADC +#include #endif -extern __pdata int16_t ao_ground_pres; /* startup pressure */ -extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ - -#if HAS_ACCEL -extern __pdata int16_t ao_ground_accel; /* startup acceleration */ -extern __pdata int16_t ao_accel_2g; /* factory accel calibration */ -extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#if HAS_BEEP +#include #endif -void ao_sample_init(void); - -/* returns FALSE in preflight mode, TRUE in flight mode */ -uint8_t ao_sample(void); - -/* - * ao_kalman.c - */ - -#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) -#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) -#define from_fix(x) ((x) >> 16) +#if LEDS_AVAILABLE +#include +#endif -extern __pdata int16_t ao_height; /* meters */ -extern __pdata int16_t ao_speed; /* m/s * 16 */ -extern __pdata int16_t ao_accel; /* m/s² * 16 */ -extern __pdata int16_t ao_max_height; /* max of ao_height */ -extern __pdata int16_t ao_avg_height; /* running average of height */ +#if HAS_USB +#include +#endif -extern __pdata int16_t ao_error_h; -extern __pdata int16_t ao_error_h_sq_avg; +#if HAS_EEPROM +#include +#endif -#if HAS_ACCEL -extern __pdata int16_t ao_error_a; +#if HAS_LOG +#include #endif -void ao_kalman(void); +#if HAS_FLIGHT +#include +#include +#endif /* * ao_report.c @@ -819,125 +282,12 @@ ao_altitude_to_pres(int16_t alt) __reentrant; int16_t ao_temp_to_dC(int16_t temp) __reentrant; -/* - * ao_dbg.c - * - * debug another telemetrum board - */ - -/* Send a byte to the dbg target */ -void -ao_dbg_send_byte(uint8_t byte); - -/* Receive a byte from the dbg target */ -uint8_t -ao_dbg_recv_byte(void); - -/* Start a bulk transfer to/from dbg target memory */ -void -ao_dbg_start_transfer(uint16_t addr); - -/* End a bulk transfer to/from dbg target memory */ -void -ao_dbg_end_transfer(void); - -/* Write a byte to dbg target memory */ -void -ao_dbg_write_byte(uint8_t byte); - -/* Read a byte from dbg target memory */ -uint8_t -ao_dbg_read_byte(void); - -/* Enable dbg mode, switching use of the pins */ -void -ao_dbg_debug_mode(void); - -/* Reset the dbg target */ -void -ao_dbg_reset(void); - -void -ao_dbg_init(void); - -/* - * ao_serial.c - */ - -#ifndef HAS_SERIAL_1 -#error Please define HAS_SERIAL_1 +#if HAS_DBG +#include #endif -#if HAS_SERIAL_1 | HAS_SERIAL_2 | HAS_SERIAL_3 -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - -void -ao_serial_rx1_isr(void) ao_arch_interrupt(3); - -void -ao_serial_tx1_isr(void) ao_arch_interrupt(14); - -char -ao_serial_getchar(void) __critical; - -#if USE_SERIAL_STDIN -char -ao_serial_pollchar(void) __critical; - -void -ao_serial_set_stdin(uint8_t in); -#endif - -void -ao_serial_putchar(char c) __critical; - -void -ao_serial_drain(void) __critical; - -#define AO_SERIAL_SPEED_4800 0 -#define AO_SERIAL_SPEED_9600 1 -#define AO_SERIAL_SPEED_19200 2 -#define AO_SERIAL_SPEED_57600 3 - -void -ao_serial_set_speed(uint8_t speed); - -void -ao_serial_init(void); -#endif - -#ifndef HAS_SERIAL_0 -#define HAS_SERIAL_0 0 -#endif - -#if HAS_SERIAL_0 - -extern volatile __xdata struct ao_fifo ao_usart0_rx_fifo; -extern volatile __xdata struct ao_fifo ao_usart0_tx_fifo; - -void -ao_serial0_rx0_isr(void) ao_arch_interrupt(2); - -void -ao_serial0_tx0_isr(void) ao_arch_interrupt(7); - -char -ao_serial0_getchar(void) __critical; - -void -ao_serial0_putchar(char c) __critical; - -void -ao_serial0_drain(void) __critical; - -void -ao_serial0_set_speed(uint8_t speed); - -void -ao_serial0_init(void); - +#if HAS_SERIAL_0 || HAS_SERIAL_1 || HAS_SERIAL_2 || HAS_SERIAL_3 +#include #endif diff --git a/src/core/ao_adc.h b/src/core/ao_adc.h new file mode 100644 index 00000000..db5bfab3 --- /dev/null +++ b/src/core/ao_adc.h @@ -0,0 +1,62 @@ +/* + * 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_ADC_H_ +#define _AO_ADC_H_ + + + +/* + * One set of samples read from the A/D converter or telemetry + */ + + +/* + * ao_adc.c + */ + +#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) +#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) + + +/* + * A/D data is stored in a ring, with the next sample to be written + * at ao_adc_head + */ +extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; +extern volatile __data uint8_t ao_adc_head; +#if HAS_ACCEL_REF +extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; +#endif + +/* Trigger a conversion sequence (called from the timer interrupt) */ +void +ao_adc_poll(void); + +/* Suspend the current task until another A/D sample is converted */ +void +ao_adc_sleep(void); + +/* Get a copy of the last complete A/D sample set */ +void +ao_adc_get(__xdata struct ao_adc *packet); + +/* Initialize the A/D converter */ +void +ao_adc_init(void); + +#endif /* _AO_ADC_H_ */ diff --git a/src/core/ao_beep.h b/src/core/ao_beep.h new file mode 100644 index 00000000..55f61171 --- /dev/null +++ b/src/core/ao_beep.h @@ -0,0 +1,74 @@ +/* + * 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_BEEP_H_ +#define _AO_BEEP_H_ + +/* + * ao_beep.c + */ + +/* + * Various pre-defined beep frequencies + * + * frequency = 1/2 (24e6/32) / beep + */ + +#define AO_BEEP_LOW 150 /* 2500Hz */ +#define AO_BEEP_MID 94 /* 3989Hz */ +#define AO_BEEP_HIGH 75 /* 5000Hz */ +#define AO_BEEP_OFF 0 /* off */ + +#define AO_BEEP_g 240 /* 1562.5Hz */ +#define AO_BEEP_gs 227 /* 1652Hz (1655Hz) */ +#define AO_BEEP_aa 214 /* 1752Hz (1754Hz) */ +#define AO_BEEP_bbf 202 /* 1856Hz (1858Hz) */ +#define AO_BEEP_bb 190 /* 1974Hz (1969Hz) */ +#define AO_BEEP_cc 180 /* 2083Hz (2086Hz) */ +#define AO_BEEP_ccs 170 /* 2205Hz (2210Hz) */ +#define AO_BEEP_dd 160 /* 2344Hz (2341Hz) */ +#define AO_BEEP_eef 151 /* 2483Hz (2480Hz) */ +#define AO_BEEP_ee 143 /* 2622Hz (2628Hz) */ +#define AO_BEEP_ff 135 /* 2778Hz (2784Hz) */ +#define AO_BEEP_ffs 127 /* 2953Hz (2950Hz) */ +#define AO_BEEP_gg 120 /* 3125Hz */ +#define AO_BEEP_ggs 113 /* 3319Hz (3311Hz) */ +#define AO_BEEP_aaa 107 /* 3504Hz (3508Hz) */ +#define AO_BEEP_bbbf 101 /* 3713Hz (3716Hz) */ +#define AO_BEEP_bbb 95 /* 3947Hz (3937Hz) */ +#define AO_BEEP_ccc 90 /* 4167Hz (4171Hz) */ +#define AO_BEEP_cccs 85 /* 4412Hz (4419Hz) */ +#define AO_BEEP_ddd 80 /* 4688Hz (4682Hz) */ +#define AO_BEEP_eeef 76 /* 4934Hz (4961Hz) */ +#define AO_BEEP_eee 71 /* 5282Hz (5256Hz) */ +#define AO_BEEP_fff 67 /* 5597Hz (5568Hz) */ +#define AO_BEEP_fffs 64 /* 5859Hz (5899Hz) */ +#define AO_BEEP_ggg 60 /* 6250Hz */ + +/* Set the beeper to the specified tone */ +void +ao_beep(uint8_t beep); + +/* Turn on the beeper for the specified time */ +void +ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant; + +/* Initialize the beeper */ +void +ao_beep_init(void); + +#endif /* _AO_BEEP_H_ */ diff --git a/src/core/ao_dbg.h b/src/core/ao_dbg.h new file mode 100644 index 00000000..181e6ec2 --- /dev/null +++ b/src/core/ao_dbg.h @@ -0,0 +1,62 @@ +/* + * 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_DBG_H_ +#define _AO_DBG_H_ + +/* + * ao_dbg.c + * + * debug another telemetrum board + */ + +/* Send a byte to the dbg target */ +void +ao_dbg_send_byte(uint8_t byte); + +/* Receive a byte from the dbg target */ +uint8_t +ao_dbg_recv_byte(void); + +/* Start a bulk transfer to/from dbg target memory */ +void +ao_dbg_start_transfer(uint16_t addr); + +/* End a bulk transfer to/from dbg target memory */ +void +ao_dbg_end_transfer(void); + +/* Write a byte to dbg target memory */ +void +ao_dbg_write_byte(uint8_t byte); + +/* Read a byte from dbg target memory */ +uint8_t +ao_dbg_read_byte(void); + +/* Enable dbg mode, switching use of the pins */ +void +ao_dbg_debug_mode(void); + +/* Reset the dbg target */ +void +ao_dbg_reset(void); + +void +ao_dbg_init(void); + +#endif /* _AO_DBG_H_ */ diff --git a/src/core/ao_flight.h b/src/core/ao_flight.h new file mode 100644 index 00000000..aa5ab60d --- /dev/null +++ b/src/core/ao_flight.h @@ -0,0 +1,59 @@ +/* + * 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_FLIGHT_H_ +#define _AO_FLIGHT_H_ + + +/* + * ao_flight.c + */ + +enum ao_flight_state { + ao_flight_startup = 0, + ao_flight_idle = 1, + ao_flight_pad = 2, + ao_flight_boost = 3, + ao_flight_fast = 4, + ao_flight_coast = 5, + ao_flight_drogue = 6, + ao_flight_main = 7, + ao_flight_landed = 8, + ao_flight_invalid = 9 +}; + +extern __pdata enum ao_flight_state ao_flight_state; + +extern __pdata uint16_t ao_launch_time; +extern __pdata uint8_t ao_flight_force_idle; + +/* Flight thread */ +void +ao_flight(void); + +/* Initialize flight thread */ +void +ao_flight_init(void); + +/* + * ao_flight_nano.c + */ + +void +ao_flight_nano_init(void); + +#endif /* _AO_FLIGHT_H_ */ diff --git a/src/core/ao_led.h b/src/core/ao_led.h new file mode 100644 index 00000000..edc5fd1f --- /dev/null +++ b/src/core/ao_led.h @@ -0,0 +1,55 @@ +/* + * 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_LED_H_ +#define _AO_LED_H_ + +/* + * ao_led.c + */ + +#define AO_LED_NONE 0 + +#ifndef AO_LED_TYPE +#define AO_LED_TYPE uint8_t +#endif + +/* Turn on the specified LEDs */ +void +ao_led_on(AO_LED_TYPE colors); + +/* Turn off the specified LEDs */ +void +ao_led_off(AO_LED_TYPE colors); + +/* Set all of the LEDs to the specified state */ +void +ao_led_set(AO_LED_TYPE colors); + +/* Toggle the specified LEDs */ +void +ao_led_toggle(AO_LED_TYPE colors); + +/* Turn on the specified LEDs for the indicated interval */ +void +ao_led_for(AO_LED_TYPE colors, uint16_t ticks) __reentrant; + +/* Initialize the LEDs */ +void +ao_led_init(AO_LED_TYPE enable); + +#endif /* _AO_LED_H_ */ diff --git a/src/core/ao_log.h b/src/core/ao_log.h new file mode 100644 index 00000000..611c00d5 --- /dev/null +++ b/src/core/ao_log.h @@ -0,0 +1,196 @@ +/* + * 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_LOG_H_ +#define _AO_LOG_H_ + +/* + * ao_log.c + */ + +/* We record flight numbers in the first record of + * the log. Tasks may wait for this to be initialized + * by sleeping on this variable. + */ +extern __xdata uint16_t ao_flight_number; + +extern __pdata uint32_t ao_log_current_pos; +extern __pdata uint32_t ao_log_end_pos; +extern __pdata uint32_t ao_log_start_pos; +extern __xdata uint8_t ao_log_running; +extern __pdata enum flight_state ao_log_state; + +/* required functions from the underlying log system */ + +#define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ +#define AO_LOG_FORMAT_FULL 1 /* 8 byte typed log records */ +#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ +#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ +#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ +#define AO_LOG_FORMAT_NONE 127 /* No log at all */ + +extern __code uint8_t ao_log_format; + +/* Return the flight number from the given log slot, 0 if none */ +uint16_t +ao_log_flight(uint8_t slot); + +/* Flush the log */ +void +ao_log_flush(void); + +/* Logging thread main routine */ +void +ao_log(void); + +/* functions provided in ao_log.c */ + +/* Figure out the current flight number */ +void +ao_log_scan(void) __reentrant; + +/* Return the position of the start of the given log slot */ +uint32_t +ao_log_pos(uint8_t slot); + +/* Start logging to eeprom */ +void +ao_log_start(void); + +/* Stop logging */ +void +ao_log_stop(void); + +/* Initialize the logging system */ +void +ao_log_init(void); + +/* Write out the current flight number to the erase log */ +void +ao_log_write_erase(uint8_t pos); + +/* Returns true if there are any logs stored in eeprom */ +uint8_t +ao_log_present(void); + +/* Returns true if there is no more storage space available */ +uint8_t +ao_log_full(void); + +/* + * ao_log_big.c + */ + +/* + * The data log is recorded in the eeprom as a sequence + * of data packets. + * + * Each packet starts with a 4-byte header that has the + * packet type, the packet checksum and the tick count. Then + * they all contain 2 16 bit values which hold packet-specific + * data. + * + * For each flight, the first packet + * is FLIGHT packet, indicating the serial number of the + * device and a unique number marking the number of flights + * recorded by this device. + * + * During flight, data from the accelerometer and barometer + * are recorded in SENSOR packets, using the raw 16-bit values + * read from the A/D converter. + * + * Also during flight, but at a lower rate, the deployment + * sensors are recorded in DEPLOY packets. The goal here is to + * detect failure in the deployment circuits. + * + * STATE packets hold state transitions as the flight computer + * transitions through different stages of the flight. + */ +#define AO_LOG_FLIGHT 'F' +#define AO_LOG_SENSOR 'A' +#define AO_LOG_TEMP_VOLT 'T' +#define AO_LOG_DEPLOY 'D' +#define AO_LOG_STATE 'S' +#define AO_LOG_GPS_TIME 'G' +#define AO_LOG_GPS_LAT 'N' +#define AO_LOG_GPS_LON 'W' +#define AO_LOG_GPS_ALT 'H' +#define AO_LOG_GPS_SAT 'V' +#define AO_LOG_GPS_DATE 'Y' + +#define AO_LOG_POS_NONE (~0UL) + +struct ao_log_record { + char type; + uint8_t csum; + uint16_t tick; + union { + struct { + int16_t ground_accel; + uint16_t flight; + } flight; + struct { + int16_t accel; + int16_t pres; + } sensor; + struct { + int16_t temp; + int16_t v_batt; + } temp_volt; + struct { + int16_t drogue; + int16_t main; + } deploy; + struct { + uint16_t state; + uint16_t reason; + } state; + struct { + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + } gps_time; + int32_t gps_latitude; + int32_t gps_longitude; + struct { + int16_t altitude; + uint16_t unused; + } gps_altitude; + struct { + uint16_t svid; + uint8_t unused; + uint8_t c_n; + } gps_sat; + struct { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t extra; + } gps_date; + struct { + uint16_t d0; + uint16_t d1; + } anon; + } u; +}; + +/* Write a record to the eeprom log */ +uint8_t +ao_log_data(__xdata struct ao_log_record *log) __reentrant; + +#endif /* _AO_LOG_H_ */ diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 9e1b06d3..18ab85dd 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -15,7 +15,9 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" +#include +#include +#include __code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRY; diff --git a/src/core/ao_product.c b/src/core/ao_product.c index fb59580b..f79922f5 100644 --- a/src/core/ao_product.c +++ b/src/core/ao_product.c @@ -70,26 +70,26 @@ __code __at(0x00aa) uint8_t ao_usb_descriptors [] = /* Header functional descriptor */ 0x05, - CS_INTERFACE, + AO_USB_CS_INTERFACE, 0x00, /* bDescriptor SubType Header */ LE_WORD(0x0110), /* CDC version 1.1 */ /* Call management functional descriptor */ 0x05, - CS_INTERFACE, + AO_USB_CS_INTERFACE, 0x01, /* bDescriptor SubType Call Management */ 0x01, /* bmCapabilities = device handles call management */ 0x01, /* bDataInterface call management interface number */ /* ACM functional descriptor */ 0x04, - CS_INTERFACE, + AO_USB_CS_INTERFACE, 0x02, /* bDescriptor SubType Abstract Control Management */ 0x02, /* bmCapabilities = D1 (Set_line_Coding, Set_Control_Line_State, Get_Line_Coding and Serial_State) */ /* Union functional descriptor */ 0x05, - CS_INTERFACE, + AO_USB_CS_INTERFACE, 0x06, /* bDescriptor SubType Union Functional descriptor */ 0x00, /* bMasterInterface */ 0x01, /* bSlaveInterface0 */ diff --git a/src/core/ao_report.c b/src/core/ao_report.c index 7c928792..eb90a4f8 100644 --- a/src/core/ao_report.c +++ b/src/core/ao_report.c @@ -16,6 +16,8 @@ */ #include "ao.h" +#include +#include #define BIT(i,x) ((x) ? (1 << (i)) : 0) #define MORSE1(a) (1 | BIT(3,a)) diff --git a/src/core/ao_sample.h b/src/core/ao_sample.h new file mode 100644 index 00000000..fb0e69e8 --- /dev/null +++ b/src/core/ao_sample.h @@ -0,0 +1,137 @@ +/* + * 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_SAMPLE_H_ +#define _AO_SAMPLE_H_ + +/* + * ao_sample.c + */ + +/* + * Barometer calibration + * + * We directly sample the barometer. The specs say: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * If we want to detect launch with the barometer, we need + * a large enough bump to not be fooled by noise. At typical + * launch elevations (0-2000m), a 200Pa pressure change cooresponds + * to about a 20m elevation change. This is 5.4mV, or about 3LSB. + * As all of our calculations are done in 16 bits, we'll actually see a change + * of 16 times this though + * + * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa + */ + +/* Accelerometer calibration + * + * We're sampling the accelerometer through a resistor divider which + * consists of 5k and 10k resistors. This multiplies the values by 2/3. + * That goes into the cc1111 A/D converter, which is running at 11 bits + * of precision with the bits in the MSB of the 16 bit value. Only positive + * values are used, so values should range from 0-32752 for 0-3.3V. The + * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what + * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV, + * for a final computation of: + * + * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g + * + * Zero g was measured at 16000 (we would expect 16384). + * Note that this value is only require to tell if the + * rocket is standing upright. Once that is determined, + * the value of the accelerometer is averaged for 100 samples + * to find the resting accelerometer value, which is used + * for all further flight computations + */ + +#define GRAVITY 9.80665 + +/* + * Above this height, the baro sensor doesn't work + */ +#define AO_MAX_BARO_HEIGHT 12000 + +/* + * Above this speed, baro measurements are unreliable + */ +#define AO_MAX_BARO_SPEED 200 + +#define ACCEL_NOSE_UP (ao_accel_2g >> 2) + +/* + * Speed and acceleration are scaled by 16 to provide a bit more + * resolution while still having reasonable range. Note that this + * limits speed to 2047m/s (around mach 6) and acceleration to + * 2047m/s² (over 200g) + */ + +#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) +#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) +#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) + +extern __pdata uint16_t ao_sample_tick; /* time of last data */ +extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */ +extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */ +extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */ +extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ + +#if HAS_ACCEL +extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ +#endif + +extern __pdata int16_t ao_ground_pres; /* startup pressure */ +extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +extern __pdata int16_t ao_ground_accel; /* startup acceleration */ +extern __pdata int16_t ao_accel_2g; /* factory accel calibration */ +extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +void ao_sample_init(void); + +/* returns FALSE in preflight mode, TRUE in flight mode */ +uint8_t ao_sample(void); + +/* + * ao_kalman.c + */ + +#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) +#define from_fix(x) ((x) >> 16) + +extern __pdata int16_t ao_height; /* meters */ +extern __pdata int16_t ao_speed; /* m/s * 16 */ +extern __pdata int16_t ao_accel; /* m/s² * 16 */ +extern __pdata int16_t ao_max_height; /* max of ao_height */ +extern __pdata int16_t ao_avg_height; /* running average of height */ + +extern __pdata int16_t ao_error_h; +extern __pdata int16_t ao_error_h_sq_avg; + +#if HAS_ACCEL +extern __pdata int16_t ao_error_a; +#endif + +void ao_kalman(void); + +#endif /* _AO_SAMPLE_H_ */ diff --git a/src/core/ao_serial.h b/src/core/ao_serial.h new file mode 100644 index 00000000..53aa8a89 --- /dev/null +++ b/src/core/ao_serial.h @@ -0,0 +1,86 @@ +/* + * 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_SERIAL_H_ +#define _AO_SERIAL_H_ + +#define AO_SERIAL_SPEED_4800 0 +#define AO_SERIAL_SPEED_9600 1 +#define AO_SERIAL_SPEED_19200 2 +#define AO_SERIAL_SPEED_57600 3 + +#if HAS_SERIAL_0 +extern volatile __xdata struct ao_fifo ao_serial0_rx_fifo; +extern volatile __xdata struct ao_fifo ao_serial0_tx_fifo; + +char +ao_serial0_getchar(void); + +void +ao_serial0_putchar(char c); + +void +ao_serial0_drain(void); + +void +ao_serial0_set_speed(uint8_t speed); +#endif + +#if HAS_SERIAL_1 +extern volatile __xdata struct ao_fifo ao_serial1_rx_fifo; +extern volatile __xdata struct ao_fifo ao_serial1_tx_fifo; + +char +ao_serial1_getchar(void); + +char +ao_serial1_pollchar(void); + +void +ao_serial1_putchar(char c); + +void +ao_serial1_drain(void); + +void +ao_serial1_set_speed(uint8_t speed); +#endif + +#if HAS_SERIAL_2 +extern volatile __xdata struct ao_fifo ao_serial2_rx_fifo; +extern volatile __xdata struct ao_fifo ao_serial2_tx_fifo; + +char +ao_serial2_getchar(void); + +char +ao_serial2_pollchar(void); + +void +ao_serial2_putchar(char c); + +void +ao_serial2_drain(void); + +void +ao_serial2_set_speed(uint8_t speed); +#endif + +void +ao_serial_init(void); + +#endif /* _AO_SERIAL_H_ */ diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index 2967e705..18fa913e 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -21,6 +21,12 @@ * Basic I/O functions to support SDCC stdio package */ +#ifdef SERIAL_STDIN_PORT +#define USE_SERIAL_STDIN 1 +#else +#define USE_SERIAL_STDIN 0 +#endif + #define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) __xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS]; diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c index ff4747d0..66394e01 100644 --- a/src/core/ao_storage.c +++ b/src/core/ao_storage.c @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" +#include uint8_t ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant diff --git a/src/core/ao_storage.h b/src/core/ao_storage.h new file mode 100644 index 00000000..873fe097 --- /dev/null +++ b/src/core/ao_storage.h @@ -0,0 +1,84 @@ +/* + * 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_STORAGE_H_ +#define _AO_STORAGE_H_ + +/* + * Storage interface, provided by one of the eeprom or flash + * drivers + */ + +/* Total bytes of available storage */ +extern __pdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +extern __pdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +extern __pdata uint32_t ao_storage_config; + +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +extern __pdata uint16_t ao_storage_unit; + +#define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) + +/* Initialize above values. Can only be called once the OS is running */ +void +ao_storage_setup(void) __reentrant; + +/* Write data. Returns 0 on failure, 1 on success */ +uint8_t +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Read data. Returns 0 on failure, 1 on success */ +uint8_t +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Erase a block of storage. This always clears ao_storage_block bytes */ +uint8_t +ao_storage_erase(uint32_t pos) __reentrant; + +/* Flush any pending writes to stable storage */ +void +ao_storage_flush(void) __reentrant; + +/* Initialize the storage code */ +void +ao_storage_init(void); + +/* + * Low-level functions wrapped by ao_storage.c + */ + +/* Read data within a storage unit */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Write data within a storage unit */ +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Initialize low-level device bits */ +void +ao_storage_device_init(void); + +/* Print out information about flash chips */ +void +ao_storage_device_info(void) __reentrant; + +#endif /* _AO_STORAGE_H_ */ diff --git a/src/core/ao_usb.h b/src/core/ao_usb.h new file mode 100644 index 00000000..e051db93 --- /dev/null +++ b/src/core/ao_usb.h @@ -0,0 +1,136 @@ +/* + * 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_USB_H_ +#define _AO_USB_H_ + +/* + * ao_usb.c + */ + +/* Put one character to the USB output queue */ +void +ao_usb_putchar(char c); + +/* Get one character from the USB input queue */ +char +ao_usb_getchar(void); + +/* Poll for a charcter on the USB input queue. + * returns AO_READ_AGAIN if none are available + */ +char +ao_usb_pollchar(void); + +/* Flush the USB output queue */ +void +ao_usb_flush(void); + +/* Enable the USB controller */ +void +ao_usb_enable(void); + +/* Disable the USB controller */ +void +ao_usb_disable(void); + +/* Initialize the USB system */ +void +ao_usb_init(void); + +extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; + +#define AO_USB_SETUP_DIR_MASK (0x01 << 7) +#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) +#define AO_USB_SETUP_RECIP_MASK (0x1f) + +#define AO_USB_DIR_OUT 0 +#define AO_USB_DIR_IN (1 << 7) + +#define AO_USB_TYPE_STANDARD 0 +#define AO_USB_TYPE_CLASS (1 << 5) +#define AO_USB_TYPE_VENDOR (2 << 5) +#define AO_USB_TYPE_RESERVED (3 << 5) + +#define AO_USB_RECIP_DEVICE 0 +#define AO_USB_RECIP_INTERFACE 1 +#define AO_USB_RECIP_ENDPOINT 2 +#define AO_USB_RECIP_OTHER 3 + +/* standard requests */ +#define AO_USB_REQ_GET_STATUS 0x00 +#define AO_USB_REQ_CLEAR_FEATURE 0x01 +#define AO_USB_REQ_SET_FEATURE 0x03 +#define AO_USB_REQ_SET_ADDRESS 0x05 +#define AO_USB_REQ_GET_DESCRIPTOR 0x06 +#define AO_USB_REQ_SET_DESCRIPTOR 0x07 +#define AO_USB_REQ_GET_CONFIGURATION 0x08 +#define AO_USB_REQ_SET_CONFIGURATION 0x09 +#define AO_USB_REQ_GET_INTERFACE 0x0A +#define AO_USB_REQ_SET_INTERFACE 0x0B +#define AO_USB_REQ_SYNCH_FRAME 0x0C + +#define AO_USB_DESC_DEVICE 1 +#define AO_USB_DESC_CONFIGURATION 2 +#define AO_USB_DESC_STRING 3 +#define AO_USB_DESC_INTERFACE 4 +#define AO_USB_DESC_ENDPOINT 5 +#define AO_USB_DESC_DEVICE_QUALIFIER 6 +#define AO_USB_DESC_OTHER_SPEED 7 +#define AO_USB_DESC_INTERFACE_POWER 8 + +#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) +#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) + +#define AO_USB_CONTROL_EP 0 +#define AO_USB_CONTROL_SIZE 32 + +#define AO_USB_INT_EP 1 +#define AO_USB_INT_SIZE 8 + +#define AO_USB_OUT_EP 4 +#define AO_USB_IN_EP 5 +/* + * USB bulk packets can only come in 8, 16, 32 and 64 + * byte sizes, so we'll use 64 for everything + */ +#define AO_USB_IN_SIZE 64 +#define AO_USB_OUT_SIZE 64 + +#define AO_USB_EP0_IDLE 0 +#define AO_USB_EP0_DATA_IN 1 +#define AO_USB_EP0_DATA_OUT 2 + +#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) + +/* CDC definitions */ +#define AO_USB_CS_INTERFACE 0x24 +#define AO_USB_CS_ENDPOINT 0x25 + +#define AO_USB_SET_LINE_CODING 0x20 +#define AO_USB_GET_LINE_CODING 0x21 +#define AO_USB_SET_CONTROL_LINE_STATE 0x22 + +/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ +struct ao_usb_line_coding { + uint32_t rate; + uint8_t char_format; + uint8_t parity; + uint8_t data_bits; +} ; + +#endif /* _AO_USB_H_ */ diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index 5eb78815..f193ac8e 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -17,6 +17,13 @@ #include "ao.h" +#ifndef ao_serial_btm_getchar +#define ao_serial_btm_putchar ao_serial1_putchar +#define ao_serial_btm_pollchar ao_serial1_pollchar +#define ao_serial_btm_set_speed ao_serial1_set_speed +#define ao_serial_btm_drain ao_serial1_drain +#endif + int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; @@ -80,9 +87,9 @@ ao_btm_speed(void) { ao_cmd_decimal(); if (ao_cmd_lex_u32 == 57600) - ao_serial_set_speed(AO_SERIAL_SPEED_57600); + ao_serial_btm_set_speed(AO_SERIAL_SPEED_57600); else if (ao_cmd_lex_u32 == 19200) - ao_serial_set_speed(AO_SERIAL_SPEED_19200); + ao_serial_btm_set_speed(AO_SERIAL_SPEED_19200); else ao_cmd_status = ao_cmd_syntax_error; } @@ -104,8 +111,6 @@ __code struct ao_cmds ao_btm_cmds[] = { #define AO_BTM_MAX_REPLY 16 __xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; -extern volatile __xdata struct ao_fifo ao_usart1_rx_fifo; - /* * Read a line of data from the serial port, truncating * it after a few characters. @@ -119,7 +124,7 @@ ao_btm_get_line(void) for (;;) { - while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { + while ((c = ao_serial_btm_pollchar()) != AO_READ_AGAIN) { ao_btm_log_in_char(c); if (ao_btm_reply_len < sizeof (ao_btm_reply)) ao_btm_reply[ao_btm_reply_len++] = c; @@ -128,7 +133,7 @@ ao_btm_get_line(void) } for (c = 0; c < 10; c++) { ao_delay(AO_MS_TO_TICKS(10)); - if (!ao_fifo_empty(ao_usart1_rx_fifo)) + if (!ao_fifo_empty(ao_serial1_rx_fifo)) break; } if (c == 10) @@ -168,7 +173,7 @@ void ao_btm_putchar(char c) { ao_btm_log_out_char(c); - ao_serial_putchar(c); + ao_serial_btm_putchar(c); ao_delay(1); } @@ -229,8 +234,8 @@ ao_btm_set_name(void) uint8_t ao_btm_try_speed(uint8_t speed) { - ao_serial_set_speed(speed); - ao_btm_drain(); + ao_serial_btm_set_speed(speed); + ao_serial_btm_drain(); (void) ao_btm_cmd("\rATE0\rATQ0\r"); if (ao_btm_cmd("AT\r") == 1) return 1; @@ -274,8 +279,8 @@ ao_btm(void) /* Turn off status reporting */ ao_btm_cmd("ATQ1\r"); - ao_btm_stdio = ao_add_stdio(ao_serial_pollchar, - ao_serial_putchar, + ao_btm_stdio = ao_add_stdio(ao_serial_btm_pollchar, + ao_serial_btm_putchar, NULL); ao_btm_echo(0); @@ -341,7 +346,8 @@ void ao_btm_init (void) { ao_serial_init(); - ao_serial_set_speed(AO_SERIAL_SPEED_19200); + + ao_serial_btm_set_speed(AO_SERIAL_SPEED_19200); #if BT_LINK_ON_P1 /* diff --git a/src/drivers/ao_gps_sirf.c b/src/drivers/ao_gps_sirf.c index f2abbf84..91fc948b 100644 --- a/src/drivers/ao_gps_sirf.c +++ b/src/drivers/ao_gps_sirf.c @@ -124,7 +124,13 @@ static __xdata struct sirf_measured_tracker_data ao_sirf_tracker_data; static __pdata uint16_t ao_sirf_cksum; static __pdata uint16_t ao_sirf_len; -#define ao_sirf_byte() ((uint8_t) ao_serial_getchar()) +#ifndef ao_sirf_getchar +#define ao_sirf_getchar ao_serial1_getchar +#define ao_sirf_putchar ao_serial1_putchar +#define ao_sirf_set_speed ao_serial1_set_speed +#endif + +#define ao_sirf_byte() ((uint8_t) ao_sirf_getchar()) static uint8_t data_byte(void) { @@ -283,15 +289,15 @@ static void ao_gps_setup(void) __reentrant { uint8_t i, k; - ao_serial_set_speed(AO_SERIAL_SPEED_4800); + ao_sirf_set_speed(AO_SERIAL_SPEED_4800); for (i = 0; i < 64; i++) - ao_serial_putchar(0x00); + ao_sirf_putchar(0x00); for (k = 0; k < 3; k++) for (i = 0; i < sizeof (ao_gps_set_nmea); i++) - ao_serial_putchar(ao_gps_set_nmea[i]); - ao_serial_set_speed(AO_SERIAL_SPEED_57600); + ao_sirf_putchar(ao_gps_set_nmea[i]); + ao_sirf_set_speed(AO_SERIAL_SPEED_57600); for (i = 0; i < 64; i++) - ao_serial_putchar(0x00); + ao_sirf_putchar(0x00); } static const char ao_gps_set_message_rate[] = { @@ -307,16 +313,16 @@ ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) __reentrant uint8_t i; for (i = 0; i < sizeof (ao_gps_set_message_rate); i++) - ao_serial_putchar(ao_gps_set_message_rate[i]); - ao_serial_putchar(msg); - ao_serial_putchar(rate); + ao_sirf_putchar(ao_gps_set_message_rate[i]); + ao_sirf_putchar(msg); + ao_sirf_putchar(rate); cksum = 0xa6 + msg + rate; for (i = 0; i < 4; i++) - ao_serial_putchar(0); - ao_serial_putchar((cksum >> 8) & 0x7f); - ao_serial_putchar(cksum & 0xff); - ao_serial_putchar(0xb0); - ao_serial_putchar(0xb3); + ao_sirf_putchar(0); + ao_sirf_putchar((cksum >> 8) & 0x7f); + ao_sirf_putchar(cksum & 0xff); + ao_sirf_putchar(0xb0); + ao_sirf_putchar(0xb3); } static const uint8_t sirf_disable[] = { @@ -338,7 +344,7 @@ ao_gps(void) __reentrant for (k = 0; k < 5; k++) { for (i = 0; i < sizeof (ao_gps_config); i++) - ao_serial_putchar(ao_gps_config[i]); + ao_sirf_putchar(ao_gps_config[i]); for (i = 0; i < sizeof (sirf_disable); i++) ao_sirf_set_message_rate(sirf_disable[i], 0); ao_sirf_set_message_rate(41, 1); diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 39e36cc8..84616a05 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -20,15 +20,15 @@ #endif #ifndef ao_gps_getchar -#define ao_gps_getchar ao_serial_getchar +#define ao_gps_getchar ao_serial1_getchar #endif #ifndef ao_gps_putchar -#define ao_gps_putchar ao_serial_putchar +#define ao_gps_putchar ao_serial1_putchar #endif #ifndef ao_gps_set_speed -#define ao_gps_set_speed ao_serial_set_speed +#define ao_gps_set_speed ao_serial1_set_speed #endif __xdata uint8_t ao_gps_mutex; diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c index 1ebb1480..fa9db98b 100644 --- a/src/drivers/ao_science_slave.c +++ b/src/drivers/ao_science_slave.c @@ -17,6 +17,7 @@ #include "ao.h" #include "ao_product.h" +#include "ao_flight.h" struct ao_companion_command ao_companion_command; diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index e4e5def6..f761e5c3 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -61,6 +61,8 @@ #define ao_gps_putchar ao_serial3_putchar #define ao_gps_set_speed ao_serial3_set_speed +#define HAS_EEPROM 1 +#define USE_INTERNAL_FLASH 0 #define HAS_USB 1 #define HAS_BEEP 1 diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 97c9d792..46c63418 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -17,7 +17,9 @@ #include "ao.h" +#if HAS_LOG __code uint8_t ao_log_format = AO_LOG_FORMAT_NONE; /* until we actually log stuff */ +#endif void main(void) diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 8875ff48..963c7be4 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include #include static __xdata struct ao_telemetry_sensor ao_tel_sensor; diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index adb6eb94..62af86f7 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -181,8 +181,6 @@ void ao_lcd_font_init(void); void ao_lcd_font_string(char *s); -#define USE_SERIAL_STDIN (USE_SERIAL_1_STDIN + USE_SERIAL_2_STDIN + USE_SERIAL_3_STDIN) - char ao_serial1_getchar(void); diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 3cebc094..406da9fb 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -249,7 +249,7 @@ ao_serial2_set_speed(uint8_t speed) struct ao_stm_usart ao_stm_usart3; -void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_3_STDIN); } +void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_2_STDIN); } char ao_serial3_getchar(void) diff --git a/src/stm/ao_usb.h b/src/stm/ao_usb.h deleted file mode 100644 index d3129d34..00000000 --- a/src/stm/ao_usb.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright © 2009 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_USB_H_ -#define _AO_USB_H_ - -#define AO_USB_SETUP_DIR_MASK (0x01 << 7) -#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) -#define AO_USB_SETUP_RECIP_MASK (0x1f) - -#define AO_USB_DIR_OUT 0 -#define AO_USB_DIR_IN (1 << 7) - -#define AO_USB_TYPE_STANDARD 0 -#define AO_USB_TYPE_CLASS (1 << 5) -#define AO_USB_TYPE_VENDOR (2 << 5) -#define AO_USB_TYPE_RESERVED (3 << 5) - -#define AO_USB_RECIP_DEVICE 0 -#define AO_USB_RECIP_INTERFACE 1 -#define AO_USB_RECIP_ENDPOINT 2 -#define AO_USB_RECIP_OTHER 3 - -/* standard requests */ -#define AO_USB_REQ_GET_STATUS 0x00 -#define AO_USB_REQ_CLEAR_FEATURE 0x01 -#define AO_USB_REQ_SET_FEATURE 0x03 -#define AO_USB_REQ_SET_ADDRESS 0x05 -#define AO_USB_REQ_GET_DESCRIPTOR 0x06 -#define AO_USB_REQ_SET_DESCRIPTOR 0x07 -#define AO_USB_REQ_GET_CONFIGURATION 0x08 -#define AO_USB_REQ_SET_CONFIGURATION 0x09 -#define AO_USB_REQ_GET_INTERFACE 0x0A -#define AO_USB_REQ_SET_INTERFACE 0x0B -#define AO_USB_REQ_SYNCH_FRAME 0x0C - -#define AO_USB_DESC_DEVICE 1 -#define AO_USB_DESC_CONFIGURATION 2 -#define AO_USB_DESC_STRING 3 -#define AO_USB_DESC_INTERFACE 4 -#define AO_USB_DESC_ENDPOINT 5 -#define AO_USB_DESC_DEVICE_QUALIFIER 6 -#define AO_USB_DESC_OTHER_SPEED 7 -#define AO_USB_DESC_INTERFACE_POWER 8 - -#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) -#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) - -#define AO_USB_CONTROL_EP 0 -#define AO_USB_INT_EP 1 -#define AO_USB_OUT_EP 4 -#define AO_USB_IN_EP 5 -#define AO_USB_CONTROL_SIZE 32 -/* - * Double buffer IN and OUT EPs, so each - * gets half of the available space - * - * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 - * byte sizes, so we'll use 64 for everything - */ -#define AO_USB_INT_SIZE 8 -#define AO_USB_IN_SIZE 64 -#define AO_USB_OUT_SIZE 64 - -#define AO_USB_EP0_IDLE 0 -#define AO_USB_EP0_DATA_IN 1 -#define AO_USB_EP0_DATA_OUT 2 - -#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) - -/* CDC definitions */ -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 - -#define SET_LINE_CODING 0x20 -#define GET_LINE_CODING 0x21 -#define SET_CONTROL_LINE_STATE 0x22 - -/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ -struct ao_usb_line_coding { - uint32_t rate; - uint8_t char_format; - uint8_t parity; - uint8_t data_bits; -} ; - -#endif /* _AO_USB_H_ */ diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 5a447d43..586f1e33 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -717,17 +717,17 @@ ao_usb_ep0_setup(void) case AO_USB_TYPE_CLASS: debug ("Class setup packet\n"); switch (ao_usb_setup.request) { - case SET_LINE_CODING: + case AO_USB_SET_LINE_CODING: debug ("set line coding\n"); ao_usb_ep0_out_len = 7; ao_usb_ep0_out_data = (uint8_t *) &ao_usb_line_coding; break; - case GET_LINE_CODING: + case AO_USB_GET_LINE_CODING: debug ("get line coding\n"); ao_usb_ep0_in_len = 7; ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; break; - case SET_CONTROL_LINE_STATE: + case AO_USB_SET_CONTROL_LINE_STATE: break; } break; diff --git a/src/teleballoon-v1.1/ao_pins.h b/src/teleballoon-v1.1/ao_pins.h index a96c6f2b..3305719a 100644 --- a/src/teleballoon-v1.1/ao_pins.h +++ b/src/teleballoon-v1.1/ao_pins.h @@ -30,7 +30,6 @@ #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 @@ -127,10 +126,6 @@ #error Please define HAS_SERIAL_1 #endif -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/telepyro-v0.1/Makefile b/src/telepyro-v0.1/Makefile index 2f664fcb..2ac7e747 100644 --- a/src/telepyro-v0.1/Makefile +++ b/src/telepyro-v0.1/Makefile @@ -85,8 +85,10 @@ load: $(PROG).hex ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ -ao_product.rel: ao_product.c ao_product.h - $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< +ao_product.o: ao_product.c ao_product.h + +%.o : %.c + $(call quiet,CC) -c $(CFLAGS) $< distclean: clean diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index be99f10d..10e4a2a3 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -22,7 +22,8 @@ INC = \ ao.h \ ao_arch.h \ ao_usb.h \ - ao_pins.h + ao_pins.h \ + ao_product.h # # Common AltOS sources @@ -96,8 +97,10 @@ load: $(PROG).hex ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ -ao_product.rel: ao_product.c ao_product.h - $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< +ao_product.o: ao_product.c ao_product.h + +%.o : %.c $(INC) + $(call quiet,CC) -c $(CFLAGS) $< distclean: clean diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile index 44780476..c1f45f37 100644 --- a/src/teleshield-v0.1/Makefile +++ b/src/teleshield-v0.1/Makefile @@ -54,7 +54,6 @@ CC1111_SRC = \ ao_radio.c \ ao_romconfig.c \ ao_serial.c \ - ao_serial0.c \ ao_string.c \ ao_timer.c \ ao_usb.c \ diff --git a/src/teleshield-v0.1/ao_ardu_serial.c b/src/teleshield-v0.1/ao_ardu_serial.c index 7ff859af..e6e19f67 100644 --- a/src/teleshield-v0.1/ao_ardu_serial.c +++ b/src/teleshield-v0.1/ao_ardu_serial.c @@ -23,7 +23,7 @@ ao_ardu_serial_recv(void) char c; for (;;) { - if (ao_fifo_empty(ao_usart0_rx_fifo)) + if (ao_fifo_empty(ao_serial0_rx_fifo)) flush(); c = ao_serial0_getchar(); putchar (c); @@ -35,6 +35,5 @@ static __xdata struct ao_task ao_ardu_serial_recv_task; void ao_ardu_serial_init (void) { - ao_serial0_init(); ao_add_task(&ao_ardu_serial_recv_task, ao_ardu_serial_recv, "recv"); } diff --git a/src/teleshield-v0.1/ao_pins.h b/src/teleshield-v0.1/ao_pins.h index a907e2a5..701e25fc 100644 --- a/src/teleshield-v0.1/ao_pins.h +++ b/src/teleshield-v0.1/ao_pins.h @@ -26,14 +26,14 @@ #define HAS_SERIAL_1_ALT_1 1 #define HAS_SERIAL_1_ALT_2 0 #define HAS_SERIAL_1_HW_FLOW 1 - #define USE_SERIAL_STDIN 1 + #define USE_SERIAL_1_STDIN 1 #define HAS_SERIAL_0 1 #define HAS_SERIAL_0_ALT_1 0 #define HAS_SERIAL_0_ALT_2 1 #define HAS_SERIAL_0_HW_FLOW 0 #define HAS_ADC 0 #define HAS_DBG 1 - #define HAS_EEPROM 0 + #define HAS_EEPROM 1 #define HAS_LOG 0 #define USE_INTERNAL_FLASH 1 #define HAS_BTM 1 @@ -128,10 +128,6 @@ #error Please define HAS_SERIAL_1 #endif -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/teleshield-v0.1/ao_teleshield.c b/src/teleshield-v0.1/ao_teleshield.c index fd12ce7a..4c32817a 100644 --- a/src/teleshield-v0.1/ao_teleshield.c +++ b/src/teleshield-v0.1/ao_teleshield.c @@ -17,7 +17,9 @@ #include "ao.h" +#if 0 __code uint8_t ao_log_format = AO_LOG_FORMAT_NONE; /* until we actually log stuff */ +#endif void main(void) @@ -43,6 +45,7 @@ main(void) ao_aes_init(); ao_radio_cmac_init(); #endif + ao_serial_init(); ao_ardu_serial_init(); ao_config_init(); ao_start_scheduler(); diff --git a/src/teleterra-v0.1/ao_pins.h b/src/teleterra-v0.1/ao_pins.h index 33de055e..ba7177af 100644 --- a/src/teleterra-v0.1/ao_pins.h +++ b/src/teleterra-v0.1/ao_pins.h @@ -25,7 +25,6 @@ #define HAS_GPS 0 #define HAS_SERIAL_1 0 #define HAS_ADC 0 - #define USE_SERIAL_STDIN 0 #define HAS_EEPROM 1 #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 @@ -124,10 +123,6 @@ #error Please define HAS_SERIAL_1 #endif -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 29b97385..2bea4e04 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -25,7 +25,6 @@ #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 0 - #define USE_SERIAL_STDIN 0 #define HAS_EEPROM 1 #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 @@ -139,10 +138,6 @@ #error Please define HAS_SERIAL_1 #endif -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/test/ao_gps_test.c b/src/test/ao_gps_test.c index 93d7a9ab..4d4012df 100644 --- a/src/test/ao_gps_test.c +++ b/src/test/ao_gps_test.c @@ -317,7 +317,7 @@ static uint8_t sirf_in_message[4096]; static int sirf_in_len; char -ao_serial_getchar(void) +ao_serial1_getchar(void) { char c; uint8_t uc; @@ -351,7 +351,7 @@ ao_serial_getchar(void) void -ao_serial_putchar(char c) +ao_serial1_putchar(char c) { int i; uint8_t uc = (uint8_t) c; @@ -388,7 +388,7 @@ ao_serial_putchar(char c) #define AO_SERIAL_SPEED_57600 1 static void -ao_serial_set_speed(uint8_t speed) +ao_serial1_set_speed(uint8_t speed) { int fd = ao_gps_fd; struct termios termios; diff --git a/src/test/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c index a78fae0f..88bed305 100644 --- a/src/test/ao_gps_test_skytraq.c +++ b/src/test/ao_gps_test_skytraq.c @@ -319,7 +319,7 @@ static uint8_t skytraq_in_message[4096]; static int skytraq_in_len; char -ao_serial_getchar(void) +ao_serial1_getchar(void) { char c; uint8_t uc; @@ -354,7 +354,7 @@ ao_serial_getchar(void) void -ao_serial_putchar(char c) +ao_serial1_putchar(char c) { int i; uint8_t uc = (uint8_t) c; @@ -392,7 +392,7 @@ ao_serial_putchar(char c) #define AO_SERIAL_SPEED_57600 2 static void -ao_serial_set_speed(uint8_t speed) +ao_serial1_set_speed(uint8_t speed) { int fd = ao_gps_fd; struct termios termios; -- cgit v1.2.3 From 0667261e03b3fd403e97d02ea6204b007bb13f58 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Apr 2012 09:39:20 -0700 Subject: altos: Pull more interfaces out of ao.h and move to separate files This moves the aes, btm, companion, lcd and packet interfaces out of ao.h Signed-off-by: Keith Packard --- src/core/ao.h | 199 +++------------------------------------- src/core/ao_aes.h | 69 ++++++++++++++ src/core/ao_btm.h | 36 ++++++++ src/core/ao_companion.h | 51 ++++++++++ src/core/ao_lcd.h | 60 ++++++++++++ src/core/ao_log_telescience.c | 2 + src/core/ao_packet.h | 88 ++++++++++++++++++ src/drivers/ao_pyro_slave.c | 5 +- src/drivers/ao_science_slave.c | 1 + src/product/Makefile.telelaunch | 2 - src/teleterra-v0.2/ao_pins.h | 1 + 11 files changed, 323 insertions(+), 191 deletions(-) create mode 100644 src/core/ao_aes.h create mode 100644 src/core/ao_btm.h create mode 100644 src/core/ao_companion.h create mode 100644 src/core/ao_lcd.h create mode 100644 src/core/ao_packet.h (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index 28d0ba87..27b9c5c4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -900,201 +900,26 @@ struct ao_fifo { #define ao_fifo_full(f) ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove) #define ao_fifo_empty(f) ((f).insert == (f).remove) -/* - * ao_packet.c - * - * Packet-based command interface - */ - -#define AO_PACKET_MAX 64 -#define AO_PACKET_SYN (uint8_t) 0xff - -struct ao_packet { - uint8_t addr; - uint8_t len; - uint8_t seq; - uint8_t ack; - uint8_t d[AO_PACKET_MAX]; - uint8_t callsign[AO_MAX_CALLSIGN]; -}; - -struct ao_packet_recv { - struct ao_packet packet; - int8_t rssi; - uint8_t status; -}; - -extern __xdata struct ao_packet_recv ao_rx_packet; -extern __xdata struct ao_packet ao_tx_packet; -extern __xdata struct ao_task ao_packet_task; -extern __xdata uint8_t ao_packet_enable; -extern __xdata uint8_t ao_packet_master_sleeping; -extern __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; - -void -ao_packet_send(void); - -uint8_t -ao_packet_recv(void); - -void -ao_packet_flush(void); - -void -ao_packet_putchar(char c) __reentrant; - -char -ao_packet_pollchar(void) __critical; - -/* ao_packet_master.c */ - -void -ao_packet_master_init(void); - -/* ao_packet_slave.c */ - -void -ao_packet_slave_start(void); - -void -ao_packet_slave_stop(void); - -void -ao_packet_slave_init(uint8_t enable); - -/* ao_btm.c */ - -/* If bt_link is on P2, this interrupt is shared by USB, so the USB - * code calls this function. Otherwise, it's a regular ISR. - */ - -void -ao_btm_isr(void) -#if BT_LINK_ON_P1 - __interrupt 15 +#if PACKET_HAS_MASTER || PACKET_HAS_SLAVE +#include #endif - ; - -void -ao_btm_init(void); - -/* ao_companion.c */ - -#define AO_COMPANION_SETUP 1 -#define AO_COMPANION_FETCH 2 -#define AO_COMPANION_NOTIFY 3 - -struct ao_companion_command { - uint8_t command; - uint8_t flight_state; - uint16_t tick; - uint16_t serial; - uint16_t flight; -}; - -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 uint8_t ao_companion_mutex; -extern __xdata struct ao_companion_command ao_companion_command; -extern __xdata struct ao_companion_setup ao_companion_setup; -extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; - -void -ao_companion_init(void); - -/* ao_lcd.c */ - -void -ao_lcd_putchar(uint8_t d); - -void -ao_lcd_putstring(char *string); - -void -ao_lcd_contrast_set(uint8_t contrast); - -void -ao_lcd_clear(void); - -void -ao_lcd_cursor_on(void); - -void -ao_lcd_cursor_off(void); - -#define AO_LCD_ADDR(row,col) ((row << 6) | (col)) - -void -ao_lcd_goto(uint8_t addr); - -void -ao_lcd_start(void); - -void -ao_lcd_init(void); - -/* ao_lcd_port.c */ - -void -ao_lcd_port_put_nibble(uint8_t rs, uint8_t d); - -void -ao_lcd_port_init(void); - -/* ao_aes.c */ -extern __xdata uint8_t ao_aes_mutex; +#if HAS_BTM +#include +#endif -/* AES keys and blocks are 128 bits */ +#if HAS_COMPANION +#include +#endif -enum ao_aes_mode { - ao_aes_mode_cbc_mac -}; +#if HAS_LCD +#include +#endif #if HAS_AES -void -ao_aes_isr(void) __interrupt 4; +#include #endif -void -ao_aes_set_mode(enum ao_aes_mode mode); - -void -ao_aes_set_key(__xdata uint8_t *in); - -void -ao_aes_zero_iv(void); - -void -ao_aes_run(__xdata uint8_t *in, - __xdata uint8_t *out); - -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); - /* ao_launch.c */ struct ao_launch_command { diff --git a/src/core/ao_aes.h b/src/core/ao_aes.h new file mode 100644 index 00000000..7f67374d --- /dev/null +++ b/src/core/ao_aes.h @@ -0,0 +1,69 @@ +/* + * 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_AES_H_ +#define _AO_AES_H_ + +/* ao_aes.c */ + +extern __xdata uint8_t ao_aes_mutex; + +/* AES keys and blocks are 128 bits */ + +enum ao_aes_mode { + ao_aes_mode_cbc_mac +}; + +#if HAS_AES +void +ao_aes_isr(void) __interrupt 4; +#endif + +void +ao_aes_set_mode(enum ao_aes_mode mode); + +void +ao_aes_set_key(__xdata uint8_t *in); + +void +ao_aes_zero_iv(void); + +void +ao_aes_run(__xdata uint8_t *in, + __xdata uint8_t *out); + +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_btm.h b/src/core/ao_btm.h new file mode 100644 index 00000000..484e5d7f --- /dev/null +++ b/src/core/ao_btm.h @@ -0,0 +1,36 @@ +/* + * 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_BTM_H_ +#define _AO_BTM_H_ + +/* ao_btm.c */ + +/* If bt_link is on P2, this interrupt is shared by USB, so the USB + * code calls this function. Otherwise, it's a regular ISR. + */ + +void +ao_btm_isr(void) +#if BT_LINK_ON_P1 + __interrupt 15 +#endif + ; +void +ao_btm_init(void); + +#endif /* _AO_BTM_H_ */ diff --git a/src/core/ao_companion.h b/src/core/ao_companion.h new file mode 100644 index 00000000..47e0acf5 --- /dev/null +++ b/src/core/ao_companion.h @@ -0,0 +1,51 @@ +/* + * 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_COMPANION_H_ +#define _AO_COMPANION_H_ + +/* ao_companion.c */ + +#define AO_COMPANION_SETUP 1 +#define AO_COMPANION_FETCH 2 +#define AO_COMPANION_NOTIFY 3 + +struct ao_companion_command { + uint8_t command; + uint8_t flight_state; + uint16_t tick; + uint16_t serial; + uint16_t flight; +}; + +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 uint8_t ao_companion_mutex; +extern __xdata struct ao_companion_command ao_companion_command; +extern __xdata struct ao_companion_setup ao_companion_setup; +extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; + +void +ao_companion_init(void); + +#endif /* _AO_COMPANION_H_ */ diff --git a/src/core/ao_lcd.h b/src/core/ao_lcd.h new file mode 100644 index 00000000..f7e1391a --- /dev/null +++ b/src/core/ao_lcd.h @@ -0,0 +1,60 @@ +/* + * 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_LCD_H_ +#define _AO_LCD_H_ + +/* ao_lcd.c */ + +void +ao_lcd_putchar(uint8_t d); + +void +ao_lcd_putstring(char *string); + +void +ao_lcd_contrast_set(uint8_t contrast); + +void +ao_lcd_clear(void); + +void +ao_lcd_cursor_on(void); + +void +ao_lcd_cursor_off(void); + +#define AO_LCD_ADDR(row,col) ((row << 6) | (col)) + +void +ao_lcd_goto(uint8_t addr); + +void +ao_lcd_start(void); + +void +ao_lcd_init(void); + +/* ao_lcd_port.c */ + +void +ao_lcd_port_put_nibble(uint8_t rs, uint8_t d); + +void +ao_lcd_port_init(void); + +#endif /* _AO_LCD_H_ */ diff --git a/src/core/ao_log_telescience.c b/src/core/ao_log_telescience.c index 31eda381..ae045281 100644 --- a/src/core/ao_log_telescience.c +++ b/src/core/ao_log_telescience.c @@ -17,6 +17,8 @@ #include "ao.h" #include "ao_product.h" +#include "ao_log.h" +#include "ao_companion.h" static uint8_t ao_log_adc_pos; diff --git a/src/core/ao_packet.h b/src/core/ao_packet.h new file mode 100644 index 00000000..618ccda4 --- /dev/null +++ b/src/core/ao_packet.h @@ -0,0 +1,88 @@ +/* + * 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_PACKET_H_ +#define _AO_PACKET_H_ + +/* + * ao_packet.c + * + * Packet-based command interface + */ + +#define AO_PACKET_MAX 64 +#define AO_PACKET_SYN (uint8_t) 0xff + +struct ao_packet { + uint8_t addr; + uint8_t len; + uint8_t seq; + uint8_t ack; + uint8_t d[AO_PACKET_MAX]; + uint8_t callsign[AO_MAX_CALLSIGN]; +}; + +struct ao_packet_recv { + struct ao_packet packet; + int8_t rssi; + uint8_t status; +}; + +extern __xdata struct ao_packet_recv ao_rx_packet; +extern __xdata struct ao_packet ao_tx_packet; +extern __xdata struct ao_task ao_packet_task; +extern __xdata uint8_t ao_packet_enable; +extern __xdata uint8_t ao_packet_master_sleeping; +extern __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; + +void +ao_packet_send(void); + +uint8_t +ao_packet_recv(void); + +void +ao_packet_flush(void); + +void +ao_packet_putchar(char c) __reentrant; + +char +ao_packet_pollchar(void) __critical; + +#if PACKET_HAS_MASTER +/* ao_packet_master.c */ + +void +ao_packet_master_init(void); +#endif + +#if PACKET_HAS_SLAVE +/* ao_packet_slave.c */ + +void +ao_packet_slave_start(void); + +void +ao_packet_slave_stop(void); + +void +ao_packet_slave_init(uint8_t enable); + +#endif + +#endif /* _AO_PACKET_H_ */ diff --git a/src/drivers/ao_pyro_slave.c b/src/drivers/ao_pyro_slave.c index 5ef42b5a..5a8ab922 100644 --- a/src/drivers/ao_pyro_slave.c +++ b/src/drivers/ao_pyro_slave.c @@ -15,8 +15,9 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" -#include "ao_product.h" +#include +#include +#include struct ao_companion_command ao_companion_command; diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c index fa9db98b..a86b5151 100644 --- a/src/drivers/ao_science_slave.c +++ b/src/drivers/ao_science_slave.c @@ -18,6 +18,7 @@ #include "ao.h" #include "ao_product.h" #include "ao_flight.h" +#include "ao_companion.h" struct ao_companion_command ao_companion_command; diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 8aab50e0..688ac5f3 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -39,8 +39,6 @@ CC1111_SRC = \ ao_ignite.c \ ao_intflash.c \ ao_led.c \ - ao_packet.c \ - ao_packet_slave.c \ ao_radio.c \ ao_radio_cmac.c \ ao_romconfig.c \ diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 2bea4e04..bcabdfee 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -25,6 +25,7 @@ #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 0 + #define HAS_LCD 1 #define HAS_EEPROM 1 #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 -- cgit v1.2.3 From 3c67543f3e5fddc6a8850f33ac519ccd55b607f0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Apr 2012 18:34:52 -0700 Subject: altos: Set USB Interrupt endpoint interval to maximum allowed We don't ever send anything over this channel, so there's no sense asking the host to poll it very often. Signed-off-by: Keith Packard --- src/core/ao_product.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao_product.c b/src/core/ao_product.c index f79922f5..67ec6793 100644 --- a/src/core/ao_product.c +++ b/src/core/ao_product.c @@ -100,7 +100,7 @@ __code __at(0x00aa) uint8_t ao_usb_descriptors [] = AO_USB_INT_EP|0x80, /* bEndpointAddress */ 0x03, /* bmAttributes = intr */ LE_WORD(8), /* wMaxPacketSize */ - 0x0A, /* bInterval */ + 0xff, /* bInterval */ /* Data class interface descriptor */ 0x09, -- cgit v1.2.3 From 1a84d34fa08f43a5f79b1a5f8d8de7674d04647d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Apr 2012 18:35:46 -0700 Subject: altos: Check all USE_SERIAL_*_STDIO when computing AO_NUM_STDIOS AO_NUM_STDIOS is allocated based on the total number of possible stdio values. Now that multiple serial stdio are possible, make sure to check all of them. Signed-off-by: Keith Packard --- src/core/ao_stdio.c | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index 18fa913e..9b4ea473 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -21,11 +21,47 @@ * Basic I/O functions to support SDCC stdio package */ -#ifdef SERIAL_STDIN_PORT -#define USE_SERIAL_STDIN 1 -#else -#define USE_SERIAL_STDIN 0 +#ifndef USE_SERIAL_0_STDIN +#define USE_SERIAL_0_STDIN 0 #endif +#ifndef USE_SERIAL_1_STDIN +#define USE_SERIAL_1_STDIN 0 +#endif +#ifndef USE_SERIAL_2_STDIN +#define USE_SERIAL_2_STDIN 0 +#endif +#ifndef USE_SERIAL_3_STDIN +#define USE_SERIAL_3_STDIN 0 +#endif +#ifndef USE_SERIAL_4_STDIN +#define USE_SERIAL_4_STDIN 0 +#endif +#ifndef USE_SERIAL_5_STDIN +#define USE_SERIAL_5_STDIN 0 +#endif +#ifndef USE_SERIAL_6_STDIN +#define USE_SERIAL_6_STDIN 0 +#endif +#ifndef USE_SERIAL_7_STDIN +#define USE_SERIAL_7_STDIN 0 +#endif +#ifndef USE_SERIAL_8_STDIN +#define USE_SERIAL_8_STDIN 0 +#endif +#ifndef USE_SERIAL_9_STDIN +#define USE_SERIAL_9_STDIN 0 +#endif + +#define USE_SERIAL_STDIN (USE_SERIAL_0_STDIN + \ + USE_SERIAL_1_STDIN | \ + USE_SERIAL_2_STDIN | \ + USE_SERIAL_3_STDIN | \ + USE_SERIAL_4_STDIN | \ + USE_SERIAL_5_STDIN | \ + USE_SERIAL_6_STDIN | \ + USE_SERIAL_7_STDIN | \ + USE_SERIAL_8_STDIN | \ + USE_SERIAL_9_STDIN) #define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) -- cgit v1.2.3 From 6cb744e305116a738b5d71686c6748f6f08c12ea Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Apr 2012 12:02:14 -0700 Subject: altos: Respect apogee lockout time in flight algorithm This prevents any apogee detection from occurring until the specified number of seconds after boost. This also prevents the switch from accel+baro to baro only mode in the Kalman filter. The test frame work is also changed to look for Apogee lockout: in the eeprom input file. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 11 +++++++++++ src/test/ao_flight_test.c | 4 ++++ 2 files changed, 15 insertions(+) (limited to 'src/core') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 5e194638..494e656d 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -223,6 +223,17 @@ ao_flight(void) #endif case ao_flight_coast: + /* + * By customer request - allow the user + * to lock out apogee detection for a specified + * number of seconds. + */ + if (ao_config.apogee_lockout) { + if ((ao_sample_tick - ao_boost_tick) < + AO_SEC_TO_TICKS(ao_config.apogee_lockout)) + break; + } + /* apogee detect: coast to drogue deploy: * * speed: < 0 diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 921d44e7..4a8625cf 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -184,6 +184,7 @@ struct ao_config { int16_t accel_plus_g; int16_t accel_minus_g; uint8_t pad_orientation; + uint16_t apogee_lockout; }; #define AO_PAD_ORIENTATION_ANTENNA_UP 0 @@ -523,6 +524,9 @@ ao_sleep(void *wchan) ao_config.accel_minus_g = atoi(words[5]); } else if (nword >= 4 && strcmp(words[0], "Main") == 0) { ao_config.main_deploy = atoi(words[2]); + } else if (nword >= 3 && strcmp(words[0], "Apogee") == 0 && + strcmp(words[1], "lockout:") == 0) { + ao_config.apogee_lockout = atoi(words[2]); } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) { tick = atoi(words[10]); if (!ao_flight_started) { -- cgit v1.2.3 From 8b08095b3d41e21684a10bddfb54431019da5af6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 May 2012 11:08:49 -0700 Subject: altos: Report latest telemetry data, rather than using the oldest ao_sample_adc points to the *next* ADC entry, rather than the most recent one. Step back one entry to get the latest valid data. Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index eb614b0f..46d72609 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -53,8 +53,7 @@ static __xdata union ao_telemetry_all telemetry; static void ao_send_sensor(void) { - uint8_t sample; - sample = ao_sample_adc; + uint8_t sample = ao_adc_ring_prev(ao_sample_adc); telemetry.generic.tick = ao_adc_ring[sample].tick; telemetry.generic.type = AO_TELEMETRY_SENSOR; -- cgit v1.2.3 From 5d8b9d524d6424ff98dcc4155fe8b8bd892b6d8f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 May 2012 20:04:57 -0700 Subject: altos: Add conversion between Pa and meters To be used with the MS5607 which generates data in calibrated units. Signed-off-by: Keith Packard --- src/Makefile | 6 +- src/core/ao.h | 12 ++ src/core/ao_convert_pa.c | 72 +++++++++++ src/core/ao_convert_pa_test.c | 76 ++++++++++++ src/test/Makefile | 5 +- src/util/make-altitude-pa | 275 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 444 insertions(+), 2 deletions(-) create mode 100644 src/core/ao_convert_pa.c create mode 100644 src/core/ao_convert_pa_test.c create mode 100644 src/util/make-altitude-pa (limited to 'src/core') diff --git a/src/Makefile b/src/Makefile index db9bd508..c2e324c4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,6 +4,7 @@ # vpath make-altitude util +vpath make-altitude-pa util vpath make-kalman util vpath kalman.5c kalman vpath kalman_filter.5c kalman @@ -45,11 +46,14 @@ uninstall: all-recursive: all-local -all-local: altitude.h ao_kalman.h +all-local: altitude.h altitude-pa.h ao_kalman.h altitude.h: make-altitude nickle $< > $@ +altitude-pa.h: make-altitude-pa + nickle $< > $@ + ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c bash $< kalman > $@ diff --git a/src/core/ao.h b/src/core/ao.h index 27b9c5c4..a2092cfe 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -282,6 +282,18 @@ ao_altitude_to_pres(int16_t alt) __reentrant; int16_t ao_temp_to_dC(int16_t temp) __reentrant; +/* + * ao_convert_pa.c + * + * Convert between pressure in Pa and altitude in meters + */ + +int32_t +ao_pa_to_altitude(int32_t pa); + +int32_t +ao_altitude_to_pa(int32_t alt); + #if HAS_DBG #include #endif diff --git a/src/core/ao_convert_pa.c b/src/core/ao_convert_pa.c new file mode 100644 index 00000000..0c93caea --- /dev/null +++ b/src/core/ao_convert_pa.c @@ -0,0 +1,72 @@ +/* + * 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. + */ + +#if !defined(AO_CONVERT_TEST) && !defined(AO_FLIGHT_TEST) +#include "ao.h" +#endif + +static const int32_t altitude_table[] = { +#include "altitude-pa.h" +}; + +#define ALT_SCALE (1 << ALT_SHIFT) +#define ALT_MASK (ALT_SCALE - 1) + +int32_t +ao_pa_to_altitude(int32_t pa) +{ + int16_t o; + int16_t part; + int32_t low, high; + + if (pa < 0) + pa = 0; + if (pa > 120000) + pa = 120000; + o = pa >> ALT_SHIFT; + part = pa & ALT_MASK; + + low = (int32_t) altitude_table[o] * (ALT_SCALE - part); + high = (int32_t) altitude_table[o+1] * part + (ALT_SCALE >> 1); + return (low + high) >> ALT_SHIFT; +} + +int32_t +ao_altitude_to_pa(int32_t alt) +{ + int32_t span, sub_span; + uint16_t l, h, m; + int32_t pa; + + l = 0; + h = NALT - 1; + while ((h - l) != 1) { + m = (l + h) >> 1; + if (altitude_table[m] < alt) + h = m; + else + l = m; + } + span = altitude_table[l] - altitude_table[h]; + sub_span = altitude_table[l] - alt; + pa = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_SHIFT) + (span >> 1)) / span; + if (pa > 120000) + pa = 120000; + if (pa < 0) + pa = 0; + return pa; +} diff --git a/src/core/ao_convert_pa_test.c b/src/core/ao_convert_pa_test.c new file mode 100644 index 00000000..972a4d4c --- /dev/null +++ b/src/core/ao_convert_pa_test.c @@ -0,0 +1,76 @@ +/* + * 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 +#define AO_CONVERT_TEST +#include "ao_host.h" +#include "ao_convert_pa.c" + +#define STEP_P 1 +#define STEP_A 1 + +static inline i_abs(int i) { return i < 0 ? -i : i; } + +main () +{ + int i; + int32_t p_to_a, p_to_a_to_p; + int32_t a_to_p, a_to_p_to_a; + int max_p_error = 0, max_p_error_p = -1; + int max_a_error = 0, max_a_error_a = -1; + int p_error; + int a_error; + int ret = 0; + + for (i = 0; i < 120000 + STEP_P; i += STEP_P) { + if (i > 120000) + i = 120000; + p_to_a = ao_pa_to_altitude(i); + p_to_a_to_p = ao_altitude_to_pa(p_to_a); + p_error = i_abs(p_to_a_to_p - i); + if (p_error > max_p_error) { + max_p_error = p_error; + max_p_error_p = i; + } +// printf ("pa %d alt %d pa %d\n", +// i, p_to_a, p_to_a_to_p); + } + for (i = -1450; i < 74250 + STEP_A; i += STEP_A) { + if (i > 74250) + i = 74250; + a_to_p = ao_altitude_to_pa(i); + a_to_p_to_a = ao_pa_to_altitude(a_to_p); + a_error = i_abs(a_to_p_to_a - i); + if (a_error > max_a_error) { + max_a_error = a_error; + max_a_error_a = i; + } +// printf ("alt %d pa %d alt %d\n", +// i, a_to_p, a_to_p_to_a); + } + if (max_p_error > 2) { + printf ("max p error %d at %d\n", max_p_error, + max_p_error_p); + ret++; + } + if (max_a_error > 1) { + printf ("max a error %d at %d\n", max_a_error, + max_a_error_a); + ret++; + } + return ret; +} diff --git a/src/test/Makefile b/src/test/Makefile index 4e403da6..3c2b8732 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,6 @@ vpath % ..:../core:../drivers:../util -PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test +PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test KALMAN=make-kalman @@ -34,5 +34,8 @@ ao_gps_test_skytraq: ao_gps_test_skytraq.c ao_gps_skytraq.c ao_gps_print.c ao_ho ao_convert_test: ao_convert_test.c ao_convert.c altitude.h cc $(CFLAGS) -o $@ $< +ao_convert_pa_test: ao_convert_pa_test.c ao_convert_pa.c altitude-pa.h + cc $(CFLAGS) -o $@ $< + ao_kalman.h: $(KALMAN) (cd .. && make ao_kalman.h) \ No newline at end of file diff --git a/src/util/make-altitude-pa b/src/util/make-altitude-pa new file mode 100644 index 00000000..190b36fc --- /dev/null +++ b/src/util/make-altitude-pa @@ -0,0 +1,275 @@ +#!/usr/bin/nickle -f +/* + * Pressure Sensor Model, version 1.1 + * + * written by Holly Grimes + * + * Uses the International Standard Atmosphere as described in + * "A Quick Derivation relating altitude to air pressure" (version 1.03) + * from the Portland State Aerospace Society, except that the atmosphere + * is divided into layers with each layer having a different lapse rate. + * + * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007 + * at site MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */ + return 0; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted altitude */ + for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) { + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + base_pressure *= exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + base_pressure *= pow(base, exponent); + } + base_temperature += delta_z * lapse_rate[layer_number]; + } + + /* calculate the pressure at the inputted altitude */ + delta_z = altitude - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + pressure = base_pressure * exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + pressure = base_pressure * pow(base, exponent); + } + + return pressure; +} + + +/* outputs the altitude associated with the given pressure. the altitude + returned is measured with respect to the mean sea level */ +real pressure_to_altitude(real pressure) { + + real next_base_temperature = LAYER0_BASE_TEMPERATURE; + real next_base_pressure = LAYER0_BASE_PRESSURE; + + real altitude; + real base_pressure; + real base_temperature; + real base; /* base for function to determine base pressure of next layer */ + real exponent; /* exponent for function to determine base pressure + of next layer */ + real coefficient; + int layer_number; /* identifies layer in the atmosphere */ + int delta_z; /* difference between two altitudes */ + + if (pressure < 0) /* illegal pressure */ + return -1; + if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */ + return MAXIMUM_ALTITUDE; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted pressure. */ + layer_number = -1; + do { + layer_number++; + base_pressure = next_base_pressure; + base_temperature = next_base_temperature; + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + next_base_pressure *= exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + next_base_pressure *= pow(base, exponent); + } + next_base_temperature += delta_z * lapse_rate[layer_number]; + } + while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure); + + /* calculate the altitude associated with the inputted pressure */ + if (lapse_rate[layer_number] == 0.0) { + coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION) + * base_temperature; + altitude = base_altitude[layer_number] + + coefficient * log(pressure / base_pressure); + } + else { + base = pressure / base_pressure; + exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number] + / GRAVITATIONAL_ACCELERATION; + coefficient = base_temperature / lapse_rate[layer_number]; + altitude = base_altitude[layer_number] + + coefficient * (pow(base, exponent) - 1); + } + + return altitude; +} + +real feet_to_meters(real feet) +{ + return feet * (12 * 2.54 / 100); +} + +real meters_to_feet(real meters) +{ + return meters / (12 * 2.54 / 100); +} + +/* + * Values for our MS5607 + * + * From the data sheet: + * + * Pressure range: 10-1200 mbar (1000 - 120000 Pa) + * + * Pressure data is reported in units of Pa + */ + +typedef struct { + real m, b; + int m_i, b_i; +} line_t; + +line_t best_fit(real[] values, int first, int last) { + real sum_x = 0, sum_x2 = 0, sum_y = 0, sum_xy = 0; + int n = last - first + 1; + real m, b; + int m_i, b_i; + + for (int i = first; i <= last; i++) { + sum_x += i; + sum_x2 += i**2; + sum_y += values[i]; + sum_xy += values[i] * i; + } + m = (n*sum_xy - sum_y*sum_x) / (n*sum_x2 - sum_x**2); + b = sum_y/n - m*(sum_x/n); + return (line_t) { m = m, b = b }; +} + +real min_Pa = 0; +real max_Pa = 120000; + +/* Target is an array of < 2000 entries */ +int pa_sample_shift = 3; +int pa_part_shift = 3; + +int num_part = ceil(max_Pa / (2 ** (pa_part_shift + pa_sample_shift))); + +int num_samples = num_part << pa_part_shift; + +real sample_to_Pa(int sample) = sample << pa_sample_shift; + +real sample_to_altitude(int sample) = pressure_to_altitude(sample_to_Pa(sample)); + +int part_to_sample(int part) = part << pa_part_shift; + +real[num_samples] alt = { [n] = sample_to_altitude(n) }; + +int seg_len = 1 << pa_part_shift; + +line_t [num_part] fit = { + [n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1) +}; + +int[num_samples/seg_len + 1] alt_part; + +alt_part[0] = floor (fit[0].b + 0.5); +alt_part[dim(fit)] = floor(fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b + 0.5); + +for (int i = 0; i < dim(fit) - 1; i++) { + real here, there; + here = fit[i].m * (i+1) * seg_len + fit[i].b; + there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b; + alt_part[i+1] = floor ((here + there) / 2 + 0.5); +} + +real sample_to_fit_altitude(int sample) { + int sub = sample // seg_len; + int off = sample % seg_len; + line_t l = fit[sub]; + real r_v; + real i_v; + + r_v = sample * l.m + l.b; + i_v = (alt_part[sub] * (seg_len - off) + alt_part[sub+1] * off) / seg_len; + return i_v; +} + +real max_error = 0; +int max_error_sample = 0; +real total_error = 0; + +for (int sample = 0; sample < num_samples; sample++) { + real Pa = sample_to_Pa(sample); + real meters = pressure_to_altitude(Pa); + + real meters_approx = sample_to_fit_altitude(sample); + real error = abs(meters - meters_approx); + + total_error += error; + if (error > max_error) { + max_error = error; + max_error_sample = sample; + } +# printf (" %7d, /* %6.2f kPa %5d sample approx %d */\n", +# floor (meters + 0.5), Pa / 1000, sample, floor(sample_to_fit_altitude(sample) + 0.5)); +} + +printf ("/*max error %f at %7.3f%%. Average error %f*/\n", max_error, max_error_sample / (num_samples - 1) * 100, total_error / num_samples); + +printf ("#define NALT %d\n", dim(alt_part)); +printf ("#define ALT_SHIFT %d\n", pa_part_shift + pa_sample_shift); + +for (int part = 0; part < dim(alt_part); part++) { + real kPa = sample_to_Pa(part_to_sample(part)) / 1000; + printf ("%9d, /* %6.2f kPa */\n", + alt_part[part], kPa); +} -- cgit v1.2.3 From 34bb17bc1a3d8a1c95b5e57f059e7a1747e17a03 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 May 2012 20:16:35 -0700 Subject: altos: Finish ms5607 support This has the MS5607 polling once each tick for pressure and temperature and then saving that in a global variable. The command UI provides for dumping the prom data so that an eeprom file can have raw sensor data along with the conversion factors necessary to compute useful values. Signed-off-by: Keith Packard --- src/core/ao.h | 1 + src/drivers/ao_ms5607.c | 114 +++++++++++++++++++++++++++++++++--------- src/drivers/ao_ms5607.h | 19 +++++-- src/megametrum-v0.1/Makefile | 3 +- src/megametrum-v0.1/ao_pins.h | 7 ++- 5 files changed, 115 insertions(+), 29 deletions(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index a2092cfe..da1fd67b 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -115,6 +115,7 @@ ao_start_scheduler(void); #define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ #define AO_PANIC_STACK 12 /* Stack overflow */ #define AO_PANIC_SPI 13 /* SPI communication failure */ +#define AO_PANIC_SELF_TEST 14 /* Self test failure */ /* Stop the operating system, beeping and blinking the reason */ void diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 4594f07c..f79c315a 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -16,10 +16,11 @@ */ #include +#include #include "ao_ms5607.h" -static struct ms5607_prom ms5607_prom; -static uint8_t ms5607_configured; +static struct ao_ms5607_prom ms5607_prom; +static uint8_t ms5607_configured; static void ao_ms5607_start(void) { @@ -69,7 +70,7 @@ ao_ms5607_crc(uint8_t *prom) } static void -ao_ms5607_prom_read(struct ms5607_prom *prom) +ao_ms5607_prom_read(struct ao_ms5607_prom *prom) { uint8_t addr; uint8_t crc; @@ -85,8 +86,12 @@ ao_ms5607_prom_read(struct ms5607_prom *prom) r++; } crc = ao_ms5607_crc((uint8_t *) prom); - if (crc != (((uint8_t *) prom)[15] & 0xf)) - printf ("MS5607 PROM CRC error (computed %x actual %x)\n", crc, (((uint8_t *) prom)[15] & 0xf)); + if (crc != (((uint8_t *) prom)[15] & 0xf)) { + printf ("MS5607 PROM CRC error (computed %x actual %x)\n", + crc, (((uint8_t *) prom)[15] & 0xf)); + flush(); + ao_panic(AO_PANIC_SELF_TEST); + } #if __BYTE_ORDER == __LITTLE_ENDIAN /* Byte swap */ @@ -108,17 +113,33 @@ ao_ms5607_setup(void) ao_ms5607_prom_read(&ms5607_prom); } +static uint8_t ao_ms5607_done; + +static void +ao_ms5607_isr(void) +{ + ao_ms5607_done = 1; + ao_wakeup(&ao_ms5607_done); +} + static uint32_t -ao_ms5607_convert(uint8_t cmd) { +ao_ms5607_get_sample(uint8_t cmd) { uint8_t reply[3]; uint8_t read; + uint16_t now; + + ao_ms5607_done = 0; ao_ms5607_start(); ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_exti_enable(&AO_MS5607_MISO_GPIO, AO_MS5607_MISO); + cli(); + while (!ao_ms5607_done) + ao_sleep(&ao_ms5607_done); + sei(); + ao_exti_disable(&AO_MS5607_MISO_GPIO, AO_MS5607_MISO); ao_ms5607_stop(); - ao_delay(AO_MS_TO_TICKS(20)); - ao_ms5607_start(); read = AO_MS5607_ADC_READ; ao_spi_send(&read, 1, AO_MS5607_SPI_INDEX); @@ -130,23 +151,22 @@ ao_ms5607_convert(uint8_t cmd) { void ao_ms5607_sample(struct ao_ms5607_sample *sample) +{ + sample->pres = ao_ms5607_get_sample(AO_MS5607_CONVERT_D1_2048); + sample->temp = ao_ms5607_get_sample(AO_MS5607_CONVERT_D2_2048); +} + +void +ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value) { uint8_t addr; - uint32_t D1, D2; int32_t dT; int32_t TEMP; int64_t OFF; int64_t SENS; int32_t P; - ao_ms5607_setup(); - - D2 = ao_ms5607_convert(AO_MS5607_CONVERT_D2_4096); - printf ("Conversion D2: %d\n", D2); - D1 = ao_ms5607_convert(AO_MS5607_CONVERT_D1_4096); - printf ("Conversion D1: %d\n", D1); - - dT = D2 - ((int32_t) ms5607_prom.tref << 8); + dT = sample->temp - ((int32_t) ms5607_prom.tref << 8); TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23); @@ -170,19 +190,49 @@ ao_ms5607_sample(struct ao_ms5607_sample *sample) SENS -= SENS2; } - P = ((((int64_t) D1 * SENS) >> 21) - OFF) >> 15; - sample->temp = TEMP; - sample->pres = P; + value->pres = ((((int64_t) sample->pres * SENS) >> 21) - OFF) >> 15; + value->temp = TEMP; } +struct ao_ms5607_sample ao_ms5607_current; + +static void +ao_ms5607(void) +{ + ao_ms5607_setup(); + for (;;) + { + struct ao_ms5607_sample ao_ms5607_next; + ao_ms5607_sample(&ao_ms5607_next); + ao_arch_critical( + ao_ms5607_current = ao_ms5607_next; + ); + ao_delay(0); + } +} + +__xdata struct ao_task ao_ms5607_task; + static void ao_ms5607_dump(void) { struct ao_ms5607_sample sample; + struct ao_ms5607_value value; + + printf ("ms5607 reserved: %u\n", ms5607_prom.reserved); + printf ("ms5607 sens: %u\n", ms5607_prom.sens); + printf ("ms5607 off: %u\n", ms5607_prom.off); + printf ("ms5607 tcs: %u\n", ms5607_prom.tcs); + printf ("ms5607 tco: %u\n", ms5607_prom.tco); + printf ("ms5607 tref: %u\n", ms5607_prom.tref); + printf ("ms5607 tempsens: %u\n", ms5607_prom.tempsens); + printf ("ms5607 crc: %u\n", ms5607_prom.crc); - ao_ms5607_sample(&sample); - printf ("Temperature: %d\n", sample.temp); - printf ("Pressure %d\n", sample.pres); + 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); + printf ("Altitude: %ld\n", ao_pa_to_altitude(value.pres)); } __code struct ao_cmds ao_ms5607_cmds[] = { @@ -196,4 +246,22 @@ ao_ms5607_init(void) ms5607_configured = 0; ao_cmd_register(&ao_ms5607_cmds[0]); ao_spi_init_cs(AO_MS5607_CS_GPIO, (1 << AO_MS5607_CS)); + + ao_add_task(&ao_ms5607_task, ao_ms5607, "ms5607"); + + /* Configure the MISO pin as an interrupt; when the + * conversion is complete, the MS5607 will raise this + * pin as a signal + */ + ao_exti_setup(&AO_MS5607_MISO_GPIO, + AO_MS5607_MISO, + AO_EXTI_MODE_RISING, + ao_ms5607_isr); + + /* Reset the pin from INPUT to ALTERNATE so that SPI works + * This needs an abstraction at some point... + */ + stm_moder_set(&AO_MS5607_MISO_GPIO, + AO_MS5607_MISO, + STM_MODER_ALTERNATE); } diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index 29df25e4..fd5bc984 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -35,7 +35,7 @@ #define AO_MS5607_ADC_READ 0x00 #define AO_MS5607_PROM_READ(ad) (0xA0 | ((ad) << 1)) -struct ms5607_prom { +struct ao_ms5607_prom { uint16_t reserved; uint16_t sens; uint16_t off; @@ -47,8 +47,15 @@ struct ms5607_prom { }; struct ao_ms5607_sample { - int32_t temp; - int32_t pres; + uint32_t pres; /* raw 24 bit sensor */ + uint32_t temp; /* raw 24 bit sensor */ +}; + +extern struct ao_ms5607_sample ao_ms5607_current; + +struct ao_ms5607_value { + int32_t pres; /* in Pa * 10 */ + int32_t temp; /* in °C * 100 */ }; void @@ -57,4 +64,10 @@ ao_ms5607_init(void); void ao_ms5607_sample(struct ao_ms5607_sample *sample); +void +ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value); + +void +ao_ms5607_get_prom(struct ao_ms5607_prom *prom); + #endif /* _AO_MS5607_H_ */ diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 437e1a9e..6524d8b8 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -50,7 +50,8 @@ ALTOS_SRC = \ ao_packet_slave.c \ ao_i2c_stm.c \ ao_hmc5883.c \ - ao_mpu6000.c + ao_mpu6000.c \ + ao_convert_pa.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index cd270739..adc56151 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -182,6 +182,9 @@ struct ao_adc { #define AO_MS5607_CS_GPIO stm_gpioc #define AO_MS5607_CS 4 #define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) +#define AO_MS5607_MISO_GPIO stm_gpioa +#define AO_MS5607_MISO 6 +#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO) #define AO_MS5607_SPI_INDEX (STM_SPI_INDEX(1)) /* @@ -212,7 +215,7 @@ struct ao_adc { #define AO_HMC5883_INT_PORT stm_gpioc #define AO_HMC5883_INT_PIN 12 -#define AO_HMC5883_I2C_INDEX STM_SPI_INDEX(1) +#define AO_HMC5883_I2C_INDEX STM_I2C_INDEX(1) /* * mpu6000 @@ -220,6 +223,6 @@ struct ao_adc { #define AO_MPU6000_INT_PORT stm_gpioc #define AO_MPU6000_INT_PIN 13 -#define AO_MPU6000_I2C_INDEX STM_SPI_INDEX(1) +#define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 78423f3fc5164ea9fd428606419784c1700ad5c5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 25 May 2012 23:18:06 -0600 Subject: Get megametrum ready to at least log flight data Doesn't track flight state changes correctly. Signed-off-by: Keith Packard --- src/core/ao_adc.h | 5 ++- src/core/ao_config.c | 33 ++++++++++++++++---- src/core/ao_kalman.c | 3 ++ src/core/ao_log.c | 3 +- src/core/ao_log.h | 62 ++++++++++++++++++++++++++++++++++++- src/core/ao_sample.h | 19 +++++++----- src/megametrum-v0.1/Makefile | 19 +++++++++--- src/megametrum-v0.1/ao_megametrum.c | 8 +++-- src/megametrum-v0.1/ao_pins.h | 7 ++++- src/stm/ao_adc_stm.c | 42 ++++++++++++++++++------- 10 files changed, 164 insertions(+), 37 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_adc.h b/src/core/ao_adc.h index db5bfab3..8ec740c4 100644 --- a/src/core/ao_adc.h +++ b/src/core/ao_adc.h @@ -18,13 +18,11 @@ #ifndef _AO_ADC_H_ #define _AO_ADC_H_ - - /* * One set of samples read from the A/D converter or telemetry */ - +#if AO_ADC_RING /* * ao_adc.c */ @@ -42,6 +40,7 @@ extern volatile __data uint8_t ao_adc_head; #if HAS_ACCEL_REF extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; #endif +#endif /* Trigger a conversion sequence (called from the timer interrupt) */ void diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 55fb8590..55ec9f40 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -16,6 +16,9 @@ */ #include "ao.h" +#include "ao_log.h" +#include +#include __xdata struct ao_config ao_config; __pdata uint8_t ao_config_loaded; @@ -64,11 +67,13 @@ ao_config_put(void) } #endif +#if HAS_RADIO void ao_config_set_radio(void) { ao_config.radio_setting = ao_freq_to_set(ao_config.frequency, ao_config.radio_cal); } +#endif /* HAS_RADIO */ static void _ao_config_get(void) @@ -100,8 +105,10 @@ _ao_config_get(void) ao_config.accel_minus_g = 0; } /* Fixups for minor version 3 */ +#if HAS_RADIO if (ao_config.minor < 3) ao_config.radio_cal = ao_radio_cal; +#endif /* Fixups for minor version 4 */ if (ao_config.minor < 4) ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; @@ -121,7 +128,9 @@ _ao_config_get(void) ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } +#if HAS_RADIO ao_config_set_radio(); +#endif ao_config_loaded = 1; } @@ -176,6 +185,7 @@ ao_config_callsign_set(void) __reentrant _ao_config_edit_finish(); } +#if HAS_RADIO void ao_config_frequency_show(void) __reentrant { @@ -195,6 +205,7 @@ ao_config_frequency_set(void) __reentrant _ao_config_edit_finish(); ao_radio_recv_abort(); } +#endif #if HAS_FLIGHT @@ -232,7 +243,7 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant { uint16_t i; int32_t accel_total; - uint8_t cal_adc_ring; + uint8_t cal_data_ring; printf("Orient antenna %s and press a key...", orientation); flush(); @@ -241,12 +252,14 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant puts("Calibrating..."); flush(); i = ACCEL_CALIBRATE_SAMPLES; accel_total = 0; - cal_adc_ring = ao_sample_adc; + cal_data_ring = ao_sample_data; while (i) { - ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); - while (i && cal_adc_ring != ao_sample_adc) { - accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel; - cal_adc_ring = ao_adc_ring_next(cal_adc_ring); + ao_sleep(DATA_TO_XDATA(&ao_sample_data)); + while (i && cal_data_ring != ao_sample_data) { + int16_t accel = ao_data_accel(&ao_data_ring[cal_data_ring]); + printf ("accel %d\n", accel); + accel_total += (int32_t) ao_data_accel(&ao_data_ring[cal_data_ring]); + cal_data_ring = ao_data_ring_next(cal_data_ring); i--; } } @@ -320,6 +333,7 @@ ao_config_apogee_lockout_set(void) __reentrant #endif /* HAS_FLIGHT */ +#if HAS_RADIO void ao_config_radio_cal_show(void) __reentrant { @@ -337,6 +351,7 @@ ao_config_radio_cal_set(void) __reentrant ao_config_set_radio(); _ao_config_edit_finish(); } +#endif #if HAS_LOG void @@ -413,6 +428,7 @@ ao_config_pad_orientation_set(void) __reentrant } #endif +#if HAS_RADIO void ao_config_radio_enable_show(void) __reentrant { @@ -429,6 +445,7 @@ ao_config_radio_enable_set(void) __reentrant ao_config.radio_enable = ao_cmd_lex_i; _ao_config_edit_finish(); } +#endif /* HAS_RADIO */ #if HAS_AES void @@ -481,18 +498,22 @@ __code struct ao_config_var ao_config_vars[] = { { "L \0Apogee detect lockout (s)", ao_config_apogee_lockout_set, ao_config_apogee_lockout_show, }, #endif /* HAS_FLIGHT */ +#if HAS_RADIO { "F \0Frequency (kHz)", ao_config_frequency_set, ao_config_frequency_show }, { "c \0Callsign (8 char max)", ao_config_callsign_set, ao_config_callsign_show }, { "e <0 disable, 1 enable>\0Enable telemetry and RDF", ao_config_radio_enable_set, ao_config_radio_enable_show }, +#endif /* HAS_RADIO */ #if HAS_ACCEL { "a <+g> <-g>\0Accel calib (0 for auto)", ao_config_accel_calibrate_set,ao_config_accel_calibrate_show }, #endif /* HAS_ACCEL */ +#if HAS_RADIO { "f \0Radio calib (cal = rf/(xtal/2^16))", ao_config_radio_cal_set, ao_config_radio_cal_show }, +#endif /* HAS_RADIO */ #if HAS_LOG { "l \0Flight log size (kB)", ao_config_log_set, ao_config_log_show }, diff --git a/src/core/ao_kalman.c b/src/core/ao_kalman.c index ee01949e..68725f69 100644 --- a/src/core/ao_kalman.c +++ b/src/core/ao_kalman.c @@ -17,10 +17,13 @@ #ifndef AO_FLIGHT_TEST #include "ao.h" +#include "ao_flight.h" #endif +#include "ao_sample.h" #include "ao_kalman.h" + static __pdata int32_t ao_k_height; static __pdata int32_t ao_k_speed; static __pdata int32_t ao_k_accel; diff --git a/src/core/ao_log.c b/src/core/ao_log.c index db60707d..d696625e 100644 --- a/src/core/ao_log.c +++ b/src/core/ao_log.c @@ -16,12 +16,13 @@ */ #include "ao.h" +#include __pdata uint32_t ao_log_current_pos; __pdata uint32_t ao_log_end_pos; __pdata uint32_t ao_log_start_pos; __xdata uint8_t ao_log_running; -__pdata enum flight_state ao_log_state; +__pdata enum ao_flight_state ao_log_state; __xdata uint16_t ao_flight_number; __code uint8_t ao_log_format = AO_LOG_FORMAT_FULL; diff --git a/src/core/ao_log.h b/src/core/ao_log.h index 611c00d5..e585750f 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -18,6 +18,8 @@ #ifndef _AO_LOG_H_ #define _AO_LOG_H_ +#include + /* * ao_log.c */ @@ -32,7 +34,7 @@ extern __pdata uint32_t ao_log_current_pos; extern __pdata uint32_t ao_log_end_pos; extern __pdata uint32_t ao_log_start_pos; extern __xdata uint8_t ao_log_running; -extern __pdata enum flight_state ao_log_state; +extern __pdata enum ao_flight_state ao_log_state; /* required functions from the underlying log system */ @@ -41,6 +43,7 @@ extern __pdata enum flight_state ao_log_state; #define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ #define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ #define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ +#define AO_LOG_FORMAT_MEGAMETRUM 5 /* 32 byte typed megametrum records */ #define AO_LOG_FORMAT_NONE 127 /* No log at all */ extern __code uint8_t ao_log_format; @@ -189,8 +192,65 @@ struct ao_log_record { } u; }; +struct ao_log_mega { + char type; /* 0 */ + uint8_t csum; /* 1 */ + uint16_t tick; /* 2 */ + union { /* 4 */ + struct { + uint16_t flight; /* 4 */ + int16_t ground_accel; /* 6 */ + uint32_t ground_pres; /* 8 */ + uint32_t ground_temp; /* 12 */ + } flight; /* 16 */ + struct { + uint16_t state; + uint16_t reason; + } state; + struct { + uint32_t pres; /* 4 */ + uint32_t temp; /* 8 */ + int16_t accel_x; /* 12 */ + int16_t accel_y; /* 14 */ + int16_t accel_z; /* 16 */ + int16_t gyro_x; /* 18 */ + int16_t gyro_y; /* 20 */ + int16_t gyro_z; /* 22 */ + } sensor; /* 24 */ + struct { + int16_t v_batt; /* 4 */ + int16_t v_pbatt; /* 8 */ + int16_t n_sense; /* 10 */ + int16_t sense[10]; /* 12 */ + } volt; /* 32 */ + struct { + int32_t latitude; /* 4 */ + int32_t longitude; /* 8 */ + int16_t altitude; /* 12 */ + uint8_t hour; /* 14 */ + uint8_t minute; /* 15 */ + uint8_t second; /* 16 */ + uint8_t flags; /* 17 */ + uint8_t year; /* 18 */ + uint8_t month; /* 19 */ + uint8_t day; /* 20 */ + uint8_t pad; /* 21 */ + } gps; /* 22 */ + struct { + uint16_t channels; /* 4 */ + struct { + uint8_t svid; + uint8_t c_n; + } sats[12]; /* 6 */ + } gps_sat; /* 30 */ + } u; +}; + /* Write a record to the eeprom log */ uint8_t ao_log_data(__xdata struct ao_log_record *log) __reentrant; +uint8_t +ao_log_mega(__xdata struct ao_log_mega *log) __reentrant; + #endif /* _AO_LOG_H_ */ diff --git a/src/core/ao_sample.h b/src/core/ao_sample.h index fb0e69e8..189b2019 100644 --- a/src/core/ao_sample.h +++ b/src/core/ao_sample.h @@ -18,6 +18,8 @@ #ifndef _AO_SAMPLE_H_ #define _AO_SAMPLE_H_ +#include + /* * ao_sample.c */ @@ -88,21 +90,22 @@ #define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) extern __pdata uint16_t ao_sample_tick; /* time of last data */ -extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */ -extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */ -extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */ +extern __pdata pres_t ao_sample_pres; /* most recent pressure sensor reading */ +extern __pdata alt_t ao_sample_alt; /* MSL of ao_sample_pres */ +extern __pdata alt_t ao_sample_height; /* AGL of ao_sample_pres */ extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ +extern __data uint8_t ao_sample_data; /* Ring position of last processed sample */ #if HAS_ACCEL -extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ +extern __pdata accel_t ao_sample_accel; /* most recent accel sensor reading */ #endif -extern __pdata int16_t ao_ground_pres; /* startup pressure */ -extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ +extern __pdata pres_t ao_ground_pres; /* startup pressure */ +extern __pdata alt_t ao_ground_height; /* MSL of ao_ground_pres */ #if HAS_ACCEL -extern __pdata int16_t ao_ground_accel; /* startup acceleration */ -extern __pdata int16_t ao_accel_2g; /* factory accel calibration */ +extern __pdata accel_t ao_ground_accel; /* startup acceleration */ +extern __pdata accel_t ao_accel_2g; /* factory accel calibration */ extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ #endif diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 6524d8b8..a07b25ee 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -9,6 +9,8 @@ INC = \ ao.h \ ao_arch.h \ ao_arch_funcs.h \ + ao_data.h \ + ao_sample.h \ ao_pins.h \ altitude.h \ ao_kalman.h \ @@ -21,6 +23,11 @@ INC = \ # # Common AltOS sources # + +# ao_cc1120.c \ +# ao_packet.c \ +# ao_packet_slave.c \ + ALTOS_SRC = \ ao_interrupt.c \ ao_product.c \ @@ -35,7 +42,6 @@ ALTOS_SRC = \ ao_mutex.c \ ao_serial_stm.c \ ao_gps_skytraq.c \ - ao_cc1120.c \ ao_freq.c \ ao_dma_stm.c \ ao_spi_stm.c \ @@ -46,12 +52,17 @@ ALTOS_SRC = \ ao_m25.c \ ao_usb_stm.c \ ao_exti_stm.c \ - ao_packet.c \ - ao_packet_slave.c \ + ao_report.c \ ao_i2c_stm.c \ ao_hmc5883.c \ ao_mpu6000.c \ - ao_convert_pa.c + ao_convert_pa.c \ + ao_log.c \ + ao_log_mega.c \ + ao_sample_mm.c \ + ao_kalman.c \ + ao_flight_mm.c + PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 2e1f9298..19746d37 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 void @@ -46,7 +47,6 @@ main(void) ao_timer_init(); ao_cmd_init(); ao_gps_init(); - ao_config_init(); ao_dma_init(); ao_spi_init(); ao_ms5607_init(); @@ -55,10 +55,14 @@ main(void) ao_storage_init(); ao_usb_init(); ao_exti_init(); - ao_radio_init(); +// ao_radio_init(); ao_i2c_init(); ao_hmc5883_init(); ao_mpu6000_init(); + ao_flight_init(); + ao_log_init(); + ao_report_init(); + ao_config_init(); ao_cmd_register(&ao_mm_cmds[0]); ao_start_scheduler(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index adc56151..3ab7e15a 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -94,9 +94,12 @@ #define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) +#define HAS_GPS 1 +#define HAS_FLIGHT 1 #define HAS_ADC 1 +#define HAS_ACCEL 1 -#define AO_ADC_RING 32 +#define AO_DATA_RING 32 #define AO_ADC_NUM_SENSE 6 struct ao_adc { @@ -179,6 +182,7 @@ struct ao_adc { /* * Pressure sensor settings */ +#define HAS_MS5607 1 #define AO_MS5607_CS_GPIO stm_gpioc #define AO_MS5607_CS 4 #define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) @@ -221,6 +225,7 @@ struct ao_adc { * mpu6000 */ +#define HAS_MPU6000 1 #define AO_MPU6000_INT_PORT stm_gpioc #define AO_MPU6000_INT_PIN 13 #define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index a2569908..af2968d6 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -16,10 +16,17 @@ */ #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; -volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -volatile __data uint8_t ao_adc_head; static uint8_t ao_adc_ready; #define AO_ADC_CR2_VAL ((0 << STM_ADC_CR2_SWSTART) | \ @@ -43,9 +50,15 @@ static uint8_t ao_adc_ready; */ static void ao_adc_done(int index) { - ao_adc_ring[ao_adc_head].tick = ao_time(); - ao_adc_head = ao_adc_ring_next(ao_adc_head); - ao_wakeup((void *) &ao_adc_head); + ao_data_ring[ao_data_head].adc.tick = ao_time(); +#if HAS_MPU6000 + ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current; +#endif +#if HAS_MS5607 + ao_data_ring[ao_data_head].ms5607 = ao_ms5607_current; +#endif + ao_data_head = ao_data_ring_next(ao_data_head); + ao_wakeup((void *) &ao_data_head); ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); ao_adc_ready = 1; } @@ -62,7 +75,7 @@ ao_adc_poll(void) stm_adc.sr = 0; ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), &stm_adc.dr, - (void *) (&ao_adc_ring[ao_adc_head].tick + 1), + (void *) (&ao_data_ring[ao_data_head].tick + 1), AO_NUM_ADC, (0 << STM_DMA_CCR_MEM2MEM) | (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) | @@ -84,20 +97,27 @@ ao_adc_poll(void) void ao_adc_get(__xdata struct ao_adc *packet) { - uint8_t i = ao_adc_ring_prev(ao_adc_head); - memcpy(packet, (void *) &ao_adc_ring[i], sizeof (struct ao_adc)); + uint8_t i = ao_data_ring_prev(ao_data_head); + memcpy(packet, (void *) &ao_data_ring[i].adc, sizeof (struct ao_adc)); +} + +void +ao_data_get(__xdata struct ao_data *packet) +{ + uint8_t i = ao_data_ring_prev(ao_data_head); + memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data)); } static void ao_adc_dump(void) __reentrant { - struct ao_adc packet; + struct ao_data packet; int16_t *d; uint8_t i; - ao_adc_get(&packet); + ao_data_get(&packet); printf("tick: %5u", packet.tick); - d = (int16_t *) (&packet.tick + 1); + d = (int16_t *) (&packet.adc); for (i = 0; i < AO_NUM_ADC; i++) printf (" %2d: %5d", i, d[i]); printf("\n"); -- cgit v1.2.3 From dd73c9b441f7672fb9982c4caeb5178df30f5d2b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 16:47:30 -0600 Subject: altos: Split out mm-specific versions of sampling code Avoid breaking telemetrum (too much) by splitting this stuff apart. Signed-off-by: Keith Packard --- src/core/ao_data.h | 191 +++++++++++++++++++++++++ src/core/ao_flight_mm.c | 362 ++++++++++++++++++++++++++++++++++++++++++++++++ src/core/ao_log_mega.c | 174 +++++++++++++++++++++++ src/core/ao_sample_mm.c | 135 ++++++++++++++++++ 4 files changed, 862 insertions(+) create mode 100644 src/core/ao_data.h create mode 100644 src/core/ao_flight_mm.c create mode 100644 src/core/ao_log_mega.c create mode 100644 src/core/ao_sample_mm.c (limited to 'src/core') diff --git a/src/core/ao_data.h b/src/core/ao_data.h new file mode 100644 index 00000000..d28730a8 --- /dev/null +++ b/src/core/ao_data.h @@ -0,0 +1,191 @@ +/* + * 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_DATA_H_ +#define _AO_DATA_H_ + +#if HAS_MS5607 +#include +#endif + +#if HAS_MPU6000 +#include +#endif + +struct ao_data { + uint16_t tick; +#if HAS_ADC + struct ao_adc adc; +#endif +#if HAS_ACCEL_REF + uint16_t accel_ref; +#endif +#if HAS_MS5607 + struct ao_ms5607_sample ms5607; +#endif +#if HAS_MPU6000 + struct ao_mpu6000_sample mpu6000; +#endif +}; + +#define ao_data_ring_next(n) (((n) + 1) & (AO_DATA_RING - 1)) +#define ao_data_ring_prev(n) (((n) - 1) & (AO_DATA_RING - 1)) + +extern volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; +extern volatile __data uint8_t ao_data_head; + +#if HAS_MS5607 + +typedef int32_t pres_t; +typedef int32_t alt_t; + +static inline pres_t ao_data_pres(struct ao_data *packet) +{ + struct ao_ms5607_value value; + + ao_ms5607_convert(&packet->ms5607, &value); + return value.pres; +} + +#define pres_to_altitude(p) ao_pa_to_altitude(p) + +#else + +typedef int16_t pres_t; +typedef int16_t alt_t; + +#define ao_data_pres(packet) ((packet)->adc.pres) +#define pres_to_altitude(p) ao_pres_to_altitude(p) + +#endif + +/* + * Need a few macros to pull data from the sensors: + * + * ao_data_accel_sample - pull raw sensor and convert to normalized values + * ao_data_accel - pull normalized value (lives in the same memory) + * ao_data_set_accel - store normalized value back in the sensor location + * ao_data_accel_invert - flip rocket ends for positive acceleration + */ + +#if HAS_MPU6000 + +typedef int16_t accel_t; + +/* MPU6000 is hooked up so that positive y is positive acceleration */ +#define ao_data_accel(packet) ((packet)->mpu6000.accel_y) +#define ao_data_accel_sample(packet) (-ao_data_accel(packet)) +#define ao_data_set_accel(packet, accel) ((packet)->mpu6000.accel_y = (accel)) +#define ao_data_accel_invert(a) (-(a)) + +#else + +typedef int16_t accel_t; +#define ao_data_accel(packet) ((packet)->adc.accel) +#define ao_data_set_accel(packet, accel) ((packet)->adc.accel = (accel)) +#define ao_data_accel_invert(a) (0x7fff -(a)) + +/* + * Ok, the math here is a bit tricky. + * + * ao_sample_accel: ADC output for acceleration + * ao_accel_ref: ADC output for the 5V reference. + * ao_cook_accel: Corrected acceleration value + * Vcc: 3.3V supply to the CC1111 + * Vac: 5V supply to the accelerometer + * accel: input voltage to accelerometer ADC pin + * ref: input voltage to 5V reference ADC pin + * + * + * Measured acceleration is ratiometric to Vcc: + * + * ao_sample_accel accel + * ------------ = ----- + * 32767 Vcc + * + * Measured 5v reference is also ratiometric to Vcc: + * + * ao_accel_ref ref + * ------------ = ----- + * 32767 Vcc + * + * + * ao_accel_ref = 32767 * (ref / Vcc) + * + * Acceleration is measured ratiometric to the 5V supply, + * so what we want is: + * + * ao_cook_accel accel + * ------------- = ----- + * 32767 ref + * + * + * accel Vcc + * = ----- * --- + * Vcc ref + * + * ao_sample_accel 32767 + * = ------------ * ------------ + * 32767 ao_accel_ref + * + * Multiply through by 32767: + * + * ao_sample_accel * 32767 + * ao_cook_accel = -------------------- + * ao_accel_ref + * + * Now, the tricky part. Getting this to compile efficiently + * and keeping all of the values in-range. + * + * First off, we need to use a shift of 16 instead of * 32767 as SDCC + * does the obvious optimizations for byte-granularity shifts: + * + * ao_cook_accel = (ao_sample_accel << 16) / ao_accel_ref + * + * Next, lets check our input ranges: + * + * 0 <= ao_sample_accel <= 0x7fff (singled ended ADC conversion) + * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) + * + * Plugging in our input ranges, we get an output range of 0 - 0x12490, + * which is 17 bits. That won't work. If we take the accel ref and shift + * by a bit, we'll change its range: + * + * 0xe000 <= ao_accel_ref<<1 <= 0xfffe + * + * ao_cook_accel = (ao_sample_accel << 16) / (ao_accel_ref << 1) + * + * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It + * is, however, one bit too large for our signed computations. So, we + * take the result and shift that by a bit: + * + * ao_cook_accel = ((ao_sample_accel << 16) / (ao_accel_ref << 1)) >> 1 + * + * This finally creates an output range of 0 - 0x4924. As the ADC only + * provides 11 bits of data, we haven't actually lost any precision, + * just dropped a bit of noise off the low end. + */ +#if HAS_ACCEL_REF +#define ao_data_accel_sample(packet) \ + ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->accel_ref << 1))) >> 1) +#else +#define ao_data_accel(packet) ((packet)->adc.accel) +#endif /* HAS_ACCEL_REF */ + +#endif /* else some other pressure sensor */ + +#endif /* _AO_DATA_H_ */ diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c new file mode 100644 index 00000000..27087e55 --- /dev/null +++ b/src/core/ao_flight_mm.c @@ -0,0 +1,362 @@ +/* + * Copyright © 2009 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_FLIGHT_TEST +#include "ao.h" +#include +#endif + +#ifndef HAS_ACCEL +#error Please define HAS_ACCEL +#endif + +#ifndef HAS_GPS +#error Please define HAS_GPS +#endif + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ +__pdata uint16_t ao_boost_tick; /* time of launch detect */ + +/* + * track min/max data over a long interval to detect + * resting + */ +static __data uint16_t ao_interval_end; +static __data int16_t ao_interval_min_height; +static __data int16_t ao_interval_max_height; +static __data int16_t ao_coast_avg_accel; + +__pdata uint8_t ao_flight_force_idle; + +/* We also have a clock, which can be used to sanity check things in + * case of other failures + */ + +#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) + +/* Landing is detected by getting constant readings from both pressure and accelerometer + * for a fairly long time (AO_INTERVAL_TICKS) + */ +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) + +#define abs(a) ((a) < 0 ? -(a) : (a)) + +void +ao_flight(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + for (;;) { + + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + + /* Check to see what mode we should go to. + * - Invalid mode if accel cal appears to be out + * - pad mode if we're upright, + * - idle mode otherwise + */ +#if HAS_ACCEL + if (ao_config.accel_plus_g == 0 || + ao_config.accel_minus_g == 0 || + ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) + { + /* Detected an accel value outside -1.5g to 1.5g + * (or uncalibrated values), so we go into invalid mode + */ + ao_flight_state = ao_flight_invalid; + +#if HAS_RADIO + /* Turn on packet system in invalid mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + } else +#endif + if (!ao_flight_force_idle +#if HAS_ACCEL + && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP +#endif + ) + { + /* Set pad mode - we can fly! */ + ao_flight_state = ao_flight_pad; +#if HAS_USB + /* Disable the USB controller in flight mode + * to save power + */ + ao_usb_disable(); +#endif + +#if !HAS_ACCEL + /* Disable packet mode in pad state on TeleMini */ + ao_packet_slave_stop(); +#endif + +#if HAS_RADIO + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); +#endif + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } else { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + +#if HAS_ACCEL && HAS_RADIO + /* Turn on packet system in idle mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + + break; + case ao_flight_pad: + + /* pad to boost: + * + * barometer: > 20m vertical motion + * OR + * accelerometer: > 2g AND velocity > 5m/s + * + * The accelerometer should always detect motion before + * the barometer, but we use both to make sure this + * transition is detected. If the device + * doesn't have an accelerometer, then ignore the + * speed and acceleration as they are quite noisy + * on the pad. + */ + if (ao_height > AO_M_TO_HEIGHT(20) +#if HAS_ACCEL + || (ao_accel > AO_MSS_TO_ACCEL(20) && + ao_speed > AO_MS_TO_SPEED(5)) +#endif + ) + { + ao_flight_state = ao_flight_boost; + ao_boost_tick = ao_sample_tick; + + /* start logging data */ + ao_log_start(); + +#if HAS_RADIO + /* Increase telemetry rate */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); + + /* disable RDF beacon */ + ao_rdf_set(0); +#endif + +#if HAS_GPS + /* Record current GPS position by waking up GPS log tasks */ + ao_wakeup(&ao_gps_data); + ao_wakeup(&ao_gps_tracking_data); +#endif + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_boost: + + /* boost to fast: + * + * accelerometer: start to fall at > 1/4 G + * OR + * time: boost for more than 15 seconds + * + * Detects motor burn out by the switch from acceleration to + * deceleration, or by waiting until the maximum burn duration + * (15 seconds) has past. + */ + if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || + (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX) + { +#if HAS_ACCEL + ao_flight_state = ao_flight_fast; + ao_coast_avg_accel = ao_accel; +#else + ao_flight_state = ao_flight_coast; +#endif + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; +#if HAS_ACCEL + case ao_flight_fast: + /* + * This is essentially the same as coast, + * but the barometer is being ignored as + * it may be unreliable. + */ + if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) + { + ao_flight_state = ao_flight_coast; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } else + goto check_re_boost; + break; +#endif + case ao_flight_coast: + + /* + * By customer request - allow the user + * to lock out apogee detection for a specified + * number of seconds. + */ + if (ao_config.apogee_lockout) { + if ((ao_sample_tick - ao_boost_tick) < + AO_SEC_TO_TICKS(ao_config.apogee_lockout)) + break; + } + + /* apogee detect: coast to drogue deploy: + * + * speed: < 0 + * + * Also make sure the model altitude is tracking + * the measured altitude reasonably closely; otherwise + * we're probably transsonic. + */ + if (ao_speed < 0 +#if !HAS_ACCEL + && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) +#endif + ) + { +#if HAS_IGNITE + /* ignite the drogue charge */ + ao_ignite(ao_igniter_drogue); +#endif + +#if HAS_RADIO + /* slow down the telemetry system */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); + + /* Turn the RDF beacon back on */ + ao_rdf_set(1); +#endif + + /* and enter drogue state */ + ao_flight_state = ao_flight_drogue; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } +#if HAS_ACCEL + else { + check_re_boost: + ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); + if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) { + ao_boost_tick = ao_sample_tick; + ao_flight_state = ao_flight_boost; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + } +#endif + + break; + case ao_flight_drogue: + + /* drogue to main deploy: + * + * barometer: reach main deploy altitude + * + * Would like to use the accelerometer for this test, but + * the orientation of the flight computer is unknown after + * drogue deploy, so we ignore it. Could also detect + * high descent rate using the pressure sensor to + * recognize drogue deploy failure and eject the main + * at that point. Perhaps also use the drogue sense lines + * to notice continutity? + */ + if (ao_height <= ao_config.main_deploy) + { +#if HAS_IGNITE + ao_ignite(ao_igniter_main); +#endif + + /* + * Start recording min/max height + * to figure out when the rocket has landed + */ + + /* initialize interval values */ + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + + ao_flight_state = ao_flight_main; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + + /* fall through... */ + case ao_flight_main: + + /* main to land: + * + * barometer: altitude stable + */ + + if (ao_avg_height < ao_interval_min_height) + ao_interval_min_height = ao_avg_height; + if (ao_avg_height > ao_interval_max_height) + ao_interval_max_height = ao_avg_height; + + if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { + if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) + { + ao_flight_state = ao_flight_landed; + + /* turn off the ADC capture */ + ao_timer_set_adc_interval(0); + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + } + break; + case ao_flight_landed: + break; + } + } +} + +static __xdata struct ao_task flight_task; + +void +ao_flight_init(void) +{ + ao_flight_state = ao_flight_startup; + ao_add_task(&flight_task, ao_flight, "flight"); +} diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c new file mode 100644 index 00000000..1763b9eb --- /dev/null +++ b/src/core/ao_log_mega.c @@ -0,0 +1,174 @@ +/* + * 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 "ao.h" +#include +#include +#include + +static __xdata uint8_t ao_log_mutex; +static __xdata struct ao_log_mega log; + +static uint8_t +ao_log_csum(__xdata uint8_t *b) __reentrant +{ + uint8_t sum = 0x5a; + uint8_t i; + + for (i = 0; i < sizeof (struct ao_log_mega); i++) + sum += *b++; + return -sum; +} + +uint8_t +ao_log_mega(__xdata struct ao_log_mega *log) __reentrant +{ + uint8_t wrote = 0; + /* set checksum */ + log->csum = 0; + log->csum = ao_log_csum((__xdata uint8_t *) log); + ao_mutex_get(&ao_log_mutex); { + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + log, + sizeof (struct ao_log_mega)); + ao_log_current_pos += sizeof (struct ao_log_mega); + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_dump_check_data(void) +{ + if (ao_log_csum((uint8_t *) &log) != 0) + return 0; + return 1; +} + +static __data uint8_t ao_log_data_pos; + +/* a hack to make sure that ao_log_megas fill the eeprom block in even units */ +typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_mega))] ; + +#ifndef AO_SENSOR_INTERVAL_ASCENT +#define AO_SENSOR_INTERVAL_ASCENT 1 +#define AO_SENSOR_INTERVAL_DESCENT 10 +#define AO_OTHER_INTERVAL 32 +#endif + +void +ao_log(void) +{ + __pdata uint16_t next_sensor, next_other; + uint8_t i; + + ao_storage_setup(); + + ao_log_scan(); + + while (!ao_log_running) + ao_sleep(&ao_log_running); + +#if HAS_FLIGHT + log.type = AO_LOG_FLIGHT; + log.tick = ao_sample_tick; +#if HAS_ACCEL + log.u.flight.ground_accel = ao_ground_accel; +#endif + log.u.flight.ground_pres = ao_ground_pres; + log.u.flight.flight = ao_flight_number; + ao_log_mega(&log); +#endif + + /* Write the whole contents of the ring to the log + * when starting up. + */ + ao_log_data_pos = ao_data_ring_next(ao_data_head); + next_other = next_sensor = ao_data_ring[ao_log_data_pos].tick; + ao_log_state = ao_flight_startup; + for (;;) { + /* Write samples to EEPROM */ + while (ao_log_data_pos != ao_data_head) { + log.tick = ao_data_ring[ao_log_data_pos].tick; + if ((int16_t) (log.tick - next_sensor) >= 0) { + log.type = AO_LOG_SENSOR; + log.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607.pres; + log.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607.temp; + log.u.sensor.accel_x = ao_data_ring[ao_log_data_pos].mpu6000.accel_x; + log.u.sensor.accel_y = ao_data_ring[ao_log_data_pos].mpu6000.accel_y; + log.u.sensor.accel_z = ao_data_ring[ao_log_data_pos].mpu6000.accel_z; + log.u.sensor.gyro_x = ao_data_ring[ao_log_data_pos].mpu6000.gyro_x; + log.u.sensor.gyro_y = ao_data_ring[ao_log_data_pos].mpu6000.gyro_y; + log.u.sensor.gyro_z = ao_data_ring[ao_log_data_pos].mpu6000.gyro_z; + ao_log_mega(&log); + if (ao_log_state <= ao_flight_coast) + next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; + else + next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT; + } + if ((int16_t) (log.tick - next_other) >= 0) { + log.type = AO_LOG_TEMP_VOLT; + log.u.volt.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt; + log.u.volt.v_pbatt = ao_data_ring[ao_log_data_pos].adc.v_pbatt; + log.u.volt.n_sense = AO_ADC_NUM_SENSE; + for (i = 0; i < AO_ADC_NUM_SENSE; i++) + log.u.volt.sense[i] = ao_data_ring[ao_log_data_pos].adc.sense[i]; + ao_log_mega(&log); + next_other = log.tick + AO_OTHER_INTERVAL; + } + ao_log_data_pos = ao_data_ring_next(ao_log_data_pos); + } +#if HAS_FLIGHT + /* Write state change to EEPROM */ + if (ao_flight_state != ao_log_state) { + ao_log_state = ao_flight_state; + log.type = AO_LOG_STATE; + log.tick = ao_time(); + log.u.state.state = ao_log_state; + log.u.state.reason = 0; + ao_log_mega(&log); + + if (ao_log_state == ao_flight_landed) + ao_log_stop(); + } +#endif + + /* Wait for a while */ + ao_delay(AO_MS_TO_TICKS(100)); + + /* Stop logging when told to */ + while (!ao_log_running) + ao_sleep(&ao_log_running); + } +} + +uint16_t +ao_log_flight(uint8_t slot) +{ + if (!ao_storage_read(ao_log_pos(slot), + &log, + sizeof (struct ao_log_mega))) + return 0; + + if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) + return log.u.flight.flight; + return 0; +} diff --git a/src/core/ao_sample_mm.c b/src/core/ao_sample_mm.c new file mode 100644 index 00000000..8cfadc40 --- /dev/null +++ b/src/core/ao_sample_mm.c @@ -0,0 +1,135 @@ +/* + * 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. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#include +#endif + +/* + * Current sensor values + */ + +#ifndef PRES_TYPE +#define PRES_TYPE int32_t +#define ALT_TYPE int32_t +#define ACCEL_TYPE int16_t +#endif + +__pdata uint16_t ao_sample_tick; /* time of last data */ +__pdata pres_t ao_sample_pres; +__pdata alt_t ao_sample_alt; +__pdata alt_t ao_sample_height; +#if HAS_ACCEL +__pdata accel_t ao_sample_accel; +#endif + +__data uint8_t ao_sample_data; + +/* + * Sensor calibration values + */ + +__pdata pres_t ao_ground_pres; /* startup pressure */ +__pdata alt_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +__pdata accel_t ao_ground_accel; /* startup acceleration */ +__pdata accel_t ao_accel_2g; /* factory accel calibration */ +__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +static __pdata uint8_t ao_preflight; /* in preflight mode */ + +static __pdata uint16_t nsamples; +__pdata int32_t ao_sample_pres_sum; +#if HAS_ACCEL +__pdata int32_t ao_sample_accel_sum; +#endif + +static void +ao_sample_preflight(void) +{ + /* startup state: + * + * Collect 512 samples of acceleration and pressure + * data and average them to find the resting values + */ + if (nsamples < 512) { +#if HAS_ACCEL + ao_sample_accel_sum += ao_sample_accel; +#endif + ao_sample_pres_sum += ao_sample_pres; + ++nsamples; + } else { + ao_config_get(); +#if HAS_ACCEL + ao_ground_accel = ao_sample_accel_sum >> 9; + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; +#endif + ao_ground_pres = ao_sample_pres_sum >> 9; + ao_ground_height = pres_to_altitude(ao_ground_pres); + ao_preflight = FALSE; + } +} + + +uint8_t +ao_sample(void) +{ + ao_config_get(); + ao_wakeup(DATA_TO_XDATA(&ao_sample_data)); + ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); + while (ao_sample_data != ao_data_head) { + __xdata struct ao_data *ao_data; + + /* Capture a sample */ + ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data]; + ao_sample_tick = ao_data->tick; + ao_sample_pres = ao_data_pres(ao_data); + ao_sample_alt = pres_to_altitude(ao_sample_pres); + ao_sample_height = ao_sample_alt - ao_ground_height; +#if HAS_ACCEL + ao_sample_accel = ao_data_accel_sample(ao_data); + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) + ao_sample_accel = ao_data_accel_invert(ao_sample_accel); + ao_data_set_accel(ao_data, ao_sample_accel); +#endif + + if (ao_preflight) + ao_sample_preflight(); + else + ao_kalman(); + ao_sample_data = ao_data_ring_next(ao_sample_data); + } + return !ao_preflight; +} + +void +ao_sample_init(void) +{ + nsamples = 0; + ao_sample_pres_sum = 0; + ao_sample_pres = 0; +#if HAS_ACCEL + ao_sample_accel_sum = 0; + ao_sample_accel = 0; +#endif + ao_sample_data = ao_data_head; + ao_preflight = TRUE; +} -- cgit v1.2.3 From ce8153472069ed56b24ac36f297ac569d1f767d4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:24:09 -0600 Subject: altos: Make telemetrum-v1.1 compile with new ao_data structure Signed-off-by: Keith Packard --- src/cc1111/ao_adc.c | 36 ++++++++++++++++-------------------- src/cc1111/ao_arch.h | 3 +-- src/cc1111/ao_ignite.c | 9 +++++---- src/core/ao_adc.h | 28 +++------------------------- src/core/ao_data.h | 2 +- src/core/ao_log_big.c | 24 ++++++++++++------------ src/core/ao_telemetry.c | 28 ++++++++++++++-------------- src/product/Makefile.telemetrum | 4 ++-- src/stm/ao_adc_stm.c | 8 ++++++++ 9 files changed, 62 insertions(+), 80 deletions(-) (limited to 'src/core') diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 1688eceb..1e3d8cab 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -16,13 +16,9 @@ */ #include "ao.h" -#include "ao_pins.h" -volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -#if HAS_ACCEL_REF -volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; -#endif -volatile __data uint8_t ao_adc_head; +volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; +volatile __data uint8_t ao_data_head; void ao_adc_poll(void) @@ -39,14 +35,14 @@ ao_adc_poll(void) } void -ao_adc_get(__xdata struct ao_adc *packet) +ao_data_get(__xdata struct ao_data *packet) { #if HAS_FLIGHT - uint8_t i = ao_adc_ring_prev(ao_sample_adc); + uint8_t i = ao_data_ring_prev(ao_sample_data); #else - uint8_t i = ao_adc_ring_prev(ao_adc_head); + uint8_t i = ao_data_ring_prev(ao_data_head); #endif - ao_xmemcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); + ao_xmemcpy(packet, (void __xdata *) &ao_data_ring[i], sizeof (struct ao_data)); } void @@ -60,14 +56,14 @@ ao_adc_isr(void) __interrupt 1 /* TeleMetrum readings */ #if HAS_ACCEL_REF if (sequence == 2) { - a = (uint8_t __xdata *) (&ao_accel_ref[ao_adc_head]); + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].accel_ref); sequence = 0; } else #endif { if (sequence == ADCCON3_ECH_TEMP) sequence = 2; - a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence); + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.accel + sequence); sequence++; } #define GOT_ADC @@ -87,7 +83,7 @@ ao_adc_isr(void) __interrupt 1 #if IGNITE_ON_P0 /* TeleMini readings */ - a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].pres); + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].pres); #ifdef TELEMINI_V_1_0 switch (sequence) { case 0: @@ -149,20 +145,20 @@ ao_adc_isr(void) __interrupt 1 else { /* record this conversion series */ - ao_adc_ring[ao_adc_head].tick = ao_time(); - ao_adc_head = ao_adc_ring_next(ao_adc_head); - ao_wakeup(DATA_TO_XDATA(&ao_adc_head)); + ao_data_ring[ao_data_head].tick = ao_time(); + ao_data_head = ao_data_ring_next(ao_data_head); + ao_wakeup(DATA_TO_XDATA(&ao_data_head)); } } static void ao_adc_dump(void) __reentrant { - static __xdata struct ao_adc packet; - ao_adc_get(&packet); + static __xdata struct ao_data packet; + ao_data_get(&packet); printf("tick: %5u accel: %5d pres: %5d temp: %5d batt: %5d drogue: %5d main: %5d\n", - packet.tick, packet.accel, packet.pres, packet.temp, - packet.v_batt, packet.sense_d, packet.sense_m); + packet.tick, packet.adc.accel, packet.adc.pres, packet.adc.temp, + packet.adc.v_batt, packet.adc.sense_d, packet.adc.sense_m); } __code struct ao_cmds ao_adc_cmds[] = { diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 9d0643b4..704ae4f9 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -199,7 +199,6 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; #define ao_arch_critical(b) __critical { b } struct ao_adc { - uint16_t tick; /* tick when the sample was read */ int16_t accel; /* accelerometer */ int16_t pres; /* pressure sensor */ int16_t temp; /* temperature sensor */ @@ -208,7 +207,7 @@ struct ao_adc { int16_t sense_m; /* main continuity sense */ }; -#define AO_ADC_RING 32 +#define AO_DATA_RING 32 /* ao_button.c */ #ifdef HAS_BUTTON diff --git a/src/cc1111/ao_ignite.c b/src/cc1111/ao_ignite.c index dd529088..cf07dfe8 100644 --- a/src/cc1111/ao_ignite.c +++ b/src/cc1111/ao_ignite.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include __xdata struct ao_ignition ao_ignition[2]; @@ -29,12 +30,12 @@ ao_ignite(enum ao_igniter igniter) __critical enum ao_igniter_status ao_igniter_status(enum ao_igniter igniter) { - __xdata struct ao_adc adc; + __xdata struct ao_data packet; __pdata int16_t value; __pdata uint8_t request, firing, fired; __critical { - ao_adc_get(&adc); + ao_data_get(&packet); request = ao_ignition[igniter].request; fired = ao_ignition[igniter].fired; firing = ao_ignition[igniter].firing; @@ -45,10 +46,10 @@ ao_igniter_status(enum ao_igniter igniter) value = (AO_IGNITER_CLOSED>>1); switch (igniter) { case ao_igniter_drogue: - value = adc.sense_d; + value = packet.adc.sense_d; break; case ao_igniter_main: - value = adc.sense_m; + value = packet.adc.sense_m; break; } if (value < AO_IGNITER_OPEN) diff --git a/src/core/ao_adc.h b/src/core/ao_adc.h index 8ec740c4..0dd87080 100644 --- a/src/core/ao_adc.h +++ b/src/core/ao_adc.h @@ -18,29 +18,7 @@ #ifndef _AO_ADC_H_ #define _AO_ADC_H_ -/* - * One set of samples read from the A/D converter or telemetry - */ - -#if AO_ADC_RING -/* - * ao_adc.c - */ - -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) - - -/* - * A/D data is stored in a ring, with the next sample to be written - * at ao_adc_head - */ -extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -extern volatile __data uint8_t ao_adc_head; -#if HAS_ACCEL_REF -extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; -#endif -#endif +#include /* Trigger a conversion sequence (called from the timer interrupt) */ void @@ -50,9 +28,9 @@ ao_adc_poll(void); void ao_adc_sleep(void); -/* Get a copy of the last complete A/D sample set */ +/* Get a copy of the last complete sample set */ void -ao_adc_get(__xdata struct ao_adc *packet); +ao_data_get(__xdata struct ao_data *packet); /* Initialize the A/D converter */ void diff --git a/src/core/ao_data.h b/src/core/ao_data.h index d28730a8..bd7e2d54 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -96,7 +96,7 @@ typedef int16_t accel_t; typedef int16_t accel_t; #define ao_data_accel(packet) ((packet)->adc.accel) -#define ao_data_set_accel(packet, accel) ((packet)->adc.accel = (accel)) +#define ao_data_set_accel(packet, a) ((packet)->adc.accel = (a)) #define ao_data_accel_invert(a) (0x7fff -(a)) /* diff --git a/src/core/ao_log_big.c b/src/core/ao_log_big.c index 43b3aa0c..50eca069 100644 --- a/src/core/ao_log_big.c +++ b/src/core/ao_log_big.c @@ -60,7 +60,7 @@ ao_log_dump_check_data(void) return 1; } -static __data uint8_t ao_log_adc_pos; +static __data uint8_t ao_log_data_pos; /* a hack to make sure that ao_log_records fill the eeprom block in even units */ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; @@ -94,17 +94,17 @@ ao_log(void) /* Write the whole contents of the ring to the log * when starting up. */ - ao_log_adc_pos = ao_adc_ring_next(ao_sample_adc); - next_other = next_sensor = ao_adc_ring[ao_log_adc_pos].tick; + ao_log_data_pos = ao_data_ring_next(ao_sample_data); + next_other = next_sensor = ao_data_ring[ao_log_data_pos].tick; ao_log_state = ao_flight_startup; for (;;) { /* Write samples to EEPROM */ - while (ao_log_adc_pos != ao_sample_adc) { - log.tick = ao_adc_ring[ao_log_adc_pos].tick; + while (ao_log_data_pos != ao_sample_data) { + log.tick = ao_data_ring[ao_log_data_pos].tick; if ((int16_t) (log.tick - next_sensor) >= 0) { log.type = AO_LOG_SENSOR; - log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; - log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; + log.u.sensor.accel = ao_data_ring[ao_log_data_pos].adc.accel; + log.u.sensor.pres = ao_data_ring[ao_log_data_pos].adc.pres; ao_log_data(&log); if (ao_log_state <= ao_flight_coast) next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; @@ -113,16 +113,16 @@ ao_log(void) } if ((int16_t) (log.tick - next_other) >= 0) { log.type = AO_LOG_TEMP_VOLT; - log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp; - log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt; + log.u.temp_volt.temp = ao_data_ring[ao_log_data_pos].adc.temp; + log.u.temp_volt.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt; ao_log_data(&log); log.type = AO_LOG_DEPLOY; - log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d; - log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m; + log.u.deploy.drogue = ao_data_ring[ao_log_data_pos].adc.sense_d; + log.u.deploy.main = ao_data_ring[ao_log_data_pos].adc.sense_m; ao_log_data(&log); next_other = log.tick + AO_OTHER_INTERVAL; } - ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); + ao_log_data_pos = ao_data_ring_next(ao_log_data_pos); } /* Write state change to EEPROM */ if (ao_flight_state != ao_log_state) { diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 46d72609..800adfcb 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -53,23 +53,23 @@ static __xdata union ao_telemetry_all telemetry; static void ao_send_sensor(void) { - uint8_t sample = ao_adc_ring_prev(ao_sample_adc); + uint8_t sample = ao_data_ring_prev(ao_sample_data); - telemetry.generic.tick = ao_adc_ring[sample].tick; + telemetry.generic.tick = ao_data_ring[sample].tick; telemetry.generic.type = AO_TELEMETRY_SENSOR; telemetry.sensor.state = ao_flight_state; #if HAS_ACCEL - telemetry.sensor.accel = ao_adc_ring[sample].accel; + telemetry.sensor.accel = ao_data_ring[sample].adc.accel; #else telemetry.sensor.accel = 0; #endif - telemetry.sensor.pres = ao_adc_ring[sample].pres; - telemetry.sensor.temp = ao_adc_ring[sample].temp; - telemetry.sensor.v_batt = ao_adc_ring[sample].v_batt; + telemetry.sensor.pres = ao_data_ring[sample].adc.pres; + telemetry.sensor.temp = ao_data_ring[sample].adc.temp; + telemetry.sensor.v_batt = ao_data_ring[sample].adc.v_batt; #if HAS_IGNITE - telemetry.sensor.sense_d = ao_adc_ring[sample].sense_d; - telemetry.sensor.sense_m = ao_adc_ring[sample].sense_m; + telemetry.sensor.sense_d = ao_data_ring[sample].adc.sense_d; + telemetry.sensor.sense_m = ao_data_ring[sample].adc.sense_m; #else telemetry.sensor.sense_d = 0; telemetry.sensor.sense_m = 0; @@ -99,19 +99,19 @@ static uint8_t ao_baro_sample; static void ao_send_baro(void) { - uint8_t sample = ao_sample_adc; - uint8_t samples = (sample - ao_baro_sample) & (AO_ADC_RING - 1); + uint8_t sample = ao_sample_data; + uint8_t samples = (sample - ao_baro_sample) & (AO_DATA_RING - 1); if (samples > 12) { - ao_baro_sample = (ao_baro_sample + (samples - 12)) & (AO_ADC_RING - 1); + ao_baro_sample = (ao_baro_sample + (samples - 12)) & (AO_DATA_RING - 1); samples = 12; } - telemetry.generic.tick = ao_adc_ring[sample].tick; + telemetry.generic.tick = ao_data_ring[sample].tick; telemetry.generic.type = AO_TELEMETRY_BARO; telemetry.baro.samples = samples; for (sample = 0; sample < samples; sample++) { - telemetry.baro.baro[sample] = ao_adc_ring[ao_baro_sample].pres; - ao_baro_sample = ao_adc_ring_next(ao_baro_sample); + telemetry.baro.baro[sample] = ao_data_ring[ao_baro_sample].adc.pres; + ao_baro_sample = ao_data_ring_next(ao_baro_sample); } ao_radio_send(&telemetry, sizeof (telemetry)); } diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index e4f55f88..b1111053 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -34,8 +34,8 @@ CORE_SRC = \ ao_stdio.c \ ao_storage.c \ ao_task.c \ - ao_flight.c \ - ao_sample.c \ + ao_flight_mm.c \ + ao_sample_mm.c \ ao_kalman.c \ ao_log.c \ ao_log_big.c \ diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 02187205..ea9e25e4 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -104,14 +104,22 @@ ao_adc_poll(void) void ao_adc_get(__xdata struct ao_adc *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].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)); } -- cgit v1.2.3 From 98e992b65d366d9f79d7d2dd2dd4d1886dd1d9c4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:25:17 -0600 Subject: altos: Make telemetrum-v1.0 build with new ao_data structure Signed-off-by: Keith Packard --- src/core/ao_data.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao_data.h b/src/core/ao_data.h index bd7e2d54..bb26c4c0 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -183,7 +183,7 @@ typedef int16_t accel_t; #define ao_data_accel_sample(packet) \ ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->accel_ref << 1))) >> 1) #else -#define ao_data_accel(packet) ((packet)->adc.accel) +#define ao_data_accel_sample(packet) ((packet)->adc.accel) #endif /* HAS_ACCEL_REF */ #endif /* else some other pressure sensor */ -- cgit v1.2.3 From 090dc9aecdf4cfd1ac727325ae141d441c5b28aa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:26:43 -0600 Subject: altos: Make telemini-v1.0 compile with new ao_data structure Signed-off-by: Keith Packard --- src/cc1111/ao_adc.c | 2 +- src/core/ao_log_tiny.c | 12 ++++++------ src/product/Makefile.telemini | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src/core') diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 1e3d8cab..f34bc042 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -83,7 +83,7 @@ ao_adc_isr(void) __interrupt 1 #if IGNITE_ON_P0 /* TeleMini readings */ - a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].pres); + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.pres); #ifdef TELEMINI_V_1_0 switch (sequence) { case 0: diff --git a/src/core/ao_log_tiny.c b/src/core/ao_log_tiny.c index d5a3b99f..492658ea 100644 --- a/src/core/ao_log_tiny.c +++ b/src/core/ao_log_tiny.c @@ -85,7 +85,7 @@ ao_log(void) enum ao_flight_state ao_log_tiny_state; int32_t sum; int16_t count; - uint8_t ao_log_adc; + uint8_t ao_log_data; uint8_t ao_log_started = 0; ao_storage_setup(); @@ -96,18 +96,18 @@ ao_log(void) ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; sum = 0; count = 0; - ao_log_adc = ao_sample_adc; + ao_log_data = ao_sample_data; last_time = ao_time(); for (;;) { /* * Add in pending sample data */ - ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); - while (ao_log_adc != ao_sample_adc) { - sum += ao_adc_ring[ao_log_adc].pres; + ao_sleep(DATA_TO_XDATA(&ao_sample_data)); + while (ao_log_data != ao_sample_data) { + sum += ao_data_ring[ao_log_data].adc.pres; count++; - ao_log_adc = ao_adc_ring_next(ao_log_adc); + ao_log_data = ao_data_ring_next(ao_log_data); } if (ao_log_running) { if (!ao_log_started) { diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 82ec42a2..9506eb65 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -22,14 +22,14 @@ CORE_SRC = \ ao_cmd.c \ ao_config.c \ ao_convert.c \ - ao_flight.c \ + ao_flight_mm.c \ ao_kalman.c \ ao_log.c \ ao_log_tiny.c \ ao_mutex.c \ ao_panic.c \ ao_report.c \ - ao_sample.c \ + ao_sample_mm.c \ ao_stdio.c \ ao_storage.c \ ao_task.c \ -- cgit v1.2.3 From 5fd869b244f8f2b76258dc31a5507a73fd47cf1d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:31:12 -0600 Subject: altos: Make telenano build with new ao_data structure Signed-off-by: Keith Packard --- src/core/ao_flight_nano.c | 4 ++-- src/product/Makefile.telenano | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_flight_nano.c b/src/core/ao_flight_nano.c index 2e332b12..406d81ad 100644 --- a/src/core/ao_flight_nano.c +++ b/src/core/ao_flight_nano.c @@ -27,8 +27,8 @@ __pdata uint16_t ao_launch_tick; /* time of launch detect */ * resting */ __pdata uint16_t ao_interval_end; -__pdata int16_t ao_interval_min_height; -__pdata int16_t ao_interval_max_height; +__pdata alt_t ao_interval_min_height; +__pdata alt_t ao_interval_max_height; __pdata uint8_t ao_flight_force_idle; diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index cf27527c..56db1c2c 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -29,7 +29,7 @@ CORE_SRC = \ ao_mutex.c \ ao_panic.c \ ao_report.c \ - ao_sample.c \ + ao_sample_mm.c \ ao_stdio.c \ ao_storage.c \ ao_task.c \ -- cgit v1.2.3 From 29edf6d901432a1afc65900ff599c963edac5a2b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:44:01 -0600 Subject: altos: Make telescience-v0.1 build with new ao_data struct Signed-off-by: Keith Packard --- src/avr/ao_adc_avr.c | 24 ++++++++--------- src/avr/ao_pins.h | 3 +-- src/core/ao_log_telescience.c | 14 +++++----- src/core/ao_stdio.c | 16 ++++++------ src/drivers/ao_science_slave.c | 2 +- src/test/Makefile | 4 +-- src/test/ao_flight_test.c | 58 ++++++++++++++++++++++-------------------- 7 files changed, 61 insertions(+), 60 deletions(-) (limited to 'src/core') diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 4f6f0e60..928cd3e1 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -17,8 +17,8 @@ #include "ao.h" -volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -volatile __data uint8_t ao_adc_head; +volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; +volatile __data uint8_t ao_data_head; #ifdef TELESCIENCE const uint8_t adc_channels[AO_LOG_TELESCIENCE_NUM_ADC] = { @@ -92,14 +92,14 @@ ISR(ADC_vect) /* Must read ADCL first or the value there will be lost */ value = ADCL; value |= (ADCH << 8); - ao_adc_ring[ao_adc_head].adc[ao_adc_channel] = value; + ao_data_ring[ao_data_head].adc.adc[ao_adc_channel] = value; if (++ao_adc_channel < NUM_ADC) ao_adc_start(); else { ADCSRA = ADCSRA_INIT; - ao_adc_ring[ao_adc_head].tick = ao_time(); - ao_adc_head = ao_adc_ring_next(ao_adc_head); - ao_wakeup((void *) &ao_adc_head); + ao_data_ring[ao_data_head].tick = ao_time(); + ao_data_head = ao_data_ring_next(ao_data_head); + ao_wakeup((void *) &ao_data_head); ao_cpu_sleep_disable = 0; } } @@ -113,18 +113,18 @@ ao_adc_poll(void) } void -ao_adc_get(__xdata struct ao_adc *packet) +ao_data_get(__xdata struct ao_data *packet) { - uint8_t i = ao_adc_ring_prev(ao_adc_head); - memcpy(packet, (void *) &ao_adc_ring[i], sizeof (struct ao_adc)); + uint8_t i = ao_data_ring_prev(ao_data_head); + memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data)); } static void ao_adc_dump(void) __reentrant { - static __xdata struct ao_adc packet; + static __xdata struct ao_data packet; uint8_t i; - ao_adc_get(&packet); + ao_data_get(&packet); #ifdef TELEPYRO printf("ADMUX: %02x\n", ADMUX); printf("ADCSRA: %02x\n", ADCSRA); @@ -137,7 +137,7 @@ ao_adc_dump(void) __reentrant #endif printf("tick: %5u", packet.tick); for (i = 0; i < NUM_ADC; i++) - printf (" %2d: %5u", i, packet.adc[i]); + printf (" %2d: %5u", i, packet.adc.adc[i]); printf("\n"); diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index f2b40fb4..850a08ec 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -91,10 +91,9 @@ #define AO_TELESCIENCE_NUM_ADC 12 struct ao_adc { - uint16_t tick; /* tick when the sample was read */ uint16_t adc[AO_TELESCIENCE_NUM_ADC]; /* samples */ }; -#define AO_ADC_RING 16 +#define AO_DATA_RING 16 #endif /* _AO_PINS_H_ */ diff --git a/src/core/ao_log_telescience.c b/src/core/ao_log_telescience.c index ae045281..002a10bd 100644 --- a/src/core/ao_log_telescience.c +++ b/src/core/ao_log_telescience.c @@ -20,7 +20,7 @@ #include "ao_log.h" #include "ao_companion.h" -static uint8_t ao_log_adc_pos; +static uint8_t ao_log_data_pos; __code uint8_t ao_log_format = AO_LOG_FORMAT_TELESCIENCE; @@ -62,20 +62,20 @@ ao_log_single(void) /* Write the whole contents of the ring to the log * when starting up. */ - ao_log_adc_pos = ao_adc_ring_next(ao_adc_head); + ao_log_data_pos = ao_data_ring_next(ao_data_head); ao_log_single_write_data.telescience.type = AO_LOG_TELESCIENCE_DATA; while (ao_log_running) { /* Write samples to EEPROM */ - while (ao_log_adc_pos != ao_adc_head) { - ao_log_single_write_data.telescience.tick = ao_adc_ring[ao_log_adc_pos].tick; - memcpy(&ao_log_single_write_data.telescience.adc, (void *) ao_adc_ring[ao_log_adc_pos].adc, + while (ao_log_data_pos != ao_data_head) { + ao_log_single_write_data.telescience.tick = ao_data_ring[ao_log_data_pos].tick; + memcpy(&ao_log_single_write_data.telescience.adc, (void *) ao_data_ring[ao_log_data_pos].adc.adc, AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); ao_log_telescience_csum(); ao_log_single_write(); - ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); + ao_log_data_pos = ao_data_ring_next(ao_log_data_pos); } /* Wait for more ADC data to arrive */ - ao_sleep((void *) &ao_adc_head); + ao_sleep((void *) &ao_data_head); } memset(&ao_log_single_write_data.telescience.adc, '\0', sizeof (ao_log_single_write_data.telescience.adc)); } diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index 9b4ea473..656b23c9 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -53,14 +53,14 @@ #endif #define USE_SERIAL_STDIN (USE_SERIAL_0_STDIN + \ - USE_SERIAL_1_STDIN | \ - USE_SERIAL_2_STDIN | \ - USE_SERIAL_3_STDIN | \ - USE_SERIAL_4_STDIN | \ - USE_SERIAL_5_STDIN | \ - USE_SERIAL_6_STDIN | \ - USE_SERIAL_7_STDIN | \ - USE_SERIAL_8_STDIN | \ + USE_SERIAL_1_STDIN + \ + USE_SERIAL_2_STDIN + \ + USE_SERIAL_3_STDIN + \ + USE_SERIAL_4_STDIN + \ + USE_SERIAL_5_STDIN + \ + USE_SERIAL_6_STDIN + \ + USE_SERIAL_7_STDIN + \ + USE_SERIAL_8_STDIN + \ USE_SERIAL_9_STDIN) #define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c index a86b5151..996e98d9 100644 --- a/src/drivers/ao_science_slave.c +++ b/src/drivers/ao_science_slave.c @@ -42,7 +42,7 @@ void ao_spi_slave(void) sizeof (ao_telescience_setup)); break; case AO_COMPANION_FETCH: - ao_spi_slave_send((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + ao_spi_slave_send((uint8_t *) &ao_data_ring[ao_data_ring_prev(ao_data_head)].adc, AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); break; case AO_COMPANION_NOTIFY: diff --git a/src/test/Makefile b/src/test/Makefile index 3c2b8732..1e54f5e0 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -13,10 +13,10 @@ clean: install: -ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h +ao_flight_test: ao_flight_test.c ao_host.h ao_flight_mm.c ao_sample_mm.c ao_kalman.c altitude.h ao_kalman.h cc $(CFLAGS) -o $@ $< -ao_flight_test_noisy_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h +ao_flight_test_noisy_accel: ao_flight_test.c ao_host.h ao_flight_mm.c ao_sample_mm.c ao_kalman.c altitude.h ao_kalman.h cc -DNOISY_ACCEL=1 $(CFLAGS) -o $@ $< ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 4a8625cf..baf2ad1d 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -26,9 +26,10 @@ #define AO_HERTZ 100 -#define AO_ADC_RING 64 -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) +#define HAS_ADC 1 +#define AO_DATA_RING 64 +#define ao_data_ring_next(n) (((n) + 1) & (AO_DATA_RING - 1)) +#define ao_data_ring_prev(n) (((n) - 1) & (AO_DATA_RING - 1)) #define AO_M_TO_HEIGHT(m) ((int16_t) (m)) #define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) @@ -38,7 +39,6 @@ * One set of samples read from the A/D converter */ struct ao_adc { - uint16_t tick; /* tick when the sample was read */ int16_t accel; /* accelerometer */ int16_t pres; /* pressure sensor */ int16_t pres_real; /* unclipped */ @@ -54,6 +54,8 @@ struct ao_adc { #define __code #define __reentrant +#include + #define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) #define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) #define from_fix(x) ((x) >> 16) @@ -90,8 +92,8 @@ extern enum ao_flight_state ao_flight_state; #define FALSE 0 #define TRUE 1 -struct ao_adc ao_adc_ring[AO_ADC_RING]; -uint8_t ao_adc_head; +volatile struct ao_data ao_data_ring[AO_DATA_RING]; +volatile uint8_t ao_data_head; int ao_summary = 0; #define ao_led_on(l) @@ -110,7 +112,7 @@ enum ao_igniter { ao_igniter_main = 1 }; -struct ao_adc ao_adc_static; +struct ao_data ao_data_static; int drogue_height; double drogue_time; @@ -124,7 +126,7 @@ static int32_t ao_k_height; void ao_ignite(enum ao_igniter igniter) { - double time = (double) (ao_adc_static.tick + tick_offset) / 100; + double time = (double) (ao_data_static.tick + tick_offset) / 100; if (igniter == ao_igniter_drogue) { drogue_time = time; @@ -221,8 +223,8 @@ int ao_sample_prev_tick; uint16_t prev_tick; #include "ao_kalman.c" -#include "ao_sample.c" -#include "ao_flight.c" +#include "ao_sample_mm.c" +#include "ao_flight_mm.c" #define to_double(f) ((f) / 65536.0) @@ -282,19 +284,19 @@ ao_insert(void) { double time; - ao_adc_ring[ao_adc_head] = ao_adc_static; - ao_adc_head = ao_adc_ring_next(ao_adc_head); + ao_data_ring[ao_data_head] = ao_data_static; + ao_data_head = ao_data_ring_next(ao_data_head); if (ao_flight_state != ao_flight_startup) { - double height = ao_pres_to_altitude(ao_adc_static.pres_real) - ao_ground_height; - double accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) / + double height = ao_pres_to_altitude(ao_data_static.adc.pres_real) - ao_ground_height; + double accel = ((ao_flight_ground_accel - ao_data_static.adc.accel) * GRAVITY * 2.0) / (ao_config.accel_minus_g - ao_config.accel_plus_g); if (!tick_offset) - tick_offset = -ao_adc_static.tick; - if ((prev_tick - ao_adc_static.tick) > 0x400) + tick_offset = -ao_data_static.tick; + if ((prev_tick - ao_data_static.tick) > 0x400) tick_offset += 65536; - prev_tick = ao_adc_static.tick; - time = (double) (ao_adc_static.tick + tick_offset) / 100; + prev_tick = ao_data_static.tick; + time = (double) (ao_data_static.tick + tick_offset) / 100; if (ao_test_max_height < height) { ao_test_max_height = height; @@ -474,7 +476,7 @@ int16(uint8_t *bytes, int off) void ao_sleep(void *wchan) { - if (wchan == &ao_adc_head) { + if (wchan == &ao_data_head) { char type; uint16_t tick; uint16_t a, b; @@ -490,7 +492,7 @@ ao_sleep(void *wchan) for (;;) { if (ao_records_read > 2 && ao_flight_state == ao_flight_startup) { - ao_adc_static.accel = ao_flight_ground_accel; + ao_data_static.adc.accel = ao_flight_ground_accel; ao_insert(); return; } @@ -501,7 +503,7 @@ ao_sleep(void *wchan) printf ("no more data, exiting simulation\n"); ao_test_exit(); } - ao_adc_static.tick += 10; + ao_data_static.tick += 10; ao_insert(); return; } @@ -639,19 +641,19 @@ ao_sleep(void *wchan) case 'S': break; case 'A': - ao_adc_static.tick = tick; - ao_adc_static.accel = a; - ao_adc_static.pres_real = b; + ao_data_static.tick = tick; + ao_data_static.adc.accel = a; + ao_data_static.adc.pres_real = b; if (b < AO_MIN_BARO_VALUE) b = AO_MIN_BARO_VALUE; - ao_adc_static.pres = b; + ao_data_static.adc.pres = b; ao_records_read++; ao_insert(); return; case 'T': - ao_adc_static.tick = tick; - ao_adc_static.temp = a; - ao_adc_static.v_batt = b; + ao_data_static.tick = tick; + ao_data_static.adc.temp = a; + ao_data_static.adc.v_batt = b; break; case 'D': case 'G': -- cgit v1.2.3 From a53b8b84283eb62157b0f8ecd8061f61a4b6bd6f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2012 11:44:45 -0600 Subject: altos: Shrink telemetry generation code otherwise TM doesn't build anymore Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 800adfcb..6e8fc02f 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -53,23 +53,23 @@ static __xdata union ao_telemetry_all telemetry; static void ao_send_sensor(void) { - uint8_t sample = ao_data_ring_prev(ao_sample_data); + __xdata struct ao_data *packet = &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; - telemetry.generic.tick = ao_data_ring[sample].tick; + telemetry.generic.tick = packet->tick; telemetry.generic.type = AO_TELEMETRY_SENSOR; telemetry.sensor.state = ao_flight_state; #if HAS_ACCEL - telemetry.sensor.accel = ao_data_ring[sample].adc.accel; + telemetry.sensor.accel = packet->adc.accel; #else telemetry.sensor.accel = 0; #endif - telemetry.sensor.pres = ao_data_ring[sample].adc.pres; - telemetry.sensor.temp = ao_data_ring[sample].adc.temp; - telemetry.sensor.v_batt = ao_data_ring[sample].adc.v_batt; + telemetry.sensor.pres = packet->adc.pres; + telemetry.sensor.temp = packet->adc.temp; + telemetry.sensor.v_batt = packet->adc.v_batt; #if HAS_IGNITE - telemetry.sensor.sense_d = ao_data_ring[sample].adc.sense_d; - telemetry.sensor.sense_m = ao_data_ring[sample].adc.sense_m; + telemetry.sensor.sense_d = packet->adc.sense_d; + telemetry.sensor.sense_m = packet->adc.sense_m; #else telemetry.sensor.sense_d = 0; telemetry.sensor.sense_m = 0; -- cgit v1.2.3 From 8164cd95db62e4564b3a9ba5c06a74c870c03841 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2012 11:46:51 -0600 Subject: altos: Remove debug printf from accel auto-cal Otherwise, this goes way too slow Signed-off-by: Keith Packard --- src/core/ao_config.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 55ec9f40..76a8ed4a 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -256,8 +256,6 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant while (i) { ao_sleep(DATA_TO_XDATA(&ao_sample_data)); while (i && cal_data_ring != ao_sample_data) { - int16_t accel = ao_data_accel(&ao_data_ring[cal_data_ring]); - printf ("accel %d\n", accel); accel_total += (int32_t) ao_data_accel(&ao_data_ring[cal_data_ring]); cal_data_ring = ao_data_ring_next(cal_data_ring); i--; -- cgit v1.2.3 From e5aebfe0203de9e69712fac291c8cd0d3a96a385 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Jun 2012 19:33:18 -0700 Subject: altos: Mark full and mega logging correctly in 'v' command Make sure megametrum reports 'log format 5'. Signed-off-by: Keith Packard --- src/core/ao_log.c | 2 -- src/core/ao_log_big.c | 2 ++ src/core/ao_log_mega.c | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_log.c b/src/core/ao_log.c index d696625e..7884ec3c 100644 --- a/src/core/ao_log.c +++ b/src/core/ao_log.c @@ -25,8 +25,6 @@ __xdata uint8_t ao_log_running; __pdata enum ao_flight_state ao_log_state; __xdata uint16_t ao_flight_number; -__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL; - void ao_log_flush(void) { diff --git a/src/core/ao_log_big.c b/src/core/ao_log_big.c index 50eca069..db01f46c 100644 --- a/src/core/ao_log_big.c +++ b/src/core/ao_log_big.c @@ -20,6 +20,8 @@ static __xdata uint8_t ao_log_mutex; static __xdata struct ao_log_record log; +__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL; + static uint8_t ao_log_csum(__xdata uint8_t *b) __reentrant { diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index 1763b9eb..404e6bf7 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -23,6 +23,8 @@ static __xdata uint8_t ao_log_mutex; static __xdata struct ao_log_mega log; +__code uint8_t ao_log_format = AO_LOG_FORMAT_MEGAMETRUM; + static uint8_t ao_log_csum(__xdata uint8_t *b) __reentrant { -- cgit v1.2.3 From 6806103bad98385c0ec122d400f981eb81c59dd3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Jun 2012 19:34:17 -0700 Subject: altos: add high-z accel and mag sensor to megametrum logging These nicely fill the 32-byte sensor log record Signed-off-by: Keith Packard --- src/core/ao_log.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_log.h b/src/core/ao_log.h index e585750f..04abeb7e 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -216,13 +216,17 @@ struct ao_log_mega { int16_t gyro_x; /* 18 */ int16_t gyro_y; /* 20 */ int16_t gyro_z; /* 22 */ - } sensor; /* 24 */ + int16_t mag_x; /* 24 */ + int16_t mag_y; /* 26 */ + int16_t mag_z; /* 28 */ + int16_t accel; /* 30 */ + } sensor; /* 32 */ struct { int16_t v_batt; /* 4 */ - int16_t v_pbatt; /* 8 */ - int16_t n_sense; /* 10 */ - int16_t sense[10]; /* 12 */ - } volt; /* 32 */ + int16_t v_pbatt; /* 6 */ + int16_t n_sense; /* 8 */ + int16_t sense[10]; /* 10 */ + } volt; /* 30 */ struct { int32_t latitude; /* 4 */ int32_t longitude; /* 8 */ -- cgit v1.2.3 From c04af7533bd3fd3f3260338c0753fde966131720 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Jun 2012 23:07:38 -0700 Subject: altos: Add support for MegaAccel daughter card. Switches all acceleration computation to using the MegaAccel accelerometer to ensure support for high-g flights. MPU6000 values continue to be logged as normal Signed-off-by: Keith Packard --- src/cc1111/ao_adc.c | 2 +- src/cc1111/ao_arch.h | 1 + src/core/ao_data.h | 7 ++----- src/megametrum-v0.1/ao_pins.h | 28 ++++++++++++++++++++++++---- src/stm/ao_adc_stm.c | 25 +++++++++++++++++++++++-- 5 files changed, 51 insertions(+), 12 deletions(-) (limited to 'src/core') diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 95643956..ce827e25 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -56,7 +56,7 @@ ao_adc_isr(void) __interrupt 1 /* TeleMetrum readings */ #if HAS_ACCEL_REF if (sequence == 2) { - a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].accel_ref); + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.accel_ref); sequence = 0; } else #endif diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 704ae4f9..44116b81 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -205,6 +205,7 @@ struct ao_adc { int16_t v_batt; /* battery voltage */ int16_t sense_d; /* drogue continuity sense */ int16_t sense_m; /* main continuity sense */ + int16_t accel_ref; /* acceleration reference */ }; #define AO_DATA_RING 32 diff --git a/src/core/ao_data.h b/src/core/ao_data.h index bb26c4c0..83f8df59 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -31,9 +31,6 @@ struct ao_data { #if HAS_ADC struct ao_adc adc; #endif -#if HAS_ACCEL_REF - uint16_t accel_ref; -#endif #if HAS_MS5607 struct ao_ms5607_sample ms5607; #endif @@ -82,7 +79,7 @@ typedef int16_t alt_t; * ao_data_accel_invert - flip rocket ends for positive acceleration */ -#if HAS_MPU6000 +#if HAS_MPU6000 && !HAS_HIGHG_ACCEL typedef int16_t accel_t; @@ -181,7 +178,7 @@ typedef int16_t accel_t; */ #if HAS_ACCEL_REF #define ao_data_accel_sample(packet) \ - ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->accel_ref << 1))) >> 1) + ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->adc.accel_ref << 1))) >> 1) #else #define ao_data_accel_sample(packet) ((packet)->adc.accel) #endif /* HAS_ACCEL_REF */ diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index ff0edaa9..75b22045 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -98,6 +98,7 @@ #define HAS_FLIGHT 1 #define HAS_ADC 1 #define HAS_ACCEL 1 +#define HAS_ACCEL_REF 1 #define HAS_LOG 1 #define AO_DATA_RING 32 @@ -107,6 +108,8 @@ struct ao_adc { int16_t sense[AO_ADC_NUM_SENSE]; int16_t v_batt; int16_t v_pbatt; + int16_t accel_ref; + int16_t accel; int16_t temp; }; @@ -142,13 +145,22 @@ struct ao_adc { #define AO_ADC_V_PBATT_PORT stm_gpiob #define AO_ADC_V_PBATT_PIN 1 +#define AO_ADC_ACCEL_REF 10 +#define AO_ADC_ACCEL_REF_PORT stm_gpioc +#define AO_ADC_ACCEL_REF_PIN 0 + +#define AO_ADC_ACCEL 11 +#define AO_ADC_ACCEL_PORT stm_gpioc +#define AO_ADC_ACCEL_PIN 1 + #define AO_ADC_TEMP 16 #define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN) | \ (1 << STM_RCC_AHBENR_GPIOEEN) | \ - (1 << STM_RCC_AHBENR_GPIOBEN)) + (1 << STM_RCC_AHBENR_GPIOBEN) | \ + (1 << STM_RCC_AHBENR_GPIOCEN)) -#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 2) +#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 4) #define AO_ADC_PIN0_PORT AO_ADC_SENSE_A_PORT #define AO_ADC_PIN0_PIN AO_ADC_SENSE_A_PIN @@ -166,8 +178,12 @@ struct ao_adc { #define AO_ADC_PIN6_PIN AO_ADC_V_BATT_PIN #define AO_ADC_PIN7_PORT AO_ADC_V_PBATT_PORT #define AO_ADC_PIN7_PIN AO_ADC_V_PBATT_PIN +#define AO_ADC_PIN8_PORT AO_ADC_ACCEL_REF_PORT +#define AO_ADC_PIN8_PIN AO_ADC_ACCEL_REF_PIN +#define AO_ADC_PIN9_PORT AO_ADC_ACCEL_PORT +#define AO_ADC_PIN9_PIN AO_ADC_ACCEL_PIN -#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 3) +#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 5) #define AO_ADC_SQ1 AO_ADC_SENSE_A #define AO_ADC_SQ2 AO_ADC_SENSE_B @@ -177,7 +193,9 @@ struct ao_adc { #define AO_ADC_SQ6 AO_ADC_SENSE_F #define AO_ADC_SQ7 AO_ADC_V_BATT #define AO_ADC_SQ8 AO_ADC_V_PBATT -#define AO_ADC_SQ9 AO_ADC_TEMP +#define AO_ADC_SQ9 AO_ADC_ACCEL_REF +#define AO_ADC_SQ10 AO_ADC_ACCEL +#define AO_ADC_SQ11 AO_ADC_TEMP /* * Pressure sensor settings @@ -230,4 +248,6 @@ struct ao_adc { #define AO_MPU6000_INT_PIN 13 #define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) +#define HAS_HIGHG_ACCEL 1 + #endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index ea9e25e4..24a1fdd0 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -82,7 +82,7 @@ ao_adc_poll(void) stm_adc.sr = 0; ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), &stm_adc.dr, - (void *) (&ao_data_ring[ao_data_head].tick + 1), + (void *) (&ao_data_ring[ao_data_head].adc), AO_NUM_ADC, (0 << STM_DMA_CCR_MEM2MEM) | (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) | @@ -180,6 +180,15 @@ ao_adc_init(void) #ifdef AO_ADC_PIN9_PORT stm_moder_set(&AO_ADC_PIN9_PORT, AO_ADC_PIN9_PIN, STM_MODER_ANALOG); #endif +#ifdef AO_ADC_PIN10_PORT + stm_moder_set(&AO_ADC_PIN10_PORT, AO_ADC_PIN10_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN11_PORT + stm_moder_set(&AO_ADC_PIN11_PORT, AO_ADC_PIN11_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN12_PORT + stm_moder_set(&AO_ADC_PIN12_PORT, AO_ADC_PIN12_PIN, STM_MODER_ANALOG); +#endif stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADC1EN); @@ -240,7 +249,19 @@ ao_adc_init(void) #if AO_NUM_ADC > 8 stm_adc.sqr4 |= (AO_ADC_SQ9 << 10); #endif - +#if AO_NUM_ADC > 9 + stm_adc.sqr4 |= (AO_ADC_SQ10 << 15); +#endif +#if AO_NUM_ADC > 10 + stm_adc.sqr4 |= (AO_ADC_SQ11 << 20); +#endif +#if AO_NUM_ADC > 11 + stm_adc.sqr4 |= (AO_ADC_SQ12 << 25); +#endif +#if AO_NUM_ADC > 12 +#error "need to finish stm_adc.sqr settings" +#endif + /* Turn ADC on */ stm_adc.cr2 = AO_ADC_CR2_VAL; -- cgit v1.2.3 From 1353b277f8314fbddef81c743bd6ea229364fd18 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 14:58:00 -0700 Subject: altos: Enable some debugging during flight mode on MM Until we've got the radio working, there's no way to see inside the MM state without using USB. Add a diagnostic command to dump out the internal flight state variables. Signed-off-by: Keith Packard --- src/core/ao_flight_mm.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c index 27087e55..e812016e 100644 --- a/src/core/ao_flight_mm.c +++ b/src/core/ao_flight_mm.c @@ -108,7 +108,7 @@ ao_flight(void) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; -#if HAS_USB +#if HAS_USB && HAS_RADIO /* Disable the USB controller in flight mode * to save power */ @@ -352,11 +352,59 @@ ao_flight(void) } } +#if !HAS_RADIO +static inline int int_part(int16_t i) { return i >> 4; } +static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; } + +static void +ao_flight_dump(void) +{ + int16_t accel; + + accel = ((ao_ground_accel - ao_sample_accel) * ao_accel_scale) >> 16; + + printf ("sample:\n"); + printf (" tick %d\n", ao_sample_tick); + printf (" raw pres %d\n", ao_sample_pres); +#if HAS_ACCEL + printf (" raw accel %d\n", ao_sample_accel); +#endif + printf (" ground pres %d\n", ao_ground_pres); +#if HAS_ACCEL + printf (" raw accel %d\n", ao_sample_accel); + printf (" groundaccel %d\n", ao_ground_accel); + printf (" accel_2g %d\n", ao_accel_2g); +#endif + + printf (" alt %d\n", ao_sample_alt); + printf (" height %d\n", ao_sample_height); + printf (" accel %d.%02d\n", int_part(accel), frac_part(accel)); + + + printf ("kalman:\n"); + printf (" height %d\n", ao_height); + printf (" speed %d.%02d\n", int_part(ao_speed), frac_part(ao_speed)); + printf (" accel %d.%02d\n", int_part(ao_accel), frac_part(ao_accel)); + printf (" max_height %d\n", ao_max_height); + printf (" avg_height %d\n", ao_avg_height); + printf (" error_h %d\n", ao_error_h); + printf (" error_avg %d\n", ao_error_h_sq_avg); +} + +__code struct ao_cmds ao_flight_cmds[] = { + { ao_flight_dump, "F\0Dump flight status" }, + { 0, NULL }, +}; +#endif + static __xdata struct ao_task flight_task; void ao_flight_init(void) { ao_flight_state = ao_flight_startup; +#if !HAS_RADIO + ao_cmd_register(&ao_flight_cmds[0]); +#endif ao_add_task(&flight_task, ao_flight, "flight"); } -- cgit v1.2.3 From 9aa7993ee31bdfd6890ad7262a0375c07464ee76 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 17:09:00 -0700 Subject: altos: Intgrate hmc5883 sensor into adc ring Creates a task to poll the mag sensor and place the data into the sensor data ring. Signed-off-by: Keith Packard --- src/core/ao_data.h | 7 +++++++ src/core/ao_log_mega.c | 4 ++++ src/drivers/ao_hmc5883.c | 47 ++++++++++++++++++++++++++----------------- src/drivers/ao_hmc5883.h | 4 ++++ src/megametrum-v0.1/ao_pins.h | 1 + src/stm/ao_adc_stm.c | 5 +++++ 6 files changed, 50 insertions(+), 18 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 83f8df59..502df6c9 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -26,6 +26,10 @@ #include #endif +#if HAS_HMC5883 +#include +#endif + struct ao_data { uint16_t tick; #if HAS_ADC @@ -37,6 +41,9 @@ struct ao_data { #if HAS_MPU6000 struct ao_mpu6000_sample mpu6000; #endif +#if HAS_HMC5883 + struct ao_hmc5883_sample hmc5883; +#endif }; #define ao_data_ring_next(n) (((n) + 1) & (AO_DATA_RING - 1)) diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index 404e6bf7..68e2af49 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -120,6 +120,10 @@ ao_log(void) log.u.sensor.gyro_x = ao_data_ring[ao_log_data_pos].mpu6000.gyro_x; log.u.sensor.gyro_y = ao_data_ring[ao_log_data_pos].mpu6000.gyro_y; log.u.sensor.gyro_z = ao_data_ring[ao_log_data_pos].mpu6000.gyro_z; + log.u.sensor.mag_x = ao_data_ring[ao_log_data_pos].hmc5883.x; + log.u.sensor.mag_y = ao_data_ring[ao_log_data_pos].hmc5883.y; + log.u.sensor.mag_z = ao_data_ring[ao_log_data_pos].hmc5883.z; + log.u.sensor.accel = ao_data_ring[ao_log_data_pos].adc.accel; ao_log_mega(&log); if (ao_log_state <= ao_flight_coast) next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index f50376c8..1bc914e6 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -19,6 +19,8 @@ #include #include +uint8_t ao_hmc5883_valid; + static uint8_t ao_hmc5883_configured; static uint8_t ao_hmc5883_addr; @@ -57,7 +59,7 @@ static void ao_hmc5883_isr(void) { ao_exti_disable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); - ++ao_hmc5883_done; + ao_hmc5883_done = 1; ao_wakeup(&ao_hmc5883_done); } @@ -77,8 +79,6 @@ ao_hmc5883_sample(struct ao_hmc5883_sample *sample) ao_sleep(&ao_hmc5883_done); sei(); - printf ("done %d\n", ao_hmc5883_done); - ao_hmc5883_read(HMC5883_X_MSB, (uint8_t *) sample, sizeof (struct ao_hmc5883_sample)); #if __BYTE_ORDER == __LITTLE_ENDIAN /* byte swap */ @@ -94,6 +94,7 @@ ao_hmc5883_setup(void) { uint8_t d; uint8_t present; + if (ao_hmc5883_configured) return 1; @@ -103,7 +104,7 @@ ao_hmc5883_setup(void) ao_i2c_put(AO_HMC5883_I2C_INDEX); if (!present) - return 0; + ao_panic(AO_PANIC_SELF_TEST); ao_hmc5883_reg_write(HMC5883_CONFIG_A, (HMC5883_CONFIG_A_MA_8 << HMC5883_CONFIG_A_MA) | @@ -117,24 +118,32 @@ 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_arch_critical( + ao_hmc5883_current = ao_hmc5883_next; + ao_hmc5883_valid = 1; + ); + ao_delay(0); + } +} + +static struct ao_task ao_hmc5883_task; + static void ao_hmc5883_show(void) { - uint8_t addr, data; - struct ao_hmc5883_sample sample; + struct ao_hmc5883_sample sample; - if (!ao_hmc5883_setup()) { - printf("hmc5883 not present\n"); - return; - } -#if 0 - for (addr = 0; addr <= 12; addr++) { - ao_hmc5883_read(addr, &data, 1); - printf ("hmc5883 register %2d: %02x\n", - addr, data); - } -#endif - ao_hmc5883_sample(&sample); + sample = ao_hmc5883_current; printf ("X: %d Y: %d Z: %d\n", sample.x, sample.y, sample.z); } @@ -147,6 +156,7 @@ 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, @@ -154,5 +164,6 @@ ao_hmc5883_init(void) AO_EXTI_MODE_FALLING | AO_EXTI_MODE_PULL_UP, ao_hmc5883_isr); + ao_add_task(&ao_hmc5883_task, ao_hmc5883, "hmc5883"); ao_cmd_register(&ao_hmc5883_cmds[0]); } diff --git a/src/drivers/ao_hmc5883.h b/src/drivers/ao_hmc5883.h index 55690978..8d726510 100644 --- a/src/drivers/ao_hmc5883.h +++ b/src/drivers/ao_hmc5883.h @@ -75,10 +75,14 @@ #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/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 75b22045..d6394d9b 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -235,6 +235,7 @@ struct ao_adc { * Mag sensor (hmc5883) */ +#define HAS_HMC5883 1 #define AO_HMC5883_INT_PORT stm_gpioc #define AO_HMC5883_INT_PIN 12 #define AO_HMC5883_I2C_INDEX STM_I2C_INDEX(1) diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 24a1fdd0..71299de9 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -62,6 +62,11 @@ static void ao_adc_done(int index) step = 0; ao_data_ring[ao_data_head].ms5607 = 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); -- cgit v1.2.3 From 06afa2c3e78ea5bc9f1eb4913ee35c0eab0ac1bf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:50:10 -0700 Subject: altos: Legacy telemetry needs original ADC record The legacy telemetry packets included the raw ADC structure directly, so make sure that doesn't change further, allowing teledongle firmware to remain compatible with old TM firmware. Signed-off-by: Keith Packard --- src/core/ao.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index da1fd67b..a4136a9b 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -574,6 +574,16 @@ ao_gps_report_init(void); * ao_telemetry_orig.c */ +struct ao_adc_orig { + uint16_t tick; /* tick when the sample was read */ + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +}; + struct ao_telemetry_orig { uint16_t serial; uint16_t flight; @@ -591,7 +601,7 @@ struct ao_telemetry_orig { int16_t ground_pres; int16_t accel_plus_g; int16_t accel_minus_g; - struct ao_adc adc; + struct ao_adc_orig adc; struct ao_gps_orig gps; char callsign[AO_MAX_CALLSIGN]; struct ao_gps_tracking_orig gps_tracking; -- cgit v1.2.3 From 1832e2f76c844e97a2bd11226b003fb2af8057db Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:51:35 -0700 Subject: altos: fix test builds of non-accel flight code Remove references to accel variables when building baro-only flight test code. Signed-off-by: Keith Packard --- src/core/ao_flight_mm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/core') diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c index e812016e..2bc5c36a 100644 --- a/src/core/ao_flight_mm.c +++ b/src/core/ao_flight_mm.c @@ -359,9 +359,11 @@ static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; } static void ao_flight_dump(void) { +#if HAS_ACCEL int16_t accel; accel = ((ao_ground_accel - ao_sample_accel) * ao_accel_scale) >> 16; +#endif printf ("sample:\n"); printf (" tick %d\n", ao_sample_tick); @@ -378,7 +380,9 @@ ao_flight_dump(void) printf (" alt %d\n", ao_sample_alt); printf (" height %d\n", ao_sample_height); +#if HAS_ACCEL printf (" accel %d.%02d\n", int_part(accel), frac_part(accel)); +#endif printf ("kalman:\n"); -- cgit v1.2.3 From e687a9bafc696998b47fd0300fbc89dece09509c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:52:38 -0700 Subject: altos: Make 'v' command dump pressure sensor ROM values Avoids needing a new command Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/core') diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index fdc70007..40bb476c 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -251,6 +251,9 @@ version(void) printf("serial-number %u\n", ao_serial_number); #if HAS_LOG printf("log-format %u\n", ao_log_format); +#endif +#if HAS_MS5607 + ao_ms5607_info(); #endif printf("software-version %s\n", ao_version); } -- cgit v1.2.3 From dec5cbee22f13c47690b0c6bf7ca724ef132fe5e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:53:06 -0700 Subject: altos: typo in ao_monitor prevented ground station from including code This created ground station software that couldn't actually receive and report telemetry packets. Signed-off-by: Keith Packard --- src/core/ao_monitor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 830464d8..4ca641b7 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -17,6 +17,7 @@ #include "ao.h" #include "ao_telem.h" +#include "ao_flight.h" #if !HAS_MONITOR #error Must define HAS_MONITOR to 1 @@ -27,7 +28,7 @@ #endif #ifndef HAS_MONITOR_PUT -#define HAS_MONIOTOR_PUT 1 +#define HAS_MONITOR_PUT 1 #endif #ifndef AO_MONITOR_LED -- cgit v1.2.3 From baf1be1def01266512e67068948bf19b04ead6aa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:23:10 -0700 Subject: Allow product to override maximum number of command lists (NUM_CMDS) Just in case some product wants to save memory, or have more. Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/core') diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 40bb476c..fbf0c347 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -258,7 +258,9 @@ version(void) printf("software-version %s\n", ao_version); } +#ifndef NUM_CMDS #define NUM_CMDS 11 +#endif static __code struct ao_cmds *__xdata (ao_cmds[NUM_CMDS]); static __pdata uint8_t ao_ncmds; -- cgit v1.2.3 From a5a7df405c242593cbc828d5b66bbfc141a35947 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:26:06 -0700 Subject: Temporarily disable packet and telem on MM While work on the radio code progresses Signed-off-by: Keith Packard --- src/core/ao_flight_mm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c index 2bc5c36a..c2a7cd64 100644 --- a/src/core/ao_flight_mm.c +++ b/src/core/ao_flight_mm.c @@ -94,7 +94,7 @@ ao_flight(void) */ ao_flight_state = ao_flight_invalid; -#if HAS_RADIO +#if HAS_RADIO && PACKET_HAS_SLAVE /* Turn on packet system in invalid mode on TeleMetrum */ ao_packet_slave_start(); #endif @@ -120,7 +120,7 @@ ao_flight(void) ao_packet_slave_stop(); #endif -#if HAS_RADIO +#if HAS_RADIO && !defined (MEGAMETRUM) /* Turn on telemetry system */ ao_rdf_set(1); ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); @@ -131,7 +131,7 @@ ao_flight(void) /* Set idle mode */ ao_flight_state = ao_flight_idle; -#if HAS_ACCEL && HAS_RADIO +#if HAS_ACCEL && HAS_RADIO && PACKET_HAS_SLAVE /* Turn on packet system in idle mode on TeleMetrum */ ao_packet_slave_start(); #endif @@ -171,7 +171,7 @@ ao_flight(void) /* start logging data */ ao_log_start(); -#if HAS_RADIO +#if HAS_RADIO && !defined(MEGAMETRUM) /* Increase telemetry rate */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); @@ -259,7 +259,7 @@ ao_flight(void) ao_ignite(ao_igniter_drogue); #endif -#if HAS_RADIO +#if HAS_RADIO && !defined(MEGAMETRUM) /* slow down the telemetry system */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); -- cgit v1.2.3 From 4e6d96816e6604ee8d9bb49345a1c1211699a655 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 16:11:23 -0700 Subject: altos: ao_storage_read already calls ao_storage_setup No need to call twice. Signed-off-by: Keith Packard --- src/core/ao_config.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 76a8ed4a..a4877b06 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -81,7 +81,6 @@ _ao_config_get(void) if (ao_config_loaded) return; #if HAS_EEPROM - ao_storage_setup(); ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config)); #endif if (ao_config.major != AO_CONFIG_MAJOR) { -- cgit v1.2.3 From 9d3fe2a80d0925e3eded6d738d05c5b4ea61504c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 16:12:18 -0700 Subject: altos: Don't lose IRQ disabled state in ao_sleep Using ao_arch_critical around the wchan setting will force interrupts to be re-enabled before ao_yield records the state of that bit, potentially causing problems with functions not atomically testing and sleeping. Tasks that need to set wchan with interrupts disabled should have interrupts disabled when entering ao_sleep already. Signed-off-by: Keith Packard --- src/core/ao_task.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_task.c b/src/core/ao_task.c index d7d0e8a2..910f1587 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -103,9 +103,7 @@ ao_yield(void) ao_arch_naked_define uint8_t ao_sleep(__xdata void *wchan) { - ao_arch_critical( - ao_cur_task->wchan = wchan; - ); + ao_cur_task->wchan = wchan; ao_yield(); if (ao_cur_task->wchan) { ao_cur_task->wchan = NULL; -- cgit v1.2.3 From 629f43e7c7abbff33e14b168a08a4b6a9c88b937 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 19:04:22 -0700 Subject: altos: Add telemetry to megametrum Now that the radio works Signed-off-by: Keith Packard --- src/core/ao.h | 1 + src/core/ao_flight_mm.c | 16 ++++++++++------ src/core/ao_telemetry.c | 8 ++++++-- src/megametrum-v0.1/Makefile | 5 +++-- src/megametrum-v0.1/ao_megametrum.c | 1 + src/megametrum-v0.1/ao_pins.h | 1 + 6 files changed, 22 insertions(+), 10 deletions(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index a4136a9b..3dae8b40 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -347,6 +347,7 @@ struct ao_telemetry_generic { #define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 #define AO_TELEMETRY_SENSOR_TELEMINI 0x02 #define AO_TELEMETRY_SENSOR_TELENANO 0x03 +#define AO_TELEMETRY_SENSOR_MEGAMETRUM 0x08 struct ao_telemetry_sensor { uint16_t serial; /* 0 */ diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c index c2a7cd64..28b9869f 100644 --- a/src/core/ao_flight_mm.c +++ b/src/core/ao_flight_mm.c @@ -32,6 +32,10 @@ #error Please define HAS_USB #endif +#ifndef HAS_TELEMETRY +#define HAS_TELEMETRY HAS_RADIO +#endif + /* Main flight thread. */ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ @@ -83,7 +87,7 @@ ao_flight(void) * - pad mode if we're upright, * - idle mode otherwise */ -#if HAS_ACCEL +#if HAS_ACCEL && 0 if (ao_config.accel_plus_g == 0 || ao_config.accel_minus_g == 0 || ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || @@ -101,14 +105,14 @@ ao_flight(void) } else #endif if (!ao_flight_force_idle -#if HAS_ACCEL +#if HAS_ACCEL && 0 && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP #endif ) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; -#if HAS_USB && HAS_RADIO +#if HAS_USB && HAS_RADIO && 0 /* Disable the USB controller in flight mode * to save power */ @@ -120,7 +124,7 @@ ao_flight(void) ao_packet_slave_stop(); #endif -#if HAS_RADIO && !defined (MEGAMETRUM) +#if HAS_TELEMETRY /* Turn on telemetry system */ ao_rdf_set(1); ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); @@ -171,7 +175,7 @@ ao_flight(void) /* start logging data */ ao_log_start(); -#if HAS_RADIO && !defined(MEGAMETRUM) +#if HAS_TELEMETRY /* Increase telemetry rate */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); @@ -259,7 +263,7 @@ ao_flight(void) ao_ignite(ao_igniter_drogue); #endif -#if HAS_RADIO && !defined(MEGAMETRUM) +#if HAS_TELEMETRY /* slow down the telemetry system */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 6e8fc02f..5857c44d 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -35,6 +35,10 @@ static __pdata uint16_t ao_rdf_time; #define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) #define AO_RDF_LENGTH_MS 500 +#if defined(MEGAMETRUM) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_MEGAMETRUM +#endif + #if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) || defined(TELEMETRUM_V_1_2) #define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM #endif @@ -53,7 +57,7 @@ static __xdata union ao_telemetry_all telemetry; static void ao_send_sensor(void) { - __xdata struct ao_data *packet = &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; + __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; telemetry.generic.tick = packet->tick; telemetry.generic.type = AO_TELEMETRY_SENSOR; @@ -64,7 +68,7 @@ ao_send_sensor(void) #else telemetry.sensor.accel = 0; #endif - telemetry.sensor.pres = packet->adc.pres; + telemetry.sensor.pres = ao_data_pres(packet); telemetry.sensor.temp = packet->adc.temp; telemetry.sensor.v_batt = packet->adc.v_batt; #if HAS_IGNITE diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 054855ba..5c641e9a 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -64,12 +64,13 @@ ALTOS_SRC = \ ao_log_mega.c \ ao_sample_mm.c \ ao_kalman.c \ - ao_flight_mm.c + ao_flight_mm.c \ + ao_telemetry.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM -IDPRODUCT=0x000a +IDPRODUCT=0x0023 CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 628c5538..dc9c0d19 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -47,6 +47,7 @@ main(void) ao_flight_init(); ao_log_init(); ao_report_init(); + ao_telemetry_init(); ao_config_init(); ao_start_scheduler(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 5121ad58..5c5c5972 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -66,6 +66,7 @@ #define HAS_USB 1 #define HAS_BEEP 1 #define HAS_RADIO 1 +#define HAS_TELEMETRY 1 #define HAS_SPI_1 1 #define SPI_1_PA5_PA6_PA7 1 -- cgit v1.2.3 From 611f37607fadcdc9908d67456f844a452ad4a87a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 19:11:35 -0700 Subject: altos: Make sure ao_storage_config is set before reading config block ao_storage_read does in fact call ao_storage_setup, but we need the value of ao_storage_config *before* calling ao_storage_read, so call ao_storage_setup first. Signed-off-by: Keith Packard --- src/core/ao_config.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/core') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index a4877b06..cc580d66 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -81,6 +81,11 @@ _ao_config_get(void) if (ao_config_loaded) return; #if HAS_EEPROM + /* Yes, I know ao_storage_read calls ao_storage_setup, + * but ao_storage_setup *also* sets ao_storage_config, which we + * need before calling ao_storage_read here + */ + ao_storage_setup(); ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config)); #endif if (ao_config.major != AO_CONFIG_MAJOR) { -- cgit v1.2.3 From d2bd95edb6f77daeb1e8f043c4a239c248728e0c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jun 2012 09:45:42 -0700 Subject: altos: Add full MM telemetry Create two new telemetry packets to hold all of the MM data. This patch also splits the telemetry structures out of ao.h Signed-off-by: Keith Packard --- src/core/ao.h | 177 +----------------------------------------------- src/core/ao_data.h | 33 +++++---- src/core/ao_log_mega.c | 4 +- src/core/ao_sample_mm.c | 5 +- src/core/ao_telemetry.c | 135 +++++++++++++++++++++++++++++------- src/stm/ao_adc_stm.c | 2 +- 6 files changed, 138 insertions(+), 218 deletions(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index 3dae8b40..204c8530 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -325,182 +325,7 @@ ao_spi_slave_init(void); void ao_spi_slave(void); -/* - * ao_telemetry.c - */ -#define AO_MAX_CALLSIGN 8 -#define AO_MAX_VERSION 8 -#if LEGACY_MONITOR -#define AO_MAX_TELEMETRY 128 -#else -#define AO_MAX_TELEMETRY 32 -#endif - -struct ao_telemetry_generic { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t payload[27]; /* 5 */ - /* 32 */ -}; - -#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 -#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 -#define AO_TELEMETRY_SENSOR_TELENANO 0x03 -#define AO_TELEMETRY_SENSOR_MEGAMETRUM 0x08 - -struct ao_telemetry_sensor { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t state; /* 5 flight state */ - int16_t accel; /* 6 accelerometer (TM only) */ - int16_t pres; /* 8 pressure sensor */ - int16_t temp; /* 10 temperature sensor */ - int16_t v_batt; /* 12 battery voltage */ - int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ - int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ - - int16_t acceleration; /* 18 m/s² * 16 */ - int16_t speed; /* 20 m/s * 16 */ - int16_t height; /* 22 m */ - - int16_t ground_pres; /* 24 average pres on pad */ - int16_t ground_accel; /* 26 average accel on pad */ - int16_t accel_plus_g; /* 28 accel calibration at +1g */ - int16_t accel_minus_g; /* 30 accel calibration at -1g */ - /* 32 */ -}; - -#define AO_TELEMETRY_CONFIGURATION 0x04 - -struct ao_telemetry_configuration { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t device; /* 5 device type */ - uint16_t flight; /* 6 flight number */ - uint8_t config_major; /* 8 Config major version */ - uint8_t config_minor; /* 9 Config minor version */ - uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ - uint16_t main_deploy; /* 12 Main deploy alt in meters */ - uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ - char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ - char version[AO_MAX_VERSION]; /* 24 Software version */ - /* 32 */ -}; - -#define AO_TELEMETRY_LOCATION 0x05 - -#define AO_GPS_MODE_NOT_VALID 'N' -#define AO_GPS_MODE_AUTONOMOUS 'A' -#define AO_GPS_MODE_DIFFERENTIAL 'D' -#define AO_GPS_MODE_ESTIMATED 'E' -#define AO_GPS_MODE_MANUAL 'M' -#define AO_GPS_MODE_SIMULATED 'S' - -struct ao_telemetry_location { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t flags; /* 5 Number of sats and other flags */ - int16_t altitude; /* 6 GPS reported altitude (m) */ - int32_t latitude; /* 8 latitude (degrees * 10⁷) */ - int32_t longitude; /* 12 longitude (degrees * 10⁷) */ - uint8_t year; /* 16 (- 2000) */ - uint8_t month; /* 17 (1-12) */ - uint8_t day; /* 18 (1-31) */ - uint8_t hour; /* 19 (0-23) */ - uint8_t minute; /* 20 (0-59) */ - uint8_t second; /* 21 (0-59) */ - uint8_t pdop; /* 22 (m * 5) */ - uint8_t hdop; /* 23 (m * 5) */ - uint8_t vdop; /* 24 (m * 5) */ - uint8_t mode; /* 25 */ - uint16_t ground_speed; /* 26 cm/s */ - int16_t climb_rate; /* 28 cm/s */ - uint8_t course; /* 30 degrees / 2 */ - uint8_t unused[1]; /* 31 */ - /* 32 */ -}; - -#define AO_TELEMETRY_SATELLITE 0x06 - -struct ao_telemetry_satellite_info { - uint8_t svid; - uint8_t c_n_1; -}; - -struct ao_telemetry_satellite { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t channels; /* 5 number of reported sats */ - - struct ao_telemetry_satellite_info sats[12]; /* 6 */ - uint8_t unused[2]; /* 30 */ - /* 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 */ -}; - -/* #define AO_SEND_ALL_BARO */ - -#define AO_TELEMETRY_BARO 0x80 - -/* - * This packet allows the full sampling rate baro - * data to be captured over the RF link so that the - * flight software can be tested using 'real' data. - * - * Along with this telemetry packet, the flight - * code is modified to send full-rate telemetry all the time - * and never send an RDF tone; this ensure that the full radio - * link is available. - */ -struct ao_telemetry_baro { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t samples; /* 5 number samples */ - - int16_t baro[12]; /* 6 samples */ - /* 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; - struct ao_telemetry_baro baro; -}; - -struct ao_telemetry_all_recv { - union ao_telemetry_all telemetry; - int8_t rssi; - uint8_t status; -}; - +#include /* * ao_gps.c */ diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 502df6c9..fdc49ca2 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -36,7 +36,8 @@ struct ao_data { struct ao_adc adc; #endif #if HAS_MS5607 - struct ao_ms5607_sample ms5607; + struct ao_ms5607_sample ms5607_raw; + struct ao_ms5607_value ms5607_cooked; #endif #if HAS_MPU6000 struct ao_mpu6000_sample mpu6000; @@ -57,25 +58,24 @@ extern volatile __data uint8_t ao_data_head; typedef int32_t pres_t; typedef int32_t alt_t; -static inline pres_t ao_data_pres(struct ao_data *packet) -{ - struct ao_ms5607_value value; +#define ao_data_pres_cook(packet) ao_ms5607_convert(&packet->ms5607_raw, &packet->ms5607_cooked) - ao_ms5607_convert(&packet->ms5607, &value); - return value.pres; -} +#define ao_data_pres(packet) ((packet)->ms5607_cooked.pres) +#define ao_data_temp(packet) ((packet)->ms5607_cooked.temp) #define pres_to_altitude(p) ao_pa_to_altitude(p) -#else +#else /* HAS_MS5607 */ typedef int16_t pres_t; typedef int16_t alt_t; #define ao_data_pres(packet) ((packet)->adc.pres) +#define ao_data_temp(packet) ((packet)->adc.temp) #define pres_to_altitude(p) ao_pres_to_altitude(p) +#define ao_data_pres_cook(p) -#endif +#endif /* else HAS_MS5607 */ /* * Need a few macros to pull data from the sensors: @@ -92,11 +92,11 @@ typedef int16_t accel_t; /* MPU6000 is hooked up so that positive y is positive acceleration */ #define ao_data_accel(packet) ((packet)->mpu6000.accel_y) -#define ao_data_accel_sample(packet) (-ao_data_accel(packet)) +#define ao_data_accel_cook(packet) (-(packet)->mpu6000.accel_y) #define ao_data_set_accel(packet, accel) ((packet)->mpu6000.accel_y = (accel)) #define ao_data_accel_invert(a) (-(a)) -#else +#else /* HAS_MPU6000 && !HAS_HIGHG_ACCEL */ typedef int16_t accel_t; #define ao_data_accel(packet) ((packet)->adc.accel) @@ -183,13 +183,18 @@ typedef int16_t accel_t; * provides 11 bits of data, we haven't actually lost any precision, * just dropped a bit of noise off the low end. */ + #if HAS_ACCEL_REF -#define ao_data_accel_sample(packet) \ + +#define ao_data_accel_cook(packet) \ ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->adc.accel_ref << 1))) >> 1) + #else -#define ao_data_accel_sample(packet) ((packet)->adc.accel) + +#define ao_data_accel_cook(packet) ((packet)->adc.accel) + #endif /* HAS_ACCEL_REF */ -#endif /* else some other pressure sensor */ +#endif /* else some other accel sensor */ #endif /* _AO_DATA_H_ */ diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index 68e2af49..e7c2b0d9 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -112,8 +112,8 @@ ao_log(void) log.tick = ao_data_ring[ao_log_data_pos].tick; if ((int16_t) (log.tick - next_sensor) >= 0) { log.type = AO_LOG_SENSOR; - log.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607.pres; - log.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607.temp; + log.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607_raw.pres; + log.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607_raw.temp; log.u.sensor.accel_x = ao_data_ring[ao_log_data_pos].mpu6000.accel_x; log.u.sensor.accel_y = ao_data_ring[ao_log_data_pos].mpu6000.accel_y; log.u.sensor.accel_z = ao_data_ring[ao_log_data_pos].mpu6000.accel_z; diff --git a/src/core/ao_sample_mm.c b/src/core/ao_sample_mm.c index 8cfadc40..ac11eef0 100644 --- a/src/core/ao_sample_mm.c +++ b/src/core/ao_sample_mm.c @@ -101,11 +101,14 @@ ao_sample(void) /* Capture a sample */ ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data]; ao_sample_tick = ao_data->tick; + + ao_data_pres_cook(ao_data); ao_sample_pres = ao_data_pres(ao_data); ao_sample_alt = pres_to_altitude(ao_sample_pres); ao_sample_height = ao_sample_alt - ao_ground_height; + #if HAS_ACCEL - ao_sample_accel = ao_data_accel_sample(ao_data); + ao_sample_accel = ao_data_accel_cook(ao_data); if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) ao_sample_accel = ao_data_accel_invert(ao_sample_accel); ao_data_set_accel(ao_data, ao_sample_accel); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 5857c44d..9000a149 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -19,16 +19,6 @@ #include "ao_product.h" static __pdata uint16_t ao_telemetry_interval; -static __pdata int8_t ao_telemetry_config_max; -static __pdata int8_t ao_telemetry_config_cur; -#if HAS_GPS -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; @@ -36,7 +26,7 @@ static __pdata uint16_t ao_rdf_time; #define AO_RDF_LENGTH_MS 500 #if defined(MEGAMETRUM) -#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_MEGAMETRUM +#define AO_SEND_MEGA 1 #endif #if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) || defined(TELEMETRUM_V_1_2) @@ -53,6 +43,7 @@ static __pdata uint16_t ao_rdf_time; static __xdata union ao_telemetry_all telemetry; +#if defined AO_TELEMETRY_SENSOR /* Send sensor packet */ static void ao_send_sensor(void) @@ -96,10 +87,78 @@ ao_send_sensor(void) ao_radio_send(&telemetry, sizeof (telemetry)); } +#endif -static uint8_t ao_baro_sample; + +#ifdef AO_SEND_MEGA +/* Send mega sensor packet */ +static void +ao_send_mega_sensor(void) +{ + __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; + + telemetry.generic.tick = packet->tick; + telemetry.generic.type = AO_TELEMETRY_MEGA_SENSOR; + + telemetry.mega_sensor.accel = ao_data_accel(packet); + telemetry.mega_sensor.pres = ao_data_pres(packet); + telemetry.mega_sensor.temp = ao_data_temp(packet); + + telemetry.mega_sensor.accel_x = packet->mpu6000.accel_x; + telemetry.mega_sensor.accel_y = packet->mpu6000.accel_y; + telemetry.mega_sensor.accel_z = packet->mpu6000.accel_z; + + telemetry.mega_sensor.gyro_x = packet->mpu6000.gyro_x; + telemetry.mega_sensor.gyro_y = packet->mpu6000.gyro_y; + telemetry.mega_sensor.gyro_z = packet->mpu6000.gyro_z; + + telemetry.mega_sensor.mag_x = packet->hmc5883.x; + telemetry.mega_sensor.mag_y = packet->hmc5883.y; + telemetry.mega_sensor.mag_z = packet->hmc5883.z; + + ao_radio_send(&telemetry, sizeof (telemetry)); +} + +static __pdata int8_t ao_telemetry_mega_data_max; +static __pdata int8_t ao_telemetry_mega_data_cur; + +/* Send mega data packet */ +static void +ao_send_mega_data(void) +{ + if (--ao_telemetry_mega_data_cur <= 0) { + __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; + uint8_t i; + + telemetry.generic.tick = packet->tick; + telemetry.generic.type = AO_TELEMETRY_MEGA_DATA; + + telemetry.mega_data.state = ao_flight_state; + telemetry.mega_data.v_batt = packet->adc.v_batt; + telemetry.mega_data.v_pyro = packet->adc.v_pbatt; + + /* XXX figure out right shift value; 4 might suffice */ + for (i = 0; i < AO_ADC_NUM_SENSE; i++) + telemetry.mega_data.sense[i] = packet->adc.sense[i] >> 8; + + telemetry.mega_data.ground_pres = ao_ground_pres; + telemetry.mega_data.ground_accel = ao_ground_accel; + telemetry.mega_data.accel_plus_g = ao_config.accel_plus_g; + telemetry.mega_data.accel_minus_g = ao_config.accel_minus_g; + + telemetry.mega_data.acceleration = ao_accel; + telemetry.mega_data.speed = ao_speed; + telemetry.mega_data.height = ao_height; + + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_mega_data_cur = ao_telemetry_mega_data_max; + } +} +#endif /* AO_SEND_MEGA */ #ifdef AO_SEND_ALL_BARO +static uint8_t ao_baro_sample; + static void ao_send_baro(void) { @@ -121,6 +180,9 @@ ao_send_baro(void) } #endif +static __pdata int8_t ao_telemetry_config_max; +static __pdata int8_t ao_telemetry_config_cur; + static void ao_send_configuration(void) { @@ -146,6 +208,10 @@ ao_send_configuration(void) } #if HAS_GPS + +static __pdata int8_t ao_telemetry_loc_cur; +static __pdata int8_t ao_telemetry_sat_cur; + static void ao_send_location(void) { @@ -181,6 +247,10 @@ ao_send_satellite(void) #endif #if HAS_COMPANION + +static __pdata int8_t ao_telemetry_companion_max; +static __pdata int8_t ao_telemetry_companion_cur; + static void ao_send_companion(void) { @@ -223,7 +293,13 @@ ao_telemetry(void) #ifdef AO_SEND_ALL_BARO ao_send_baro(); #endif +#ifdef AO_SEND_MEGA + ao_send_mega_sensor(); + ao_send_mega_data(); +#else ao_send_sensor(); +#endif + #if HAS_COMPANION if (ao_companion_running) ao_send_companion(); @@ -257,31 +333,42 @@ ao_telemetry(void) void ao_telemetry_set_interval(uint16_t interval) { + uint8_t cur = 0; ao_telemetry_interval = interval; + +#if AO_SEND_MEGA + if (interval > 1) + ao_telemetry_mega_data_max = 1; + else + ao_telemetry_mega_data_max = 2; + if (ao_telemetry_mega_data_max > cur) + cur++; + ao_telemetry_mega_data_cur = cur; +#endif #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; + if (ao_telemetry_companion_max > cur) + cur++; + ao_telemetry_companion_cur = cur; #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; + if (ao_telemetry_config_max > cur) + cur++; + ao_telemetry_config_cur = cur; #endif #if HAS_GPS - 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; - if (ao_telemetry_config_max > ao_telemetry_sat_cur) - ao_telemetry_sat_cur++; + if (ao_telemetry_config_max > cur) + cur++; + ao_telemetry_loc_cur = cur; + if (ao_telemetry_config_max > cur) + cur++; + ao_telemetry_sat_cur = cur; #endif ao_wakeup(&telemetry); } diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 71299de9..ed1d20c9 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -60,7 +60,7 @@ static void ao_adc_done(int index) #if HAS_MS5607 if (!ao_ms5607_valid) step = 0; - ao_data_ring[ao_data_head].ms5607 = ao_ms5607_current; + ao_data_ring[ao_data_head].ms5607_raw = ao_ms5607_current; #endif #if HAS_HMC5883 if (!ao_hmc5883_valid) -- cgit v1.2.3 From 75e4521ec42a368cebc67a07f8713d7a854ea265 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jun 2012 09:52:37 -0700 Subject: altos: Move FEC code to core It's not a driver as it's not specific to the 1120 chip Signed-off-by: Keith Packard --- src/core/ao_fec.h | 60 ++++++++++++++++++++ src/core/ao_fec_tx.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_fec.h | 60 -------------------- src/drivers/ao_fec_tx.c | 139 ---------------------------------------------- 4 files changed, 204 insertions(+), 199 deletions(-) create mode 100644 src/core/ao_fec.h create mode 100644 src/core/ao_fec_tx.c delete mode 100644 src/drivers/ao_fec.h delete mode 100644 src/drivers/ao_fec_tx.c (limited to 'src/core') diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h new file mode 100644 index 00000000..db5523a3 --- /dev/null +++ b/src/core/ao_fec.h @@ -0,0 +1,60 @@ +/* + * 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_FEC_H_ +#define _AO_FEC_H_ + +#include + +#define AO_FEC_CRC_INIT 0xffff +#define AO_FEC_TRELLIS_TERMINATOR 0x0b +#define AO_FEC_PREPARE_EXTRA 4 + +void +ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name); + +uint16_t +ao_fec_crc(uint8_t *bytes, uint8_t len); + +/* + * Append CRC and terminator bytes, returns resulting length. + * 'out' must be at least len + AO_FEC_PREPARE_EXTRA bytes long + */ +uint8_t +ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Whiten data using the cc1111 PN9 sequence. 'out' + * must be 'len' bytes long. 'out' and 'in' can be + * the same array + */ +uint8_t +ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Encode data. 'out' must be len*2 bytes long + */ +uint8_t +ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Interleave data. 'out' must be 'len' bytes long + */ +uint8_t +ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); + +#endif /* _AO_FEC_H_ */ diff --git a/src/core/ao_fec_tx.c b/src/core/ao_fec_tx.c new file mode 100644 index 00000000..bf32c506 --- /dev/null +++ b/src/core/ao_fec_tx.c @@ -0,0 +1,144 @@ +/* + * 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 + +void +ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name) +{ + uint8_t i; + + printf ("%s (%d):", name, len); + for (i = 0; i < len; i++) { + if ((i & 7) == 0) + printf ("\n\t%02x:", i); + printf(" %02x", bytes[i]); + } + printf ("\n"); +} + +static uint16_t inline +crc_byte(uint8_t byte, uint16_t crc) +{ + uint8_t bit; + + for (bit = 0; bit < 8; bit++) { + if (((crc & 0x8000) >> 8) ^ (byte & 0x80)) + crc = (crc << 1) ^ 0x8005; + else + crc = (crc << 1); + byte <<= 1; + } + return crc; +} + +uint16_t +ao_fec_crc(uint8_t *bytes, uint8_t len) +{ + uint16_t crc = AO_FEC_CRC_INIT; + + while (len--) + crc = crc_byte(*bytes++, crc); + return crc; +} + +uint8_t +ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out) +{ + uint16_t crc = ao_fec_crc (in, len); + uint8_t i; + uint8_t num_fec; + + /* Copy data */ + for (i = 0; i < len; i++) + out[i] = in[i]; + + /* Append CRC */ + out[i++] = crc >> 8; + out[i++] = crc; + + /* Append FEC -- 1 byte if odd, two bytes if even */ + num_fec = 2 - (i & 1); + while (num_fec--) + out[i++] = AO_FEC_TRELLIS_TERMINATOR; + return i; +} + +static const uint8_t whiten[] = { +#include "ao_whiten.h" +}; + +uint8_t +ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) +{ + const uint8_t *w = whiten; + + while (len--) + *out++ = *in++ ^ *w++; +} + +static const uint8_t ao_fec_encode_table[16] = { +/* next 0 1 state */ + 0, 3, /* 000 */ + 1, 2, /* 001 */ + 3, 0, /* 010 */ + 2, 1, /* 011 */ + 3, 0, /* 100 */ + 2, 1, /* 101 */ + 0, 3, /* 110 */ + 1, 2 /* 111 */ +}; + +uint8_t +ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out) +{ + uint16_t fec = 0, output; + uint8_t byte, bit; + + for (byte = 0; byte < len; byte++) { + fec = (fec & 0x700) | in[byte]; + output = 0; + for (bit = 0; bit < 8; bit++) { + output = output << 2 | ao_fec_encode_table[fec >> 7]; + fec = (fec << 1) & 0x7ff; + } + out[byte * 2] = output >> 8; + out[byte * 2 + 1] = output; + } + return len * 2; +} + +uint8_t +ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out) +{ + uint8_t i, j; + + for (i = 0; i < len; i += 4) { + uint32_t interleaved = 0; + + for (j = 0; j < 4 * 4; j++) { + interleaved <<= 2; + interleaved |= (in[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; + } + out[i+0] = interleaved >> 24; + out[i+1] = interleaved >> 16; + out[i+2] = interleaved >> 8; + out[i+3] = interleaved; + } + return len; +} diff --git a/src/drivers/ao_fec.h b/src/drivers/ao_fec.h deleted file mode 100644 index db5523a3..00000000 --- a/src/drivers/ao_fec.h +++ /dev/null @@ -1,60 +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_FEC_H_ -#define _AO_FEC_H_ - -#include - -#define AO_FEC_CRC_INIT 0xffff -#define AO_FEC_TRELLIS_TERMINATOR 0x0b -#define AO_FEC_PREPARE_EXTRA 4 - -void -ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name); - -uint16_t -ao_fec_crc(uint8_t *bytes, uint8_t len); - -/* - * Append CRC and terminator bytes, returns resulting length. - * 'out' must be at least len + AO_FEC_PREPARE_EXTRA bytes long - */ -uint8_t -ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out); - -/* - * Whiten data using the cc1111 PN9 sequence. 'out' - * must be 'len' bytes long. 'out' and 'in' can be - * the same array - */ -uint8_t -ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); - -/* - * Encode data. 'out' must be len*2 bytes long - */ -uint8_t -ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); - -/* - * Interleave data. 'out' must be 'len' bytes long - */ -uint8_t -ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); - -#endif /* _AO_FEC_H_ */ diff --git a/src/drivers/ao_fec_tx.c b/src/drivers/ao_fec_tx.c deleted file mode 100644 index b8933956..00000000 --- a/src/drivers/ao_fec_tx.c +++ /dev/null @@ -1,139 +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 - -void -ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name) -{ - uint8_t i; - - printf ("%s (%d):", name, len); - for (i = 0; i < len; i++) { - if ((i & 7) == 0) - printf ("\n\t%02x:", i); - printf(" %02x", bytes[i]); - } - printf ("\n"); -} - -static uint16_t inline -crc_byte(uint8_t byte, uint16_t crc) -{ - uint8_t bit; - - for (bit = 0; bit < 8; bit++) { - if (((crc & 0x8000) >> 8) ^ (byte & 0x80)) - crc = (crc << 1) ^ 0x8005; - else - crc = (crc << 1); - byte <<= 1; - } - return crc; -} - -uint16_t -ao_fec_crc(uint8_t *bytes, uint8_t len) -{ - uint16_t crc = AO_FEC_CRC_INIT; - - while (len--) - crc = crc_byte(*bytes++, crc); - return crc; -} - -uint8_t -ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out) -{ - uint16_t crc = ao_fec_crc (in, len); - uint8_t i; - uint8_t num_fec; - - /* Copy data */ - for (i = 0; i < len; i++) - out[i] = in[i]; - - /* Append CRC */ - out[i++] = crc >> 8; - out[i++] = crc; - - /* Append FEC -- 1 byte if odd, two bytes if even */ - num_fec = 2 - (i & 1); - while (num_fec--) - out[i++] = AO_FEC_TRELLIS_TERMINATOR; - return i; -} - -static const uint8_t whiten[] = { -#include "ao_whiten.h" -}; - -uint8_t -ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) -{ - const uint8_t *w = whiten; - - while (len--) - *out++ = *in++ ^ *w++; -} - -static const uint8_t ao_fec_encode_table[16] = { - 0, 3, 1, 2, - 3, 0, 2, 1, - 3, 0, 2, 1, - 0, 3, 1, 2 -}; - -uint8_t -ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out) -{ - uint16_t fec = 0, output; - uint8_t byte, bit; - - for (byte = 0; byte < len; byte++) { - fec = (fec & 0x700) | in[byte]; - output = 0; - for (bit = 0; bit < 8; bit++) { - output = output << 2 | ao_fec_encode_table[fec >> 7]; - fec = (fec << 1) & 0x7ff; - } - out[byte * 2] = output >> 8; - out[byte * 2 + 1] = output; - } - return len * 2; -} - -uint8_t -ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out) -{ - uint8_t i, j; - - for (i = 0; i < len; i += 4) { - uint32_t interleaved = 0; - - for (j = 0; j < 4 * 4; j++) { - interleaved <<= 2; - interleaved |= (in[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; - } - out[i+0] = interleaved >> 24; - out[i+1] = interleaved >> 16; - out[i+2] = interleaved >> 8; - out[i+3] = interleaved; - } - return len; -} -- cgit v1.2.3 From cbf79a0f9cb859d04e8e03d627219cb2bf49611f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 22 Jun 2012 23:12:02 -0700 Subject: altos: Add the simplest possible viterbi decoder I think I understand how it works now. It's not exactly speedy, and it uses a lot of memory. Signed-off-by: Keith Packard --- src/core/ao_fec.h | 9 +++ src/core/ao_viterbi.c | 143 ++++++++++++++++++++++++++++++++++++++++ src/test/Makefile | 4 +- src/test/ao_fec_tx_test.c | 163 +++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 307 insertions(+), 12 deletions(-) create mode 100644 src/core/ao_viterbi.c (limited to 'src/core') diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index db5523a3..985352dd 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -57,4 +57,13 @@ ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); uint8_t ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Decode data. 'in' is one byte per bit, soft decision + * 'out' must be len/8 bytes long + */ + +uint8_t +ao_fec_decode(uint8_t *in, int in_len, uint8_t *out); + #endif /* _AO_FEC_H_ */ diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c new file mode 100644 index 00000000..2d441f4b --- /dev/null +++ b/src/core/ao_viterbi.c @@ -0,0 +1,143 @@ +/* + * 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 + +/* + * 'input' is 8-bits per symbol soft decision data + * 'len' is output byte length + */ + +static const uint8_t ao_fec_encode_table[16] = { +/* next 0 1 state */ + 0, 3, /* 000 */ + 1, 2, /* 001 */ + 3, 0, /* 010 */ + 2, 1, /* 011 */ + 3, 0, /* 100 */ + 2, 1, /* 101 */ + 0, 3, /* 110 */ + 1, 2 /* 111 */ +}; + +struct ao_soft_sym { + uint8_t a, b; +}; + +struct ao_soft_sym +ao_soft_sym(uint8_t bits) +{ + struct ao_soft_sym s; + + s.a = ((bits & 2) >> 1) * 0xff; + s.b = (bits & 1) * 0xff; + return s; +} + +uint8_t +ao_next_state(uint8_t state, uint8_t bit) +{ + return ((state << 1) | bit) & 0x7; +} + +static inline abs(int x) { return x < 0 ? -x : x; } + +int +ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) +{ + return abs(a.a - b.a) + abs(a.b - b.b); +} + +uint8_t +ao_fec_decode(uint8_t *in, int len, uint8_t *out) +{ + int cost[len/2 + 1][8]; + uint8_t prev[len/2 + 1][8]; + int c; + int i, b; + uint8_t state = 0, min_state; + uint8_t bits[len/2]; + + for (c = 0; c < 8; c++) + cost[0][c] = 10000; + cost[0][0] = 0; + + for (i = 0; i < len; i += 2) { + b = i/2; + struct ao_soft_sym s = { .a = in[i], .b = in[i+1] }; + + for (state = 0; state < 8; state++) + cost[b+1][state] = 10000; + + for (state = 0; state < 8; state++) { + struct ao_soft_sym zero = ao_soft_sym(ao_fec_encode_table[state * 2 + 0]); + struct ao_soft_sym one = ao_soft_sym(ao_fec_encode_table[state * 2 + 1]); + uint8_t zero_state = ao_next_state(state, 0); + uint8_t one_state = ao_next_state(state, 1); + int zero_cost = ao_cost(s, zero); + int one_cost = ao_cost(s, one); + +#if 0 + printf ("saw %02x %02x expected %02x %02x (%d) or %02x %02x (%d)\n", + s.a, s.b, zero.a, zero.b, zero_cost, one.a, one.b, one_cost); +#endif + zero_cost += cost[b][state]; + one_cost += cost[b][state]; + if (zero_cost < cost[b+1][zero_state]) { + prev[b+1][zero_state] = state; + cost[b+1][zero_state] = zero_cost; + } + + if (one_cost < cost[b+1][one_state]) { + prev[b+1][one_state] = state; + cost[b+1][one_state] = one_cost; + } + } + + printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); + for (state = 0; state < 8; state++) { + printf (" %5d", cost[b+1][state]); + } + printf ("\n"); + } + + b = len / 2; + c = cost[b][0]; + min_state = 0; + for (state = 1; state < 8; state++) { + if (cost[b][state] < c) { + c = cost[b][state]; + min_state = state; + } + } + + for (b = len/2; b > 0; b--) { + bits[b-1] = min_state & 1; + min_state = prev[b][min_state]; + } + + for (i = 0; i < len/2; i += 8) { + uint8_t byte; + + byte = 0; + for (b = 0; b < 8; b++) + byte = (byte << 1) | bits[i + b]; + out[i/8] = byte; + } + return len/16; +} diff --git a/src/test/Makefile b/src/test/Makefile index 3e308dd7..024a54c1 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -40,5 +40,5 @@ ao_convert_pa_test: ao_convert_pa_test.c ao_convert_pa.c altitude-pa.h ao_kalman.h: $(KALMAN) (cd .. && make ao_kalman.h) -ao_fec_tx_test: ao_fec_tx_test.c ao_fec_tx.c - cc $(CFLAGS) -o $@ ao_fec_tx_test.c ../drivers/ao_fec_tx.c +ao_fec_tx_test: ao_fec_tx_test.c ao_fec_tx.c ao_viterbi.c + cc $(CFLAGS) -o $@ ao_fec_tx_test.c ../core/ao_fec_tx.c ../core/ao_viterbi.c -lm diff --git a/src/test/ao_fec_tx_test.c b/src/test/ao_fec_tx_test.c index b8dc9308..d01eadc5 100644 --- a/src/test/ao_fec_tx_test.c +++ b/src/test/ao_fec_tx_test.c @@ -18,21 +18,73 @@ #include #include #include +#include +#include -int -main(int argc, char **argv) +#ifndef RANDOM_MAX +#define RANDOM_MAX 0x7fffffff +#endif + +static double +rand_real(void) { + return (double) random() / (double) RANDOM_MAX; +} + +static double +gaussian_random(double mean, double dev) { - uint8_t input[4] = { 3, 1, 2, 3 }; - uint8_t prepare[sizeof(input) + AO_FEC_PREPARE_EXTRA]; - uint8_t encode[sizeof(prepare) * 2]; - uint8_t interleave[sizeof(encode)]; + static int save_x_valid = 0; + static double save_x; + double x; + + if (save_x_valid) + { + x = save_x; + save_x_valid = 0; + } + else + { + double w; + double normal_x1, normal_x2; + + do { + normal_x1 = 2 * rand_real () - 1; + normal_x2 = 2 * rand_real () - 1; + w = normal_x1*normal_x1 + normal_x2*normal_x2; + } while (w >= 1 || w < 1E-30); + + w = sqrt(log(w)*(-2./w)); + + /* + * normal_x1 and normal_x2 are independent normally + * distributed variates + */ + + x = normal_x1 * w; + /* save normal_x2 for next call */ + save_x = normal_x2 * w; + save_x_valid = 1; + } + return x * dev + mean; +} + +#define PREPARE_LEN(input_len) ((input_len) + AO_FEC_PREPARE_EXTRA) +#define ENCODE_LEN(input_len) (PREPARE_LEN(input_len) * 2) +#define INTERLEAVE_LEN(input_len) ENCODE_LEN(input_len) + +static int +ao_encode(uint8_t *input, int input_len, uint8_t *output) +{ + uint8_t prepare[PREPARE_LEN(input_len)]; + uint8_t encode[ENCODE_LEN(input_len)]; + uint8_t interleave[INTERLEAVE_LEN(input_len)]; uint8_t prepare_len; uint8_t encode_len; uint8_t interleave_len; - ao_fec_dump_bytes(input, sizeof(input), "Input"); + ao_fec_dump_bytes(input, input_len, "Input"); - prepare_len = ao_fec_prepare(input, sizeof (input), prepare); + prepare_len = ao_fec_prepare(input, input_len, prepare); ao_fec_dump_bytes(prepare, prepare_len, "Prepare"); @@ -40,8 +92,99 @@ main(int argc, char **argv) ao_fec_dump_bytes(encode, encode_len, "Encode"); - interleave_len = ao_fec_interleave(encode, encode_len, interleave); + interleave_len = ao_fec_interleave(encode, encode_len, output); + + ao_fec_dump_bytes(output, interleave_len, "Interleave"); + + return interleave_len; +} + +#define RADIO_LEN(input_len) (INTERLEAVE_LEN(input_len) * 8) + +static int +ao_radio(uint8_t *bits, int bits_len, uint8_t *bytes) +{ + uint8_t b, *bytes_orig = bytes; + uint8_t interleave[bits_len]; + int i, bit; + + ao_fec_interleave(bits, bits_len, interleave); + + ao_fec_dump_bytes(interleave, bits_len, "De-interleave"); + + for (i = 0; i < bits_len; i++) { + b = interleave[i]; + for (bit = 7; bit >= 0; bit--) + *bytes++ = ((b >> bit) & 1) * 0xff; + } + + ao_fec_dump_bytes(bytes_orig, bits_len * 8, "Bytes"); - ao_fec_dump_bytes(interleave, interleave_len, "Interleave"); + return bits_len * 8; } +static int +ao_fuzz (uint8_t *in, int in_len, uint8_t *out, double dev) +{ + int i; + int errors = 0; + + for (i = 0; i < in_len; i++) { + double error = gaussian_random(0, dev); + uint8_t byte = in[i]; + + if (error > 0) { + if (error > 0xff) + error = 0xff; + if (error >= 0x80) + errors++; + if (byte < 0x80) + byte += error; + else + byte -= error; + } + out[i] = byte; + } + + printf ("Introduced %d errors\n", errors); + ao_fec_dump_bytes(out, in_len, "Fuzz"); + return in_len; +} + +static int +ao_decode(uint8_t *bytes, int bytes_len, uint8_t *bits) +{ + int bits_len; + + bits_len = ao_fec_decode(bytes, bytes_len, bits); + + ao_fec_dump_bytes(bits, bits_len, "Decode"); +} + +int +main(int argc, char **argv) +{ + uint8_t original[4] = { 3, 1, 2, 3 }; + uint8_t encode[INTERLEAVE_LEN(sizeof(original))]; + int encode_len; + + uint8_t transmit[RADIO_LEN(sizeof(original))]; + int transmit_len; + + uint8_t receive[RADIO_LEN(sizeof(original))]; + int receive_len; + + uint8_t decode[INTERLEAVE_LEN(sizeof(original))]; + int decode_len; + + encode_len = ao_encode(original, sizeof(original), encode); + + transmit_len = ao_radio(encode, encode_len, transmit); + + /* apply gaussian noise to test viterbi code against errors */ + receive_len = ao_fuzz(transmit, transmit_len, receive, 0x80); + + decode_len = ao_decode(receive, receive_len, decode); +} + + -- cgit v1.2.3 From 047e95421c87c5d056038797b48f759bedabf245 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 22 Jun 2012 23:31:11 -0700 Subject: altos: Start optimizing viterbi decoder Only need two cost arrays (previous and next). Create constant full-width decoder table instead of expanding bits into bytes for each decode step. Signed-off-by: Keith Packard --- src/core/ao_viterbi.c | 94 +++++++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 47 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 2d441f4b..916c4d7c 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -23,22 +23,22 @@ * 'len' is output byte length */ -static const uint8_t ao_fec_encode_table[16] = { -/* next 0 1 state */ - 0, 3, /* 000 */ - 1, 2, /* 001 */ - 3, 0, /* 010 */ - 2, 1, /* 011 */ - 3, 0, /* 100 */ - 2, 1, /* 101 */ - 0, 3, /* 110 */ - 1, 2 /* 111 */ -}; - struct ao_soft_sym { uint8_t a, b; }; +static const struct ao_soft_sym ao_fec_decode_table[16] = { +/* next 0 1 state */ + { 0x00, 0x00 }, { 0xff, 0xff }, /* 000 */ + { 0x00, 0xff }, { 0xff, 0x00 }, /* 001 */ + { 0xff, 0xff }, { 0x00, 0x00 }, /* 010 */ + { 0xff, 0x00 }, { 0x00, 0xff }, /* 011 */ + { 0xff, 0xff }, { 0x00, 0x00 }, /* 100 */ + { 0xff, 0x00 }, { 0x00, 0xff }, /* 101 */ + { 0x00, 0x00 }, { 0xff, 0xff }, /* 110 */ + { 0x00, 0xff }, { 0xff, 0x00 } /* 111 */ +}; + struct ao_soft_sym ao_soft_sym(uint8_t bits) { @@ -57,71 +57,71 @@ ao_next_state(uint8_t state, uint8_t bit) static inline abs(int x) { return x < 0 ? -x : x; } -int +static inline uint16_t ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) { return abs(a.a - b.a) + abs(a.b - b.b); } +#define NUM_STATE 8 + uint8_t ao_fec_decode(uint8_t *in, int len, uint8_t *out) { - int cost[len/2 + 1][8]; - uint8_t prev[len/2 + 1][8]; - int c; - int i, b; - uint8_t state = 0, min_state; - uint8_t bits[len/2]; - - for (c = 0; c < 8; c++) - cost[0][c] = 10000; + uint16_t cost[2][NUM_STATE]; + uint8_t prev[len/2 + 1][NUM_STATE]; + int c; + int i, b; + uint8_t p, n; + uint8_t state = 0, min_state; + uint8_t bits[len/2]; + + p = 0; + for (c = 0; c < NUM_STATE; c++) + cost[0][c] = 0xffff; cost[0][0] = 0; for (i = 0; i < len; i += 2) { b = i/2; + n = p ^ 1; struct ao_soft_sym s = { .a = in[i], .b = in[i+1] }; - for (state = 0; state < 8; state++) - cost[b+1][state] = 10000; + for (state = 0; state < NUM_STATE; state++) + cost[n][state] = 0xffff; + + for (state = 0; state < NUM_STATE; state++) { + int zero_cost = ao_cost(s, ao_fec_decode_table[state * 2 + 0]); + int one_cost = ao_cost(s, ao_fec_decode_table[state * 2 + 1]); - for (state = 0; state < 8; state++) { - struct ao_soft_sym zero = ao_soft_sym(ao_fec_encode_table[state * 2 + 0]); - struct ao_soft_sym one = ao_soft_sym(ao_fec_encode_table[state * 2 + 1]); uint8_t zero_state = ao_next_state(state, 0); uint8_t one_state = ao_next_state(state, 1); - int zero_cost = ao_cost(s, zero); - int one_cost = ao_cost(s, one); - -#if 0 - printf ("saw %02x %02x expected %02x %02x (%d) or %02x %02x (%d)\n", - s.a, s.b, zero.a, zero.b, zero_cost, one.a, one.b, one_cost); -#endif - zero_cost += cost[b][state]; - one_cost += cost[b][state]; - if (zero_cost < cost[b+1][zero_state]) { + + zero_cost += cost[p][state]; + one_cost += cost[p][state]; + if (zero_cost < cost[n][zero_state]) { prev[b+1][zero_state] = state; - cost[b+1][zero_state] = zero_cost; + cost[n][zero_state] = zero_cost; } - if (one_cost < cost[b+1][one_state]) { + if (one_cost < cost[n][one_state]) { prev[b+1][one_state] = state; - cost[b+1][one_state] = one_cost; + cost[n][one_state] = one_cost; } } printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); - for (state = 0; state < 8; state++) { - printf (" %5d", cost[b+1][state]); + for (state = 0; state < NUM_STATE; state++) { + printf (" %5d", cost[n][state]); } printf ("\n"); + p = n; } - b = len / 2; - c = cost[b][0]; + c = cost[p][0]; min_state = 0; - for (state = 1; state < 8; state++) { - if (cost[b][state] < c) { - c = cost[b][state]; + for (state = 1; state < NUM_STATE; state++) { + if (cost[p][state] < c) { + c = cost[p][state]; min_state = state; } } -- cgit v1.2.3 From ff8de3af193839de4bacfd07ade7a5f9ac0bf5b3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Jun 2012 00:54:42 -0700 Subject: altos: incremental viterbi decode Decode bits incrementally. Don't bother decoding the last byte; it's always a pad byte. Signed-off-by: Keith Packard --- src/core/ao_viterbi.c | 70 +++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 30 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 916c4d7c..df95e979 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -49,18 +49,18 @@ ao_soft_sym(uint8_t bits) return s; } -uint8_t +static inline uint8_t ao_next_state(uint8_t state, uint8_t bit) { return ((state << 1) | bit) & 0x7; } -static inline abs(int x) { return x < 0 ? -x : x; } +static inline uint16_t ao_abs(int16_t x) { return x < 0 ? -x : x; } static inline uint16_t ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) { - return abs(a.a - b.a) + abs(a.b - b.b); + return ao_abs(a.a - b.a) + ao_abs(a.b - b.b); } #define NUM_STATE 8 @@ -68,19 +68,23 @@ ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) uint8_t ao_fec_decode(uint8_t *in, int len, uint8_t *out) { - uint16_t cost[2][NUM_STATE]; + uint16_t cost[2][NUM_STATE], min_cost; uint8_t prev[len/2 + 1][NUM_STATE]; - int c; - int i, b; + uint16_t prev_bits[2][NUM_STATE]; + int i, b, dump; uint8_t p, n; uint8_t state = 0, min_state; - uint8_t bits[len/2]; p = 0; - for (c = 0; c < NUM_STATE; c++) - cost[0][c] = 0xffff; + for (state = 0; state < NUM_STATE; state++) { + cost[0][state] = 0xffff; + prev_bits[0][state] = 0; + } cost[0][0] = 0; + min_state = 0; + min_cost = 0; + dump = 0; for (i = 0; i < len; i += 2) { b = i/2; n = p ^ 1; @@ -101,43 +105,49 @@ ao_fec_decode(uint8_t *in, int len, uint8_t *out) if (zero_cost < cost[n][zero_state]) { prev[b+1][zero_state] = state; cost[n][zero_state] = zero_cost; + prev_bits[n][zero_state] = (prev_bits[p][state] << 1) | (state & 1); } if (one_cost < cost[n][one_state]) { prev[b+1][one_state] = state; cost[n][one_state] = one_cost; + prev_bits[n][one_state] = (prev_bits[p][state] << 1) | (state & 1); } } +#if 0 printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); for (state = 0; state < NUM_STATE; state++) { - printf (" %5d", cost[n][state]); + printf (" %5d(%04x)", cost[n][state], prev_bits[n][state]); } printf ("\n"); +#endif p = n; - } - c = cost[p][0]; - min_state = 0; - for (state = 1; state < NUM_STATE; state++) { - if (cost[p][state] < c) { - c = cost[p][state]; - min_state = state; + b++; + if ((b - dump) > 16 || i + 2 >= len) { + uint8_t dist = b - (dump + 9); + uint8_t rev; + min_cost = cost[p][0]; + min_state = 0; + for (state = 1; state < NUM_STATE; state++) { + if (cost[p][state] < min_cost) { + min_cost = cost[p][state]; + min_state = state; + } + } + for (rev = 0; rev < dist; rev++) { + min_state = prev[b][min_state]; + b--; + } +#if 0 + printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x\n", + i/2, min_cost, b-1, min_state, (prev_bits[p][min_state] >> dist) & 0xff); +#endif + out[dump/8] = prev_bits[p][min_state] >> dist; + dump = b - 1; } - } - - for (b = len/2; b > 0; b--) { - bits[b-1] = min_state & 1; - min_state = prev[b][min_state]; - } - - for (i = 0; i < len/2; i += 8) { - uint8_t byte; - byte = 0; - for (b = 0; b < 8; b++) - byte = (byte << 1) | bits[i + b]; - out[i/8] = byte; } return len/16; } -- cgit v1.2.3 From f7bf07dfdad260c1f219064957ef08fb480bf20f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Jun 2012 02:12:58 -0700 Subject: altos: optimize Viterbi implementation Minimize data usage, make data arrays static Signed-off-by: Keith Packard --- src/core/ao_fec.h | 5 +- src/core/ao_fec_tx.c | 2 +- src/core/ao_viterbi.c | 149 ++++++++++++++++++++++++++++---------------------- 3 files changed, 86 insertions(+), 70 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index 985352dd..d4f64b74 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -42,7 +42,7 @@ ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out); * must be 'len' bytes long. 'out' and 'in' can be * the same array */ -uint8_t +void ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); /* @@ -57,13 +57,12 @@ ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); uint8_t ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); - /* * Decode data. 'in' is one byte per bit, soft decision * 'out' must be len/8 bytes long */ uint8_t -ao_fec_decode(uint8_t *in, int in_len, uint8_t *out); +ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out); #endif /* _AO_FEC_H_ */ diff --git a/src/core/ao_fec_tx.c b/src/core/ao_fec_tx.c index bf32c506..c5f410b8 100644 --- a/src/core/ao_fec_tx.c +++ b/src/core/ao_fec_tx.c @@ -83,7 +83,7 @@ static const uint8_t whiten[] = { #include "ao_whiten.h" }; -uint8_t +void ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) { const uint8_t *w = whiten; diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index df95e979..1b1784b3 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -18,37 +18,26 @@ #include #include -/* - * 'input' is 8-bits per symbol soft decision data - * 'len' is output byte length - */ - struct ao_soft_sym { uint8_t a, b; }; -static const struct ao_soft_sym ao_fec_decode_table[16] = { +#define NUM_STATE 8 +#define NUM_HIST 8 +#define MOD_HIST(b) ((b) & 7) + +static const struct ao_soft_sym ao_fec_decode_table[NUM_STATE][2] = { /* next 0 1 state */ - { 0x00, 0x00 }, { 0xff, 0xff }, /* 000 */ - { 0x00, 0xff }, { 0xff, 0x00 }, /* 001 */ - { 0xff, 0xff }, { 0x00, 0x00 }, /* 010 */ - { 0xff, 0x00 }, { 0x00, 0xff }, /* 011 */ - { 0xff, 0xff }, { 0x00, 0x00 }, /* 100 */ - { 0xff, 0x00 }, { 0x00, 0xff }, /* 101 */ - { 0x00, 0x00 }, { 0xff, 0xff }, /* 110 */ - { 0x00, 0xff }, { 0xff, 0x00 } /* 111 */ + { { 0x00, 0x00 }, { 0xff, 0xff } } , /* 000 */ + { { 0x00, 0xff }, { 0xff, 0x00 } }, /* 001 */ + { { 0xff, 0xff }, { 0x00, 0x00 } }, /* 010 */ + { { 0xff, 0x00 }, { 0x00, 0xff } }, /* 011 */ + { { 0xff, 0xff }, { 0x00, 0x00 } }, /* 100 */ + { { 0xff, 0x00 }, { 0x00, 0xff } }, /* 101 */ + { { 0x00, 0x00 }, { 0xff, 0xff } }, /* 110 */ + { { 0x00, 0xff }, { 0xff, 0x00 } } /* 111 */ }; -struct ao_soft_sym -ao_soft_sym(uint8_t bits) -{ - struct ao_soft_sym s; - - s.a = ((bits & 2) >> 1) * 0xff; - s.b = (bits & 1) * 0xff; - return s; -} - static inline uint8_t ao_next_state(uint8_t state, uint8_t bit) { @@ -63,71 +52,93 @@ ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) return ao_abs(a.a - b.a) + ao_abs(a.b - b.b); } -#define NUM_STATE 8 +/* + * 'in' is 8-bits per symbol soft decision data + * 'len' is input byte length. 'out' must be + * 'len'/16 bytes long + */ uint8_t -ao_fec_decode(uint8_t *in, int len, uint8_t *out) +ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) { - uint16_t cost[2][NUM_STATE], min_cost; - uint8_t prev[len/2 + 1][NUM_STATE]; - uint16_t prev_bits[2][NUM_STATE]; - int i, b, dump; - uint8_t p, n; - uint8_t state = 0, min_state; + static uint16_t cost[2][NUM_STATE]; /* path cost */ + static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ + uint16_t i; /* input byte index */ + uint16_t b; /* encoded symbol index (bytes/2) */ + uint16_t o; /* output bit index */ + uint8_t p; /* previous cost/bits index */ + uint8_t n; /* next cost/bits index */ + uint8_t state; /* state index */ + uint8_t bit; /* original encoded bit index */ p = 0; for (state = 0; state < NUM_STATE; state++) { cost[0][state] = 0xffff; - prev_bits[0][state] = 0; + bits[0][state] = 0; } cost[0][0] = 0; - min_state = 0; - min_cost = 0; - dump = 0; + o = 0; for (i = 0; i < len; i += 2) { b = i/2; n = p ^ 1; struct ao_soft_sym s = { .a = in[i], .b = in[i+1] }; + /* Reset next costs to 'impossibly high' values so that + * the first path through this state is cheaper than this + */ for (state = 0; state < NUM_STATE; state++) cost[n][state] = 0xffff; + /* Compute path costs and accumulate output bit path + * for each state and encoded bit value + */ for (state = 0; state < NUM_STATE; state++) { - int zero_cost = ao_cost(s, ao_fec_decode_table[state * 2 + 0]); - int one_cost = ao_cost(s, ao_fec_decode_table[state * 2 + 1]); - - uint8_t zero_state = ao_next_state(state, 0); - uint8_t one_state = ao_next_state(state, 1); - - zero_cost += cost[p][state]; - one_cost += cost[p][state]; - if (zero_cost < cost[n][zero_state]) { - prev[b+1][zero_state] = state; - cost[n][zero_state] = zero_cost; - prev_bits[n][zero_state] = (prev_bits[p][state] << 1) | (state & 1); - } - - if (one_cost < cost[n][one_state]) { - prev[b+1][one_state] = state; - cost[n][one_state] = one_cost; - prev_bits[n][one_state] = (prev_bits[p][state] << 1) | (state & 1); + for (bit = 0; bit < 2; bit++) { + int bit_cost = cost[p][state] + ao_cost(s, ao_fec_decode_table[state][bit]); + uint8_t bit_state = ao_next_state(state, bit); + + /* Only track the minimal cost to reach + * this state; the best path can never + * go through the higher cost paths as + * total path cost is cumulative + */ + if (bit_cost < cost[n][bit_state]) { + cost[n][bit_state] = bit_cost; + bits[n][bit_state] = (bits[p][state] << 1) | (state & 1); + } } } #if 0 printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); for (state = 0; state < NUM_STATE; state++) { - printf (" %5d(%04x)", cost[n][state], prev_bits[n][state]); + printf (" %5d(%04x)", cost[n][state], bits[n][state]); } printf ("\n"); #endif p = n; - b++; - if ((b - dump) > 16 || i + 2 >= len) { - uint8_t dist = b - (dump + 9); - uint8_t rev; + /* A loop is needed to handle the last output byte. It + * won't have a full NUM_HIST bits of future data to + * perform full error correction, but we might as well + * give the best possible answer anyways. + */ + while ((b - o) >= (8 + NUM_HIST) || (i + 2 >= len && b > o)) { + + /* Compute number of bits to the end of the + * last full byte of data. This is generally + * NUM_HIST, unless we've reached + * the end of the input, in which case + * it will be seven. + */ + int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */ + uint16_t min_cost; /* lowest cost */ + uint8_t min_state; /* lowest cost state */ + + /* Find the best fit at the current point + * of the decode. + */ min_cost = cost[p][0]; min_state = 0; for (state = 1; state < NUM_STATE; state++) { @@ -136,18 +147,24 @@ ao_fec_decode(uint8_t *in, int len, uint8_t *out) min_state = state; } } - for (rev = 0; rev < dist; rev++) { - min_state = prev[b][min_state]; - b--; + + /* The very last byte of data has the very last bit + * of data left in the state value; just smash the + * bits value in place and reset the 'dist' from + * -1 to 0 so that the full byte is read out + */ + if (dist < 0) { + bits[p][min_state] = (bits[p][min_state] << 1) | (min_state & 1); + dist = 0; } + #if 0 printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x\n", - i/2, min_cost, b-1, min_state, (prev_bits[p][min_state] >> dist) & 0xff); + i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff); #endif - out[dump/8] = prev_bits[p][min_state] >> dist; - dump = b - 1; + out[o >> 3] = bits[p][min_state] >> dist; + o += 8; } - } return len/16; } -- cgit v1.2.3 From 566a0c277de01963922cabc80db8ec3a129923bd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Jun 2012 02:23:08 -0700 Subject: altos: fix comment about decoding last byte of FEC data There aren't *any* forward bits to use when decoding the last byte. Signed-off-by: Keith Packard --- src/core/ao_viterbi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 1b1784b3..17464cd1 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -120,9 +120,9 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) p = n; /* A loop is needed to handle the last output byte. It - * won't have a full NUM_HIST bits of future data to - * perform full error correction, but we might as well - * give the best possible answer anyways. + * won't have any bits of future data to perform full + * error correction, but we might as well give the + * best possible answer anyways. */ while ((b - o) >= (8 + NUM_HIST) || (i + 2 >= len && b > o)) { -- cgit v1.2.3 From b292c14790fc225029cba3f80ce8ad6c5652bc4e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Jun 2012 16:05:42 -0700 Subject: altos: improve FEC apis to reduce data copying Integrate interleaving and whitening into encode and decode steps. Add CRC checking function for receive. Make ao_fec_test program round-trip the data and verify correctness. Signed-off-by: Keith Packard --- src/core/ao_fec.h | 26 ++++-- src/core/ao_fec_tx.c | 118 +++++++++++++++++---------- src/core/ao_viterbi.c | 46 ++++++++++- src/test/Makefile | 6 +- src/test/ao_fec_test.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++ src/test/ao_fec_tx_test.c | 192 -------------------------------------------- 6 files changed, 337 insertions(+), 249 deletions(-) create mode 100644 src/test/ao_fec_test.c delete mode 100644 src/test/ao_fec_tx_test.c (limited to 'src/core') diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index d4f64b74..f3f55fa8 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -24,12 +24,22 @@ #define AO_FEC_TRELLIS_TERMINATOR 0x0b #define AO_FEC_PREPARE_EXTRA 4 +extern const uint8_t ao_fec_whiten_table[]; + void -ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name); +ao_fec_dump_bytes(uint8_t *bytes, uint16_t len, char *name); uint16_t ao_fec_crc(uint8_t *bytes, uint8_t len); +/* + * 'len' is the length of the original data; 'bytes' + * must be four bytes longer than that, and the first + * two after 'len' must be the received crc + */ +uint8_t +ao_fec_check_crc(uint8_t *bytes, uint8_t len); + /* * Append CRC and terminator bytes, returns resulting length. * 'out' must be at least len + AO_FEC_PREPARE_EXTRA bytes long @@ -46,17 +56,11 @@ void ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); /* - * Encode data. 'out' must be len*2 bytes long + * Encode and interleave data. 'out' must be len*2 bytes long */ uint8_t ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); -/* - * Interleave data. 'out' must be 'len' bytes long - */ -uint8_t -ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); - /* * Decode data. 'in' is one byte per bit, soft decision * 'out' must be len/8 bytes long @@ -65,4 +69,10 @@ ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); uint8_t ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out); +/* + * Interleave data packed in bytes. 'out' must be 'len' bytes long. + */ +uint16_t +ao_fec_interleave_bytes(uint8_t *in, uint16_t len, uint8_t *out); + #endif /* _AO_FEC_H_ */ diff --git a/src/core/ao_fec_tx.c b/src/core/ao_fec_tx.c index c5f410b8..c9c0a3d6 100644 --- a/src/core/ao_fec_tx.c +++ b/src/core/ao_fec_tx.c @@ -19,9 +19,9 @@ #include void -ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name) +ao_fec_dump_bytes(uint8_t *bytes, uint16_t len, char *name) { - uint8_t i; + uint16_t i; printf ("%s (%d):", name, len); for (i = 0; i < len; i++) { @@ -57,41 +57,76 @@ ao_fec_crc(uint8_t *bytes, uint8_t len) return crc; } +/* + * len is the length of the data; the crc will be + * the fist two bytes after that + */ + uint8_t -ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out) +ao_fec_check_crc(uint8_t *bytes, uint8_t len) +{ + uint16_t computed_crc = ao_fec_crc(bytes, len); + uint16_t received_crc = (bytes[len] << 8) | (bytes[len+1]); + + return computed_crc == received_crc; +} + +uint8_t +ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *extra) { uint16_t crc = ao_fec_crc (in, len); - uint8_t i; + uint8_t i = 0; uint8_t num_fec; - /* Copy data */ - for (i = 0; i < len; i++) - out[i] = in[i]; - /* Append CRC */ - out[i++] = crc >> 8; - out[i++] = crc; + extra[i++] = crc >> 8; + extra[i++] = crc; /* Append FEC -- 1 byte if odd, two bytes if even */ num_fec = 2 - (i & 1); while (num_fec--) - out[i++] = AO_FEC_TRELLIS_TERMINATOR; + extra[i++] = AO_FEC_TRELLIS_TERMINATOR; return i; } -static const uint8_t whiten[] = { +const uint8_t ao_fec_whiten_table[] = { #include "ao_whiten.h" }; +#if 0 void ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) { - const uint8_t *w = whiten; + const uint8_t *w = ao_fec_whiten_table; while (len--) *out++ = *in++ ^ *w++; } +/* + * Unused as interleaving is now built in to ao_fec_encode + */ + +static void +ao_fec_interleave(uint8_t *d, uint8_t len) +{ + uint8_t i, j; + + for (i = 0; i < len; i += 4) { + uint32_t interleaved = 0; + + for (j = 0; j < 4 * 4; j++) { + interleaved <<= 2; + interleaved |= (d[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; + } + d[i+0] = interleaved >> 24; + d[i+1] = interleaved >> 16; + d[i+2] = interleaved >> 8; + d[i+3] = interleaved; + } +} +#endif + static const uint8_t ao_fec_encode_table[16] = { /* next 0 1 state */ 0, 3, /* 000 */ @@ -107,38 +142,37 @@ static const uint8_t ao_fec_encode_table[16] = { uint8_t ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out) { - uint16_t fec = 0, output; - uint8_t byte, bit; - - for (byte = 0; byte < len; byte++) { - fec = (fec & 0x700) | in[byte]; - output = 0; - for (bit = 0; bit < 8; bit++) { - output = output << 2 | ao_fec_encode_table[fec >> 7]; - fec = (fec << 1) & 0x7ff; + uint8_t extra[AO_FEC_PREPARE_EXTRA]; + uint8_t extra_len; + uint32_t encode, interleave; + uint8_t pair, byte, bit; + uint16_t fec = 0; + const uint8_t *whiten = ao_fec_whiten_table; + + extra_len = ao_fec_prepare(in, len, extra); + for (pair = 0; pair < len + extra_len; pair += 2) { + encode = 0; + for (byte = 0; byte < 2; byte++) { + if (pair + byte == len) + in = extra; + fec |= *in++ ^ *whiten++; + for (bit = 0; bit < 8; bit++) { + encode = encode << 2 | ao_fec_encode_table[fec >> 7]; + fec = (fec << 1) & 0x7ff; + } } - out[byte * 2] = output >> 8; - out[byte * 2 + 1] = output; - } - return len * 2; -} -uint8_t -ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out) -{ - uint8_t i, j; - - for (i = 0; i < len; i += 4) { - uint32_t interleaved = 0; + interleave = 0; + for (bit = 0; bit < 4 * 4; bit++) { + uint8_t byte_shift = (bit & 0x3) << 3; + uint8_t bit_shift = (bit & 0xc) >> 1; - for (j = 0; j < 4 * 4; j++) { - interleaved <<= 2; - interleaved |= (in[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; + interleave = (interleave << 2) | ((encode >> (byte_shift + bit_shift)) & 0x3); } - out[i+0] = interleaved >> 24; - out[i+1] = interleaved >> 16; - out[i+2] = interleaved >> 8; - out[i+3] = interleaved; + *out++ = interleave >> 24; + *out++ = interleave >> 16; + *out++ = interleave >> 8; + *out++ = interleave >> 0; } - return len; + return (len + extra_len) * 2; } diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 17464cd1..bb93bc83 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -18,6 +18,35 @@ #include #include +/* + * byte order repeats through 3 2 1 0 + * + * bit-pair order repeats through + * + * 1/0 3/2 5/4 7/6 + * + * So, the over all order is: + * + * 3,1/0 2,1/0 1,1/0 0,1/0 + * 3,3/2 2,3/2 1,3/2 0,3/2 + * 3,5/4 2,5/4 1,5/4 0,5/4 + * 3,7/6 2,7/6 1,7/6 0,7/6 + * + * The raw bit order is thus + * + * 1e/1f 16/17 0e/0f 06/07 + * 1c/1d 14/15 0c/0d 04/05 + * 1a/1b 12/13 0a/0b 02/03 + * 18/19 10/11 08/09 00/01 + */ + +static inline uint16_t ao_interleave_index(uint16_t i) { + uint8_t l = i & 0x1e; + uint16_t h = i & ~0x1e; + uint8_t o = 0x1e ^ (((l >> 2) & 0x6) | ((l << 2) & 0x18)); + return h | o; +} + struct ao_soft_sym { uint8_t a, b; }; @@ -70,6 +99,9 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) uint8_t n; /* next cost/bits index */ uint8_t state; /* state index */ uint8_t bit; /* original encoded bit index */ + const uint8_t *whiten = ao_fec_whiten_table; + uint16_t interleave; /* input byte array index */ + struct ao_soft_sym s; /* input symbol pair */ p = 0; for (state = 0; state < NUM_STATE; state++) { @@ -82,7 +114,13 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) for (i = 0; i < len; i += 2) { b = i/2; n = p ^ 1; - struct ao_soft_sym s = { .a = in[i], .b = in[i+1] }; + + /* Fetch one pair of input bytes, de-interleaving + * the input. + */ + interleave = ao_interleave_index(i); + s.a = in[interleave]; + s.b = in[interleave+1]; /* Reset next costs to 'impossibly high' values so that * the first path through this state is cheaper than this @@ -159,10 +197,10 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) } #if 0 - printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x\n", - i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff); + printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n", + i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); #endif - out[o >> 3] = bits[p][min_state] >> dist; + *out++ = (bits[p][min_state] >> dist) ^ *whiten++; o += 8; } } diff --git a/src/test/Makefile b/src/test/Makefile index 7bcf24e1..cdcecd51 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,6 @@ vpath % ..:../core:../drivers:../util -PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test ao_fec_tx_test +PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test ao_fec_test KALMAN=make-kalman @@ -40,5 +40,5 @@ ao_convert_pa_test: ao_convert_pa_test.c ao_convert_pa.c altitude-pa.h ao_kalman.h: $(KALMAN) (cd .. && make ao_kalman.h) -ao_fec_tx_test: ao_fec_tx_test.c ao_fec_tx.c ao_viterbi.c - cc $(CFLAGS) -o $@ ao_fec_tx_test.c ../core/ao_fec_tx.c ../core/ao_viterbi.c -lm +ao_fec_test: ao_fec_test.c ao_fec_tx.c ao_viterbi.c + cc $(CFLAGS) -o $@ ao_fec_test.c ../core/ao_fec_tx.c ../core/ao_viterbi.c -lm diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c new file mode 100644 index 00000000..c7509728 --- /dev/null +++ b/src/test/ao_fec_test.c @@ -0,0 +1,198 @@ +/* + * 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 +#include +#include + +#ifndef RANDOM_MAX +#define RANDOM_MAX 0x7fffffff +#endif + +static double +rand_real(void) { + return (double) random() / (double) RANDOM_MAX; +} + +static double +gaussian_random(double mean, double dev) +{ + static int save_x_valid = 0; + static double save_x; + double x; + + if (save_x_valid) + { + x = save_x; + save_x_valid = 0; + } + else + { + double w; + double normal_x1, normal_x2; + + do { + normal_x1 = 2 * rand_real () - 1; + normal_x2 = 2 * rand_real () - 1; + w = normal_x1*normal_x1 + normal_x2*normal_x2; + } while (w >= 1 || w < 1E-30); + + w = sqrt(log(w)*(-2./w)); + + /* + * normal_x1 and normal_x2 are independent normally + * distributed variates + */ + + x = normal_x1 * w; + /* save normal_x2 for next call */ + save_x = normal_x2 * w; + save_x_valid = 1; + } + return x * dev + mean; +} + +#define PREPARE_LEN(input_len) ((input_len) + AO_FEC_PREPARE_EXTRA) +#define ENCODE_LEN(input_len) (PREPARE_LEN(input_len) * 2) +#define DECODE_LEN(input_len) ((input_len) + AO_FEC_PREPARE_EXTRA) +#define EXPAND_LEN(input_len) (ENCODE_LEN(input_len) * 8) + +static int +ao_expand(uint8_t *bits, int bits_len, uint8_t *bytes) +{ + int i, bit; + uint8_t b; + + for (i = 0; i < bits_len; i++) { + b = bits[i]; + for (bit = 7; bit >= 0; bit--) + *bytes++ = ((b >> bit) & 1) * 0xff; + } + + return bits_len * 8; +} + +static int +ao_fuzz (uint8_t *in, int in_len, uint8_t *out, double dev) +{ + int i; + int errors = 0; + + for (i = 0; i < in_len; i++) { + double error = gaussian_random(0, dev); + uint8_t byte = in[i]; + + if (error > 0) { + if (error > 0xff) + error = 0xff; + if (error >= 0x80) + errors++; + if (byte < 0x80) + byte += error; + else + byte -= error; + } + out[i] = byte; + } + return errors; +} + +static uint8_t +ao_random_data(uint8_t *out, uint8_t out_len) +{ + uint8_t len = random() % (out_len + 1); + uint8_t i; + + for (i = 0; i < len; i++) + out[i] = random(); + return len; +} + + +int +main(int argc, char **argv) +{ + int trial; + + uint8_t original[120]; + uint8_t original_len; + + uint8_t encode[ENCODE_LEN(sizeof(original))]; + int encode_len; + + uint8_t transmit[EXPAND_LEN(sizeof(original))]; + int transmit_len; + + uint8_t receive[EXPAND_LEN(sizeof(original))]; + int receive_len, receive_errors; + + uint8_t decode[DECODE_LEN(sizeof(original))]; + int decode_len; + + int errors = 0; + int error; + + srandom(0); + for (trial = 0; trial < 10000; trial++) { + + /* Compute some random data */ + original_len = ao_random_data(original, sizeof(original)); + + /* Encode it */ + encode_len = ao_fec_encode(original, original_len, encode); + + /* Expand from 1-bit-per-symbol to 1-byte-per-symbol */ + transmit_len = ao_expand(encode, encode_len, transmit); + + /* Add gaussian noise to the signal */ + receive_errors = ao_fuzz(transmit, transmit_len, receive, 0x30); + receive_len = transmit_len; + + /* Decode it */ + decode_len = ao_fec_decode(receive, receive_len, decode); + + /* Check to see if we received the right data */ + error = 0; + + if (decode_len < original_len + 2) { + printf ("len mis-match\n"); + error++; + } + + if (!ao_fec_check_crc(decode, original_len)) { + printf ("crc mis-match\n"); + error++; + } + + if (memcmp(original, decode, original_len) != 0) { + printf ("data mis-match\n"); + error++; + } + if (error) { + printf ("Errors: %d\n", receive_errors); + ao_fec_dump_bytes(original, original_len, "Input"); + ao_fec_dump_bytes(decode, original_len, "Decode"); + errors += error; + } + } + return errors; +} + + diff --git a/src/test/ao_fec_tx_test.c b/src/test/ao_fec_tx_test.c deleted file mode 100644 index 1b1fd56d..00000000 --- a/src/test/ao_fec_tx_test.c +++ /dev/null @@ -1,192 +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 -#include -#include -#include - -#ifndef RANDOM_MAX -#define RANDOM_MAX 0x7fffffff -#endif - -static double -rand_real(void) { - return (double) random() / (double) RANDOM_MAX; -} - -static double -gaussian_random(double mean, double dev) -{ - static int save_x_valid = 0; - static double save_x; - double x; - - if (save_x_valid) - { - x = save_x; - save_x_valid = 0; - } - else - { - double w; - double normal_x1, normal_x2; - - do { - normal_x1 = 2 * rand_real () - 1; - normal_x2 = 2 * rand_real () - 1; - w = normal_x1*normal_x1 + normal_x2*normal_x2; - } while (w >= 1 || w < 1E-30); - - w = sqrt(log(w)*(-2./w)); - - /* - * normal_x1 and normal_x2 are independent normally - * distributed variates - */ - - x = normal_x1 * w; - /* save normal_x2 for next call */ - save_x = normal_x2 * w; - save_x_valid = 1; - } - return x * dev + mean; -} - -#define PREPARE_LEN(input_len) ((input_len) + AO_FEC_PREPARE_EXTRA) -#define ENCODE_LEN(input_len) (PREPARE_LEN(input_len) * 2) -#define INTERLEAVE_LEN(input_len) ENCODE_LEN(input_len) - -static int -ao_encode(uint8_t *input, int input_len, uint8_t *output) -{ - uint8_t prepare[PREPARE_LEN(input_len)]; - uint8_t encode[ENCODE_LEN(input_len)]; - uint8_t prepare_len; - uint8_t encode_len; - uint8_t interleave_len; - - ao_fec_dump_bytes(input, input_len, "Input"); - - prepare_len = ao_fec_prepare(input, input_len, prepare); - - ao_fec_dump_bytes(prepare, prepare_len, "Prepare"); - - encode_len = ao_fec_encode(prepare, prepare_len, encode); - - ao_fec_dump_bytes(encode, encode_len, "Encode"); - - interleave_len = ao_fec_interleave(encode, encode_len, output); - - ao_fec_dump_bytes(output, interleave_len, "Interleave"); - - return interleave_len; -} - -#define RADIO_LEN(input_len) (INTERLEAVE_LEN(input_len) * 8) - -static int -ao_radio(uint8_t *bits, int bits_len, uint8_t *bytes) -{ - uint8_t b, *bytes_orig = bytes; - uint8_t interleave[bits_len]; - int i, bit; - - ao_fec_interleave(bits, bits_len, interleave); - - ao_fec_dump_bytes(interleave, bits_len, "De-interleave"); - - for (i = 0; i < bits_len; i++) { - b = interleave[i]; - for (bit = 7; bit >= 0; bit--) - *bytes++ = ((b >> bit) & 1) * 0xff; - } - - ao_fec_dump_bytes(bytes_orig, bits_len * 8, "Bytes"); - - return bits_len * 8; -} - -static int -ao_fuzz (uint8_t *in, int in_len, uint8_t *out, double dev) -{ - int i; - int errors = 0; - - for (i = 0; i < in_len; i++) { - double error = gaussian_random(0, dev); - uint8_t byte = in[i]; - - if (error > 0) { - if (error > 0xff) - error = 0xff; - if (error >= 0x80) - errors++; - if (byte < 0x80) - byte += error; - else - byte -= error; - } - out[i] = byte; - } - - printf ("Introduced %d errors\n", errors); - ao_fec_dump_bytes(out, in_len, "Fuzz"); - return in_len; -} - -static int -ao_decode(uint8_t *bytes, int bytes_len, uint8_t *bits) -{ - int bits_len; - - bits_len = ao_fec_decode(bytes, bytes_len, bits); - - ao_fec_dump_bytes(bits, bits_len, "Decode"); - return bits_len; -} - -int -main(int argc, char **argv) -{ - uint8_t original[4] = { 3, 1, 2, 3 }; - uint8_t encode[INTERLEAVE_LEN(sizeof(original))]; - int encode_len; - - uint8_t transmit[RADIO_LEN(sizeof(original))]; - int transmit_len; - - uint8_t receive[RADIO_LEN(sizeof(original))]; - int receive_len; - - uint8_t decode[INTERLEAVE_LEN(sizeof(original))]; - int decode_len; - - encode_len = ao_encode(original, sizeof(original), encode); - - transmit_len = ao_radio(encode, encode_len, transmit); - - /* apply gaussian noise to test viterbi code against errors */ - receive_len = ao_fuzz(transmit, transmit_len, receive, 0x70); - - decode_len = ao_decode(receive, receive_len, decode); - - return decode_len >= sizeof(original); -} - - -- cgit v1.2.3 From 246174b32bb6cf827d240c32d6a51c3513a08c37 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jun 2012 05:03:16 -0700 Subject: altos: Forgot ao_telemetry.h Not much builds without this... Signed-off-by: Keith Packard --- src/core/ao_telemetry.h | 250 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 src/core/ao_telemetry.h (limited to 'src/core') diff --git a/src/core/ao_telemetry.h b/src/core/ao_telemetry.h new file mode 100644 index 00000000..32a1668c --- /dev/null +++ b/src/core/ao_telemetry.h @@ -0,0 +1,250 @@ +/* + * 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_TELEMETRY_H_ +#define _AO_TELEMETRY_H_ + +/* + * ao_telemetry.c + */ +#define AO_MAX_CALLSIGN 8 +#define AO_MAX_VERSION 8 +#if LEGACY_MONITOR +#define AO_MAX_TELEMETRY 128 +#else +#define AO_MAX_TELEMETRY 32 +#endif + +struct ao_telemetry_generic { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t payload[27]; /* 5 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 +#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 +#define AO_TELEMETRY_SENSOR_TELENANO 0x03 + +struct ao_telemetry_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + int16_t accel; /* 6 accelerometer (TM only) */ + int16_t pres; /* 8 pressure sensor */ + int16_t temp; /* 10 temperature sensor */ + int16_t v_batt; /* 12 battery voltage */ + int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ + int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ + + int16_t acceleration; /* 18 m/s² * 16 */ + int16_t speed; /* 20 m/s * 16 */ + int16_t height; /* 22 m */ + + int16_t ground_pres; /* 24 average pres on pad */ + int16_t ground_accel; /* 26 average accel on pad */ + int16_t accel_plus_g; /* 28 accel calibration at +1g */ + int16_t accel_minus_g; /* 30 accel calibration at -1g */ + /* 32 */ +}; + +#define AO_TELEMETRY_CONFIGURATION 0x04 + +struct ao_telemetry_configuration { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t device; /* 5 device type */ + uint16_t flight; /* 6 flight number */ + uint8_t config_major; /* 8 Config major version */ + uint8_t config_minor; /* 9 Config minor version */ + uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ + uint16_t main_deploy; /* 12 Main deploy alt in meters */ + uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ + char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ + char version[AO_MAX_VERSION]; /* 24 Software version */ + /* 32 */ +}; + +#define AO_TELEMETRY_LOCATION 0x05 + +#define AO_GPS_MODE_NOT_VALID 'N' +#define AO_GPS_MODE_AUTONOMOUS 'A' +#define AO_GPS_MODE_DIFFERENTIAL 'D' +#define AO_GPS_MODE_ESTIMATED 'E' +#define AO_GPS_MODE_MANUAL 'M' +#define AO_GPS_MODE_SIMULATED 'S' + +struct ao_telemetry_location { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t flags; /* 5 Number of sats and other flags */ + int16_t altitude; /* 6 GPS reported altitude (m) */ + int32_t latitude; /* 8 latitude (degrees * 10⁷) */ + int32_t longitude; /* 12 longitude (degrees * 10⁷) */ + uint8_t year; /* 16 (- 2000) */ + uint8_t month; /* 17 (1-12) */ + uint8_t day; /* 18 (1-31) */ + uint8_t hour; /* 19 (0-23) */ + uint8_t minute; /* 20 (0-59) */ + uint8_t second; /* 21 (0-59) */ + uint8_t pdop; /* 22 (m * 5) */ + uint8_t hdop; /* 23 (m * 5) */ + uint8_t vdop; /* 24 (m * 5) */ + uint8_t mode; /* 25 */ + uint16_t ground_speed; /* 26 cm/s */ + int16_t climb_rate; /* 28 cm/s */ + uint8_t course; /* 30 degrees / 2 */ + uint8_t unused[1]; /* 31 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SATELLITE 0x06 + +struct ao_telemetry_satellite_info { + uint8_t svid; + uint8_t c_n_1; +}; + +struct ao_telemetry_satellite { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t channels; /* 5 number of reported sats */ + + struct ao_telemetry_satellite_info sats[12]; /* 6 */ + uint8_t unused[2]; /* 30 */ + /* 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 */ +}; + +#define AO_TELEMETRY_MEGA_SENSOR 0x08 + +struct ao_telemetry_mega_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t pad5; /* 5 */ + int16_t accel; /* 6 Z axis */ + + int32_t pres; /* 8 Pa * 10 */ + int16_t temp; /* 12 °C * 100 */ + + int16_t accel_x; /* 14 */ + int16_t accel_y; /* 16 */ + int16_t accel_z; /* 18 */ + + int16_t gyro_x; /* 20 */ + int16_t gyro_y; /* 22 */ + int16_t gyro_z; /* 24 */ + + int16_t mag_x; /* 26 */ + int16_t mag_y; /* 28 */ + int16_t mag_z; /* 30 */ + /* 32 */ +}; + +#define AO_TELEMETRY_MEGA_DATA 0x09 + +struct ao_telemetry_mega_data { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + + int16_t v_batt; /* 6 battery voltage */ + int16_t v_pyro; /* 8 pyro battery voltage */ + int8_t sense[6]; /* 10 continuity sense */ + + int32_t ground_pres; /* 16 average pres on pad */ + int16_t ground_accel; /* 20 average accel on pad */ + int16_t accel_plus_g; /* 22 accel calibration at +1g */ + int16_t accel_minus_g; /* 24 accel calibration at -1g */ + + int16_t acceleration; /* 26 m/s² * 16 */ + int16_t speed; /* 28 m/s * 16 */ + int16_t height; /* 30 m */ + /* 32 */ +}; + + +/* #define AO_SEND_ALL_BARO */ + +#define AO_TELEMETRY_BARO 0x80 + +/* + * This packet allows the full sampling rate baro + * data to be captured over the RF link so that the + * flight software can be tested using 'real' data. + * + * Along with this telemetry packet, the flight + * code is modified to send full-rate telemetry all the time + * and never send an RDF tone; this ensure that the full radio + * link is available. + */ +struct ao_telemetry_baro { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t samples; /* 5 number samples */ + + int16_t baro[12]; /* 6 samples */ + /* 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; + struct ao_telemetry_mega_sensor mega_sensor; + struct ao_telemetry_mega_data mega_data; + struct ao_telemetry_baro baro; +}; + +struct ao_telemetry_all_recv { + union ao_telemetry_all telemetry; + int8_t rssi; + uint8_t status; +}; + +#endif /* _AO_TELEMETRY_H_ */ -- cgit v1.2.3 From 70cf32e89df19bde5185339fc703532c8a5b8be6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jun 2012 05:03:34 -0700 Subject: altos: Get cc1120 packet reception working Interrupt-per-bit, but it seems to work Signed-off-by: Keith Packard --- src/core/ao_viterbi.c | 19 ++-- src/drivers/ao_cc1120.c | 169 ++++++++++++++++++++++++++---------- src/megametrum-v0.1/ao_megametrum.c | 6 +- src/megametrum-v0.1/ao_pins.h | 2 +- src/stm/ao_exti.h | 3 + src/stm/ao_exti_stm.c | 5 ++ src/test/ao_fec_test.c | 151 ++++++++++++++++++++++++++++++++ 7 files changed, 299 insertions(+), 56 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index bb93bc83..594c0d91 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -55,16 +55,19 @@ struct ao_soft_sym { #define NUM_HIST 8 #define MOD_HIST(b) ((b) & 7) +#define V_0 0xc0 +#define V_1 0x40 + static const struct ao_soft_sym ao_fec_decode_table[NUM_STATE][2] = { /* next 0 1 state */ - { { 0x00, 0x00 }, { 0xff, 0xff } } , /* 000 */ - { { 0x00, 0xff }, { 0xff, 0x00 } }, /* 001 */ - { { 0xff, 0xff }, { 0x00, 0x00 } }, /* 010 */ - { { 0xff, 0x00 }, { 0x00, 0xff } }, /* 011 */ - { { 0xff, 0xff }, { 0x00, 0x00 } }, /* 100 */ - { { 0xff, 0x00 }, { 0x00, 0xff } }, /* 101 */ - { { 0x00, 0x00 }, { 0xff, 0xff } }, /* 110 */ - { { 0x00, 0xff }, { 0xff, 0x00 } } /* 111 */ + { { V_0, V_0 }, { V_1, V_1 } } , /* 000 */ + { { V_0, V_1 }, { V_1, V_0 } }, /* 001 */ + { { V_1, V_1 }, { V_0, V_0 } }, /* 010 */ + { { V_1, V_0 }, { V_0, V_1 } }, /* 011 */ + { { V_1, V_1 }, { V_0, V_0 } }, /* 100 */ + { { V_1, V_0 }, { V_0, V_1 } }, /* 101 */ + { { V_0, V_0 }, { V_1, V_1 } }, /* 110 */ + { { V_0, V_1 }, { V_1, V_0 } } /* 111 */ }; static inline uint8_t diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 67a36c5c..4378716d 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -19,6 +19,7 @@ #include #include #include +#include uint8_t ao_radio_wake; uint8_t ao_radio_mutex; @@ -102,6 +103,35 @@ ao_radio_reg_write(uint16_t addr, uint8_t value) ao_radio_deselect(); } +static void +ao_radio_burst_read_start (uint16_t addr) +{ + uint8_t data[2]; + uint8_t d; + + if (CC1120_IS_EXTENDED(addr)) { + data[0] = ((1 << CC1120_READ) | + (1 << CC1120_BURST) | + CC1120_EXTENDED); + data[1] = addr; + d = 2; + } else { + data[0] = ((1 << CC1120_READ) | + (1 << CC1120_BURST) | + addr); + d = 1; + } + ao_radio_select(); + ao_radio_spi_send(data, d); +} + +static void +ao_radio_burst_read_stop (void) +{ + ao_radio_deselect(); +} + + static uint8_t ao_radio_strobe(uint8_t addr) { @@ -247,10 +277,19 @@ ao_radio_rx_done(void) return ao_radio_marc_status() == CC1120_MARC_STATUS1_RX_FINISHED; } +static void +ao_radio_tx_isr(void) +{ + ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_wake = 1; + ao_wakeup(&ao_radio_wake); +} + static void ao_radio_start_tx(void) { ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); + ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_tx_isr); ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); ao_radio_strobe(CC1120_STX); } @@ -336,29 +375,13 @@ void ao_radio_send(void *d, uint8_t size) { uint8_t marc_status; - uint8_t prepare[size + AO_FEC_PREPARE_EXTRA]; - uint8_t prepare_len; - uint8_t encode[sizeof(prepare) * 2]; + uint8_t encode[size + AO_FEC_PREPARE_EXTRA]; uint8_t encode_len; - uint8_t interleave[sizeof(encode)]; - uint8_t interleave_len; - fec_dump_bytes(d, size, "Input"); + encode_len = ao_fec_encode(d, size, encode); - prepare_len = ao_fec_prepare(d, size, prepare); - fec_dump_bytes(prepare, prepare_len, "Prepare"); - - ao_fec_whiten(prepare, prepare_len, prepare); - fec_dump_bytes(prepare, prepare_len, "Whiten"); - - encode_len = ao_fec_encode(prepare, prepare_len, encode); - fec_dump_bytes(encode, encode_len, "Encode"); - - interleave_len = ao_fec_interleave(encode, encode_len, interleave); - fec_dump_bytes(interleave, interleave_len, "Interleave"); - - ao_radio_get(interleave_len); - ao_radio_fifo_write(interleave, interleave_len); + ao_radio_get(encode_len); + ao_radio_fifo_write(encode, encode_len); ao_radio_wake = 0; @@ -373,34 +396,92 @@ ao_radio_send(void *d, uint8_t size) ao_radio_put(); } +#define AO_RADIO_MAX_RECV 90 + +static uint8_t rx_data[2048]; +static uint16_t rx_data_count; +static uint16_t rx_data_cur; +static uint8_t rx_started; + +static void +ao_radio_rx_isr(void) +{ + if (rx_started) { + rx_data[rx_data_cur++] = stm_spi2.dr; + if (rx_data_cur >= rx_data_count) { + ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_wake = 1; + ao_wakeup(&ao_radio_wake); + } + } else { + (void) stm_spi2.dr; + rx_started = 1; + } + stm_spi2.dr = 0x00; +} + uint8_t ao_radio_recv(__xdata void *d, uint8_t size) { - uint8_t marc_status = CC1120_MARC_STATUS1_NO_FAILURE; + uint8_t len = ((size - 2) + 4) * 2; /* two bytes for status */ + uint16_t i; + + rx_data_count = sizeof (rx_data); + rx_data_cur = 0; + rx_started = 0; + + printf ("len %d rx_data_count %d\n", len, rx_data_count); /* configure interrupt pin */ - ao_radio_get(size); + ao_radio_get(len); ao_radio_wake = 0; + ao_radio_abort = 0; + + ao_radio_reg_write(CC1120_PKT_CFG2, + (CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)); + + ao_radio_reg_write(CC1120_EXT_CTRL, 0); + + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT); + + stm_spi2.cr2 = 0; + + /* clear any RXNE */ + (void) stm_spi2.dr; + + ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr); ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_SRX); - cli(); - for (;;) { - if (ao_radio_abort) - break; - if (ao_radio_wake) { - marc_status = ao_radio_marc_status(); - if (marc_status != CC1120_MARC_STATUS1_NO_FAILURE) - break; - ao_radio_wake = 0; - } + ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); +#if 1 + cli(); + while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); - } sei(); - if (marc_status != CC1120_MARC_STATUS1_RX_FINISHED) - ao_radio_fifo_read(d, size); + +#else + printf ("Hit a character to stop..."); flush(); + getchar(); + putchar('\n'); + ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); +#endif + ao_radio_burst_read_stop(); + + ao_radio_strobe(CC1120_SIDLE); + ao_radio_put(); - return marc_status == CC1120_MARC_STATUS1_RX_FINISHED; + + printf ("Received data:"); + for (i = 0; i < rx_data_cur; i++) { + if ((i & 15) == 0) + printf ("\n"); + printf (" %02x", rx_data[i]); + } + printf ("\n"); + return 1; } /* @@ -477,13 +558,6 @@ static const uint16_t radio_setup[] = { static uint8_t ao_radio_configured = 0; -static void -ao_radio_isr(void) -{ - ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_wake = 1; - ao_wakeup(&ao_radio_wake); -} static void ao_radio_setup(void) @@ -745,6 +819,12 @@ static void ao_radio_packet(void) { ao_radio_send(packet, sizeof (packet)); } +void +ao_radio_test_recv() +{ + ao_radio_recv(0, 34); +} + #endif static const struct ao_cmds ao_radio_cmds[] = { @@ -753,6 +833,7 @@ static const struct ao_cmds ao_radio_cmds[] = { { ao_radio_show, "R\0Show CC1120 status" }, { ao_radio_beep, "b\0Emit an RDF beacon" }, { ao_radio_packet, "p\0Send a test packet" }, + { ao_radio_test_recv, "q\0Recv a test packet" }, #endif { 0, NULL } }; @@ -776,7 +857,7 @@ ao_radio_init(void) /* Enable the EXTI interrupt for the appropriate pin */ ao_enable_port(AO_CC1120_INT_PORT); - ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_isr); + ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_tx_isr); ao_cmd_register(&ao_radio_cmds[0]); } diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index dc9c0d19..a2ac186b 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -44,9 +44,9 @@ main(void) ao_i2c_init(); ao_hmc5883_init(); ao_mpu6000_init(); - ao_flight_init(); - ao_log_init(); - ao_report_init(); +// ao_flight_init(); +// ao_log_init(); +// ao_report_init(); ao_telemetry_init(); ao_config_init(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 5c5c5972..9d9113c8 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -255,7 +255,7 @@ struct ao_adc { #define AO_MPU6000_INT_PIN 13 #define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) -#define HAS_HIGHG_ACCEL 1 +#define HAS_HIGHG_ACCEL 0 #define NUM_CMDS 16 diff --git a/src/stm/ao_exti.h b/src/stm/ao_exti.h index 43eaa52f..87a072e7 100644 --- a/src/stm/ao_exti.h +++ b/src/stm/ao_exti.h @@ -26,6 +26,9 @@ void ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)()); +void +ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()); + void ao_exti_enable(struct stm_gpio *gpio, uint8_t pin); diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index 0fa24188..683a91b3 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -94,6 +94,11 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback stm_nvic_set_enable(irq); } +void +ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()) { + ao_exti_callback[pin] = callback; +} + void ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) { uint32_t mask = (1 << pin); diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index c7509728..98067486 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -126,6 +126,156 @@ ao_random_data(uint8_t *out, uint8_t out_len) } +static uint8_t real_packet[] = { + 0x00, 0x40, 0x38, 0xcd, 0x38, 0x3d, 0x34, 0xca, 0x31, 0xc3, 0xc1, 0xc6, 0x35, 0xcc, 0x3a, 0x3c, + 0x3c, 0x3d, 0x3c, 0x37, 0xc5, 0xc1, 0xc0, 0xc1, 0xc1, 0xc3, 0xc0, 0xc1, 0xc6, 0x38, 0x3b, 0xc6, + 0xc0, 0xc6, 0x32, 0xc9, 0xc9, 0x34, 0xcf, 0x35, 0xcf, 0x3a, 0x3b, 0xc6, 0xc7, 0x35, 0xcf, 0x36, + 0xce, 0x37, 0xc8, 0xc8, 0x3a, 0x3c, 0xc9, 0xc8, 0x3a, 0x3c, 0xcc, 0x32, 0xcd, 0x32, 0xce, 0x32, + 0xc9, 0xc6, 0x37, 0x3e, 0x3d, 0xc8, 0xc3, 0xc6, 0x38, 0x3d, 0xcf, 0x34, 0x3d, 0x3b, 0xcb, 0x31, + 0xca, 0x35, 0x38, 0xcb, 0x31, 0xcc, 0x31, 0x3b, 0xc7, 0xbf, 0xbe, 0xbe, 0xc3, 0x35, 0x38, 0xcb, + 0x2f, 0xc9, 0xc2, 0x34, 0x3c, 0xcc, 0x31, 0xca, 0xc1, 0xc0, 0xc3, 0x33, 0x3f, 0x3f, 0x3e, 0x3c, + 0xcc, 0x31, 0xcc, 0xc3, 0xc4, 0x32, 0xd1, 0x34, 0x3f, 0x3c, 0xcc, 0x31, 0xcc, 0xc3, 0x33, 0xd0, + 0x31, 0xd1, 0x35, 0x3f, 0x3e, 0x3c, 0xca, 0xc5, 0x34, 0xcc, 0xc2, 0xc3, 0xc3, 0xc5, 0x36, 0x40, + 0x3e, 0x41, 0x3e, 0x41, 0x3e, 0x3f, 0x41, 0x40, 0xce, 0xc5, 0x33, 0xcf, 0xc7, 0x36, 0xd2, 0x32, + 0xd1, 0xc5, 0xc6, 0x35, 0xd4, 0x32, 0xd1, 0xc6, 0x34, 0x41, 0xd2, 0x30, 0xd0, 0xc2, 0xc2, 0xc5, + 0x31, 0xd3, 0x31, 0xd1, 0xc7, 0x33, 0xd4, 0xc6, 0x34, 0x42, 0x40, 0x40, 0x40, 0x41, 0x41, 0xd2, + 0xc4, 0xc4, 0x39, 0x3e, 0xce, 0x35, 0x3c, 0xcd, 0x31, 0x3d, 0xc8, 0xc3, 0x32, 0x3d, 0xcc, 0x2f, + 0xce, 0x30, 0xd0, 0x2e, 0xcf, 0x30, 0x3d, 0x3c, 0x3c, 0x3a, 0xcb, 0xbf, 0xbf, 0xc1, 0x31, 0x3d, + 0x3d, 0x3c, 0x3c, 0x3c, 0x3d, 0x3b, 0xcf, 0x2e, 0xd2, 0x2e, 0xd0, 0x2c, 0x3b, 0xd1, 0x2a, 0xcf, + 0xbe, 0xc0, 0xc0, 0xbf, 0xc1, 0xc1, 0x2c, 0x3f, 0xd0, 0xc0, 0x2e, 0xd0, 0x31, 0xd2, 0xc2, 0x2f, + 0x3e, 0x3e, 0x3d, 0xcf, 0x31, 0xcb, 0xc3, 0x32, 0xd1, 0xc4, 0x37, 0x3f, 0xce, 0xc4, 0x35, 0xd0, + 0x33, 0x3f, 0xce, 0x31, 0x3c, 0x3b, 0xcc, 0x31, 0xcd, 0x2f, 0xd1, 0x32, 0x3a, 0x3b, 0xcb, 0xc1, + 0xc0, 0x32, 0x3e, 0x3e, 0x3c, 0x3d, 0x3d, 0xce, 0x2d, 0xcd, 0xc3, 0xc2, 0x30, 0x3d, 0xcf, 0xc1, + 0xc2, 0x30, 0xd0, 0xc4, 0x31, 0xd4, 0x30, 0x40, 0x3e, 0xd0, 0x2f, 0xd0, 0x2f, 0xd1, 0xc2, 0x2e, + 0xd4, 0x2e, 0x3f, 0xce, 0xc2, 0x34, 0x3e, 0x3f, 0xd0, 0x30, 0xcf, 0x31, 0x3d, 0x3d, 0xcc, 0x2d, + 0xcf, 0x2f, 0xcf, 0x2e, 0x3b, 0xcf, 0x2c, 0x3b, 0x3b, 0x3a, 0x3d, 0x38, 0xcc, 0x2d, 0x3b, 0xcc, + 0xbe, 0x2d, 0xd1, 0x2c, 0x3c, 0x3d, 0xce, 0xc0, 0x2d, 0xd1, 0x2f, 0x3f, 0x3f, 0x3c, 0x3f, 0x3e, + 0x3e, 0x3c, 0xd3, 0x2a, 0xd1, 0xc2, 0x2e, 0x3c, 0xd1, 0x2f, 0x3d, 0xd1, 0xbe, 0xc1, 0x2d, 0xd2, + 0x2d, 0x3d, 0x3d, 0x3b, 0xcd, 0x31, 0xcc, 0x31, 0xce, 0x2e, 0x3d, 0x3e, 0x3a, 0xcd, 0x2d, 0xcc, + 0xc1, 0xc1, 0xc3, 0x2e, 0x3f, 0x3f, 0x3c, 0xcf, 0xc0, 0x31, 0xd1, 0xc2, 0xc3, 0x33, 0xd2, 0xc7, + 0x32, 0x40, 0xd3, 0xc4, 0xc4, 0x33, 0x40, 0x40, 0xd2, 0x2f, 0xd0, 0x2f, 0x3c, 0xd1, 0x2c, 0x3a, + 0x3d, 0xd0, 0x2a, 0xd0, 0x28, 0xcf, 0xc3, 0x2c, 0xd2, 0x2d, 0xd3, 0xc3, 0xc3, 0x2e, 0x3e, 0x41, + 0xd2, 0xc3, 0xc2, 0xc2, 0xc2, 0xc2, 0xc4, 0x32, 0xd2, 0x34, 0x3e, 0x3e, 0x3c, 0xd1, 0x30, 0x3d, + 0x3c, 0xce, 0x2e, 0x3b, 0x38, 0xcb, 0xbe, 0xc1, 0x2e, 0x3e, 0x3c, 0x3d, 0xd1, 0x2c, 0x3b, 0x3b, + 0xcd, 0xbf, 0x2d, 0xd0, 0x2f, 0xd0, 0x2d, 0xd1, 0x2d, 0x3d, 0xd0, 0x2b, 0x3b, 0xcf, 0x2b, 0x3a, + 0xcc, 0xbc, 0xc1, 0x2a, 0x3c, 0xce, 0x28, 0xd1, 0x2a, 0x3c, 0x3a, 0xcf, 0xbf, 0x2b, 0x3e, 0x3c, + 0xd2, 0x2b, 0x3d, 0x3a, 0x3a, 0xcf, 0x2c, 0xcc, 0xbe, 0xc1, 0xc0, 0xbf, 0xc1, 0x31, 0x3c, 0xce, + 0xc0, 0xc1, 0xc0, 0xc1, 0x31, 0x3c, 0xd1, 0xc2, 0x2e, 0xd1, 0xc3, 0xc4, 0x30, 0x3f, 0xd3, 0x2c, + 0xd3, 0xc2, 0x30, 0xd5, 0xc3, 0xc5, 0x30, 0xd5, 0xc4, 0xc5, 0xc5, 0x31, 0x41, 0xd4, 0xc4, 0x31, + 0x40, 0xd4, 0x2d, 0xd5, 0xc0, 0xc3, 0x2c, 0x3f, 0x3e, 0x3f, 0x3f, 0x3f, 0xd6, 0x2c, 0x3e, 0xd2, + 0x27, 0x37, 0xde, 0xc9, 0xe9, 0x2e, 0xc7, 0x3c, 0xd9, 0x07, 0xf3, 0x28, 0x8d, 0xa5, 0xc9, 0xca, + 0xe7, 0xcb, 0xfc, 0xb3, 0x3c, 0xd4, 0xd3, 0x9a, 0xe7, 0x2c, 0xc8, 0xf8, 0x44, 0xb3, 0xb0, 0xfa, + 0x1c, 0xbf, 0xc9, 0xff, 0xbb, 0x1d, 0x02, 0xdb, 0x45, 0xc1, 0x40, 0x1c, 0xec, 0x48, 0xda, 0x21, + 0x4c, 0xe3, 0x38, 0xdf, 0x34, 0xd8, 0x35, 0xd8, 0x31, 0xd7, 0x30, 0xd4, 0x2f, 0xd6, 0x2d, 0xd5, + 0x2b, 0xd5, 0x33, 0xce, 0x33, 0xce, 0x33, 0xd0, 0x34, 0xcf, 0x31, 0xcf, 0x30, 0xce, 0x30, 0xcf, + 0x30, 0x3d, 0xce, 0x2f, 0xcf, 0xc2, 0x30, 0x3f, 0x3d, 0xcf, 0xc1, 0x31, 0xd0, 0xc5, 0xc4, 0x33, + 0x41, 0x3e, 0xd1, 0x30, 0x3c, 0x3d, 0xce, 0x2f, 0xce, 0xc1, 0xc3, 0x2e, 0xd3, 0x30, 0x3e, 0x3e, + 0x3c, 0x3f, 0x3c, 0xd1, 0xc0, 0xc0, 0xc0, 0xc1, 0xc2, 0xc0, 0xc1, 0xc3, 0x2c, 0x3f, 0xd2, 0xbe, + 0xc1, 0x2e, 0xcf, 0xc4, 0x33, 0xd3, 0x34, 0xd0, 0x33, 0x3d, 0xcf, 0xc3, 0x32, 0xce, 0x33, 0xd2, + 0x32, 0xce, 0xc5, 0x34, 0x40, 0xce, 0xc5, 0x32, 0x3e, 0xd0, 0x31, 0xd0, 0x2f, 0xd2, 0x30, 0xce, + 0xc2, 0x33, 0x40, 0x3e, 0xd0, 0xc3, 0xc2, 0x2e, 0xd3, 0x31, 0xd0, 0xc7, 0x32, 0x40, 0x3e, 0xd3, + 0x2f, 0xd3, 0x2e, 0xd0, 0x2d, 0xd3, 0x2d, 0xd3, 0x2f, 0x3c, 0x3d, 0xd1, 0x2a, 0x3b, 0xd1, 0x28, + 0x3b, 0x3b, 0xc8, 0x31, 0x39, 0x3b, 0x38, 0xc6, 0xbf, 0x31, 0x3d, 0x3a, 0xca, 0xc0, 0x33, 0x3c, + 0xca, 0xc0, 0xc1, 0xc1, 0xc2, 0x35, 0x3e, 0x3c, 0x3d, 0x3f, 0xcc, 0xc0, 0xc3, 0x31, 0xce, 0xc5, + 0x33, 0xd0, 0xc4, 0x35, 0xd3, 0x33, 0xd3, 0x32, 0xd1, 0xc4, 0xc3, 0x35, 0xd3, 0xc6, 0xc4, 0x35, + 0xd2, 0xc6, 0x35, 0x41, 0x41, 0xd4, 0x33, 0xd1, 0xc4, 0x30, 0x41, 0xd2, 0x30, 0x3e, 0xce, 0xc1, + 0xc3, 0xc0, 0x31, 0xce, 0xc5, 0x34, 0x40, 0x3d, 0xd1, 0xc4, 0x32, 0x3e, 0xcf, 0xc2, 0xc3, 0x30, + 0xd4, 0x32, 0x3e, 0x3f, 0x3e, 0x3f, 0x3e, 0xd0, 0xc2, 0x31, 0x3e, 0x3f, 0x3f, 0xd1, 0xc2, 0x2f, + 0xd5, 0x2e, 0xd3, 0xc3, 0x2f, 0xd7, 0x30, 0x3e, 0xd2, 0x2c, 0x3e, 0x3c, 0xd0, 0xc1, 0xc1, 0xc3, + 0xc0, 0xc3, 0x2c, 0xd4, 0xc2, 0x2e, 0x40, 0xd2, 0xc3, 0x2d, 0xd5, 0xc3, 0x2f, 0x42, 0x40, 0xd6, + 0x2d, 0xd4, 0xc2, 0xc2, 0xc2, 0x32, 0xd4, 0xc3, 0xc5, 0xc4, 0x32, 0x40, 0xd3, 0x30, 0xd0, 0xc3, + 0xc4, 0x30, 0xd3, 0xc5, 0xc5, 0xc4, 0xc4, 0x33, 0x40, 0x40, 0xd4, 0x2f, 0xd2, 0x2d, 0x3d, 0xd1, + 0xc1, 0xc2, 0x2c, 0xd4, 0x2e, 0xd4, 0x2d, 0x3d, 0xd3, 0xc1, 0xc1, 0xc1, 0x2d, 0xd5, 0xc2, 0xc2, + 0xc2, 0x2d, 0xd9, 0xc4, 0xc5, 0x2f, 0x43, 0x40, 0xd6, 0xd7, 0xd7, 0x2b, 0x3e, 0xd5, 0x29, 0x3d, + 0xd4, 0x24, 0x3b, 0x3a, 0x3b, 0xce, 0x2a, 0x3a, 0xcc, 0xbe, 0x2d, 0x3b, 0x3b, 0x3d, 0x3b, 0x3b, + 0xce, 0x2b, 0x3a, 0xcc, 0x2b, 0xd0, 0x2b, 0x3b, 0x3b, 0x39, 0xcf, 0xbf, 0x2a, 0xd1, 0xc0, 0x2f, + 0x3e, 0xd0, 0x2d, 0x3a, 0xd1, 0xbe, 0x2b, 0xd2, 0xc3, 0xc2, 0xc0, 0x2d, 0xd7, 0x2c, 0xd7, 0xc2, + 0xc3, 0x2f, 0x43, 0x41, 0x40, 0xd4, 0xc3, 0xc3, 0xc3, 0xc2, 0x2c, 0x40, 0xd7, 0x2a, 0x3d, 0xd3, + 0x26, 0xd5, 0x2f, 0x3a, 0x3c, 0xca, 0xc3, 0x2c, 0xd3, 0x2e, 0x3c, 0x3d, 0x3d, 0x3d, 0xd0, 0xc2, + 0x2e, 0xd3, 0x2e, 0xd1, 0xc5, 0x2e, 0x3f, 0xd3, 0x2e, 0x3c, 0xd1, 0xc0, 0xc2, 0x2a, 0xd2, 0xc2, + 0xc4, 0x2e, 0xd7, 0x2e, 0x3e, 0xd3, 0xc1, 0xc3, 0xc1, 0x2d, 0x3f, 0xd3, 0xc2, 0x2c, 0x3f, 0xd3, + 0x2b, 0x3b, 0xd1, 0xbf, 0xc1, 0xbe, 0x29, 0x3f, 0xd4, 0x29, 0xd5, 0xbf, 0x29, 0xd7, 0xc0, 0x2d, + 0xd8, 0xc2, 0x33, 0x41, 0xd3, 0x30, 0x3d, 0xd0, 0x2c, 0xcf, 0xc1, 0xc1, 0xc2, 0x2e, 0x3f, 0xd3, + 0x2b, 0xcf, 0xc3, 0x2f, 0x40, 0x3f, 0x3e, 0xd3, 0x2a, 0x3d, 0x3d, 0xce, 0xc1, 0x2b, 0x3d, 0xd0, + 0x2b, 0xd3, 0x2b, 0x3b, 0x3d, 0xce, 0x29, 0x3b, 0x3b, 0x3b, 0xd1, 0xbe, 0x2b, 0xd2, 0x29, 0x3d, + 0x3a, 0xd3, 0x29, 0x3a, 0x3b, 0x3b, 0xd2, 0x26, 0x3b, 0xd0, 0xbf, 0xbe, 0xbc, 0xbf, 0xbe, 0xbc, + 0x27, 0x3d, 0x3a, 0x3c, 0xce, 0xc1, 0x2c, 0xd2, 0xc2, 0xc2, 0x2f, 0x40, 0xd2, 0xc2, 0xc2, 0x2e, + 0x40, 0xd4, 0x2a, 0x3b, 0xcf, 0x2b, 0xd2, 0x2a, 0x3c, 0xd0, 0xc1, 0x2a, 0x3d, 0xd0, 0xc1, 0xc0, + 0xbe, 0x2b, 0x3f, 0x3e, 0xd2, 0xc1, 0xc0, 0xc1, 0xc0, 0xc2, 0x2a, 0xd6, 0xc2, 0xc3, 0xc3, 0xc3, + 0x2c, 0x3e, 0x41, 0xd6, 0xc0, 0xc3, 0xc2, 0xc2, 0x2a, 0xd9, 0x28, 0x3f, 0xd5, 0xc1, 0xc2, 0xc0, + 0xc3, 0x28, 0xd5, 0xc2, 0xc5, 0x30, 0xd6, 0xc4, 0xc5, 0xc5, 0x31, 0x43, 0xd4, 0xc3, 0xc5, 0xc2, + 0xc2, 0x2f, 0xd6, 0xc5, 0xc2, 0x2d, 0x41, 0x41, 0x43, 0x40, 0x41, 0xd8, 0x2a, 0x3f, 0x3f, 0x3e, + 0x2c, 0x0a, 0x0d, 0x2a, 0xbb, 0x91, 0x5e, 0x2a, 0xca, 0x23, 0xf0, 0x0f, 0xbe, 0xd6, 0xfb, 0xc0, + 0x2c, 0x34, 0x7f, 0xd1, 0xc9, 0xc1, 0x1c, 0x06, 0x97, 0x1f, 0x21, 0xa8, 0x04, 0x5d, 0x07, 0xb0, + 0x49, 0xaf, 0x10, 0x60, 0xd1, 0xf1, 0xf3, 0xcb, 0x72, 0x16, 0x24, 0xe9, 0xd4, 0x28, 0xb2, 0x8c, + 0xf3, 0x3b, 0xe8, 0x06, 0xeb, 0x09, 0xec, 0x0a, 0xec, 0x0b, 0xee, 0x0b, 0xee, 0x0b, 0xf0, 0x0b, + 0xf0, 0x0a, 0xf3, 0x0b, 0xf2, 0x0a, 0xf5, 0x08, 0xf5, 0x0a, 0xf4, 0x08, 0xf5, 0x08, 0xf5, 0x09, + 0xf4, 0x07, 0x3f, 0xf5, 0x05, 0xf6, 0xbf, 0x06, 0x3f, 0x3f, 0xf8, 0xbe, 0x07, 0xf8, 0xc3, 0xc3, + 0x06, 0x41, 0x40, 0xf0, 0x0f, 0x3c, 0x3d, 0xef, 0x0e, 0xee, 0xbe, 0xbf, 0x11, 0xf2, 0x0e, 0x3e, + 0x3c, 0x3f, 0x3e, 0x3e, 0xf0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc3, 0xc0, 0xc1, 0xc1, 0x0b, 0x3f, 0xf5, + 0xc0, 0xc0, 0x08, 0xf7, 0xc2, 0x0c, 0xf6, 0x0d, 0xf9, 0x0a, 0x3f, 0xf9, 0xc0, 0x0b, 0xf6, 0x06, + 0xf8, 0x06, 0xf9, 0xc3, 0x08, 0x40, 0xfa, 0xc2, 0x09, 0x3e, 0xf7, 0x05, 0xf6, 0x04, 0xf7, 0x05, + 0xf8, 0xc1, 0xc3, 0xc1, 0x0a, 0x3e, 0x41, 0xf6, 0x07, 0xf7, 0x08, 0xf6, 0x07, 0x3e, 0x3c, 0x3f, + 0xf4, 0xbf, 0xbe, 0x06, 0xf8, 0x07, 0xf8, 0x05, 0xfb, 0xc0, 0xc1, 0x02, 0x40, 0x40, 0x3e, 0xfb, + 0x02, 0x3e, 0x3e, 0xf6, 0x01, 0xf9, 0x00, 0x3f, 0xf8, 0xbd, 0x02, 0xfc, 0xc1, 0xc0, 0x03, 0xfe, + 0xc5, 0xc4, 0xc2, 0xc5, 0xc2, 0x02, 0x41, 0x40, 0x40, 0x41, 0x40, 0xff, 0xff, 0x40, 0xfd, 0xfd, + 0xfc, 0xfd, 0x3e, 0xfc, 0xbe, 0xbf, 0xfe, 0xfc, 0xc1, 0xc0, 0xc1, 0xc1, 0x00, 0x01, 0x01, 0x02, + 0xc0, 0x00, 0x02, 0xc3, 0xc5, 0x02, 0x07, 0xc4, 0xc6, 0xc4, 0x02, 0x06, 0xc3, 0x01, 0x43, 0x43, + 0x42, 0x05, 0xfc, 0x04, 0xfd, 0x41, 0x3e, 0x05, 0xbf, 0xfb, 0x41, 0x3e, 0x3e, 0x3f, 0x3f, 0x40, + 0x02, 0xf9, 0x3e, 0x03, 0xbf, 0xbe, 0xf6, 0x3f, 0x05, 0xf6, 0x3c, 0x05, 0xbd, 0xbf, 0xbe, 0xf2, + 0x3f, 0x3c, 0x3d, 0x3e, 0x08, 0xee, 0x3d, 0x3b, 0x07, 0xbd, 0xf3, 0x0e, 0xc0, 0xc0, 0xf2, 0x0f, + 0xf2, 0x40, 0x0d, 0xef, 0x3f, 0x3e, 0x0a, 0xbf, 0xf0, 0x0e, 0xf1, 0x40, 0x0a, 0xef, 0x0e, 0xc1, + 0xc0, 0xc1, 0xc2, 0xc0, 0xee, 0x13, 0xc1, 0xee, 0x43, 0x10, 0xea, 0x15, 0xc0, 0xc0, 0xc0, 0xc3, + 0xc0, 0xec, 0x15, 0xc2, 0xf0, 0x16, 0xc2, 0xef, 0x1b, 0xc2, 0xf1, 0x44, 0x42, 0x19, 0xc2, 0xc3, + 0xed, 0x17, 0xe7, 0x21, 0xe4, 0x40, 0x3f, 0x20, 0xc0, 0xe2, 0x40, 0x3e, 0x1d, 0xc1, 0xc2, 0xc0, + 0xe2, 0x20, 0xe2, 0x3f, 0x3f, 0x3e, 0x1c, 0xdf, 0x3c, 0x3f, 0x1e, 0xbf, 0xc1, 0xbe, 0xdf, 0x3e, + 0x3d, 0x1f, 0xdc, 0x3c, 0x3b, 0x3d, 0x3a, 0x3d, 0x1f, 0xdb, 0x1e, 0xda, 0x20, 0xda, 0x21, 0xc1, + 0xc0, 0xc1, 0xdc, 0x3e, 0x23, 0xda, 0x3e, 0x20, 0xbf, 0xbd, 0xdb, 0x23, 0xbf, 0xdf, 0x26, 0xdc, + 0x26, 0xdc, 0x2e, 0xc2, 0xc3, 0xc3, 0xd4, 0x40, 0x2f, 0xc2, 0xd2, 0x3f, 0x3f, 0x3f, 0x2e, 0xd1, + 0x2d, 0xd3, 0x2c, 0xc3, 0xc3, 0xc3, 0xc2, 0xc3, 0xc2, 0xd3, 0x3e, 0x31, 0xd0, 0x2d, 0xc3, 0xc0, + 0xc1, 0xd1, 0x2f, 0xd3, 0x3f, 0x3f, 0x31, 0xc1, 0xcf, 0x31, 0xd2, 0x3e, 0x3f, 0x3c, 0x41, 0x3e, + 0x3e, 0x3f, 0x31, 0xd1, 0x30, 0xc0, 0xcf, 0x33, 0xd1, 0x3d, 0x41, 0x32, 0xc0, 0xc3, 0xce, 0x3e, + 0x32, 0xc3, 0xc3, 0xc2, 0xc0, 0xc3, 0xca, 0x3c, 0x37, 0xc5, 0xc3, 0xca, 0x34, 0xcf, 0x35, 0xc6, + 0xca, 0x3c, 0x39, 0xce, 0x3c, 0x37, 0xc2, 0xc8, 0x3c, 0x36, 0xcc, 0x30, 0xcb, 0x33, 0xc6, 0xc3, + 0xc8, 0x34, 0xcc, 0x3d, 0x37, 0xc5, 0xc9, 0x38, 0xc6, 0xca, 0x3b, 0x40, 0x40, 0x40, 0x3a, 0xc5, + 0xc8, 0x3f, 0x3e, 0x3b, 0xce, 0x3a, 0x3e, 0x38, 0xca, 0x39, 0x3c, 0x3c, 0x36, 0xcb, 0x36, 0x3b, + 0x37, 0xc8, 0x35, 0x3a, 0x36, 0xc8, 0x2f, 0xc4, 0xc5, 0x36, 0x38, 0xc7, 0xc0, 0xc7, 0x33, 0xc8, + 0xc3, 0xc5, 0x39, 0x3b, 0xc9, 0xc7, 0x34, 0xd1, 0x34, 0xcf, 0x35, 0xca, 0xc9, 0x36, 0xd0, 0x36, + 0xcc, 0xc7, 0x39, 0x41, 0x42, 0x42, 0x3e, 0xca, 0xc1, 0xc3, 0xc3, 0xc2, 0xc3, 0xc2, 0xc4, 0xc6, + 0x34, 0xd1, 0x35, 0xcf, 0x37, 0x3c, 0xce, 0x35, 0x3b, 0xcc, 0x30, 0xca, 0x33, 0x39, 0xc9, 0xbf, + 0xbf, 0xbf, 0xc3, 0x34, 0x3c, 0x3f, 0x3a, 0xcc, 0x2f, 0xcd, 0x32, 0x3c, 0x3a, 0xc8, 0xc2, 0x34, + 0x3a, 0xcb, 0xc0, 0xc0, 0x35, 0x3c, 0xce, 0x32, 0x3c, 0x3c, 0x3d, 0x3a, 0xcd, 0x2e, 0x3b, 0x39, + 0xc9, 0xbc, 0xbf, 0x30, 0xcc, 0xc0, 0xc3, 0x33, 0xce, 0xc5, 0xc2, 0xc4, 0x36, 0x3e, 0xd1, 0xc3, + 0xc2, 0xc3, 0xc5, 0x33, 0xd0, 0xc5, 0xc4, 0x35, 0x40, 0x40, 0x3e, 0x41, 0x3e, 0xd2, 0x30, 0x3f, + 0x3e, 0x3d, 0x21, 0xc8, 0x0d, 0x23, 0xec, 0xb1, 0x1a, 0xf0, 0xf3, 0x10, 0xc6, 0xbd, 0x5b, 0x0d, + 0xff, 0xe2, 0xe6, 0xd4, 0x72, 0xe2, 0xda, 0x0c, 0xf8, 0x1b, 0x04, 0x0b, 0xf7, 0xb4, 0xf0, 0x44, + 0xcd, 0xaf, 0x12, 0x1f, 0x11, 0xa1, 0x29, 0xb8, 0x1a, 0xdb, 0x09, 0x69, 0xf7, 0x20, 0xc4, 0x1c, + 0xc0, 0xc8, 0x1d, 0x45, 0xd9, 0x30, 0xd8, 0x2e, 0xd8, 0x2e, 0xd6, 0x2c, 0xd5, 0x2d, 0xd4, 0x2b, + 0xd5, 0x2b, 0xd1, 0x31, 0xd0, 0x32, 0xd2, 0x30, 0xd0, 0x31, 0xd0, 0x31, 0xce, 0x2f, 0xd3, 0x2e, + 0xce, 0x2f, 0xd1, 0x31, 0x3c, 0xd1, 0x2d, 0xd0, 0xc0, 0x2e, 0x3c, 0x3d, 0xd1, 0xc3, 0x2c, 0xd2, + 0xc3, 0xc5, 0x31, 0x40, 0x40, 0xd5, 0x2c, 0x3a, 0x3d, 0xd0, 0x2b, 0xd3, 0xc0, 0xc0, 0x2d, 0xd4, + 0x2c, 0x3f, 0x3e, 0x3c, 0x3f, 0x3c, 0xd2, 0xc1, 0xc2, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0x2a, +}; + + +void +ao_real_packet(void) +{ + uint8_t decode[64]; + uint8_t decode_len; + int off; + + for (off = 0; off < sizeof (real_packet) - 576; off++) { + decode_len = ao_fec_decode(real_packet+off, 576, decode); + + if (ao_fec_check_crc(decode, 32)) { + printf ("match at %d\n", off); + + ao_fec_dump_bytes(decode, decode_len, "Decode"); + } + } +} + int main(int argc, char **argv) { @@ -149,6 +299,7 @@ main(int argc, char **argv) int errors = 0; int error; + ao_real_packet(); exit(0); srandom(0); for (trial = 0; trial < 10000; trial++) { -- cgit v1.2.3 From 628076aa90e7bc9a894646e417dd8e1fe149b60d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jun 2012 06:38:34 -0700 Subject: altos: decode cc1120 received packets Call the fec decode function, compute RSSI and check CRC Signed-off-by: Keith Packard --- src/core/ao_fec.h | 2 +- src/core/ao_viterbi.c | 7 +++++-- src/drivers/ao_cc1120.c | 47 ++++++++++++++++++++++++++--------------------- 3 files changed, 32 insertions(+), 24 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index f3f55fa8..e3c55d6e 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -67,7 +67,7 @@ ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); */ uint8_t -ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out); +ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len); /* * Interleave data packed in bytes. 'out' must be 'len' bytes long. diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 594c0d91..77681556 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -91,7 +91,7 @@ ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) */ uint8_t -ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) +ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len) { static uint16_t cost[2][NUM_STATE]; /* path cost */ static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ @@ -203,7 +203,10 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n", i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); #endif - *out++ = (bits[p][min_state] >> dist) ^ *whiten++; + if (out_len) { + *out++ = (bits[p][min_state] >> dist) ^ *whiten++; + --out_len; + } o += 8; } } diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 4378716d..b42ca54c 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -401,12 +401,12 @@ ao_radio_send(void *d, uint8_t size) static uint8_t rx_data[2048]; static uint16_t rx_data_count; static uint16_t rx_data_cur; -static uint8_t rx_started; +static uint8_t rx_ignore; static void ao_radio_rx_isr(void) { - if (rx_started) { + if (rx_ignore == 0) { rx_data[rx_data_cur++] = stm_spi2.dr; if (rx_data_cur >= rx_data_count) { ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); @@ -415,7 +415,7 @@ ao_radio_rx_isr(void) } } else { (void) stm_spi2.dr; - rx_started = 1; + --rx_ignore; } stm_spi2.dr = 0x00; } @@ -423,12 +423,17 @@ ao_radio_rx_isr(void) uint8_t ao_radio_recv(__xdata void *d, uint8_t size) { - uint8_t len = ((size - 2) + 4) * 2; /* two bytes for status */ + uint8_t len; uint16_t i; + uint8_t rssi; - rx_data_count = sizeof (rx_data); + size -= 2; /* status bytes */ + len = size + 2; /* CRC bytes */ + len += 1 + ~(len & 1); /* 1 or two pad bytes */ + len *= 2; /* 1/2 rate convolution */ + rx_data_count = len * 8; /* bytes to bits */ rx_data_cur = 0; - rx_started = 0; + rx_ignore = 2; printf ("len %d rx_data_count %d\n", len, rx_data_count); @@ -456,31 +461,31 @@ ao_radio_recv(__xdata void *d, uint8_t size) ao_radio_strobe(CC1120_SRX); ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); -#if 1 cli(); while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); sei(); - -#else - printf ("Hit a character to stop..."); flush(); - getchar(); - putchar('\n'); - ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); -#endif ao_radio_burst_read_stop(); + /* Convert from 'real' rssi to cc1111-style values */ + + rssi = (((int8_t) ao_radio_reg_read(CC1120_RSSI1)) + 74) * 2; + ao_radio_strobe(CC1120_SIDLE); ao_radio_put(); - printf ("Received data:"); - for (i = 0; i < rx_data_cur; i++) { - if ((i & 15) == 0) - printf ("\n"); - printf (" %02x", rx_data[i]); - } - printf ("\n"); + /* Construct final packet */ + + ao_fec_decode(rx_data, rx_data_cur, d, size + 2); + + if (ao_fec_check_crc(d, size)) + ((uint8_t *) d)[size + 1] = 0x80; + else + ((uint8_t *) d)[size + 1] = 0x00; + + ((uint8_t *) d)[size] = (uint8_t) rssi; + return 1; } -- cgit v1.2.3 From 09761fe0f6ed40ff74317fbb47d6a74068fb4ce4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jun 2012 06:51:36 -0700 Subject: altos: Incremental viterbi decode Decode radio input one interleave block at a time. This overlaps the decode computation with the packet reception, leading to lower latency in an attempt to keep up with the transmitter. Signed-off-by: Keith Packard --- src/core/ao_fec.h | 4 +++- src/core/ao_viterbi.c | 14 +++++++++++++- src/drivers/ao_cc1120.c | 28 +++++++++++++++++++++------- src/test/ao_fec_test.c | 4 ++-- 4 files changed, 39 insertions(+), 11 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index e3c55d6e..4fd398eb 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -66,8 +66,10 @@ ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); * 'out' must be len/8 bytes long */ +#define AO_FEC_DECODE_BLOCK (8 * 32) /* callback must return multiples of this many bits */ + uint8_t -ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len); +ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()); /* * Interleave data packed in bytes. 'out' must be 'len' bytes long. diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 77681556..69e9c1f5 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -91,7 +91,7 @@ ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) */ uint8_t -ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len) +ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) { static uint16_t cost[2][NUM_STATE]; /* path cost */ static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ @@ -105,6 +105,7 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len) const uint8_t *whiten = ao_fec_whiten_table; uint16_t interleave; /* input byte array index */ struct ao_soft_sym s; /* input symbol pair */ + uint16_t avail; p = 0; for (state = 0; state < NUM_STATE; state++) { @@ -113,11 +114,22 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len) } cost[0][0] = 0; + if (callback) + avail = 0; + else + avail = len; + o = 0; for (i = 0; i < len; i += 2) { b = i/2; n = p ^ 1; + if (!avail) { + avail = callback(); + if (!avail) + break; + } + /* Fetch one pair of input bytes, de-interleaving * the input. */ diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index b42ca54c..394cf7c5 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -400,6 +400,7 @@ ao_radio_send(void *d, uint8_t size) static uint8_t rx_data[2048]; static uint16_t rx_data_count; +static uint16_t rx_data_consumed; static uint16_t rx_data_cur; static uint8_t rx_ignore; @@ -408,9 +409,9 @@ ao_radio_rx_isr(void) { if (rx_ignore == 0) { rx_data[rx_data_cur++] = stm_spi2.dr; - if (rx_data_cur >= rx_data_count) { + if (rx_data_cur >= rx_data_count) ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_wake = 1; + if (rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) { ao_wakeup(&ao_radio_wake); } } else { @@ -420,6 +421,19 @@ ao_radio_rx_isr(void) stm_spi2.dr = 0x00; } +static uint16_t +ao_radio_rx_wait(void) +{ + cli(); + while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK && + !ao_radio_abort) + ao_sleep(&ao_radio_wake); + sei(); + if (ao_radio_abort) + return 0; + return AO_FEC_DECODE_BLOCK; +} + uint8_t ao_radio_recv(__xdata void *d, uint8_t size) { @@ -433,6 +447,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) len *= 2; /* 1/2 rate convolution */ rx_data_count = len * 8; /* bytes to bits */ rx_data_cur = 0; + rx_data_consumed = 0; rx_ignore = 2; printf ("len %d rx_data_count %d\n", len, rx_data_count); @@ -461,10 +476,9 @@ ao_radio_recv(__xdata void *d, uint8_t size) ao_radio_strobe(CC1120_SRX); ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); - cli(); - while (!ao_radio_wake && !ao_radio_abort) - ao_sleep(&ao_radio_wake); - sei(); + + ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait); + ao_radio_burst_read_stop(); /* Convert from 'real' rssi to cc1111-style values */ @@ -477,7 +491,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) /* Construct final packet */ - ao_fec_decode(rx_data, rx_data_cur, d, size + 2); + ao_fec_decode(rx_data, rx_data_cur, d, size + 2, 0); if (ao_fec_check_crc(d, size)) ((uint8_t *) d)[size + 1] = 0x80; diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index 98067486..e8d3d8b1 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -266,7 +266,7 @@ ao_real_packet(void) int off; for (off = 0; off < sizeof (real_packet) - 576; off++) { - decode_len = ao_fec_decode(real_packet+off, 576, decode); + decode_len = ao_fec_decode(real_packet+off, 576, decode, 34, NULL); if (ao_fec_check_crc(decode, 32)) { printf ("match at %d\n", off); @@ -317,7 +317,7 @@ main(int argc, char **argv) receive_len = transmit_len; /* Decode it */ - decode_len = ao_fec_decode(receive, receive_len, decode); + decode_len = ao_fec_decode(receive, receive_len, decode, original_len + 2, NULL); /* Check to see if we received the right data */ error = 0; -- cgit v1.2.3 From eab18714ed9eabbcef0ff81b07427da042a58ccc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 22:16:44 -0700 Subject: altos: rename ao_viterbi.c to ao_fec_rx.c Keep it parallel with ao_fec_tx.c Signed-off-by: Keith Packard --- src/core/ao_fec_rx.c | 226 +++++++++++++++++++++++++++++++++++++++++++ src/core/ao_viterbi.c | 226 ------------------------------------------- src/megametrum-v0.1/Makefile | 2 +- src/test/Makefile | 4 +- 4 files changed, 229 insertions(+), 229 deletions(-) create mode 100644 src/core/ao_fec_rx.c delete mode 100644 src/core/ao_viterbi.c (limited to 'src/core') diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c new file mode 100644 index 00000000..69e9c1f5 --- /dev/null +++ b/src/core/ao_fec_rx.c @@ -0,0 +1,226 @@ +/* + * 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 + +/* + * byte order repeats through 3 2 1 0 + * + * bit-pair order repeats through + * + * 1/0 3/2 5/4 7/6 + * + * So, the over all order is: + * + * 3,1/0 2,1/0 1,1/0 0,1/0 + * 3,3/2 2,3/2 1,3/2 0,3/2 + * 3,5/4 2,5/4 1,5/4 0,5/4 + * 3,7/6 2,7/6 1,7/6 0,7/6 + * + * The raw bit order is thus + * + * 1e/1f 16/17 0e/0f 06/07 + * 1c/1d 14/15 0c/0d 04/05 + * 1a/1b 12/13 0a/0b 02/03 + * 18/19 10/11 08/09 00/01 + */ + +static inline uint16_t ao_interleave_index(uint16_t i) { + uint8_t l = i & 0x1e; + uint16_t h = i & ~0x1e; + uint8_t o = 0x1e ^ (((l >> 2) & 0x6) | ((l << 2) & 0x18)); + return h | o; +} + +struct ao_soft_sym { + uint8_t a, b; +}; + +#define NUM_STATE 8 +#define NUM_HIST 8 +#define MOD_HIST(b) ((b) & 7) + +#define V_0 0xc0 +#define V_1 0x40 + +static const struct ao_soft_sym ao_fec_decode_table[NUM_STATE][2] = { +/* next 0 1 state */ + { { V_0, V_0 }, { V_1, V_1 } } , /* 000 */ + { { V_0, V_1 }, { V_1, V_0 } }, /* 001 */ + { { V_1, V_1 }, { V_0, V_0 } }, /* 010 */ + { { V_1, V_0 }, { V_0, V_1 } }, /* 011 */ + { { V_1, V_1 }, { V_0, V_0 } }, /* 100 */ + { { V_1, V_0 }, { V_0, V_1 } }, /* 101 */ + { { V_0, V_0 }, { V_1, V_1 } }, /* 110 */ + { { V_0, V_1 }, { V_1, V_0 } } /* 111 */ +}; + +static inline uint8_t +ao_next_state(uint8_t state, uint8_t bit) +{ + return ((state << 1) | bit) & 0x7; +} + +static inline uint16_t ao_abs(int16_t x) { return x < 0 ? -x : x; } + +static inline uint16_t +ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) +{ + return ao_abs(a.a - b.a) + ao_abs(a.b - b.b); +} + +/* + * 'in' is 8-bits per symbol soft decision data + * 'len' is input byte length. 'out' must be + * 'len'/16 bytes long + */ + +uint8_t +ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) +{ + static uint16_t cost[2][NUM_STATE]; /* path cost */ + static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ + uint16_t i; /* input byte index */ + uint16_t b; /* encoded symbol index (bytes/2) */ + uint16_t o; /* output bit index */ + uint8_t p; /* previous cost/bits index */ + uint8_t n; /* next cost/bits index */ + uint8_t state; /* state index */ + uint8_t bit; /* original encoded bit index */ + const uint8_t *whiten = ao_fec_whiten_table; + uint16_t interleave; /* input byte array index */ + struct ao_soft_sym s; /* input symbol pair */ + uint16_t avail; + + p = 0; + for (state = 0; state < NUM_STATE; state++) { + cost[0][state] = 0xffff; + bits[0][state] = 0; + } + cost[0][0] = 0; + + if (callback) + avail = 0; + else + avail = len; + + o = 0; + for (i = 0; i < len; i += 2) { + b = i/2; + n = p ^ 1; + + if (!avail) { + avail = callback(); + if (!avail) + break; + } + + /* Fetch one pair of input bytes, de-interleaving + * the input. + */ + interleave = ao_interleave_index(i); + s.a = in[interleave]; + s.b = in[interleave+1]; + + /* Reset next costs to 'impossibly high' values so that + * the first path through this state is cheaper than this + */ + for (state = 0; state < NUM_STATE; state++) + cost[n][state] = 0xffff; + + /* Compute path costs and accumulate output bit path + * for each state and encoded bit value + */ + for (state = 0; state < NUM_STATE; state++) { + for (bit = 0; bit < 2; bit++) { + int bit_cost = cost[p][state] + ao_cost(s, ao_fec_decode_table[state][bit]); + uint8_t bit_state = ao_next_state(state, bit); + + /* Only track the minimal cost to reach + * this state; the best path can never + * go through the higher cost paths as + * total path cost is cumulative + */ + if (bit_cost < cost[n][bit_state]) { + cost[n][bit_state] = bit_cost; + bits[n][bit_state] = (bits[p][state] << 1) | (state & 1); + } + } + } + +#if 0 + printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); + for (state = 0; state < NUM_STATE; state++) { + printf (" %5d(%04x)", cost[n][state], bits[n][state]); + } + printf ("\n"); +#endif + p = n; + + /* A loop is needed to handle the last output byte. It + * won't have any bits of future data to perform full + * error correction, but we might as well give the + * best possible answer anyways. + */ + while ((b - o) >= (8 + NUM_HIST) || (i + 2 >= len && b > o)) { + + /* Compute number of bits to the end of the + * last full byte of data. This is generally + * NUM_HIST, unless we've reached + * the end of the input, in which case + * it will be seven. + */ + int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */ + uint16_t min_cost; /* lowest cost */ + uint8_t min_state; /* lowest cost state */ + + /* Find the best fit at the current point + * of the decode. + */ + min_cost = cost[p][0]; + min_state = 0; + for (state = 1; state < NUM_STATE; state++) { + if (cost[p][state] < min_cost) { + min_cost = cost[p][state]; + min_state = state; + } + } + + /* The very last byte of data has the very last bit + * of data left in the state value; just smash the + * bits value in place and reset the 'dist' from + * -1 to 0 so that the full byte is read out + */ + if (dist < 0) { + bits[p][min_state] = (bits[p][min_state] << 1) | (min_state & 1); + dist = 0; + } + +#if 0 + printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n", + i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); +#endif + if (out_len) { + *out++ = (bits[p][min_state] >> dist) ^ *whiten++; + --out_len; + } + o += 8; + } + } + return len/16; +} diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c deleted file mode 100644 index 69e9c1f5..00000000 --- a/src/core/ao_viterbi.c +++ /dev/null @@ -1,226 +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 - -/* - * byte order repeats through 3 2 1 0 - * - * bit-pair order repeats through - * - * 1/0 3/2 5/4 7/6 - * - * So, the over all order is: - * - * 3,1/0 2,1/0 1,1/0 0,1/0 - * 3,3/2 2,3/2 1,3/2 0,3/2 - * 3,5/4 2,5/4 1,5/4 0,5/4 - * 3,7/6 2,7/6 1,7/6 0,7/6 - * - * The raw bit order is thus - * - * 1e/1f 16/17 0e/0f 06/07 - * 1c/1d 14/15 0c/0d 04/05 - * 1a/1b 12/13 0a/0b 02/03 - * 18/19 10/11 08/09 00/01 - */ - -static inline uint16_t ao_interleave_index(uint16_t i) { - uint8_t l = i & 0x1e; - uint16_t h = i & ~0x1e; - uint8_t o = 0x1e ^ (((l >> 2) & 0x6) | ((l << 2) & 0x18)); - return h | o; -} - -struct ao_soft_sym { - uint8_t a, b; -}; - -#define NUM_STATE 8 -#define NUM_HIST 8 -#define MOD_HIST(b) ((b) & 7) - -#define V_0 0xc0 -#define V_1 0x40 - -static const struct ao_soft_sym ao_fec_decode_table[NUM_STATE][2] = { -/* next 0 1 state */ - { { V_0, V_0 }, { V_1, V_1 } } , /* 000 */ - { { V_0, V_1 }, { V_1, V_0 } }, /* 001 */ - { { V_1, V_1 }, { V_0, V_0 } }, /* 010 */ - { { V_1, V_0 }, { V_0, V_1 } }, /* 011 */ - { { V_1, V_1 }, { V_0, V_0 } }, /* 100 */ - { { V_1, V_0 }, { V_0, V_1 } }, /* 101 */ - { { V_0, V_0 }, { V_1, V_1 } }, /* 110 */ - { { V_0, V_1 }, { V_1, V_0 } } /* 111 */ -}; - -static inline uint8_t -ao_next_state(uint8_t state, uint8_t bit) -{ - return ((state << 1) | bit) & 0x7; -} - -static inline uint16_t ao_abs(int16_t x) { return x < 0 ? -x : x; } - -static inline uint16_t -ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) -{ - return ao_abs(a.a - b.a) + ao_abs(a.b - b.b); -} - -/* - * 'in' is 8-bits per symbol soft decision data - * 'len' is input byte length. 'out' must be - * 'len'/16 bytes long - */ - -uint8_t -ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) -{ - static uint16_t cost[2][NUM_STATE]; /* path cost */ - static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ - uint16_t i; /* input byte index */ - uint16_t b; /* encoded symbol index (bytes/2) */ - uint16_t o; /* output bit index */ - uint8_t p; /* previous cost/bits index */ - uint8_t n; /* next cost/bits index */ - uint8_t state; /* state index */ - uint8_t bit; /* original encoded bit index */ - const uint8_t *whiten = ao_fec_whiten_table; - uint16_t interleave; /* input byte array index */ - struct ao_soft_sym s; /* input symbol pair */ - uint16_t avail; - - p = 0; - for (state = 0; state < NUM_STATE; state++) { - cost[0][state] = 0xffff; - bits[0][state] = 0; - } - cost[0][0] = 0; - - if (callback) - avail = 0; - else - avail = len; - - o = 0; - for (i = 0; i < len; i += 2) { - b = i/2; - n = p ^ 1; - - if (!avail) { - avail = callback(); - if (!avail) - break; - } - - /* Fetch one pair of input bytes, de-interleaving - * the input. - */ - interleave = ao_interleave_index(i); - s.a = in[interleave]; - s.b = in[interleave+1]; - - /* Reset next costs to 'impossibly high' values so that - * the first path through this state is cheaper than this - */ - for (state = 0; state < NUM_STATE; state++) - cost[n][state] = 0xffff; - - /* Compute path costs and accumulate output bit path - * for each state and encoded bit value - */ - for (state = 0; state < NUM_STATE; state++) { - for (bit = 0; bit < 2; bit++) { - int bit_cost = cost[p][state] + ao_cost(s, ao_fec_decode_table[state][bit]); - uint8_t bit_state = ao_next_state(state, bit); - - /* Only track the minimal cost to reach - * this state; the best path can never - * go through the higher cost paths as - * total path cost is cumulative - */ - if (bit_cost < cost[n][bit_state]) { - cost[n][bit_state] = bit_cost; - bits[n][bit_state] = (bits[p][state] << 1) | (state & 1); - } - } - } - -#if 0 - printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); - for (state = 0; state < NUM_STATE; state++) { - printf (" %5d(%04x)", cost[n][state], bits[n][state]); - } - printf ("\n"); -#endif - p = n; - - /* A loop is needed to handle the last output byte. It - * won't have any bits of future data to perform full - * error correction, but we might as well give the - * best possible answer anyways. - */ - while ((b - o) >= (8 + NUM_HIST) || (i + 2 >= len && b > o)) { - - /* Compute number of bits to the end of the - * last full byte of data. This is generally - * NUM_HIST, unless we've reached - * the end of the input, in which case - * it will be seven. - */ - int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */ - uint16_t min_cost; /* lowest cost */ - uint8_t min_state; /* lowest cost state */ - - /* Find the best fit at the current point - * of the decode. - */ - min_cost = cost[p][0]; - min_state = 0; - for (state = 1; state < NUM_STATE; state++) { - if (cost[p][state] < min_cost) { - min_cost = cost[p][state]; - min_state = state; - } - } - - /* The very last byte of data has the very last bit - * of data left in the state value; just smash the - * bits value in place and reset the 'dist' from - * -1 to 0 so that the full byte is read out - */ - if (dist < 0) { - bits[p][min_state] = (bits[p][min_state] << 1) | (min_state & 1); - dist = 0; - } - -#if 0 - printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n", - i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); -#endif - if (out_len) { - *out++ = (bits[p][min_state] >> dist) ^ *whiten++; - --out_len; - } - o += 8; - } - } - return len/16; -} diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 857667b0..22a58ff4 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -48,7 +48,7 @@ ALTOS_SRC = \ ao_spi_stm.c \ ao_cc1120.c \ ao_fec_tx.c \ - ao_viterbi.c \ + ao_fec_rx.c \ ao_ms5607.c \ ao_adc_stm.c \ ao_beep_stm.c \ diff --git a/src/test/Makefile b/src/test/Makefile index cdcecd51..4631fb78 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -40,5 +40,5 @@ ao_convert_pa_test: ao_convert_pa_test.c ao_convert_pa.c altitude-pa.h ao_kalman.h: $(KALMAN) (cd .. && make ao_kalman.h) -ao_fec_test: ao_fec_test.c ao_fec_tx.c ao_viterbi.c - cc $(CFLAGS) -o $@ ao_fec_test.c ../core/ao_fec_tx.c ../core/ao_viterbi.c -lm +ao_fec_test: ao_fec_test.c ao_fec_tx.c ao_fec_rx.c + cc $(CFLAGS) -DAO_FEC_DEBUG=1 -o $@ ao_fec_test.c ../core/ao_fec_tx.c ../core/ao_fec_rx.c -lm -- cgit v1.2.3 From 33f8f7add27a02d24b0671da353b59762224c1ee Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:05:42 -0700 Subject: altos: Make cc1111 radio control functions static No need to publish these; they're all private to cc1111 Signed-off-by: Keith Packard --- src/cc1111/ao_radio.c | 8 +++++--- src/core/ao.h | 13 +------------ 2 files changed, 6 insertions(+), 15 deletions(-) (limited to 'src/core') diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 51ed369b..2c4a661e 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -260,7 +260,7 @@ ao_radio_general_isr(void) __interrupt 16 } } -void +static void ao_radio_set_packet(void) { uint8_t i; @@ -268,7 +268,7 @@ ao_radio_set_packet(void) RF[fixed_pkt_setup[i]] = fixed_pkt_setup[i+1]; } -void +static void ao_radio_idle(void) { if (RF_MARCSTATE != RF_MARCSTATE_IDLE) @@ -280,7 +280,9 @@ ao_radio_idle(void) } } -void +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) + +static void ao_radio_get(uint8_t len) { ao_config_get(); diff --git a/src/core/ao.h b/src/core/ao.h index 204c8530..c13029bf 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -505,15 +505,7 @@ void ao_radio_general_isr(void) ao_arch_interrupt(16); void -ao_radio_get(uint8_t len); - -#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) - -void -ao_radio_set_packet(void); - -void -ao_radio_send(__xdata void *d, uint8_t size) __reentrant; +ao_radio_send(const __xdata void *d, uint8_t size) __reentrant; uint8_t ao_radio_recv(__xdata void *d, uint8_t size) __reentrant; @@ -537,9 +529,6 @@ ao_radio_rdf(uint8_t pkt_len); void ao_radio_rdf_abort(void); -void -ao_radio_idle(void); - void ao_radio_init(void); -- cgit v1.2.3 From 936ecad62596f34773afb7460b10f63df7d0896d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:07:38 -0700 Subject: altos: Add GPS logging code for MegaMetrum MM uses a different logging format with larger log blocks, so restructure the GPS logging code to fill them up Signed-off-by: Keith Packard --- src/core/ao.h | 10 +++++ src/core/ao_gps_report_mega.c | 95 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 src/core/ao_gps_report_mega.c (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index c13029bf..62eb488e 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -396,6 +396,16 @@ ao_gps_report(void); void ao_gps_report_init(void); +/* + * ao_gps_report_mega.c + */ + +void +ao_gps_report_mega(void); + +void +ao_gps_report_mega_init(void); + /* * ao_telemetry_orig.c */ diff --git a/src/core/ao_gps_report_mega.c b/src/core/ao_gps_report_mega.c new file mode 100644 index 00000000..47891cab --- /dev/null +++ b/src/core/ao_gps_report_mega.c @@ -0,0 +1,95 @@ +/* + * Copyright © 2009 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" + +void +ao_gps_report_mega(void) +{ + static __xdata struct ao_log_mega gps_log; + static __xdata struct ao_telemetry_location gps_data; + uint8_t date_reported = 0; + + for (;;) { + ao_sleep(&ao_gps_data); + ao_mutex_get(&ao_gps_mutex); + ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); + ao_mutex_put(&ao_gps_mutex); + + if (!(gps_data.flags & AO_GPS_VALID)) + continue; + + gps_log.tick = ao_gps_tick; + gps_log.type = AO_LOG_GPS_TIME; + gps_log.u.gps.latitude = gps_data.latitude; + gps_log.u.gps.longitude = gps_data.longitude; + gps_log.u.gps.altitude = gps_data.altitude; + + gps_log.u.gps.hour = gps_data.hour; + gps_log.u.gps.minute = gps_data.minute; + gps_log.u.gps.second = gps_data.second; + gps_log.u.gps.flags = gps_data.flags; + gps_log.u.gps.year = gps_data.year; + gps_log.u.gps.month = gps_data.month; + gps_log.u.gps.day = gps_data.day; + ao_log_mega(&gps_log); + } +} + +void +ao_gps_tracking_report_mega(void) +{ + static __xdata struct ao_log_mega gps_log; + static __xdata struct ao_telemetry_satellite gps_tracking_data; + uint8_t c, n, i; + + for (;;) { + ao_sleep(&ao_gps_tracking_data); + ao_mutex_get(&ao_gps_mutex); + ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); + + if (!(n = gps_tracking_data.channels)) + continue; + + gps_log.type = AO_LOG_GPS_SAT; + gps_log.tick = ao_gps_tick; + i = 0; + for (c = 0; c < n; c++) + if ((gps_log.u.gps_sat.sats[i].svid = gps_tracking_data.sats[c].svid)) + { + gps_log.u.gps_sat.sats[i].c_n = gps_tracking_data.sats[c].c_n_1; + i++; + } + gps_log.u.gps_sat.channels = i; + ao_log_mega(&gps_log); + } +} + +__xdata struct ao_task ao_gps_report_mega_task; +__xdata struct ao_task ao_gps_tracking_report_mega_task; + +void +ao_gps_report_mega_init(void) +{ + ao_add_task(&ao_gps_report_mega_task, + ao_gps_report_mega, + "gps_report"); + ao_add_task(&ao_gps_tracking_report_mega_task, + ao_gps_tracking_report_mega, + "gps_tracking_report"); +} -- cgit v1.2.3 From f1ae622eff60e05c1f5d8f822a3cf6a85750c6cc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:11:10 -0700 Subject: altos: Optimize FEC encode and decode Integrate interleaving, CRC and padding within the decode/encode functions. Provide for ISR priorities so that the 1120 RX interrupt takes precedence over the other interrupts or we risk losing bits. Optimize the viterbi decoder a bit (goes from 10ms per packet to 7ms per packet). Signed-off-by: Keith Packard --- src/core/ao_fec.h | 46 ++-- src/core/ao_fec_rx.c | 145 ++++++++----- src/core/ao_fec_tx.c | 68 +----- src/drivers/ao_cc1120.c | 483 ++++++++++++++++++++++++++--------------- src/drivers/ao_cc1120.h | 9 + src/drivers/ao_cc1120_CC1120.h | 27 ++- src/stm/ao_arch.h | 23 +- src/stm/ao_exti.h | 3 + src/stm/ao_exti_stm.c | 73 ++++--- src/stm/ao_spi_stm.c | 6 +- src/stm/ao_timer.c | 2 +- src/test/ao_fec_test.c | 39 ++-- 12 files changed, 560 insertions(+), 364 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index 4fd398eb..f1192b62 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -26,11 +26,28 @@ extern const uint8_t ao_fec_whiten_table[]; +#if AO_FEC_DEBUG void -ao_fec_dump_bytes(uint8_t *bytes, uint16_t len, char *name); +ao_fec_dump_bytes(const uint8_t *bytes, uint16_t len, const char *name); +#endif + +static uint16_t inline +ao_fec_crc_byte(uint8_t byte, uint16_t crc) +{ + uint8_t bit; + + for (bit = 0; bit < 8; bit++) { + if (((crc & 0x8000) >> 8) ^ (byte & 0x80)) + crc = (crc << 1) ^ 0x8005; + else + crc = (crc << 1); + byte <<= 1; + } + return crc; +} uint16_t -ao_fec_crc(uint8_t *bytes, uint8_t len); +ao_fec_crc(const uint8_t *bytes, uint8_t len); /* * 'len' is the length of the original data; 'bytes' @@ -38,38 +55,23 @@ ao_fec_crc(uint8_t *bytes, uint8_t len); * two after 'len' must be the received crc */ uint8_t -ao_fec_check_crc(uint8_t *bytes, uint8_t len); - -/* - * Append CRC and terminator bytes, returns resulting length. - * 'out' must be at least len + AO_FEC_PREPARE_EXTRA bytes long - */ -uint8_t -ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out); - -/* - * Whiten data using the cc1111 PN9 sequence. 'out' - * must be 'len' bytes long. 'out' and 'in' can be - * the same array - */ -void -ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); +ao_fec_check_crc(const uint8_t *bytes, uint8_t len); /* - * Encode and interleave data. 'out' must be len*2 bytes long + * Compute CRC, whiten, convolve and interleave data. 'out' must be (len + 4) * 2 bytes long */ uint8_t -ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); +ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out); /* * Decode data. 'in' is one byte per bit, soft decision * 'out' must be len/8 bytes long */ -#define AO_FEC_DECODE_BLOCK (8 * 32) /* callback must return multiples of this many bits */ +#define AO_FEC_DECODE_BLOCK (32) /* callback must return multiples of this many bits */ uint8_t -ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()); +ao_fec_decode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()); /* * Interleave data packed in bytes. 'out' must be 'len' bytes long. diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index 69e9c1f5..0d400bb0 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -18,6 +18,16 @@ #include #include +#ifdef MEGAMETRUM +#include +#endif + +#if AO_PROFILE +#include + +uint32_t ao_fec_decode_start, ao_fec_decode_end; +#endif + /* * byte order repeats through 3 2 1 0 * @@ -40,34 +50,35 @@ * 18/19 10/11 08/09 00/01 */ +static const uint8_t ao_interleave_order[] = { + 0x1e, 0x16, 0x0e, 0x06, + 0x1c, 0x14, 0x0c, 0x04, + 0x1a, 0x12, 0x0a, 0x02, + 0x18, 0x10, 0x08, 0x00 +}; + static inline uint16_t ao_interleave_index(uint16_t i) { - uint8_t l = i & 0x1e; - uint16_t h = i & ~0x1e; - uint8_t o = 0x1e ^ (((l >> 2) & 0x6) | ((l << 2) & 0x18)); - return h | o; + return (i & ~0x1e) | ao_interleave_order[(i & 0x1e) >> 1]; } -struct ao_soft_sym { - uint8_t a, b; -}; - #define NUM_STATE 8 #define NUM_HIST 8 -#define MOD_HIST(b) ((b) & 7) - -#define V_0 0xc0 -#define V_1 0x40 - -static const struct ao_soft_sym ao_fec_decode_table[NUM_STATE][2] = { -/* next 0 1 state */ - { { V_0, V_0 }, { V_1, V_1 } } , /* 000 */ - { { V_0, V_1 }, { V_1, V_0 } }, /* 001 */ - { { V_1, V_1 }, { V_0, V_0 } }, /* 010 */ - { { V_1, V_0 }, { V_0, V_1 } }, /* 011 */ - { { V_1, V_1 }, { V_0, V_0 } }, /* 100 */ - { { V_1, V_0 }, { V_0, V_1 } }, /* 101 */ - { { V_0, V_0 }, { V_1, V_1 } }, /* 110 */ - { { V_0, V_1 }, { V_1, V_0 } } /* 111 */ + +#define V_0 0xff +#define V_1 0x00 + +/* + * These are just the 'zero' states; the 'one' states mirror them + */ +static const uint8_t ao_fec_decode_table[NUM_STATE*2] = { + V_0, V_0, /* 000 */ + V_0, V_1, /* 001 */ + V_1, V_1, /* 010 */ + V_1, V_0, /* 011 */ + V_1, V_1, /* 100 */ + V_1, V_0, /* 101 */ + V_0, V_0, /* 110 */ + V_0, V_1 /* 111 */ }; static inline uint8_t @@ -76,14 +87,6 @@ ao_next_state(uint8_t state, uint8_t bit) return ((state << 1) | bit) & 0x7; } -static inline uint16_t ao_abs(int16_t x) { return x < 0 ? -x : x; } - -static inline uint16_t -ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) -{ - return ao_abs(a.a - b.a) + ao_abs(a.b - b.b); -} - /* * 'in' is 8-bits per symbol soft decision data * 'len' is input byte length. 'out' must be @@ -91,25 +94,29 @@ ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) */ uint8_t -ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) +ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) { - static uint16_t cost[2][NUM_STATE]; /* path cost */ + static uint32_t cost[2][NUM_STATE]; /* path cost */ static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ + uint16_t i; /* input byte index */ uint16_t b; /* encoded symbol index (bytes/2) */ uint16_t o; /* output bit index */ uint8_t p; /* previous cost/bits index */ uint8_t n; /* next cost/bits index */ uint8_t state; /* state index */ - uint8_t bit; /* original encoded bit index */ const uint8_t *whiten = ao_fec_whiten_table; uint16_t interleave; /* input byte array index */ - struct ao_soft_sym s; /* input symbol pair */ + uint8_t s0, s1; uint16_t avail; + uint16_t crc = AO_FEC_CRC_INIT; +#if AO_PROFILE + uint32_t start_tick; +#endif p = 0; for (state = 0; state < NUM_STATE; state++) { - cost[0][state] = 0xffff; + cost[0][state] = 0x7fffffff; bits[0][state] = 0; } cost[0][0] = 0; @@ -119,6 +126,14 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t else avail = len; +#if AO_PROFILE + if (!avail) { + avail = callback(); + if (!avail) + return 0; + } + start_tick = ao_profile_tick(); +#endif o = 0; for (i = 0; i < len; i += 2) { b = i/2; @@ -127,44 +142,52 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t if (!avail) { avail = callback(); if (!avail) - break; + return 0; } /* Fetch one pair of input bytes, de-interleaving * the input. */ interleave = ao_interleave_index(i); - s.a = in[interleave]; - s.b = in[interleave+1]; + s0 = in[interleave]; + s1 = in[interleave+1]; + + avail -= 2; /* Reset next costs to 'impossibly high' values so that * the first path through this state is cheaper than this */ for (state = 0; state < NUM_STATE; state++) - cost[n][state] = 0xffff; + cost[n][state] = 0x7fffffff; /* Compute path costs and accumulate output bit path * for each state and encoded bit value */ for (state = 0; state < NUM_STATE; state++) { - for (bit = 0; bit < 2; bit++) { - int bit_cost = cost[p][state] + ao_cost(s, ao_fec_decode_table[state][bit]); - uint8_t bit_state = ao_next_state(state, bit); - - /* Only track the minimal cost to reach - * this state; the best path can never - * go through the higher cost paths as - * total path cost is cumulative - */ - if (bit_cost < cost[n][bit_state]) { - cost[n][bit_state] = bit_cost; - bits[n][bit_state] = (bits[p][state] << 1) | (state & 1); + uint32_t bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) + + (uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)+1])); + { + uint32_t cost0 = cost[p][state] + bitcost; + uint8_t state0 = ao_next_state(state, 0); + + if (cost0 < cost[n][state0]) { + cost[n][state0] = cost0; + bits[n][state0] = (bits[p][state] << 1) | (state & 1); + } + } + { + uint32_t cost1 = cost[p][state] + 510 - bitcost; + uint8_t state1 = ao_next_state(state, 1); + + if (cost1 < cost[n][state1]) { + cost[n][state1] = cost1; + bits[n][state1] = (bits[p][state] << 1) | (state & 1); } } } #if 0 - printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); + printf ("bit %3d symbol %2x %2x:", i/2, s0, s1); for (state = 0; state < NUM_STATE; state++) { printf (" %5d(%04x)", cost[n][state], bits[n][state]); } @@ -186,7 +209,7 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t * it will be seven. */ int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */ - uint16_t min_cost; /* lowest cost */ + uint32_t min_cost; /* lowest cost */ uint8_t min_state; /* lowest cost state */ /* Find the best fit at the current point @@ -216,11 +239,23 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); #endif if (out_len) { - *out++ = (bits[p][min_state] >> dist) ^ *whiten++; + uint8_t byte = (bits[p][min_state] >> dist) ^ *whiten++; + + if (out_len > 2) { + crc = ao_fec_crc_byte(byte, crc); + *out++ = byte; + } else { + *out++ = byte ^ (crc >> 8); + crc <<= 8; + } --out_len; } o += 8; } } +#if AO_PROFILE + ao_fec_decode_start = start_tick; + ao_fec_decode_end = ao_profile_tick(); +#endif return len/16; } diff --git a/src/core/ao_fec_tx.c b/src/core/ao_fec_tx.c index c9c0a3d6..4941d745 100644 --- a/src/core/ao_fec_tx.c +++ b/src/core/ao_fec_tx.c @@ -18,8 +18,9 @@ #include #include +#if AO_FEC_DEBUG void -ao_fec_dump_bytes(uint8_t *bytes, uint16_t len, char *name) +ao_fec_dump_bytes(const uint8_t *bytes, uint16_t len, const char *name) { uint16_t i; @@ -31,29 +32,15 @@ ao_fec_dump_bytes(uint8_t *bytes, uint16_t len, char *name) } printf ("\n"); } - -static uint16_t inline -crc_byte(uint8_t byte, uint16_t crc) -{ - uint8_t bit; - - for (bit = 0; bit < 8; bit++) { - if (((crc & 0x8000) >> 8) ^ (byte & 0x80)) - crc = (crc << 1) ^ 0x8005; - else - crc = (crc << 1); - byte <<= 1; - } - return crc; -} +#endif uint16_t -ao_fec_crc(uint8_t *bytes, uint8_t len) +ao_fec_crc(const uint8_t *bytes, uint8_t len) { uint16_t crc = AO_FEC_CRC_INIT; while (len--) - crc = crc_byte(*bytes++, crc); + crc = ao_fec_crc_byte(*bytes++, crc); return crc; } @@ -63,7 +50,7 @@ ao_fec_crc(uint8_t *bytes, uint8_t len) */ uint8_t -ao_fec_check_crc(uint8_t *bytes, uint8_t len) +ao_fec_check_crc(const uint8_t *bytes, uint8_t len) { uint16_t computed_crc = ao_fec_crc(bytes, len); uint16_t received_crc = (bytes[len] << 8) | (bytes[len+1]); @@ -71,8 +58,11 @@ ao_fec_check_crc(uint8_t *bytes, uint8_t len) return computed_crc == received_crc; } -uint8_t -ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *extra) +/* + * Compute CRC and trellis-terminator/interleave-pad bytes + */ +static uint8_t +ao_fec_prepare(const uint8_t *in, uint8_t len, uint8_t *extra) { uint16_t crc = ao_fec_crc (in, len); uint8_t i = 0; @@ -93,40 +83,6 @@ const uint8_t ao_fec_whiten_table[] = { #include "ao_whiten.h" }; -#if 0 -void -ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) -{ - const uint8_t *w = ao_fec_whiten_table; - - while (len--) - *out++ = *in++ ^ *w++; -} - -/* - * Unused as interleaving is now built in to ao_fec_encode - */ - -static void -ao_fec_interleave(uint8_t *d, uint8_t len) -{ - uint8_t i, j; - - for (i = 0; i < len; i += 4) { - uint32_t interleaved = 0; - - for (j = 0; j < 4 * 4; j++) { - interleaved <<= 2; - interleaved |= (d[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; - } - d[i+0] = interleaved >> 24; - d[i+1] = interleaved >> 16; - d[i+2] = interleaved >> 8; - d[i+3] = interleaved; - } -} -#endif - static const uint8_t ao_fec_encode_table[16] = { /* next 0 1 state */ 0, 3, /* 000 */ @@ -140,7 +96,7 @@ static const uint8_t ao_fec_encode_table[16] = { }; uint8_t -ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out) +ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out) { uint8_t extra[AO_FEC_PREPARE_EXTRA]; uint8_t extra_len; diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 394cf7c5..501b9370 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -24,8 +24,9 @@ uint8_t ao_radio_wake; uint8_t ao_radio_mutex; uint8_t ao_radio_abort; +uint8_t ao_radio_in_recv; -#define CC1120_DEBUG 1 +#define CC1120_DEBUG AO_FEC_DEBUG #define CC1120_TRACE 0 #if CC1120_TRACE @@ -34,7 +35,7 @@ uint8_t ao_radio_abort; #define fec_dump_bytes(b,l,n) #endif -uint32_t ao_radio_cal = 0x6ca333; +const uint32_t ao_radio_cal = 0x6ca333; #define FOSC 32000000 @@ -194,6 +195,12 @@ ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) return status; } +static uint8_t +ao_radio_tx_fifo_space(void) +{ + return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES); +} + static uint8_t ao_radio_status(void) { @@ -209,6 +216,97 @@ ao_radio_recv_abort(void) #define ao_radio_rdf_value 0x55 +static uint8_t +ao_radio_marc_status(void) +{ + return ao_radio_reg_read(CC1120_MARC_STATUS1); +} + +static void +ao_radio_tx_isr(void) +{ + ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_wake = 1; + ao_wakeup(&ao_radio_wake); +} + +static void +ao_radio_start_tx(void) +{ + ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_tx_isr); + ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_STX); +} + +static void +ao_radio_idle(void) +{ + for (;;) { + uint8_t state = ao_radio_strobe(CC1120_SIDLE); + if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE) + break; + } +} + +/* + * Packet deviation is 20.5kHz + * + * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * + * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz + */ + +#define PACKET_DEV_E 5 +#define PACKET_DEV_M 80 + +/* + * For our packet data, set the symbol rate to 38360 Baud + * + * (2**20 + DATARATE_M) * 2 ** DATARATE_E + * Rdata = -------------------------------------- * fosc + * 2 ** 39 + * + * + * DATARATE_M = 239914 + * DATARATE_E = 9 + */ +#define PACKET_DRATE_E 9 +#define PACKET_DRATE_M 239914 + +static const uint16_t packet_setup[] = { + CC1120_DEVIATION_M, PACKET_DEV_M, + CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | + (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | + (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)), + CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) | + (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), + CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff), + CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff), + CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), + CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) | + (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | + (0 << CC1120_PKT_CFG1_APPEND_STATUS)), + CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) | + (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1120_PKT_CFG0_UART_MODE_EN) | + (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), +}; + +static const uint16_t packet_tx_setup[] = { + CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), + CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG, +}; + +static const uint16_t packet_rx_setup[] = { + CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)), + CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT, +}; + /* * RDF deviation is 5kHz * @@ -259,50 +357,111 @@ static const uint16_t rdf_setup[] = { (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), }; -static uint8_t -ao_radio_marc_status(void) -{ - return ao_radio_reg_read(CC1120_MARC_STATUS1); -} +static uint8_t ao_radio_mode; -static uint8_t -ao_radio_tx_done(void) -{ - return ao_radio_marc_status() == CC1120_MARC_STATUS1_TX_FINISHED; -} +#define AO_RADIO_MODE_BITS_PACKET 1 +#define AO_RADIO_MODE_BITS_PACKET_TX 2 +#define AO_RADIO_MODE_BITS_TX_BUF 4 +#define AO_RADIO_MODE_BITS_TX_FINISH 8 +#define AO_RADIO_MODE_BITS_PACKET_RX 16 +#define AO_RADIO_MODE_BITS_RDF 32 -static uint8_t -ao_radio_rx_done(void) +#define AO_RADIO_MODE_NONE 0 +#define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF) +#define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH) +#define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX) +#define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH) + +static void +ao_radio_set_mode(uint8_t new_mode) { - return ao_radio_marc_status() == CC1120_MARC_STATUS1_RX_FINISHED; + uint8_t changes; + int i; + + if (new_mode == ao_radio_mode) + return; + + changes = new_mode & (~ao_radio_mode); + if (changes & AO_RADIO_MODE_BITS_PACKET) + for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2) + ao_radio_reg_write(packet_setup[i], packet_setup[i+1]); + + if (changes & AO_RADIO_MODE_BITS_PACKET_TX) + for (i = 0; i < sizeof (packet_tx_setup) / sizeof (packet_tx_setup[0]); i += 2) + ao_radio_reg_write(packet_tx_setup[i], packet_tx_setup[i+1]); + + if (changes & AO_RADIO_MODE_BITS_TX_BUF) + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR); + + if (changes & AO_RADIO_MODE_BITS_TX_FINISH) + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); + + if (changes & AO_RADIO_MODE_BITS_PACKET_RX) + for (i = 0; i < sizeof (packet_rx_setup) / sizeof (packet_rx_setup[0]); i += 2) + ao_radio_reg_write(packet_rx_setup[i], packet_rx_setup[i+1]); + + if (changes & AO_RADIO_MODE_BITS_RDF) + for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) + ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); + ao_radio_mode = new_mode; } +static const uint16_t radio_setup[] = { +#include "ao_cc1120_CC1120.h" +}; + +static uint8_t ao_radio_configured = 0; + static void -ao_radio_tx_isr(void) +ao_radio_setup(void) { - ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_wake = 1; - ao_wakeup(&ao_radio_wake); + int i; + + ao_radio_strobe(CC1120_SRES); + + for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) + ao_radio_reg_write(radio_setup[i], radio_setup[i+1]); + + ao_radio_mode = 0; + + ao_config_get(); + + ao_radio_configured = 1; } static void -ao_radio_start_tx(void) +ao_radio_get(uint8_t len) { - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); - ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_tx_isr); - ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_strobe(CC1120_STX); + static uint32_t last_radio_setting; + static uint8_t last_len; + + ao_mutex_get(&ao_radio_mutex); + if (!ao_radio_configured) + ao_radio_setup(); + if (ao_config.radio_setting != last_radio_setting) { + ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16); + ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8); + ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting); + last_radio_setting = ao_config.radio_setting; + } + if (len != last_len) { + ao_radio_reg_write(CC1120_PKT_LEN, len); + last_len = len; + } } +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) + void ao_radio_rdf(uint8_t len) { int i; + ao_radio_abort = 0; ao_radio_get(len); + + ao_radio_set_mode(AO_RADIO_MODE_RDF); ao_radio_wake = 0; - for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) - ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); @@ -311,11 +470,9 @@ ao_radio_rdf(uint8_t len) cli(); while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); - sei(); - if (!ao_radio_tx_done()) + if (!ao_radio_wake) ao_radio_idle(); - ao_radio_set_packet(); ao_radio_put(); } @@ -372,65 +529,113 @@ ao_radio_test(void) } void -ao_radio_send(void *d, uint8_t size) +ao_radio_send(const void *d, uint8_t size) { uint8_t marc_status; - uint8_t encode[size + AO_FEC_PREPARE_EXTRA]; + static uint8_t encode[256]; + uint8_t *e = encode; uint8_t encode_len; + uint8_t this_len; + uint8_t started = 0; + uint8_t fifo_space; encode_len = ao_fec_encode(d, size, encode); ao_radio_get(encode_len); - ao_radio_fifo_write(encode, encode_len); - ao_radio_wake = 0; + started = 0; + fifo_space = CC1120_FIFO_SIZE; + while (encode_len) { + this_len = encode_len; - ao_radio_start_tx(); + if (this_len > fifo_space) { + this_len = fifo_space; + ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF); + } else { + ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH); + } - cli(); - while (!ao_radio_wake && !ao_radio_abort) - ao_sleep(&ao_radio_wake); - sei(); - if (!ao_radio_tx_done()) - ao_radio_idle(); + ao_radio_fifo_write(e, this_len); + e += this_len; + encode_len -= this_len; + + if (!started) { + ao_radio_start_tx(); + started = 1; + } else { + ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + } + + do { + ao_radio_wake = 0; + cli(); + while (!ao_radio_wake) + ao_sleep(&ao_radio_wake); + sei(); + if (!encode_len) + break; + fifo_space = ao_radio_tx_fifo_space(); + } while (!fifo_space); + } ao_radio_put(); } #define AO_RADIO_MAX_RECV 90 -static uint8_t rx_data[2048]; -static uint16_t rx_data_count; -static uint16_t rx_data_consumed; -static uint16_t rx_data_cur; -static uint8_t rx_ignore; +uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8]; +uint16_t rx_data_count; +uint16_t rx_data_consumed; +uint16_t rx_data_cur; +uint8_t rx_ignore; +uint8_t rx_waiting; + +#if AO_PROFILE +static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick; + +uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick; + +#include +#endif static void ao_radio_rx_isr(void) { + uint8_t d; + + d = stm_spi2.dr; + stm_spi2.dr = 0; if (rx_ignore == 0) { - rx_data[rx_data_cur++] = stm_spi2.dr; if (rx_data_cur >= rx_data_count) - ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - if (rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) { + ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + else + rx_data[rx_data_cur++] = d; + if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) { +#if AO_PROFILE + if (rx_data_consumed == 0) + rx_packet_tick = ao_profile_tick(); +#endif + rx_waiting = 0; ao_wakeup(&ao_radio_wake); } } else { - (void) stm_spi2.dr; --rx_ignore; } - stm_spi2.dr = 0x00; } static uint16_t ao_radio_rx_wait(void) { cli(); + rx_waiting = 1; while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK && - !ao_radio_abort) + !ao_radio_abort) { ao_sleep(&ao_radio_wake); + } + rx_waiting = 0; sei(); if (ao_radio_abort) return 0; + rx_data_consumed += AO_FEC_DECODE_BLOCK; return AO_FEC_DECODE_BLOCK; } @@ -440,8 +645,17 @@ ao_radio_recv(__xdata void *d, uint8_t size) uint8_t len; uint16_t i; uint8_t rssi; + uint8_t ret; + static int been_here = 0; size -= 2; /* status bytes */ + if (size > AO_RADIO_MAX_RECV) { + ao_delay(AO_SEC_TO_TICKS(1)); + return 0; + } +#if AO_PROFILE + rx_start_tick = ao_profile_tick(); +#endif len = size + 2; /* CRC bytes */ len += 1 + ~(len & 1); /* 1 or two pad bytes */ len *= 2; /* 1/2 rate convolution */ @@ -450,162 +664,65 @@ ao_radio_recv(__xdata void *d, uint8_t size) rx_data_consumed = 0; rx_ignore = 2; - printf ("len %d rx_data_count %d\n", len, rx_data_count); - + ao_radio_abort = 0; + ao_radio_in_recv = 1; /* configure interrupt pin */ ao_radio_get(len); - ao_radio_wake = 0; - ao_radio_abort = 0; - - ao_radio_reg_write(CC1120_PKT_CFG2, - (CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | - (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)); + ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX); - ao_radio_reg_write(CC1120_EXT_CTRL, 0); - - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT); + ao_radio_wake = 0; stm_spi2.cr2 = 0; /* clear any RXNE */ (void) stm_spi2.dr; - ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr); - ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr); + ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); ao_radio_strobe(CC1120_SRX); ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); - ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait); + ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait); ao_radio_burst_read_stop(); + ao_radio_strobe(CC1120_SIDLE); + /* Convert from 'real' rssi to cc1111-style values */ rssi = (((int8_t) ao_radio_reg_read(CC1120_RSSI1)) + 74) * 2; - ao_radio_strobe(CC1120_SIDLE); - ao_radio_put(); /* Construct final packet */ - ao_fec_decode(rx_data, rx_data_cur, d, size + 2, 0); - - if (ao_fec_check_crc(d, size)) + if (ret && ((uint8_t *) d)[size] == 0 && ((uint8_t *)d)[size+1] == 0) ((uint8_t *) d)[size + 1] = 0x80; else ((uint8_t *) d)[size + 1] = 0x00; ((uint8_t *) d)[size] = (uint8_t) rssi; - return 1; -} - -/* - * Packet deviation is 20.5kHz - * - * fdev = fosc >> 24 * (256 + dev_m) << dev_e - * - * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz - */ - -#define PACKET_DEV_E 5 -#define PACKET_DEV_M 80 - -/* - * For our packet data, set the symbol rate to 38360 Baud - * - * (2**20 + DATARATE_M) * 2 ** DATARATE_E - * Rdata = -------------------------------------- * fosc - * 2 ** 39 - * - * - * DATARATE_M = 239914 - * DATARATE_E = 9 - */ -#define PACKET_DRATE_E 9 -#define PACKET_DRATE_M 239914 + ao_radio_in_recv = 0; -static const uint16_t packet_setup[] = { - CC1120_DEVIATION_M, PACKET_DEV_M, - CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | - (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | - (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)), - CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) | - (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), - CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff), - CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff), - CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | - (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), - CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) | - (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | - (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | - (1 << CC1120_PKT_CFG1_APPEND_STATUS)), - CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) | - (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | - (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | - (0 << CC1120_PKT_CFG0_UART_MODE_EN) | - (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), -}; - -void -ao_radio_set_packet(void) -{ - int i; - - for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) - ao_radio_reg_write(packet_setup[i], packet_setup[i+1]); -} - -void -ao_radio_idle(void) -{ - for (;;) { - uint8_t state = ao_radio_strobe(CC1120_SIDLE); - if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE) - break; - } - ao_radio_strobe(CC1120_SFTX); - ao_radio_strobe(CC1120_SFRX); -} - -static const uint16_t radio_setup[] = { -#include "ao_cc1120_CC1120.h" -}; - -static uint8_t ao_radio_configured = 0; - - -static void -ao_radio_setup(void) -{ - int i; - - ao_radio_strobe(CC1120_SRES); - - for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) - ao_radio_reg_write(radio_setup[i], radio_setup[i+1]); + if (ao_radio_abort) + ao_delay(1); - ao_radio_set_packet(); +#if AO_PROFILE + rx_last_done_tick = rx_done_tick; + rx_done_tick = ao_profile_tick(); - ao_config_get(); + ao_rx_start_tick = rx_start_tick; + ao_rx_packet_tick = rx_packet_tick; + ao_rx_done_tick = rx_done_tick; + ao_rx_last_done_tick = rx_last_done_tick; +#endif - ao_radio_configured = 1; + return ret; } -void -ao_radio_get(uint8_t len) -{ - ao_mutex_get(&ao_radio_mutex); - if (!ao_radio_configured) - ao_radio_setup(); - ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16); - ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8); - ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting); - ao_radio_reg_write(CC1120_PKT_LEN, len); -} #if CC1120_DEBUG static char *cc1120_state_name[] = { @@ -824,7 +941,7 @@ static void ao_radio_beep(void) { } static void ao_radio_packet(void) { - static uint8_t packet[] = { + static const uint8_t packet[] = { #if 1 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, @@ -841,7 +958,19 @@ static void ao_radio_packet(void) { void ao_radio_test_recv() { - ao_radio_recv(0, 34); + uint8_t bytes[34]; + uint8_t b; + + if (ao_radio_recv(bytes, 34)) { + if (bytes[33] & 0x80) + printf ("CRC OK"); + else + printf ("CRC BAD"); + printf (" RSSI %d", (int16_t) ((int8_t) bytes[32] >> 1) - 74); + for (b = 0; b < 32; b++) + printf (" %02x", bytes[b]); + printf ("\n"); + } } #endif @@ -865,18 +994,20 @@ ao_radio_init(void) ao_radio_configured = 0; ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN)); - AO_CC1120_SPI_CS_PORT.bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN)); + AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN)); for (i = 0; i < 10000; i++) { - if ((SPI_2_GPIO.idr & (1 << SPI_2_MISO)) == 0) + if ((SPI_2_GPIO->idr & (1 << SPI_2_MISO)) == 0) break; } - AO_CC1120_SPI_CS_PORT.bsrr = (1 << AO_CC1120_SPI_CS_PIN); + AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN); if (i == 10000) ao_panic(AO_PANIC_SELF_TEST); /* Enable the EXTI interrupt for the appropriate pin */ ao_enable_port(AO_CC1120_INT_PORT); - ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_tx_isr); + ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, + AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH, + ao_radio_tx_isr); ao_cmd_register(&ao_radio_cmds[0]); } diff --git a/src/drivers/ao_cc1120.h b/src/drivers/ao_cc1120.h index 5822a21a..60b9621e 100644 --- a/src/drivers/ao_cc1120.h +++ b/src/drivers/ao_cc1120.h @@ -181,6 +181,11 @@ #define CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_MASK 3 #define CC1120_PREAMBLE_CFG0 0x0e +#define CC1120_PREAMBLE_CFG0_PQT_EN 5 +#define CC1120_PREAMBLE_CFG0_PQT_VALID_TIMEOUT 4 +#define CC1120_PREAMBLE_CFG0_PQT 0 +#define CC1120_PREAMBLE_CFG0_PQT_MASK 0xf + #define CC1120_FREQ_IF_CFG 0x0f #define CC1120_IQIC 0x10 #define CC1120_CHAN_BW 0x11 @@ -215,6 +220,8 @@ #define CC1120_AGC_CFG1 0x1c #define CC1120_AGC_CFG0 0x1d #define CC1120_FIFO_CFG 0x1e +#define CC1120_FIFO_CFG_CRC_AUTOFLUSH 7 +#define CC1120_FIFO_CFG_FIFO_THR 0 #define CC1120_DEV_ADDR 0x1f #define CC1120_SETTLING_CFG 0x20 #define CC1120_SETTLING_CFG_FS_AUTOCAL 3 @@ -321,6 +328,8 @@ #define CC1120_DIRECT_FIFO 0x3e #define CC1120_FIFO 0x3f +#define CC1120_FIFO_SIZE 128 + /* Extended register space */ #define CC1120_EXTENDED_BIT 0x8000 diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h index c0f35a23..5376afd5 100644 --- a/src/drivers/ao_cc1120_CC1120.h +++ b/src/drivers/ao_cc1120_CC1120.h @@ -26,7 +26,9 @@ CC1120_SYNC1, 0xD3, /* Sync Word Configuration [15:8] */ CC1120_SYNC0, 0x91, /* Sync Word Configuration [7:0] */ - CC1120_SYNC_CFG1, 0x08, /* Sync Word Detection Configuration */ + CC1120_SYNC_CFG1, /* Sync Word Detection Configuration */ + (CC1120_SYNC_CFG1_DEM_CFG_PQT_GATING_ENABLED << CC1120_SYNC_CFG1_DEM_CFG) | + (0x07 << CC1120_SYNC_CFG1_SYNC_THR), CC1120_SYNC_CFG0, (CC1120_SYNC_CFG0_SYNC_MODE_16_BITS << CC1120_SYNC_CFG0_SYNC_MODE) | (CC1120_SYNC_CFG0_SYNC_NUM_ERROR_2 << CC1120_SYNC_CFG0_SYNC_NUM_ERROR), @@ -34,12 +36,21 @@ CC1120_PREAMBLE_CFG1, /* Preamble Length Configuration */ (CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) | (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD), - CC1120_PREAMBLE_CFG0, 0x2a, /* */ + CC1120_PREAMBLE_CFG0, + (1 << CC1120_PREAMBLE_CFG0_PQT_EN) | + (0x6 << CC1120_PREAMBLE_CFG0_PQT), CC1120_FREQ_IF_CFG, 0x40, /* RX Mixer Frequency Configuration */ CC1120_IQIC, 0x46, /* Digital Image Channel Compensation Configuration */ CC1120_CHAN_BW, 0x02, /* Channel Filter Configuration */ - CC1120_MDMCFG1, 0x46, /* General Modem Parameter Configuration */ + CC1120_MDMCFG1, /* General Modem Parameter Configuration */ + (0 << CC1120_MDMCFG1_CARRIER_SENSE_GATE) | + (1 << CC1120_MDMCFG1_FIFO_EN) | + (0 << CC1120_MDMCFG1_MANCHESTER_EN) | + (0 << CC1120_MDMCFG1_INVERT_DATA_EN) | + (0 << CC1120_MDMCFG1_COLLISION_DETECT_EN) | + (CC1120_MDMCFG1_DVGA_GAIN_9 << CC1120_MDMCFG1_DVGA_GAIN) | + (0 << CC1120_MDMCFG1_SINGLE_ADC_EN), CC1120_MDMCFG0, 0x05, /* General Modem Parameter Configuration */ CC1120_AGC_REF, 0x20, /* AGC Reference Level Configuration */ @@ -49,7 +60,9 @@ CC1120_AGC_CFG2, 0x20, /* AGC Configuration */ CC1120_AGC_CFG1, 0xa9, /* AGC Configuration */ CC1120_AGC_CFG0, 0xcf, /* AGC Configuration */ - CC1120_FIFO_CFG, 0x00, /* FIFO Configuration */ + CC1120_FIFO_CFG, /* FIFO Configuration */ + (0 << CC1120_FIFO_CFG_CRC_AUTOFLUSH) | + (0x40 << CC1120_FIFO_CFG_FIFO_THR), CC1120_DEV_ADDR, 0x00, /* Device Address Configuration */ CC1120_SETTLING_CFG, /* Frequency Synthesizer Calibration and Settling Configuration */ (CC1120_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON << CC1120_SETTLING_CFG_FS_AUTOCAL) | @@ -65,12 +78,12 @@ #if 0 CC1120_PKT_CFG2, 0x04, /* Packet Configuration, Reg 2 */ CC1120_PKT_CFG1, 0x45, /* Packet Configuration, Reg 1 */ -#endif CC1120_PKT_CFG0, 0x00, /* Packet Configuration, Reg 0 */ +#endif CC1120_RFEND_CFG1, 0x0f, /* RFEND Configuration, Reg 1 */ CC1120_RFEND_CFG0, 0x00, /* RFEND Configuration, Reg 0 */ // CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */ - CC1120_PA_CFG2, 0x23, /* Power Amplifier Configuration, Reg 2 */ + CC1120_PA_CFG2, 0x04, /* Power Amplifier Configuration, Reg 2 */ CC1120_PA_CFG1, 0x56, /* Power Amplifier Configuration, Reg 1 */ CC1120_PA_CFG0, 0x7b, /* Power Amplifier Configuration, Reg 0 */ CC1120_PKT_LEN, 0xff, /* Packet Length Configuration */ @@ -80,7 +93,7 @@ CC1120_MARC_SPARE, 0x00, /* MARC Spare */ CC1120_ECG_CFG, 0x00, /* External Clock Frequency Configuration */ CC1120_SOFT_TX_DATA_CFG, 0x00, /* Soft TX Data Configuration */ - CC1120_EXT_CTRL, 0x01, /* External Control Configuration */ + CC1120_EXT_CTRL, 0x00, /* External Control Configuration */ CC1120_RCCAL_FINE, 0x00, /* RC Oscillator Calibration (fine) */ CC1120_RCCAL_COARSE, 0x00, /* RC Oscillator Calibration (coarse) */ CC1120_RCCAL_OFFSET, 0x00, /* RC Oscillator Calibration Clock Offset */ diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index bbd1b3b1..30cd9ea5 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -25,7 +25,7 @@ * STM32L definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 1024 +#define AO_STACK_SIZE 512 #define AO_LED_TYPE uint16_t @@ -111,14 +111,22 @@ extern const uint16_t ao_serial_number; uint32_t *sp; \ asm("mov %0,sp" : "=&r" (sp) ); \ ao_cur_task->sp = (sp); \ - if ((uint8_t *) sp < ao_cur_task->stack) \ + if ((uint8_t *) sp < &ao_cur_task->stack[0]) \ ao_panic (AO_PANIC_STACK); \ } while (0) -#define ao_arch_isr_stack() /* nothing */ +#if 0 +#define ao_arch_isr_stack() do { \ + uint32_t *sp = (uint32_t *) 0x20004000; \ + asm("mov %0,sp" : "=&r" (sp) ); \ + } while (0) +#else +#define ao_arch_isr_stack() +#endif + #define ao_arch_cpu_idle() do { \ - asm("wfi"); \ + asm("wfi"); \ } while (0) #define ao_arch_restore_stack() do { \ @@ -173,6 +181,11 @@ extern const uint16_t ao_serial_number; #define AO_TIM91011_CLK (2 * AO_PCLK2) #endif +#define AO_STM_NVIC_HIGH_PRIORITY 4 +#define AO_STM_NVIC_CLOCK_PRIORITY 6 +#define AO_STM_NVIC_MED_PRIORITY 8 +#define AO_STM_NVIC_LOW_PRIORITY 10 + void ao_lcd_stm_init(void); void ao_lcd_font_init(void); @@ -215,7 +228,7 @@ ao_serial3_pollchar(void); void ao_serial3_set_speed(uint8_t speed); -extern uint32_t ao_radio_cal; +extern const uint32_t ao_radio_cal; void ao_adc_init(); diff --git a/src/stm/ao_exti.h b/src/stm/ao_exti.h index 87a072e7..b579ad9f 100644 --- a/src/stm/ao_exti.h +++ b/src/stm/ao_exti.h @@ -22,6 +22,9 @@ #define AO_EXTI_MODE_FALLING 2 #define AO_EXTI_MODE_PULL_UP 4 #define AO_EXTI_MODE_PULL_DOWN 8 +#define AO_EXTI_PRIORITY_LOW 16 +#define AO_EXTI_PRIORITY_MED 0 +#define AO_EXTI_PRIORITY_HIGH 32 void ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)()); diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index 683a91b3..d54e6ee6 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -20,37 +20,50 @@ static void (*ao_exti_callback[16])(void); -static void -ao_exti_isr(void) { - uint32_t pending = stm_exti.pr; - uint8_t pin; +uint32_t ao_last_exti; + +static void ao_exti_one_isr(uint8_t pin) { + uint32_t pending = (ao_last_exti = stm_exti.pr) & (1 << pin); - /* Clear pending interrupts */ stm_exti.pr = pending; - for (pin = 0; pin < 16 && pending; pin++) { - uint32_t mask = (1 << pin); + if (pending && ao_exti_callback[pin]) + (*ao_exti_callback[pin])(); +} - if (pending & mask) { - pending &= ~mask; - if (ao_exti_callback[pin]) - (*ao_exti_callback[pin])(); - } +static void ao_exti_range_isr(uint8_t first, uint8_t last, uint16_t mask) { + uint16_t pending = (ao_last_exti = stm_exti.pr) & mask; + uint8_t pin; + static uint16_t last_mask; + static uint8_t last_pin; + + if (pending == last_mask) { + stm_exti.pr = last_mask; + (*ao_exti_callback[last_pin])(); + return; } + stm_exti.pr = pending; + for (pin = first; pin <= last; pin++) + if ((pending & ((uint32_t) 1 << pin)) && ao_exti_callback[pin]) { + last_mask = (1 << pin); + last_pin = pin; + (*ao_exti_callback[pin])(); + } } -void stm_exti0_isr(void) { ao_exti_isr(); } -void stm_exti1_isr(void) { ao_exti_isr(); } -void stm_exti2_isr(void) { ao_exti_isr(); } -void stm_exti3_isr(void) { ao_exti_isr(); } -void stm_exti4_isr(void) { ao_exti_isr(); } -void stm_exti9_5_isr(void) { ao_exti_isr(); } -void stm_exti15_10_isr(void) { ao_exti_isr(); } +void stm_exti0_isr(void) { ao_exti_one_isr(0); } +void stm_exti1_isr(void) { ao_exti_one_isr(1); } +void stm_exti2_isr(void) { ao_exti_one_isr(2); } +void stm_exti3_isr(void) { ao_exti_one_isr(3); } +void stm_exti4_isr(void) { ao_exti_one_isr(4); } +void stm_exti9_5_isr(void) { ao_exti_range_isr(5, 9, 0x3e0); } +void stm_exti15_10_isr(void) { ao_exti_range_isr(10, 15, 0xfc00); } void ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) { uint32_t mask = 1 << pin; uint32_t pupdr; uint8_t irq; + uint8_t prio; ao_exti_callback[pin] = callback; @@ -90,7 +103,15 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback irq = STM_ISR_EXTI9_5_POS; else irq = STM_ISR_EXTI15_10_POS; - stm_nvic_set_priority(irq, 10); + + /* Set priority */ + prio = AO_STM_NVIC_MED_PRIORITY; + if (mode & AO_EXTI_PRIORITY_LOW) + prio = AO_STM_NVIC_LOW_PRIORITY; + else if (mode & AO_EXTI_PRIORITY_HIGH) + prio = AO_STM_NVIC_HIGH_PRIORITY; + + stm_nvic_set_priority(irq, prio); stm_nvic_set_enable(irq); } @@ -116,10 +137,10 @@ ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) { void ao_exti_init(void) { - stm_nvic_set_priority(STM_ISR_EXTI1_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI2_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI3_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI4_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI9_5_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI15_10_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI1_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI2_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI3_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI4_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI9_5_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI15_10_POS, AO_STM_NVIC_MED_PRIORITY); } diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index d3378648..26227086 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -23,7 +23,8 @@ struct ao_spi_stm_info { struct stm_spi *stm_spi; }; -uint8_t ao_spi_mutex[STM_NUM_SPI]; +uint8_t ao_spi_mutex[STM_NUM_SPI]; +uint16_t ao_spi_speed[STM_NUM_SPI]; static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = { { @@ -282,7 +283,7 @@ ao_spi_get(uint8_t spi_index) (1 << STM_SPI_CR1_SSI) | /* ... */ (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */ (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ - (STM_SPI_CR1_BR_PCLK_16 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ + (ao_spi_speed[spi_index] << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ (1 << STM_SPI_CR1_MSTR) | (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ (0 << STM_SPI_CR1_CPHA)); @@ -310,6 +311,7 @@ ao_spi_channel_init(uint8_t spi_index) (0 << STM_SPI_CR2_SSOE) | (0 << STM_SPI_CR2_TXDMAEN) | (0 << STM_SPI_CR2_RXDMAEN)); + ao_spi_speed[spi_index] = AO_SPI_SPEED_FAST; } void diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 0c44f352..936dc881 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -87,7 +87,7 @@ void ao_timer_init(void) { stm_nvic_set_enable(STM_ISR_TIM6_POS); - stm_nvic_set_priority(STM_ISR_TIM6_POS, 1); + stm_nvic_set_priority(STM_ISR_TIM6_POS, AO_STM_NVIC_CLOCK_PRIORITY); /* Turn on timer 6 */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index e8d3d8b1..8ce532c8 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -74,6 +74,12 @@ gaussian_random(double mean, double dev) #define DECODE_LEN(input_len) ((input_len) + AO_FEC_PREPARE_EXTRA) #define EXPAND_LEN(input_len) (ENCODE_LEN(input_len) * 8) +static uint8_t ao_bit(uint8_t b) { + if (b) + return 0x00; + return 0xff; +} + static int ao_expand(uint8_t *bits, int bits_len, uint8_t *bytes) { @@ -83,7 +89,7 @@ ao_expand(uint8_t *bits, int bits_len, uint8_t *bytes) for (i = 0; i < bits_len; i++) { b = bits[i]; for (bit = 7; bit >= 0; bit--) - *bytes++ = ((b >> bit) & 1) * 0xff; + *bytes++ = ao_bit ((b >> bit) & 1); } return bits_len * 8; @@ -127,7 +133,7 @@ ao_random_data(uint8_t *out, uint8_t out_len) static uint8_t real_packet[] = { - 0x00, 0x40, 0x38, 0xcd, 0x38, 0x3d, 0x34, 0xca, 0x31, 0xc3, 0xc1, 0xc6, 0x35, 0xcc, 0x3a, 0x3c, + 0x40, 0x38, 0xcd, 0x38, 0x3d, 0x34, 0xca, 0x31, 0xc3, 0xc1, 0xc6, 0x35, 0xcc, 0x3a, 0x3c, 0x3c, 0x3d, 0x3c, 0x37, 0xc5, 0xc1, 0xc0, 0xc1, 0xc1, 0xc3, 0xc0, 0xc1, 0xc6, 0x38, 0x3b, 0xc6, 0xc0, 0xc6, 0x32, 0xc9, 0xc9, 0x34, 0xcf, 0x35, 0xcf, 0x3a, 0x3b, 0xc6, 0xc7, 0x35, 0xcf, 0x36, 0xce, 0x37, 0xc8, 0xc8, 0x3a, 0x3c, 0xc9, 0xc8, 0x3a, 0x3c, 0xcc, 0x32, 0xcd, 0x32, 0xce, 0x32, @@ -258,22 +264,24 @@ static uint8_t real_packet[] = { }; -void +int ao_real_packet(void) { uint8_t decode[64]; uint8_t decode_len; - int off; + int ok = 0; - for (off = 0; off < sizeof (real_packet) - 576; off++) { - decode_len = ao_fec_decode(real_packet+off, 576, decode, 34, NULL); + decode_len = ao_fec_decode(real_packet, 576, decode, 34, NULL); - if (ao_fec_check_crc(decode, 32)) { - printf ("match at %d\n", off); + if (decode[32] == 0 && decode[33] == 0) { + printf ("match\n"); - ao_fec_dump_bytes(decode, decode_len, "Decode"); - } + ao_fec_dump_bytes(decode, decode_len, "Decode"); + ok = 1; + } else { + printf ("actual packet crc error\n"); } + return ok; } int @@ -299,9 +307,11 @@ main(int argc, char **argv) int errors = 0; int error; - ao_real_packet(); exit(0); + if (!ao_real_packet()) + errors++; + srandom(0); - for (trial = 0; trial < 10000; trial++) { + for (trial = 0; trial < 100000; trial++) { /* Compute some random data */ original_len = ao_random_data(original, sizeof(original)); @@ -313,7 +323,7 @@ main(int argc, char **argv) transmit_len = ao_expand(encode, encode_len, transmit); /* Add gaussian noise to the signal */ - receive_errors = ao_fuzz(transmit, transmit_len, receive, 0x30); + receive_errors = ao_fuzz(transmit, transmit_len, receive, 0x38); receive_len = transmit_len; /* Decode it */ @@ -327,7 +337,7 @@ main(int argc, char **argv) error++; } - if (!ao_fec_check_crc(decode, original_len)) { + if (decode[original_len] != 0 || decode[original_len+1] != 0) { printf ("crc mis-match\n"); error++; } @@ -343,6 +353,7 @@ main(int argc, char **argv) errors += error; } } + printf ("%d packets coded\n", trial); return errors; } -- cgit v1.2.3 From b5f5fd92109ac6f4909a81303d52bc9220cc2520 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:13:14 -0700 Subject: altos: custom hex printer for telemetry packets Using printf is way too slow with pdclib; just hand-write hex byte output. Signed-off-by: Keith Packard --- src/core/ao_monitor.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 4ca641b7..51d61425 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -103,6 +103,13 @@ ao_monitor_blink(void) #if HAS_MONITOR_PUT +static const char xdigit[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' +}; + +#define hex(c) do { putchar(xdigit[(c) >> 4]); putchar(xdigit[(c)&0xf]); } while (0) + void ao_monitor_put(void) { @@ -210,14 +217,27 @@ ao_monitor_put(void) break; #endif /* LEGACY_MONITOR */ default: - printf ("TELEM %02x", ao_monitoring + 2); +#if AO_PROFILE + { + extern uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick; + extern uint32_t ao_fec_decode_start, ao_fec_decode_end; + + printf ("between packet: %d\n", ao_rx_start_tick - ao_rx_last_done_tick); + printf ("receive start delay: %d\n", ao_rx_packet_tick - ao_rx_start_tick); + printf ("decode time: %d\n", ao_fec_decode_end - ao_fec_decode_start); + printf ("rx cleanup: %d\n", ao_rx_done_tick - ao_fec_decode_end); + } +#endif + printf("TELEM "); + hex((uint8_t) (ao_monitoring + 2)); sum = 0x5a; for (state = 0; state < ao_monitoring + 2; state++) { byte = recv_raw.packet[state]; sum += byte; - printf("%02x", byte); + hex(byte); } - printf("%02x\n", sum); + hex(sum); + putchar ('\n'); #if HAS_RSSI if (recv_raw.packet[ao_monitoring + 1] & PKT_APPEND_STATUS_1_CRC_OK) { rssi = ((int16_t) recv_raw.packet[ao_monitoring] >> 1) - 74; -- cgit v1.2.3 From c4036bf6e7997b618f89a05dd1214c16066ba2b2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:14:13 -0700 Subject: altos: Turn radio-related bits of ao_flight_mm.c Now that MM has full radio functionality, we can make it work right. Signed-off-by: Keith Packard --- src/core/ao_flight_mm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c index 28b9869f..a0affc48 100644 --- a/src/core/ao_flight_mm.c +++ b/src/core/ao_flight_mm.c @@ -87,7 +87,7 @@ ao_flight(void) * - pad mode if we're upright, * - idle mode otherwise */ -#if HAS_ACCEL && 0 +#if HAS_ACCEL if (ao_config.accel_plus_g == 0 || ao_config.accel_minus_g == 0 || ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || @@ -105,14 +105,14 @@ ao_flight(void) } else #endif if (!ao_flight_force_idle -#if HAS_ACCEL && 0 +#if HAS_ACCEL && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP #endif ) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; -#if HAS_USB && HAS_RADIO && 0 +#if HAS_USB && HAS_RADIO /* Disable the USB controller in flight mode * to save power */ -- cgit v1.2.3 From 1ae69a1c2ce7e45db9d9c175bc63867eff68ebe5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:15:54 -0700 Subject: altos: Make gcc happy with ao_telemetry_set_interval Using unsigned locals made GCC sad as it was compared with a signed value. Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 9000a149..b3ce8ba9 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -333,7 +333,7 @@ ao_telemetry(void) void ao_telemetry_set_interval(uint16_t interval) { - uint8_t cur = 0; + int8_t cur = 0; ao_telemetry_interval = interval; #if AO_SEND_MEGA -- cgit v1.2.3 From 8efac8eb99a9aabb45d9fbf742e4be91e4b331a5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:21:04 -0700 Subject: altos: Add debugging code to check for stack overflow Stack overflow often happens from interrupt handlers sitting on top of a task stack. Check for this during ao_wakeup as that is often called during interrupt processing. Signed-off-by: Keith Packard --- src/core/ao_task.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 910f1587..4011a36e 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" +#include #define AO_NO_TASK_INDEX 0xff @@ -28,6 +28,20 @@ __xdata struct ao_task *__data ao_cur_task; ao_arch_task_globals #endif +#define AO_CHECK_STACK 0 + +#if AO_CHECK_STACK +static uint8_t in_yield; + +static inline void ao_check_stack(void) { + uint8_t q; + if (!in_yield && ao_cur_task && &q < &ao_cur_task->stack[0]) + ao_panic(AO_PANIC_STACK); +} +#else +#define ao_check_stack() +#endif + void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant { @@ -68,6 +82,9 @@ ao_yield(void) ao_arch_naked_define ao_arch_isr_stack(); +#if 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 */ @@ -97,6 +114,10 @@ ao_yield(void) ao_arch_naked_define } } } +#if CHECK_STACK + cli(); + in_yield = 0; +#endif ao_arch_restore_stack(); } @@ -117,6 +138,7 @@ ao_wakeup(__xdata void *wchan) { uint8_t i; + ao_check_stack(); for (i = 0; i < ao_num_tasks; i++) if (ao_tasks[i]->wchan == wchan) ao_tasks[i]->wchan = NULL; -- cgit v1.2.3 From 4847595e0383e5ff9c5a373f3c7f2af8c210c50a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:25:00 -0700 Subject: altos: ao_ignite.c is no longer cc1111 specific Move it to core Signed-off-by: Keith Packard --- src/cc1111/ao_ignite.c | 193 --------------------------------------------- src/core/ao_ignite.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 210 insertions(+), 193 deletions(-) delete mode 100644 src/cc1111/ao_ignite.c create mode 100644 src/core/ao_ignite.c (limited to 'src/core') diff --git a/src/cc1111/ao_ignite.c b/src/cc1111/ao_ignite.c deleted file mode 100644 index cf07dfe8..00000000 --- a/src/cc1111/ao_ignite.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright © 2009 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" -#include - -__xdata struct ao_ignition ao_ignition[2]; - -void -ao_ignite(enum ao_igniter igniter) __critical -{ - ao_ignition[igniter].request = 1; - ao_wakeup(&ao_ignition); -} - -enum ao_igniter_status -ao_igniter_status(enum ao_igniter igniter) -{ - __xdata struct ao_data packet; - __pdata int16_t value; - __pdata uint8_t request, firing, fired; - - __critical { - ao_data_get(&packet); - request = ao_ignition[igniter].request; - fired = ao_ignition[igniter].fired; - firing = ao_ignition[igniter].firing; - } - if (firing || (request && !fired)) - return ao_igniter_active; - - value = (AO_IGNITER_CLOSED>>1); - switch (igniter) { - case ao_igniter_drogue: - value = packet.adc.sense_d; - break; - case ao_igniter_main: - value = packet.adc.sense_m; - break; - } - if (value < AO_IGNITER_OPEN) - return ao_igniter_open; - else if (value > AO_IGNITER_CLOSED) - return ao_igniter_ready; - else - return ao_igniter_unknown; -} - -void -ao_igniter_fire(enum ao_igniter igniter) __critical -{ - ao_mutex_get(&ao_radio_mutex); - ao_ignition[igniter].firing = 1; - switch(ao_config.ignite_mode) { - case AO_IGNITE_MODE_DUAL: - switch (igniter) { - case ao_igniter_drogue: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; - break; - case ao_igniter_main: - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; - break; - } - break; - case AO_IGNITE_MODE_APOGEE: - switch (igniter) { - case ao_igniter_drogue: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; - ao_delay(AO_IGNITER_CHARGE_TIME); - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; - break; - } - break; - case AO_IGNITE_MODE_MAIN: - switch (igniter) { - case ao_igniter_main: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; - ao_delay(AO_IGNITER_CHARGE_TIME); - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; - break; - } - break; - } - ao_ignition[igniter].firing = 0; - ao_mutex_put(&ao_radio_mutex); -} - -void -ao_igniter(void) -{ - __xdata enum ao_ignter igniter; - - ao_config_get(); - for (;;) { - ao_sleep(&ao_ignition); - for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) { - if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) { - if (igniter == ao_igniter_drogue && ao_config.apogee_delay) - ao_delay(AO_SEC_TO_TICKS(ao_config.apogee_delay)); - - ao_igniter_fire(igniter); - ao_delay(AO_IGNITER_CHARGE_TIME); - ao_ignition[igniter].fired = 1; - } - } - } -} - -void -ao_ignite_manual(void) -{ - ao_cmd_white(); - if (!ao_match_word("DoIt")) - return; - ao_cmd_white(); - if (ao_cmd_lex_c == 'm') { - if(ao_match_word("main")) - ao_igniter_fire(ao_igniter_main); - } else { - if(ao_match_word("drogue")) - ao_igniter_fire(ao_igniter_drogue); - } -} - -static __code char * __code igniter_status_names[] = { - "unknown", "ready", "active", "open" -}; - -void -ao_ignite_print_status(enum ao_igniter igniter, __code char *name) __reentrant -{ - enum ao_igniter_status status = ao_igniter_status(igniter); - printf("Igniter: %6s Status: %s\n", - name, - igniter_status_names[status]); -} - -void -ao_ignite_test(void) -{ - ao_ignite_print_status(ao_igniter_drogue, "drogue"); - ao_ignite_print_status(ao_igniter_main, "main"); -} - -__code struct ao_cmds ao_ignite_cmds[] = { - { ao_ignite_manual, "i {main|drogue}\0Fire igniter. is doit with D&I" }, - { ao_ignite_test, "t\0Test igniter" }, - { 0, NULL }, -}; - -__xdata struct ao_task ao_igniter_task; - -void -ao_ignite_set_pins(void) -{ - AO_IGNITER_DROGUE = 0; - AO_IGNITER_MAIN = 0; - AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; -} - -void -ao_igniter_init(void) -{ - ao_ignite_set_pins(); - ao_cmd_register(&ao_ignite_cmds[0]); - ao_add_task(&ao_igniter_task, ao_igniter, "igniter"); -} diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c new file mode 100644 index 00000000..561b5513 --- /dev/null +++ b/src/core/ao_ignite.c @@ -0,0 +1,210 @@ +/* + * Copyright © 2009 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" +#include + +__xdata struct ao_ignition ao_ignition[2]; + +void +ao_ignite(enum ao_igniter igniter) __critical +{ + ao_ignition[igniter].request = 1; + ao_wakeup(&ao_ignition); +} + +#ifndef AO_SENSE_DROGUE +#define AO_SENSE_DROGUE(p) ((p)->adc.sense_d) +#define AO_SENSE_MAIN(p) ((p)->adc.sense_m) +#endif + +enum ao_igniter_status +ao_igniter_status(enum ao_igniter igniter) +{ + __xdata struct ao_data packet; + __pdata int16_t value; + __pdata uint8_t request, firing, fired; + + __critical { + ao_data_get(&packet); + request = ao_ignition[igniter].request; + fired = ao_ignition[igniter].fired; + firing = ao_ignition[igniter].firing; + } + if (firing || (request && !fired)) + return ao_igniter_active; + + value = (AO_IGNITER_CLOSED>>1); + switch (igniter) { + case ao_igniter_drogue: + value = AO_SENSE_DROGUE(&packet); + break; + case ao_igniter_main: + value = AO_SENSE_MAIN(&packet); + break; + } + if (value < AO_IGNITER_OPEN) + return ao_igniter_open; + else if (value > AO_IGNITER_CLOSED) + return ao_igniter_ready; + else + return ao_igniter_unknown; +} + +#ifndef AO_IGNITER_SET_DROGUE +#define AO_IGNITER_SET_DROGUE(v) AO_IGNITER_DROGUE = (v) +#define AO_IGNITER_SET_MAIN(v) AO_IGNITER_MAIN = (v) +#endif + +#ifndef AO_IGNITER_FIRE_TIME +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#endif + +#ifndef AO_IGNITER_CHARGE_TIME +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) +#endif + +void +ao_igniter_fire(enum ao_igniter igniter) __critical +{ + ao_mutex_get(&ao_radio_mutex); + ao_ignition[igniter].firing = 1; + switch(ao_config.ignite_mode) { + case AO_IGNITE_MODE_DUAL: + switch (igniter) { + case ao_igniter_drogue: + AO_IGNITER_SET_DROGUE(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_DROGUE(0); + break; + case ao_igniter_main: + AO_IGNITER_SET_MAIN(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_MAIN(0); + break; + } + break; + case AO_IGNITE_MODE_APOGEE: + switch (igniter) { + case ao_igniter_drogue: + AO_IGNITER_SET_DROGUE(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_DROGUE(0); + ao_delay(AO_IGNITER_CHARGE_TIME); + AO_IGNITER_SET_MAIN(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_MAIN(0); + break; + } + break; + case AO_IGNITE_MODE_MAIN: + switch (igniter) { + case ao_igniter_main: + AO_IGNITER_SET_DROGUE(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_DROGUE(0); + ao_delay(AO_IGNITER_CHARGE_TIME); + AO_IGNITER_SET_MAIN(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_MAIN(0); + break; + } + break; + } + ao_ignition[igniter].firing = 0; + ao_mutex_put(&ao_radio_mutex); +} + +void +ao_igniter(void) +{ + __xdata enum ao_igniter igniter; + + ao_config_get(); + for (;;) { + ao_sleep(&ao_ignition); + for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) { + if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) { + if (igniter == ao_igniter_drogue && ao_config.apogee_delay) + ao_delay(AO_SEC_TO_TICKS(ao_config.apogee_delay)); + + ao_igniter_fire(igniter); + ao_delay(AO_IGNITER_CHARGE_TIME); + ao_ignition[igniter].fired = 1; + } + } + } +} + +void +ao_ignite_manual(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + ao_cmd_white(); + if (ao_cmd_lex_c == 'm') { + if(ao_match_word("main")) + ao_igniter_fire(ao_igniter_main); + } else { + if(ao_match_word("drogue")) + ao_igniter_fire(ao_igniter_drogue); + } +} + +static __code char * __code igniter_status_names[] = { + "unknown", "ready", "active", "open" +}; + +void +ao_ignite_print_status(enum ao_igniter igniter, __code char *name) __reentrant +{ + enum ao_igniter_status status = ao_igniter_status(igniter); + printf("Igniter: %6s Status: %s\n", + name, + igniter_status_names[status]); +} + +void +ao_ignite_test(void) +{ + ao_ignite_print_status(ao_igniter_drogue, "drogue"); + ao_ignite_print_status(ao_igniter_main, "main"); +} + +__code struct ao_cmds ao_ignite_cmds[] = { + { ao_ignite_manual, "i {main|drogue}\0Fire igniter. is doit with D&I" }, + { ao_ignite_test, "t\0Test igniter" }, + { 0, NULL }, +}; + +__xdata struct ao_task ao_igniter_task; + +void +ao_ignite_set_pins(void) +{ + ao_enable_output(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, 0); + ao_enable_output(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, 0); +} + +void +ao_igniter_init(void) +{ + ao_ignite_set_pins(); + ao_cmd_register(&ao_ignite_cmds[0]); + ao_add_task(&ao_igniter_task, ao_igniter, "igniter"); +} -- cgit v1.2.3 From a00aff5ee93ea9763b5c0466fcecc823cad135ef Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 01:20:43 -0700 Subject: altos: Don't try to grab radio while firing MM igniters If you're in idle mode, you stop forever as the packet mode receiver will own the radio mutex forever. Signed-off-by: Keith Packard --- src/core/ao_ignite.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/core') diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c index 561b5513..d4aef153 100644 --- a/src/core/ao_ignite.c +++ b/src/core/ao_ignite.c @@ -81,7 +81,9 @@ ao_igniter_status(enum ao_igniter igniter) void ao_igniter_fire(enum ao_igniter igniter) __critical { +#ifndef MEGAMETRUM ao_mutex_get(&ao_radio_mutex); +#endif ao_ignition[igniter].firing = 1; switch(ao_config.ignite_mode) { case AO_IGNITE_MODE_DUAL: @@ -126,7 +128,9 @@ ao_igniter_fire(enum ao_igniter igniter) __critical break; } ao_ignition[igniter].firing = 0; +#ifndef MEGAMETRUM ao_mutex_put(&ao_radio_mutex); +#endif } void -- cgit v1.2.3 From 84f9a525c64491afa9b7a565e3c10a4cee106e14 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 17:17:44 -0700 Subject: altos: Clean up radio CRC handling Make the FEC code just set the CRC_OK bit like the cc1111 radio does; eliminates a bunch of weird conventions across the FEC API. Signed-off-by: Keith Packard --- src/core/ao.h | 7 +++++++ src/core/ao_fec.h | 2 ++ src/core/ao_fec_rx.c | 26 +++++++++++++++----------- src/drivers/ao_cc1120.c | 7 +------ src/drivers/ao_packet.c | 4 +--- src/test/ao_fec_test.c | 21 ++++++++++----------- 6 files changed, 36 insertions(+), 31 deletions(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index 62eb488e..861a0fd4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -511,6 +511,13 @@ 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 +#else +#include +#define AO_RADIO_STATUS_CRC_OK AO_FEC_DECODE_CRC_OK +#endif + void ao_radio_general_isr(void) ao_arch_interrupt(16); diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index f1192b62..771732bd 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -70,6 +70,8 @@ ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out); #define AO_FEC_DECODE_BLOCK (32) /* callback must return multiples of this many bits */ +#define AO_FEC_DECODE_CRC_OK 0x80 /* stored in out[out_len-1] */ + uint8_t ao_fec_decode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()); diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index 0d400bb0..d4c98475 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -211,6 +211,7 @@ ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, ui int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */ uint32_t min_cost; /* lowest cost */ uint8_t min_state; /* lowest cost state */ + uint8_t byte; /* Find the best fit at the current point * of the decode. @@ -238,24 +239,27 @@ ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, ui printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n", i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); #endif - if (out_len) { - uint8_t byte = (bits[p][min_state] >> dist) ^ *whiten++; + byte = (bits[p][min_state] >> dist) ^ *whiten++; + *out++ = byte; + if (out_len > 2) + crc = ao_fec_crc_byte(byte, crc); - if (out_len > 2) { - crc = ao_fec_crc_byte(byte, crc); - *out++ = byte; - } else { - *out++ = byte ^ (crc >> 8); - crc <<= 8; - } - --out_len; + if (!--out_len) { + if ((out[-2] == (uint8_t) (crc >> 8)) && + out[-1] == (uint8_t) crc) + out[-1] = AO_FEC_DECODE_CRC_OK; + else + out[-1] = 0; + out[-2] = 0; + goto done; } o += 8; } } +done: #if AO_PROFILE ao_fec_decode_start = start_tick; ao_fec_decode_end = ao_profile_tick(); #endif - return len/16; + return 1; } diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index c974613e..30663042 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -690,12 +690,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) ao_radio_put(); - /* Construct final packet */ - - if (ret && ((uint8_t *) d)[size] == 0 && ((uint8_t *)d)[size+1] == 0) - ((uint8_t *) d)[size + 1] = 0x80; - else - ((uint8_t *) d)[size + 1] = 0x00; + /* Store the received RSSI value; the crc-OK byte is already done */ ((uint8_t *) d)[size] = (uint8_t) rssi; diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index 19fe0558..28a0c415 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -65,10 +65,8 @@ ao_packet_recv(void) /* Check to see if we got a valid packet */ if (!dma_done) return 0; -#ifdef PKT_APPEND_STATUS_1_CRC_OK - if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) + if (!(ao_rx_packet.status & AO_RADIO_STATUS_CRC_OK)) return 0; -#endif /* Accept packets with matching call signs, or any packet if * our callsign hasn't been configured diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index 8ce532c8..671fcafc 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -268,18 +268,17 @@ int ao_real_packet(void) { uint8_t decode[64]; - uint8_t decode_len; - int ok = 0; + int ok; - decode_len = ao_fec_decode(real_packet, 576, decode, 34, NULL); + ok = ao_fec_decode(real_packet, 576, decode, 34, NULL); - if (decode[32] == 0 && decode[33] == 0) { + if (ok && decode[33] == AO_FEC_DECODE_CRC_OK) { printf ("match\n"); - ao_fec_dump_bytes(decode, decode_len, "Decode"); - ok = 1; + ao_fec_dump_bytes(decode, 34, "Decode"); } else { printf ("actual packet crc error\n"); + ok = 0; } return ok; } @@ -302,7 +301,7 @@ main(int argc, char **argv) int receive_len, receive_errors; uint8_t decode[DECODE_LEN(sizeof(original))]; - int decode_len; + int decode_ok; int errors = 0; int error; @@ -327,17 +326,17 @@ main(int argc, char **argv) receive_len = transmit_len; /* Decode it */ - decode_len = ao_fec_decode(receive, receive_len, decode, original_len + 2, NULL); + decode_ok = ao_fec_decode(receive, receive_len, decode, original_len + 2, NULL); /* Check to see if we received the right data */ error = 0; - if (decode_len < original_len + 2) { - printf ("len mis-match\n"); + if (!decode_ok) { + printf ("decode failed\n"); error++; } - if (decode[original_len] != 0 || decode[original_len+1] != 0) { + if (decode[original_len +1] != AO_FEC_DECODE_CRC_OK) { printf ("crc mis-match\n"); error++; } -- cgit v1.2.3 From 407cefae9cb95c5910b3bd79851776c48729e06b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 19:45:22 -0700 Subject: altos: Unroll viterbi state loop for >30% performance boost 9.3ms vs 14.7ms, a clear win. Signed-off-by: Keith Packard --- src/core/ao_fec_rx.c | 56 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 22 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index d4c98475..c1a3918b 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -161,31 +161,43 @@ ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, ui cost[n][state] = 0x7fffffff; /* Compute path costs and accumulate output bit path - * for each state and encoded bit value + * for each state and encoded bit value. Unrolling + * this loop is worth about > 30% performance boost. + * Decoding 76-byte remote access packets is reduced + * from 14.700ms to 9.3ms */ - for (state = 0; state < NUM_STATE; state++) { - uint32_t bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) + - (uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)+1])); - { - uint32_t cost0 = cost[p][state] + bitcost; - uint8_t state0 = ao_next_state(state, 0); - - if (cost0 < cost[n][state0]) { - cost[n][state0] = cost0; - bits[n][state0] = (bits[p][state] << 1) | (state & 1); - } - } - { - uint32_t cost1 = cost[p][state] + 510 - bitcost; - uint8_t state1 = ao_next_state(state, 1); - - if (cost1 < cost[n][state1]) { - cost[n][state1] = cost1; - bits[n][state1] = (bits[p][state] << 1) | (state & 1); - } - } +#define DO_STATE(state) { \ + uint32_t bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) + \ + (uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)+1])); \ + { \ + uint32_t cost0 = cost[p][state] + bitcost; \ + uint8_t state0 = ao_next_state(state, 0); \ + \ + if (cost0 < cost[n][state0]) { \ + cost[n][state0] = cost0; \ + bits[n][state0] = (bits[p][state] << 1) | (state & 1); \ + } \ + } \ + { \ + uint32_t cost1 = cost[p][state] + 510 - bitcost; \ + uint8_t state1 = ao_next_state(state, 1); \ + \ + if (cost1 < cost[n][state1]) { \ + cost[n][state1] = cost1; \ + bits[n][state1] = (bits[p][state] << 1) | (state & 1); \ + } \ + } \ } + DO_STATE(0); + DO_STATE(1); + DO_STATE(2); + DO_STATE(3); + DO_STATE(4); + DO_STATE(5); + DO_STATE(6); + DO_STATE(7); + #if 0 printf ("bit %3d symbol %2x %2x:", i/2, s0, s1); for (state = 0; state < NUM_STATE; state++) { -- cgit v1.2.3 From dd623b21cb904238c6d903b6936ff2f8ebf6f339 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 23:03:33 -0700 Subject: altos: Allow megametrum to be built without using the mag sensor I'm having trouble getting it working reliably, so we'll like disable it for now. This patch makes that possible. Signed-off-by: Keith Packard --- src/core/ao_log_mega.c | 8 +++++++- src/core/ao_telemetry.c | 4 ++++ src/megametrum-v0.1/ao_megametrum.c | 6 ++++++ 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index e7c2b0d9..ac1590db 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -112,18 +112,24 @@ ao_log(void) log.tick = ao_data_ring[ao_log_data_pos].tick; if ((int16_t) (log.tick - next_sensor) >= 0) { log.type = AO_LOG_SENSOR; +#if HAS_MS5607 log.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607_raw.pres; log.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607_raw.temp; +#endif +#if HAS_MPU6000 log.u.sensor.accel_x = ao_data_ring[ao_log_data_pos].mpu6000.accel_x; log.u.sensor.accel_y = ao_data_ring[ao_log_data_pos].mpu6000.accel_y; log.u.sensor.accel_z = ao_data_ring[ao_log_data_pos].mpu6000.accel_z; log.u.sensor.gyro_x = ao_data_ring[ao_log_data_pos].mpu6000.gyro_x; log.u.sensor.gyro_y = ao_data_ring[ao_log_data_pos].mpu6000.gyro_y; log.u.sensor.gyro_z = ao_data_ring[ao_log_data_pos].mpu6000.gyro_z; +#endif +#if HAS_HMC5883 log.u.sensor.mag_x = ao_data_ring[ao_log_data_pos].hmc5883.x; log.u.sensor.mag_y = ao_data_ring[ao_log_data_pos].hmc5883.y; log.u.sensor.mag_z = ao_data_ring[ao_log_data_pos].hmc5883.z; - log.u.sensor.accel = ao_data_ring[ao_log_data_pos].adc.accel; +#endif + log.u.sensor.accel = ao_data_accel(&ao_data_ring[ao_log_data_pos]); ao_log_mega(&log); if (ao_log_state <= ao_flight_coast) next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index b3ce8ba9..3c747520 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -104,6 +104,7 @@ ao_send_mega_sensor(void) telemetry.mega_sensor.pres = ao_data_pres(packet); telemetry.mega_sensor.temp = ao_data_temp(packet); +#if HAS_MPU6000 telemetry.mega_sensor.accel_x = packet->mpu6000.accel_x; telemetry.mega_sensor.accel_y = packet->mpu6000.accel_y; telemetry.mega_sensor.accel_z = packet->mpu6000.accel_z; @@ -111,10 +112,13 @@ ao_send_mega_sensor(void) telemetry.mega_sensor.gyro_x = packet->mpu6000.gyro_x; telemetry.mega_sensor.gyro_y = packet->mpu6000.gyro_y; telemetry.mega_sensor.gyro_z = packet->mpu6000.gyro_z; +#endif +#if HAS_HMC5883 telemetry.mega_sensor.mag_x = packet->hmc5883.x; telemetry.mega_sensor.mag_y = packet->hmc5883.y; telemetry.mega_sensor.mag_z = packet->hmc5883.z; +#endif ao_radio_send(&telemetry, sizeof (telemetry)); } diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 749f251d..a6d93733 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -43,9 +43,15 @@ main(void) ao_beep_init(); ao_cmd_init(); +#if HAS_MS5607 ao_ms5607_init(); +#endif +#if HAS_HMC5883 ao_hmc5883_init(); +#endif +#if HAS_MPU6000 ao_mpu6000_init(); +#endif ao_storage_init(); -- cgit v1.2.3 From 933fc7e4c2f617e49e1cfdf45b83695290b51456 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jul 2012 23:44:10 -0700 Subject: altos: Do not block igniters on the radio mutex. Blocking igniters on the radio mutex fails when doing igniter testing over the RF link; the packet receiver task will never release the mutex and the CPU at the same time, causing the system to lock up. Signed-off-by: Keith Packard --- src/core/ao_ignite.c | 6 ------ src/telemetrum-v1.1/.sdcdbrc | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c index d4aef153..e82de355 100644 --- a/src/core/ao_ignite.c +++ b/src/core/ao_ignite.c @@ -81,9 +81,6 @@ ao_igniter_status(enum ao_igniter igniter) void ao_igniter_fire(enum ao_igniter igniter) __critical { -#ifndef MEGAMETRUM - ao_mutex_get(&ao_radio_mutex); -#endif ao_ignition[igniter].firing = 1; switch(ao_config.ignite_mode) { case AO_IGNITE_MODE_DUAL: @@ -128,9 +125,6 @@ ao_igniter_fire(enum ao_igniter igniter) __critical break; } ao_ignition[igniter].firing = 0; -#ifndef MEGAMETRUM - ao_mutex_put(&ao_radio_mutex); -#endif } void diff --git a/src/telemetrum-v1.1/.sdcdbrc b/src/telemetrum-v1.1/.sdcdbrc index 710b4a2f..fbe9a599 100644 --- a/src/telemetrum-v1.1/.sdcdbrc +++ b/src/telemetrum-v1.1/.sdcdbrc @@ -1 +1 @@ ---directory=.. +--directory=../cc1111:../product:../core:../drivers:. -- cgit v1.2.3 From e8ab00cc45e48230e3b2018ce959114d3fedd228 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jul 2012 20:59:35 -0700 Subject: altos: Viterbi performance improvments. Down to 5.7ms for command decode Stealing more of Phil's good ideas, decoding a command mode packet has been reduced from 9ms to 5.7ms. Lots more comments to help future-me figure out how this code works. Signed-off-by: Keith Packard --- src/core/ao_fec_rx.c | 105 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 32 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index c1a3918b..64426d72 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -62,7 +62,9 @@ static inline uint16_t ao_interleave_index(uint16_t i) { } #define NUM_STATE 8 -#define NUM_HIST 8 +#define NUM_HIST 24 + +typedef uint32_t bits_t; #define V_0 0xff #define V_1 0x00 @@ -97,7 +99,7 @@ uint8_t ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) { static uint32_t cost[2][NUM_STATE]; /* path cost */ - static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ + static bits_t bits[2][NUM_STATE]; /* save bits to quickly output them */ uint16_t i; /* input byte index */ uint16_t b; /* encoded symbol index (bytes/2) */ @@ -154,54 +156,93 @@ ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, ui avail -= 2; - /* Reset next costs to 'impossibly high' values so that - * the first path through this state is cheaper than this - */ - for (state = 0; state < NUM_STATE; state++) - cost[n][state] = 0x7fffffff; - /* Compute path costs and accumulate output bit path * for each state and encoded bit value. Unrolling * this loop is worth about > 30% performance boost. * Decoding 76-byte remote access packets is reduced - * from 14.700ms to 9.3ms + * from 14.700ms to 9.3ms. Redoing the loop to + * directly compare the two pasts for each future state + * reduces this down to 5.7ms + */ + + /* Ok, of course this is tricky, it's optimized. + * + * First, it's important to realize that we have 8 + * states representing the combinations of the three + * most recent bits from the encoder. Flipping any + * of these three bits flips both output bits. + * + * 'state<<1' represents the target state for a new + * bit value of 0. '(state<<1)+1' represents the + * target state for a new bit value of 1. + * + * 'state' is the previous state with an oldest bit + * value of 0. 'state + 4' is the previous state with + * an oldest bit value of 1. These two states will + * either lead to 'state<<1' or '(state<<1)+1', depending + * on whether the next encoded bit was a zero or a one. + * + * m0 and m1 are the cost of coming to 'state<<1' from + * one of the two possible previous states 'state' and + * 'state + 4'. + * + * Because we know the expected values of each + * received bit are flipped between these two previous + * states: + * + * bitcost(state+4) = 510 - bitcost(state) + * + * With those two total costs in hand, we then pick + * the lower as the cost of the 'state<<1', and compute + * the path of bits leading to that state. + * + * Then, do the same for '(state<<1) + 1'. This time, + * instead of computing the m0 and m1 values from + * scratch, because the only difference is that we're + * expecting a one bit instead of a zero bit, we just + * flip the bitcost values around to match the + * expected transmitted bits with some tricky + * arithmetic which is equivalent to: + * + * m0 = cost[p][state] + (510 - bitcost); + * m1 = cost[p][state+4] + bitcost + * + * Then, the lowest cost and bit trace of the new state + * is saved. */ + #define DO_STATE(state) { \ - uint32_t bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) + \ - (uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)+1])); \ - { \ - uint32_t cost0 = cost[p][state] + bitcost; \ - uint8_t state0 = ao_next_state(state, 0); \ + uint32_t bitcost; \ + \ + uint32_t m0; \ + uint32_t m1; \ + uint32_t bit; \ + \ + bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) + \ + (uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)|1])); \ \ - if (cost0 < cost[n][state0]) { \ - cost[n][state0] = cost0; \ - bits[n][state0] = (bits[p][state] << 1) | (state & 1); \ - } \ - } \ - { \ - uint32_t cost1 = cost[p][state] + 510 - bitcost; \ - uint8_t state1 = ao_next_state(state, 1); \ + m0 = cost[p][state] + bitcost; \ + m1 = cost[p][state+4] + (510 - bitcost); \ + bit = m0 > m1; \ + cost[n][state<<1] = bit ? m1 : m0; \ + bits[n][state<<1] = (bits[p][state + (bit<<2)] << 1) | (state&1); \ \ - if (cost1 < cost[n][state1]) { \ - cost[n][state1] = cost1; \ - bits[n][state1] = (bits[p][state] << 1) | (state & 1); \ - } \ - } \ + m0 -= (bitcost+bitcost-510); \ + m1 += (bitcost+bitcost-510); \ + bit = m0 > m1; \ + cost[n][(state<<1)+1] = bit ? m1 : m0; \ + bits[n][(state<<1)+1] = (bits[p][state + (bit<<2)] << 1) | (state&1); \ } DO_STATE(0); DO_STATE(1); DO_STATE(2); DO_STATE(3); - DO_STATE(4); - DO_STATE(5); - DO_STATE(6); - DO_STATE(7); #if 0 printf ("bit %3d symbol %2x %2x:", i/2, s0, s1); for (state = 0; state < NUM_STATE; state++) { - printf (" %5d(%04x)", cost[n][state], bits[n][state]); + printf (" %8u(%08x)", cost[n][state], bits[n][state]); } printf ("\n"); #endif -- cgit v1.2.3 From 702ca87983594880d7926d2317d63802af82746e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 15:07:34 -0700 Subject: altos: remove stale ao_flight.c and ao_sample.c The mega-metrum versions are now the official versions Signed-off-by: Keith Packard --- src/core/ao_flight.c | 350 --------------------------------------------------- src/core/ao_sample.c | 214 ------------------------------- 2 files changed, 564 deletions(-) delete mode 100644 src/core/ao_flight.c delete mode 100644 src/core/ao_sample.c (limited to 'src/core') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c deleted file mode 100644 index 494e656d..00000000 --- a/src/core/ao_flight.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright © 2009 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_FLIGHT_TEST -#include "ao.h" -#endif - -#ifndef HAS_ACCEL -#error Please define HAS_ACCEL -#endif - -#ifndef HAS_GPS -#error Please define HAS_GPS -#endif - -#ifndef HAS_USB -#error Please define HAS_USB -#endif - -/* Main flight thread. */ - -__pdata enum ao_flight_state ao_flight_state; /* current flight state */ -__pdata uint16_t ao_boost_tick; /* time of launch detect */ - -/* - * track min/max data over a long interval to detect - * resting - */ -static __data uint16_t ao_interval_end; -static __data int16_t ao_interval_min_height; -static __data int16_t ao_interval_max_height; -static __data int16_t ao_coast_avg_accel; - -__pdata uint8_t ao_flight_force_idle; - -/* We also have a clock, which can be used to sanity check things in - * case of other failures - */ - -#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) - -/* Landing is detected by getting constant readings from both pressure and accelerometer - * for a fairly long time (AO_INTERVAL_TICKS) - */ -#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) - -#define abs(a) ((a) < 0 ? -(a) : (a)) - -void -ao_flight(void) -{ - ao_sample_init(); - ao_flight_state = ao_flight_startup; - for (;;) { - - /* - * Process ADC samples, just looping - * until the sensors are calibrated. - */ - if (!ao_sample()) - continue; - - switch (ao_flight_state) { - case ao_flight_startup: - - /* Check to see what mode we should go to. - * - Invalid mode if accel cal appears to be out - * - pad mode if we're upright, - * - idle mode otherwise - */ -#if HAS_ACCEL - if (ao_config.accel_plus_g == 0 || - ao_config.accel_minus_g == 0 || - ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || - ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) - { - /* Detected an accel value outside -1.5g to 1.5g - * (or uncalibrated values), so we go into invalid mode - */ - ao_flight_state = ao_flight_invalid; - - /* Turn on packet system in invalid mode on TeleMetrum */ - ao_packet_slave_start(); - } else -#endif - if (!ao_flight_force_idle -#if HAS_ACCEL - && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP -#endif - ) - { - /* Set pad mode - we can fly! */ - ao_flight_state = ao_flight_pad; -#if HAS_USB - /* Disable the USB controller in flight mode - * to save power - */ - ao_usb_disable(); -#endif - -#if !HAS_ACCEL - /* Disable packet mode in pad state on TeleMini */ - ao_packet_slave_stop(); -#endif - - /* Turn on telemetry system */ - ao_rdf_set(1); - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); - - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - } else { - /* Set idle mode */ - ao_flight_state = ao_flight_idle; - -#if HAS_ACCEL - /* Turn on packet system in idle mode on TeleMetrum */ - ao_packet_slave_start(); -#endif - - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - } - /* wakeup threads due to state change */ - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - - break; - case ao_flight_pad: - - /* pad to boost: - * - * barometer: > 20m vertical motion - * OR - * accelerometer: > 2g AND velocity > 5m/s - * - * The accelerometer should always detect motion before - * the barometer, but we use both to make sure this - * transition is detected. If the device - * doesn't have an accelerometer, then ignore the - * speed and acceleration as they are quite noisy - * on the pad. - */ - if (ao_height > AO_M_TO_HEIGHT(20) -#if HAS_ACCEL - || (ao_accel > AO_MSS_TO_ACCEL(20) && - ao_speed > AO_MS_TO_SPEED(5)) -#endif - ) - { - ao_flight_state = ao_flight_boost; - ao_boost_tick = ao_sample_tick; - - /* start logging data */ - ao_log_start(); - - /* Increase telemetry rate */ - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); - - /* disable RDF beacon */ - ao_rdf_set(0); - -#if HAS_GPS - /* Record current GPS position by waking up GPS log tasks */ - ao_wakeup(&ao_gps_data); - ao_wakeup(&ao_gps_tracking_data); -#endif - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - case ao_flight_boost: - - /* boost to fast: - * - * accelerometer: start to fall at > 1/4 G - * OR - * time: boost for more than 15 seconds - * - * Detects motor burn out by the switch from acceleration to - * deceleration, or by waiting until the maximum burn duration - * (15 seconds) has past. - */ - if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || - (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX) - { -#if HAS_ACCEL - ao_flight_state = ao_flight_fast; - ao_coast_avg_accel = ao_accel; -#else - ao_flight_state = ao_flight_coast; -#endif - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; -#if HAS_ACCEL - case ao_flight_fast: - /* - * This is essentially the same as coast, - * but the barometer is being ignored as - * it may be unreliable. - */ - if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) - { - ao_flight_state = ao_flight_coast; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } else - goto check_re_boost; - break; -#endif - case ao_flight_coast: - - /* - * By customer request - allow the user - * to lock out apogee detection for a specified - * number of seconds. - */ - if (ao_config.apogee_lockout) { - if ((ao_sample_tick - ao_boost_tick) < - AO_SEC_TO_TICKS(ao_config.apogee_lockout)) - break; - } - - /* apogee detect: coast to drogue deploy: - * - * speed: < 0 - * - * Also make sure the model altitude is tracking - * the measured altitude reasonably closely; otherwise - * we're probably transsonic. - */ - if (ao_speed < 0 -#if !HAS_ACCEL - && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) -#endif - ) - { - /* ignite the drogue charge */ - ao_ignite(ao_igniter_drogue); - - /* slow down the telemetry system */ - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); - - /* Turn the RDF beacon back on */ - ao_rdf_set(1); - - /* and enter drogue state */ - ao_flight_state = ao_flight_drogue; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } -#if HAS_ACCEL - else { - check_re_boost: - ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); - if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) { - ao_boost_tick = ao_sample_tick; - ao_flight_state = ao_flight_boost; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - } -#endif - - break; - case ao_flight_drogue: - - /* drogue to main deploy: - * - * barometer: reach main deploy altitude - * - * Would like to use the accelerometer for this test, but - * the orientation of the flight computer is unknown after - * drogue deploy, so we ignore it. Could also detect - * high descent rate using the pressure sensor to - * recognize drogue deploy failure and eject the main - * at that point. Perhaps also use the drogue sense lines - * to notice continutity? - */ - if (ao_height <= ao_config.main_deploy) - { - ao_ignite(ao_igniter_main); - - /* - * Start recording min/max height - * to figure out when the rocket has landed - */ - - /* initialize interval values */ - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - - ao_flight_state = ao_flight_main; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - - /* fall through... */ - case ao_flight_main: - - /* main to land: - * - * barometer: altitude stable - */ - - if (ao_avg_height < ao_interval_min_height) - ao_interval_min_height = ao_avg_height; - if (ao_avg_height > ao_interval_max_height) - ao_interval_max_height = ao_avg_height; - - if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { - if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) - { - ao_flight_state = ao_flight_landed; - - /* turn off the ADC capture */ - ao_timer_set_adc_interval(0); - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - } - break; - case ao_flight_landed: - break; - } - } -} - -static __xdata struct ao_task flight_task; - -void -ao_flight_init(void) -{ - ao_flight_state = ao_flight_startup; - ao_add_task(&flight_task, ao_flight, "flight"); -} diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c deleted file mode 100644 index 2bf9632f..00000000 --- a/src/core/ao_sample.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * 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. - */ - -#ifndef AO_FLIGHT_TEST -#include "ao.h" -#endif - -/* - * Current sensor values - */ - -__pdata uint16_t ao_sample_tick; /* time of last data */ -__pdata int16_t ao_sample_pres; -__pdata int16_t ao_sample_alt; -__pdata int16_t ao_sample_height; -#if HAS_ACCEL -__pdata int16_t ao_sample_accel; -#endif - -__data uint8_t ao_sample_adc; - -/* - * Sensor calibration values - */ - -__pdata int16_t ao_ground_pres; /* startup pressure */ -__pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ - -#if HAS_ACCEL -__pdata int16_t ao_ground_accel; /* startup acceleration */ -__pdata int16_t ao_accel_2g; /* factory accel calibration */ -__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ -#endif - -static __pdata uint8_t ao_preflight; /* in preflight mode */ - -static __pdata uint16_t nsamples; -__pdata int32_t ao_sample_pres_sum; -#if HAS_ACCEL -__pdata int32_t ao_sample_accel_sum; -#endif - -static void -ao_sample_preflight(void) -{ - /* startup state: - * - * Collect 512 samples of acceleration and pressure - * data and average them to find the resting values - */ - if (nsamples < 512) { -#if HAS_ACCEL - ao_sample_accel_sum += ao_sample_accel; -#endif - ao_sample_pres_sum += ao_sample_pres; - ++nsamples; - } else { - ao_config_get(); -#if HAS_ACCEL - ao_ground_accel = ao_sample_accel_sum >> 9; - ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; - ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; -#endif - ao_ground_pres = ao_sample_pres_sum >> 9; - ao_ground_height = ao_pres_to_altitude(ao_ground_pres); - ao_preflight = FALSE; - } -} - -uint8_t -ao_sample(void) -{ - ao_wakeup(DATA_TO_XDATA(&ao_sample_adc)); - ao_sleep(DATA_TO_XDATA(&ao_adc_head)); - while (ao_sample_adc != ao_adc_head) { - __xdata struct ao_adc *ao_adc; - - /* Capture a sample */ - ao_adc = &ao_adc_ring[ao_sample_adc]; - ao_sample_tick = ao_adc->tick; - ao_sample_pres = ao_adc->pres; - ao_sample_alt = ao_pres_to_altitude(ao_sample_pres); - ao_sample_height = ao_sample_alt - ao_ground_height; -#if HAS_ACCEL - ao_sample_accel = ao_adc->accel; -#if HAS_ACCEL_REF - /* - * Ok, the math here is a bit tricky. - * - * ao_sample_accel: ADC output for acceleration - * ao_accel_ref: ADC output for the 5V reference. - * ao_cook_accel: Corrected acceleration value - * Vcc: 3.3V supply to the CC1111 - * Vac: 5V supply to the accelerometer - * accel: input voltage to accelerometer ADC pin - * ref: input voltage to 5V reference ADC pin - * - * - * Measured acceleration is ratiometric to Vcc: - * - * ao_sample_accel accel - * ------------ = ----- - * 32767 Vcc - * - * Measured 5v reference is also ratiometric to Vcc: - * - * ao_accel_ref ref - * ------------ = ----- - * 32767 Vcc - * - * - * ao_accel_ref = 32767 * (ref / Vcc) - * - * Acceleration is measured ratiometric to the 5V supply, - * so what we want is: - * - * ao_cook_accel accel - * ------------- = ----- - * 32767 ref - * - * - * accel Vcc - * = ----- * --- - * Vcc ref - * - * ao_sample_accel 32767 - * = ------------ * ------------ - * 32767 ao_accel_ref - * - * Multiply through by 32767: - * - * ao_sample_accel * 32767 - * ao_cook_accel = -------------------- - * ao_accel_ref - * - * Now, the tricky part. Getting this to compile efficiently - * and keeping all of the values in-range. - * - * First off, we need to use a shift of 16 instead of * 32767 as SDCC - * does the obvious optimizations for byte-granularity shifts: - * - * ao_cook_accel = (ao_sample_accel << 16) / ao_accel_ref - * - * Next, lets check our input ranges: - * - * 0 <= ao_sample_accel <= 0x7fff (singled ended ADC conversion) - * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) - * - * Plugging in our input ranges, we get an output range of 0 - 0x12490, - * which is 17 bits. That won't work. If we take the accel ref and shift - * by a bit, we'll change its range: - * - * 0xe000 <= ao_accel_ref<<1 <= 0xfffe - * - * ao_cook_accel = (ao_sample_accel << 16) / (ao_accel_ref << 1) - * - * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It - * is, however, one bit too large for our signed computations. So, we - * take the result and shift that by a bit: - * - * ao_cook_accel = ((ao_sample_accel << 16) / (ao_accel_ref << 1)) >> 1 - * - * This finally creates an output range of 0 - 0x4924. As the ADC only - * provides 11 bits of data, we haven't actually lost any precision, - * just dropped a bit of noise off the low end. - */ - ao_sample_accel = (uint16_t) ((((uint32_t) ao_sample_accel << 16) / (ao_accel_ref[ao_sample_adc] << 1))) >> 1; - if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) - ao_sample_accel = 0x7fff - ao_sample_accel; - ao_adc->accel = ao_sample_accel; -#else - if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) { - ao_sample_accel = 0x7fff - ao_sample_accel; - ao_adc->accel = ao_sample_accel; - } -#endif -#endif - - if (ao_preflight) - ao_sample_preflight(); - else - ao_kalman(); - ao_sample_adc = ao_adc_ring_next(ao_sample_adc); - } - return !ao_preflight; -} - -void -ao_sample_init(void) -{ - nsamples = 0; - ao_sample_pres_sum = 0; - ao_sample_pres = 0; -#if HAS_ACCEL - ao_sample_accel_sum = 0; - ao_sample_accel = 0; -#endif - ao_sample_adc = ao_adc_head; - ao_preflight = TRUE; -} -- cgit v1.2.3 From 1ae3f467a1d7be2fc3b1a45ba12568a3a25a0099 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 15:11:36 -0700 Subject: altos: Rename *_mm.c back to *.c Was just a temporary hack to keep cc1111 products building during MM development. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 418 ++++++++++++++++++++++++++++++++++++++++ src/core/ao_flight_mm.c | 418 ---------------------------------------- src/core/ao_sample.c | 138 +++++++++++++ src/core/ao_sample_mm.c | 138 ------------- src/megametrum-v0.1/Makefile | 4 +- src/product/Makefile.telemetrum | 4 +- src/product/Makefile.telemini | 4 +- src/product/Makefile.telenano | 2 +- src/test/Makefile | 9 +- src/test/ao_flight_test.c | 35 ++-- 10 files changed, 591 insertions(+), 579 deletions(-) create mode 100644 src/core/ao_flight.c delete mode 100644 src/core/ao_flight_mm.c create mode 100644 src/core/ao_sample.c delete mode 100644 src/core/ao_sample_mm.c (limited to 'src/core') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c new file mode 100644 index 00000000..a0affc48 --- /dev/null +++ b/src/core/ao_flight.c @@ -0,0 +1,418 @@ +/* + * Copyright © 2009 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_FLIGHT_TEST +#include "ao.h" +#include +#endif + +#ifndef HAS_ACCEL +#error Please define HAS_ACCEL +#endif + +#ifndef HAS_GPS +#error Please define HAS_GPS +#endif + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +#ifndef HAS_TELEMETRY +#define HAS_TELEMETRY HAS_RADIO +#endif + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ +__pdata uint16_t ao_boost_tick; /* time of launch detect */ + +/* + * track min/max data over a long interval to detect + * resting + */ +static __data uint16_t ao_interval_end; +static __data int16_t ao_interval_min_height; +static __data int16_t ao_interval_max_height; +static __data int16_t ao_coast_avg_accel; + +__pdata uint8_t ao_flight_force_idle; + +/* We also have a clock, which can be used to sanity check things in + * case of other failures + */ + +#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) + +/* Landing is detected by getting constant readings from both pressure and accelerometer + * for a fairly long time (AO_INTERVAL_TICKS) + */ +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) + +#define abs(a) ((a) < 0 ? -(a) : (a)) + +void +ao_flight(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + for (;;) { + + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + + /* Check to see what mode we should go to. + * - Invalid mode if accel cal appears to be out + * - pad mode if we're upright, + * - idle mode otherwise + */ +#if HAS_ACCEL + if (ao_config.accel_plus_g == 0 || + ao_config.accel_minus_g == 0 || + ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) + { + /* Detected an accel value outside -1.5g to 1.5g + * (or uncalibrated values), so we go into invalid mode + */ + ao_flight_state = ao_flight_invalid; + +#if HAS_RADIO && PACKET_HAS_SLAVE + /* Turn on packet system in invalid mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + } else +#endif + if (!ao_flight_force_idle +#if HAS_ACCEL + && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP +#endif + ) + { + /* Set pad mode - we can fly! */ + ao_flight_state = ao_flight_pad; +#if HAS_USB && HAS_RADIO + /* Disable the USB controller in flight mode + * to save power + */ + ao_usb_disable(); +#endif + +#if !HAS_ACCEL + /* Disable packet mode in pad state on TeleMini */ + ao_packet_slave_stop(); +#endif + +#if HAS_TELEMETRY + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); +#endif + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } else { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + +#if HAS_ACCEL && HAS_RADIO && PACKET_HAS_SLAVE + /* Turn on packet system in idle mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + + break; + case ao_flight_pad: + + /* pad to boost: + * + * barometer: > 20m vertical motion + * OR + * accelerometer: > 2g AND velocity > 5m/s + * + * The accelerometer should always detect motion before + * the barometer, but we use both to make sure this + * transition is detected. If the device + * doesn't have an accelerometer, then ignore the + * speed and acceleration as they are quite noisy + * on the pad. + */ + if (ao_height > AO_M_TO_HEIGHT(20) +#if HAS_ACCEL + || (ao_accel > AO_MSS_TO_ACCEL(20) && + ao_speed > AO_MS_TO_SPEED(5)) +#endif + ) + { + ao_flight_state = ao_flight_boost; + ao_boost_tick = ao_sample_tick; + + /* start logging data */ + ao_log_start(); + +#if HAS_TELEMETRY + /* Increase telemetry rate */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); + + /* disable RDF beacon */ + ao_rdf_set(0); +#endif + +#if HAS_GPS + /* Record current GPS position by waking up GPS log tasks */ + ao_wakeup(&ao_gps_data); + ao_wakeup(&ao_gps_tracking_data); +#endif + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_boost: + + /* boost to fast: + * + * accelerometer: start to fall at > 1/4 G + * OR + * time: boost for more than 15 seconds + * + * Detects motor burn out by the switch from acceleration to + * deceleration, or by waiting until the maximum burn duration + * (15 seconds) has past. + */ + if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || + (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX) + { +#if HAS_ACCEL + ao_flight_state = ao_flight_fast; + ao_coast_avg_accel = ao_accel; +#else + ao_flight_state = ao_flight_coast; +#endif + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; +#if HAS_ACCEL + case ao_flight_fast: + /* + * This is essentially the same as coast, + * but the barometer is being ignored as + * it may be unreliable. + */ + if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) + { + ao_flight_state = ao_flight_coast; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } else + goto check_re_boost; + break; +#endif + case ao_flight_coast: + + /* + * By customer request - allow the user + * to lock out apogee detection for a specified + * number of seconds. + */ + if (ao_config.apogee_lockout) { + if ((ao_sample_tick - ao_boost_tick) < + AO_SEC_TO_TICKS(ao_config.apogee_lockout)) + break; + } + + /* apogee detect: coast to drogue deploy: + * + * speed: < 0 + * + * Also make sure the model altitude is tracking + * the measured altitude reasonably closely; otherwise + * we're probably transsonic. + */ + if (ao_speed < 0 +#if !HAS_ACCEL + && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) +#endif + ) + { +#if HAS_IGNITE + /* ignite the drogue charge */ + ao_ignite(ao_igniter_drogue); +#endif + +#if HAS_TELEMETRY + /* slow down the telemetry system */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); + + /* Turn the RDF beacon back on */ + ao_rdf_set(1); +#endif + + /* and enter drogue state */ + ao_flight_state = ao_flight_drogue; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } +#if HAS_ACCEL + else { + check_re_boost: + ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); + if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) { + ao_boost_tick = ao_sample_tick; + ao_flight_state = ao_flight_boost; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + } +#endif + + break; + case ao_flight_drogue: + + /* drogue to main deploy: + * + * barometer: reach main deploy altitude + * + * Would like to use the accelerometer for this test, but + * the orientation of the flight computer is unknown after + * drogue deploy, so we ignore it. Could also detect + * high descent rate using the pressure sensor to + * recognize drogue deploy failure and eject the main + * at that point. Perhaps also use the drogue sense lines + * to notice continutity? + */ + if (ao_height <= ao_config.main_deploy) + { +#if HAS_IGNITE + ao_ignite(ao_igniter_main); +#endif + + /* + * Start recording min/max height + * to figure out when the rocket has landed + */ + + /* initialize interval values */ + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + + ao_flight_state = ao_flight_main; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + + /* fall through... */ + case ao_flight_main: + + /* main to land: + * + * barometer: altitude stable + */ + + if (ao_avg_height < ao_interval_min_height) + ao_interval_min_height = ao_avg_height; + if (ao_avg_height > ao_interval_max_height) + ao_interval_max_height = ao_avg_height; + + if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { + if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) + { + ao_flight_state = ao_flight_landed; + + /* turn off the ADC capture */ + ao_timer_set_adc_interval(0); + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + } + break; + case ao_flight_landed: + break; + } + } +} + +#if !HAS_RADIO +static inline int int_part(int16_t i) { return i >> 4; } +static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; } + +static void +ao_flight_dump(void) +{ +#if HAS_ACCEL + int16_t accel; + + accel = ((ao_ground_accel - ao_sample_accel) * ao_accel_scale) >> 16; +#endif + + printf ("sample:\n"); + printf (" tick %d\n", ao_sample_tick); + printf (" raw pres %d\n", ao_sample_pres); +#if HAS_ACCEL + printf (" raw accel %d\n", ao_sample_accel); +#endif + printf (" ground pres %d\n", ao_ground_pres); +#if HAS_ACCEL + printf (" raw accel %d\n", ao_sample_accel); + printf (" groundaccel %d\n", ao_ground_accel); + printf (" accel_2g %d\n", ao_accel_2g); +#endif + + printf (" alt %d\n", ao_sample_alt); + printf (" height %d\n", ao_sample_height); +#if HAS_ACCEL + printf (" accel %d.%02d\n", int_part(accel), frac_part(accel)); +#endif + + + printf ("kalman:\n"); + printf (" height %d\n", ao_height); + printf (" speed %d.%02d\n", int_part(ao_speed), frac_part(ao_speed)); + printf (" accel %d.%02d\n", int_part(ao_accel), frac_part(ao_accel)); + printf (" max_height %d\n", ao_max_height); + printf (" avg_height %d\n", ao_avg_height); + printf (" error_h %d\n", ao_error_h); + printf (" error_avg %d\n", ao_error_h_sq_avg); +} + +__code struct ao_cmds ao_flight_cmds[] = { + { ao_flight_dump, "F\0Dump flight status" }, + { 0, NULL }, +}; +#endif + +static __xdata struct ao_task flight_task; + +void +ao_flight_init(void) +{ + ao_flight_state = ao_flight_startup; +#if !HAS_RADIO + ao_cmd_register(&ao_flight_cmds[0]); +#endif + ao_add_task(&flight_task, ao_flight, "flight"); +} diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c deleted file mode 100644 index a0affc48..00000000 --- a/src/core/ao_flight_mm.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Copyright © 2009 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_FLIGHT_TEST -#include "ao.h" -#include -#endif - -#ifndef HAS_ACCEL -#error Please define HAS_ACCEL -#endif - -#ifndef HAS_GPS -#error Please define HAS_GPS -#endif - -#ifndef HAS_USB -#error Please define HAS_USB -#endif - -#ifndef HAS_TELEMETRY -#define HAS_TELEMETRY HAS_RADIO -#endif - -/* Main flight thread. */ - -__pdata enum ao_flight_state ao_flight_state; /* current flight state */ -__pdata uint16_t ao_boost_tick; /* time of launch detect */ - -/* - * track min/max data over a long interval to detect - * resting - */ -static __data uint16_t ao_interval_end; -static __data int16_t ao_interval_min_height; -static __data int16_t ao_interval_max_height; -static __data int16_t ao_coast_avg_accel; - -__pdata uint8_t ao_flight_force_idle; - -/* We also have a clock, which can be used to sanity check things in - * case of other failures - */ - -#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) - -/* Landing is detected by getting constant readings from both pressure and accelerometer - * for a fairly long time (AO_INTERVAL_TICKS) - */ -#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) - -#define abs(a) ((a) < 0 ? -(a) : (a)) - -void -ao_flight(void) -{ - ao_sample_init(); - ao_flight_state = ao_flight_startup; - for (;;) { - - /* - * Process ADC samples, just looping - * until the sensors are calibrated. - */ - if (!ao_sample()) - continue; - - switch (ao_flight_state) { - case ao_flight_startup: - - /* Check to see what mode we should go to. - * - Invalid mode if accel cal appears to be out - * - pad mode if we're upright, - * - idle mode otherwise - */ -#if HAS_ACCEL - if (ao_config.accel_plus_g == 0 || - ao_config.accel_minus_g == 0 || - ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || - ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) - { - /* Detected an accel value outside -1.5g to 1.5g - * (or uncalibrated values), so we go into invalid mode - */ - ao_flight_state = ao_flight_invalid; - -#if HAS_RADIO && PACKET_HAS_SLAVE - /* Turn on packet system in invalid mode on TeleMetrum */ - ao_packet_slave_start(); -#endif - } else -#endif - if (!ao_flight_force_idle -#if HAS_ACCEL - && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP -#endif - ) - { - /* Set pad mode - we can fly! */ - ao_flight_state = ao_flight_pad; -#if HAS_USB && HAS_RADIO - /* Disable the USB controller in flight mode - * to save power - */ - ao_usb_disable(); -#endif - -#if !HAS_ACCEL - /* Disable packet mode in pad state on TeleMini */ - ao_packet_slave_stop(); -#endif - -#if HAS_TELEMETRY - /* Turn on telemetry system */ - ao_rdf_set(1); - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); -#endif - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - } else { - /* Set idle mode */ - ao_flight_state = ao_flight_idle; - -#if HAS_ACCEL && HAS_RADIO && PACKET_HAS_SLAVE - /* Turn on packet system in idle mode on TeleMetrum */ - ao_packet_slave_start(); -#endif - - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - } - /* wakeup threads due to state change */ - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - - break; - case ao_flight_pad: - - /* pad to boost: - * - * barometer: > 20m vertical motion - * OR - * accelerometer: > 2g AND velocity > 5m/s - * - * The accelerometer should always detect motion before - * the barometer, but we use both to make sure this - * transition is detected. If the device - * doesn't have an accelerometer, then ignore the - * speed and acceleration as they are quite noisy - * on the pad. - */ - if (ao_height > AO_M_TO_HEIGHT(20) -#if HAS_ACCEL - || (ao_accel > AO_MSS_TO_ACCEL(20) && - ao_speed > AO_MS_TO_SPEED(5)) -#endif - ) - { - ao_flight_state = ao_flight_boost; - ao_boost_tick = ao_sample_tick; - - /* start logging data */ - ao_log_start(); - -#if HAS_TELEMETRY - /* Increase telemetry rate */ - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); - - /* disable RDF beacon */ - ao_rdf_set(0); -#endif - -#if HAS_GPS - /* Record current GPS position by waking up GPS log tasks */ - ao_wakeup(&ao_gps_data); - ao_wakeup(&ao_gps_tracking_data); -#endif - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - case ao_flight_boost: - - /* boost to fast: - * - * accelerometer: start to fall at > 1/4 G - * OR - * time: boost for more than 15 seconds - * - * Detects motor burn out by the switch from acceleration to - * deceleration, or by waiting until the maximum burn duration - * (15 seconds) has past. - */ - if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || - (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX) - { -#if HAS_ACCEL - ao_flight_state = ao_flight_fast; - ao_coast_avg_accel = ao_accel; -#else - ao_flight_state = ao_flight_coast; -#endif - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; -#if HAS_ACCEL - case ao_flight_fast: - /* - * This is essentially the same as coast, - * but the barometer is being ignored as - * it may be unreliable. - */ - if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) - { - ao_flight_state = ao_flight_coast; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } else - goto check_re_boost; - break; -#endif - case ao_flight_coast: - - /* - * By customer request - allow the user - * to lock out apogee detection for a specified - * number of seconds. - */ - if (ao_config.apogee_lockout) { - if ((ao_sample_tick - ao_boost_tick) < - AO_SEC_TO_TICKS(ao_config.apogee_lockout)) - break; - } - - /* apogee detect: coast to drogue deploy: - * - * speed: < 0 - * - * Also make sure the model altitude is tracking - * the measured altitude reasonably closely; otherwise - * we're probably transsonic. - */ - if (ao_speed < 0 -#if !HAS_ACCEL - && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) -#endif - ) - { -#if HAS_IGNITE - /* ignite the drogue charge */ - ao_ignite(ao_igniter_drogue); -#endif - -#if HAS_TELEMETRY - /* slow down the telemetry system */ - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); - - /* Turn the RDF beacon back on */ - ao_rdf_set(1); -#endif - - /* and enter drogue state */ - ao_flight_state = ao_flight_drogue; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } -#if HAS_ACCEL - else { - check_re_boost: - ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); - if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) { - ao_boost_tick = ao_sample_tick; - ao_flight_state = ao_flight_boost; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - } -#endif - - break; - case ao_flight_drogue: - - /* drogue to main deploy: - * - * barometer: reach main deploy altitude - * - * Would like to use the accelerometer for this test, but - * the orientation of the flight computer is unknown after - * drogue deploy, so we ignore it. Could also detect - * high descent rate using the pressure sensor to - * recognize drogue deploy failure and eject the main - * at that point. Perhaps also use the drogue sense lines - * to notice continutity? - */ - if (ao_height <= ao_config.main_deploy) - { -#if HAS_IGNITE - ao_ignite(ao_igniter_main); -#endif - - /* - * Start recording min/max height - * to figure out when the rocket has landed - */ - - /* initialize interval values */ - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - - ao_flight_state = ao_flight_main; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - - /* fall through... */ - case ao_flight_main: - - /* main to land: - * - * barometer: altitude stable - */ - - if (ao_avg_height < ao_interval_min_height) - ao_interval_min_height = ao_avg_height; - if (ao_avg_height > ao_interval_max_height) - ao_interval_max_height = ao_avg_height; - - if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { - if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) - { - ao_flight_state = ao_flight_landed; - - /* turn off the ADC capture */ - ao_timer_set_adc_interval(0); - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - } - break; - case ao_flight_landed: - break; - } - } -} - -#if !HAS_RADIO -static inline int int_part(int16_t i) { return i >> 4; } -static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; } - -static void -ao_flight_dump(void) -{ -#if HAS_ACCEL - int16_t accel; - - accel = ((ao_ground_accel - ao_sample_accel) * ao_accel_scale) >> 16; -#endif - - printf ("sample:\n"); - printf (" tick %d\n", ao_sample_tick); - printf (" raw pres %d\n", ao_sample_pres); -#if HAS_ACCEL - printf (" raw accel %d\n", ao_sample_accel); -#endif - printf (" ground pres %d\n", ao_ground_pres); -#if HAS_ACCEL - printf (" raw accel %d\n", ao_sample_accel); - printf (" groundaccel %d\n", ao_ground_accel); - printf (" accel_2g %d\n", ao_accel_2g); -#endif - - printf (" alt %d\n", ao_sample_alt); - printf (" height %d\n", ao_sample_height); -#if HAS_ACCEL - printf (" accel %d.%02d\n", int_part(accel), frac_part(accel)); -#endif - - - printf ("kalman:\n"); - printf (" height %d\n", ao_height); - printf (" speed %d.%02d\n", int_part(ao_speed), frac_part(ao_speed)); - printf (" accel %d.%02d\n", int_part(ao_accel), frac_part(ao_accel)); - printf (" max_height %d\n", ao_max_height); - printf (" avg_height %d\n", ao_avg_height); - printf (" error_h %d\n", ao_error_h); - printf (" error_avg %d\n", ao_error_h_sq_avg); -} - -__code struct ao_cmds ao_flight_cmds[] = { - { ao_flight_dump, "F\0Dump flight status" }, - { 0, NULL }, -}; -#endif - -static __xdata struct ao_task flight_task; - -void -ao_flight_init(void) -{ - ao_flight_state = ao_flight_startup; -#if !HAS_RADIO - ao_cmd_register(&ao_flight_cmds[0]); -#endif - ao_add_task(&flight_task, ao_flight, "flight"); -} diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c new file mode 100644 index 00000000..ac11eef0 --- /dev/null +++ b/src/core/ao_sample.c @@ -0,0 +1,138 @@ +/* + * 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. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#include +#endif + +/* + * Current sensor values + */ + +#ifndef PRES_TYPE +#define PRES_TYPE int32_t +#define ALT_TYPE int32_t +#define ACCEL_TYPE int16_t +#endif + +__pdata uint16_t ao_sample_tick; /* time of last data */ +__pdata pres_t ao_sample_pres; +__pdata alt_t ao_sample_alt; +__pdata alt_t ao_sample_height; +#if HAS_ACCEL +__pdata accel_t ao_sample_accel; +#endif + +__data uint8_t ao_sample_data; + +/* + * Sensor calibration values + */ + +__pdata pres_t ao_ground_pres; /* startup pressure */ +__pdata alt_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +__pdata accel_t ao_ground_accel; /* startup acceleration */ +__pdata accel_t ao_accel_2g; /* factory accel calibration */ +__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +static __pdata uint8_t ao_preflight; /* in preflight mode */ + +static __pdata uint16_t nsamples; +__pdata int32_t ao_sample_pres_sum; +#if HAS_ACCEL +__pdata int32_t ao_sample_accel_sum; +#endif + +static void +ao_sample_preflight(void) +{ + /* startup state: + * + * Collect 512 samples of acceleration and pressure + * data and average them to find the resting values + */ + if (nsamples < 512) { +#if HAS_ACCEL + ao_sample_accel_sum += ao_sample_accel; +#endif + ao_sample_pres_sum += ao_sample_pres; + ++nsamples; + } else { + ao_config_get(); +#if HAS_ACCEL + ao_ground_accel = ao_sample_accel_sum >> 9; + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; +#endif + ao_ground_pres = ao_sample_pres_sum >> 9; + ao_ground_height = pres_to_altitude(ao_ground_pres); + ao_preflight = FALSE; + } +} + + +uint8_t +ao_sample(void) +{ + ao_config_get(); + ao_wakeup(DATA_TO_XDATA(&ao_sample_data)); + ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); + while (ao_sample_data != ao_data_head) { + __xdata struct ao_data *ao_data; + + /* Capture a sample */ + ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data]; + ao_sample_tick = ao_data->tick; + + ao_data_pres_cook(ao_data); + ao_sample_pres = ao_data_pres(ao_data); + ao_sample_alt = pres_to_altitude(ao_sample_pres); + ao_sample_height = ao_sample_alt - ao_ground_height; + +#if HAS_ACCEL + ao_sample_accel = ao_data_accel_cook(ao_data); + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) + ao_sample_accel = ao_data_accel_invert(ao_sample_accel); + ao_data_set_accel(ao_data, ao_sample_accel); +#endif + + if (ao_preflight) + ao_sample_preflight(); + else + ao_kalman(); + ao_sample_data = ao_data_ring_next(ao_sample_data); + } + return !ao_preflight; +} + +void +ao_sample_init(void) +{ + nsamples = 0; + ao_sample_pres_sum = 0; + ao_sample_pres = 0; +#if HAS_ACCEL + ao_sample_accel_sum = 0; + ao_sample_accel = 0; +#endif + ao_sample_data = ao_data_head; + ao_preflight = TRUE; +} diff --git a/src/core/ao_sample_mm.c b/src/core/ao_sample_mm.c deleted file mode 100644 index ac11eef0..00000000 --- a/src/core/ao_sample_mm.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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. - */ - -#ifndef AO_FLIGHT_TEST -#include "ao.h" -#include -#endif - -/* - * Current sensor values - */ - -#ifndef PRES_TYPE -#define PRES_TYPE int32_t -#define ALT_TYPE int32_t -#define ACCEL_TYPE int16_t -#endif - -__pdata uint16_t ao_sample_tick; /* time of last data */ -__pdata pres_t ao_sample_pres; -__pdata alt_t ao_sample_alt; -__pdata alt_t ao_sample_height; -#if HAS_ACCEL -__pdata accel_t ao_sample_accel; -#endif - -__data uint8_t ao_sample_data; - -/* - * Sensor calibration values - */ - -__pdata pres_t ao_ground_pres; /* startup pressure */ -__pdata alt_t ao_ground_height; /* MSL of ao_ground_pres */ - -#if HAS_ACCEL -__pdata accel_t ao_ground_accel; /* startup acceleration */ -__pdata accel_t ao_accel_2g; /* factory accel calibration */ -__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ -#endif - -static __pdata uint8_t ao_preflight; /* in preflight mode */ - -static __pdata uint16_t nsamples; -__pdata int32_t ao_sample_pres_sum; -#if HAS_ACCEL -__pdata int32_t ao_sample_accel_sum; -#endif - -static void -ao_sample_preflight(void) -{ - /* startup state: - * - * Collect 512 samples of acceleration and pressure - * data and average them to find the resting values - */ - if (nsamples < 512) { -#if HAS_ACCEL - ao_sample_accel_sum += ao_sample_accel; -#endif - ao_sample_pres_sum += ao_sample_pres; - ++nsamples; - } else { - ao_config_get(); -#if HAS_ACCEL - ao_ground_accel = ao_sample_accel_sum >> 9; - ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; - ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; -#endif - ao_ground_pres = ao_sample_pres_sum >> 9; - ao_ground_height = pres_to_altitude(ao_ground_pres); - ao_preflight = FALSE; - } -} - - -uint8_t -ao_sample(void) -{ - ao_config_get(); - ao_wakeup(DATA_TO_XDATA(&ao_sample_data)); - ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); - while (ao_sample_data != ao_data_head) { - __xdata struct ao_data *ao_data; - - /* Capture a sample */ - ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data]; - ao_sample_tick = ao_data->tick; - - ao_data_pres_cook(ao_data); - ao_sample_pres = ao_data_pres(ao_data); - ao_sample_alt = pres_to_altitude(ao_sample_pres); - ao_sample_height = ao_sample_alt - ao_ground_height; - -#if HAS_ACCEL - ao_sample_accel = ao_data_accel_cook(ao_data); - if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) - ao_sample_accel = ao_data_accel_invert(ao_sample_accel); - ao_data_set_accel(ao_data, ao_sample_accel); -#endif - - if (ao_preflight) - ao_sample_preflight(); - else - ao_kalman(); - ao_sample_data = ao_data_ring_next(ao_sample_data); - } - return !ao_preflight; -} - -void -ao_sample_init(void) -{ - nsamples = 0; - ao_sample_pres_sum = 0; - ao_sample_pres = 0; -#if HAS_ACCEL - ao_sample_accel_sum = 0; - ao_sample_accel = 0; -#endif - ao_sample_data = ao_data_head; - ao_preflight = TRUE; -} diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 6fc9324e..13e46c97 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -67,9 +67,9 @@ ALTOS_SRC = \ ao_convert_pa.c \ ao_log.c \ ao_log_mega.c \ - ao_sample_mm.c \ + ao_sample.c \ ao_kalman.c \ - ao_flight_mm.c \ + ao_flight.c \ ao_telemetry.c \ ao_packet_slave.c \ ao_packet.c \ diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index fba2c19a..57586c95 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -36,8 +36,8 @@ CORE_SRC = \ ao_stdio.c \ ao_storage.c \ ao_task.c \ - ao_flight_mm.c \ - ao_sample_mm.c \ + ao_flight.c \ + ao_sample.c \ ao_kalman.c \ ao_log.c \ ao_log_big.c \ diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index f0ab2b14..23aed1c7 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -24,14 +24,14 @@ CORE_SRC = \ ao_cmd.c \ ao_config.c \ ao_convert.c \ - ao_flight_mm.c \ + ao_flight.c \ ao_kalman.c \ ao_log.c \ ao_log_tiny.c \ ao_mutex.c \ ao_panic.c \ ao_report.c \ - ao_sample_mm.c \ + ao_sample.c \ ao_stdio.c \ ao_storage.c \ ao_task.c \ diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index a55bcf95..ca719bbf 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -31,7 +31,7 @@ CORE_SRC = \ ao_mutex.c \ ao_panic.c \ ao_report.c \ - ao_sample_mm.c \ + ao_sample.c \ ao_stdio.c \ ao_storage.c \ ao_task.c \ diff --git a/src/test/Makefile b/src/test/Makefile index 4631fb78..963f4131 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -4,7 +4,7 @@ PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noi KALMAN=make-kalman -CFLAGS=-I.. -I. -I../core -I../drivers -O0 -g -Wall +CFLAGS=-I.. -I. -I../core -I../drivers -O3 -g -Wall all: $(PROGS) @@ -13,10 +13,10 @@ clean: install: -ao_flight_test: ao_flight_test.c ao_host.h ao_flight_mm.c ao_sample_mm.c ao_kalman.c altitude.h ao_kalman.h +ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc $(CFLAGS) -o $@ $< -ao_flight_test_noisy_accel: ao_flight_test.c ao_host.h ao_flight_mm.c ao_sample_mm.c ao_kalman.c altitude.h ao_kalman.h +ao_flight_test_noisy_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc -DNOISY_ACCEL=1 $(CFLAGS) -o $@ $< ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h @@ -42,3 +42,6 @@ ao_kalman.h: $(KALMAN) ao_fec_test: ao_fec_test.c ao_fec_tx.c ao_fec_rx.c cc $(CFLAGS) -DAO_FEC_DEBUG=1 -o $@ ao_fec_test.c ../core/ao_fec_tx.c ../core/ao_fec_rx.c -lm + +check: ao_fec_test ao_flight_test ao_flight_test_baro run-tests + ./ao_fec_test && ./run-tests \ No newline at end of file diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index baf2ad1d..9bb03d68 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -141,7 +141,7 @@ struct ao_task { int dummy; }; -#define ao_add_task(t,f,n) +#define ao_add_task(t,f,n) ((void) (t)) #define ao_log_start() #define ao_log_stop() @@ -156,6 +156,7 @@ int ao_flight_debug; FILE *emulator_in; char *emulator_app; char *emulator_name; +char *emulator_info; double emulator_error_max = 4; double emulator_height_error_max = 20; /* noise in the baro sensor */ @@ -199,6 +200,7 @@ struct ao_config ao_config; #define DATA_TO_XDATA(x) (x) #define HAS_FLIGHT 1 +#define HAS_IGNITE 1 #define HAS_ADC 1 #define HAS_USB 1 #define HAS_GPS 1 @@ -223,8 +225,8 @@ int ao_sample_prev_tick; uint16_t prev_tick; #include "ao_kalman.c" -#include "ao_sample_mm.c" -#include "ao_flight_mm.c" +#include "ao_sample.c" +#include "ao_flight.c" #define to_double(f) ((f) / 65536.0) @@ -259,10 +261,11 @@ ao_test_exit(void) main_error = fabs(ao_test_main_height_time - main_time); landed_error = fabs(ao_test_landed_height - landed_height); landed_time_error = ao_test_landed_time - landed_time; - if (drogue_error > emulator_error_max || main_error > emulator_error_max || - landed_time_error > emulator_error_max || landed_error > emulator_height_error_max) { + if (drogue_error > emulator_error_max || main_error > emulator_error_max) { printf ("%s %s\n", emulator_app, emulator_name); + if (emulator_info) + printf ("\t%s\n", emulator_info); printf ("\tApogee error %g\n", drogue_error); printf ("\tMain error %g\n", main_error); printf ("\tLanded height error %g\n", landed_error); @@ -477,10 +480,9 @@ void ao_sleep(void *wchan) { if (wchan == &ao_data_head) { - char type; - uint16_t tick; - uint16_t a, b; - int ret; + char type = 0; + uint16_t tick = 0; + uint16_t a = 0, b = 0; uint8_t bytes[1024]; union ao_telemetry_all telem; char line[1024]; @@ -676,13 +678,15 @@ ao_dump_state(void) static const struct option options[] = { { .name = "summary", .has_arg = 0, .val = 's' }, { .name = "debug", .has_arg = 0, .val = 'd' }, + { .name = "info", .has_arg = 1, .val = 'i' }, { 0, 0, 0, 0}, }; -void run_flight_fixed(char *name, FILE *f, int summary) +void run_flight_fixed(char *name, FILE *f, int summary, char *info) { emulator_name = name; emulator_in = f; + emulator_info = info; ao_summary = summary; ao_flight_init(); ao_flight(); @@ -694,13 +698,14 @@ main (int argc, char **argv) int summary = 0; int c; int i; + char *info = NULL; #if HAS_ACCEL emulator_app="full"; #else emulator_app="baro"; #endif - while ((c = getopt_long(argc, argv, "sd", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "sdi:", options, NULL)) != -1) { switch (c) { case 's': summary = 1; @@ -708,11 +713,14 @@ main (int argc, char **argv) case 'd': ao_flight_debug = 1; break; + case 'i': + info = optarg; + break; } } if (optind == argc) - run_flight_fixed("", stdin, summary); + run_flight_fixed("", stdin, summary, info); else for (i = optind; i < argc; i++) { FILE *f = fopen(argv[i], "r"); @@ -720,7 +728,8 @@ main (int argc, char **argv) perror(argv[i]); continue; } - run_flight_fixed(argv[i], f, summary); + run_flight_fixed(argv[i], f, summary, info); fclose(f); } + exit(0); } -- cgit v1.2.3 From 6694cedd560a7ea9520ef11472c2770b489187c0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 15:13:18 -0700 Subject: altos: Eliminate compiler warnings when building ao_flight_test We turn on a pile of warnings for that. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 4 +++- src/core/ao_kalman.c | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index a0affc48..39084fd0 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -48,7 +48,9 @@ __pdata uint16_t ao_boost_tick; /* time of launch detect */ static __data uint16_t ao_interval_end; static __data int16_t ao_interval_min_height; static __data int16_t ao_interval_max_height; +#if HAS_ACCEL static __data int16_t ao_coast_avg_accel; +#endif __pdata uint8_t ao_flight_force_idle; @@ -350,7 +352,7 @@ ao_flight(void) ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; } break; - case ao_flight_landed: + default: break; } } diff --git a/src/core/ao_kalman.c b/src/core/ao_kalman.c index 68725f69..59ffd8b2 100644 --- a/src/core/ao_kalman.c +++ b/src/core/ao_kalman.c @@ -172,6 +172,7 @@ ao_kalman_err_accel(void) ao_error_a = (accel - ao_k_accel) >> 16; } +#ifndef FORCE_ACCEL static void ao_kalman_correct_both(void) { @@ -242,7 +243,8 @@ ao_kalman_correct_both(void) (int32_t) AO_BOTH_K21_100 * ao_error_a; } -#ifdef FORCE_ACCEL +#else + static void ao_kalman_correct_accel(void) { @@ -258,7 +260,8 @@ ao_kalman_correct_accel(void) ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a; ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a; } -#endif + +#endif /* else FORCE_ACCEL */ #endif /* HAS_ACCEL */ void -- cgit v1.2.3 From aafa8859ecb27383f697b98f6991643b44f4721a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 20:32:31 -0700 Subject: altos: Save some memory. A few minor space savings in ao_cmd.c and ao_config.c. Don't build unused conversion functions ao_altitude_to_pres and ao_temp_to_dC Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 24 +++++++++++++----------- src/core/ao_config.c | 26 ++++++++++++++------------ src/core/ao_convert.c | 4 ++++ src/core/ao_convert_test.c | 5 +++-- src/test/ao_flight_test.c | 1 + 5 files changed, 35 insertions(+), 25 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index fbf0c347..05dbfb51 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -36,10 +36,16 @@ put_string(__code char *s) putchar(c); } +static void +backspace(void) +{ + put_string ("\010 \010"); +} + static void readline(void) { - __pdata char c; + char c; if (ao_echo()) put_string("> "); cmd_len = 0; @@ -50,7 +56,7 @@ readline(void) if (c == '\010' || c == '\177') { if (cmd_len != 0) { if (ao_echo()) - put_string("\010 \010"); + backspace(); --cmd_len; } continue; @@ -60,7 +66,7 @@ readline(void) if (c == '\025') { while (cmd_len != 0) { if (ao_echo()) - put_string("\010 \010"); + backspace(); --cmd_len; } continue; @@ -76,11 +82,8 @@ readline(void) break; } - if (cmd_len >= CMD_LEN - 2) { - if (ao_echo()) - putchar('\007'); + if (cmd_len >= CMD_LEN - 2) continue; - } cmd_line[cmd_len++] = c; if (ao_echo()) putchar(c); @@ -271,13 +274,12 @@ help(void) __pdata uint8_t cmds; __pdata uint8_t cmd; __code struct ao_cmds * __pdata cs; + const char *h; for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; - for (cmd = 0; cs[cmd].func; cmd++) - printf("%-45s %s\n", - cs[cmd].help, - cs[cmd].help+1+strlen(cs[cmd].help)); + for (cmd = 0; (h = cs[cmd].help); cmd++) + printf("%-45s %s\n", h, h + 1 + strlen(h)); } } diff --git a/src/core/ao_config.c b/src/core/ao_config.c index cc580d66..e0dabcd9 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -78,6 +78,8 @@ ao_config_set_radio(void) static void _ao_config_get(void) { + uint8_t minor; + if (ao_config_loaded) return; #if HAS_EEPROM @@ -97,37 +99,37 @@ _ao_config_get(void) ao_xmemset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); ao_xmemcpy(&ao_config.callsign, CODE_TO_XDATA(AO_CONFIG_DEFAULT_CALLSIGN), sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); - ao_config_dirty = 1; } - if (ao_config.minor != AO_CONFIG_MINOR) { + minor = ao_config.minor; + if (minor != AO_CONFIG_MINOR) { /* Fixups for minor version 1 */ - if (ao_config.minor < 1) + if (minor < 1) ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; /* Fixups for minor version 2 */ - if (ao_config.minor < 2) { + if (minor < 2) { ao_config.accel_plus_g = 0; ao_config.accel_minus_g = 0; } /* Fixups for minor version 3 */ #if HAS_RADIO - if (ao_config.minor < 3) + if (minor < 3) ao_config.radio_cal = ao_radio_cal; #endif /* Fixups for minor version 4 */ - if (ao_config.minor < 4) + if (minor < 4) ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; /* Fixupes for minor version 5 */ - if (ao_config.minor < 5) + if (minor < 5) ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; - if (ao_config.minor < 6) + if (minor < 6) ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; - if (ao_config.minor < 8) + if (minor < 8) ao_config.radio_enable = TRUE; - if (ao_config.minor < 9) + if (minor < 9) ao_xmemset(&ao_config.aes_key, '\0', AO_AES_LEN); - if (ao_config.minor < 10) + if (minor < 10) ao_config.frequency = 434550; - if (ao_config.minor < 11) + if (minor < 11) ao_config.apogee_lockout = 0; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; diff --git a/src/core/ao_convert.c b/src/core/ao_convert.c index 0969f107..aa9b5f48 100644 --- a/src/core/ao_convert.c +++ b/src/core/ao_convert.c @@ -41,6 +41,7 @@ ao_pres_to_altitude(int16_t pres) __reentrant (int32_t) altitude_table[o+1] * part + (ALT_FRAC_SCALE >> 1)) >> ALT_FRAC_BITS; } +#if AO_NEED_ALTITUDE_TO_PRES int16_t ao_altitude_to_pres(int16_t alt) __reentrant { @@ -66,7 +67,9 @@ ao_altitude_to_pres(int16_t alt) __reentrant pres = 0; return (int16_t) pres; } +#endif +#if 0 int16_t ao_temp_to_dC(int16_t temp) __reentrant { @@ -83,3 +86,4 @@ ao_temp_to_dC(int16_t temp) __reentrant ret = ((temp - 19791) * 1012L) >> 16; return ret; } +#endif diff --git a/src/core/ao_convert_test.c b/src/core/ao_convert_test.c index e2c28b73..87e76841 100644 --- a/src/core/ao_convert_test.c +++ b/src/core/ao_convert_test.c @@ -17,14 +17,15 @@ #include #define AO_CONVERT_TEST +#define AO_NEED_ALTITUDE_TO_PRES 1 #include "ao_host.h" #include "ao_convert.c" #define STEP 1 -static inline i_abs(int i) { return i < 0 ? -i : i; } +static inline int i_abs(int i) { return i < 0 ? -i : i; } -main () +int main (int argc, char **argv) { int i; int16_t p_to_a, p_to_a_to_p; diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 9bb03d68..a4ef8dc0 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -180,6 +180,7 @@ struct ao_cmds { #define ao_xmemset(d,v,c) memset(d,v,c) #define ao_xmemcmp(d,s,c) memcmp(d,s,c) +#define AO_NEED_ALTITUDE_TO_PRES 1 #include "ao_convert.c" struct ao_config { -- cgit v1.2.3 From bca72b782a2909ecedef15ad589292647221ca56 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 20:34:02 -0700 Subject: altos: Add 'void' parameter to ao_fec_decode callback parameter This keeps the compiler from whinging about the lack of a prototype. Signed-off-by: Keith Packard --- src/core/ao_fec.h | 2 +- src/core/ao_fec_rx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index 771732bd..eedea8f4 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -73,7 +73,7 @@ ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out); #define AO_FEC_DECODE_CRC_OK 0x80 /* stored in out[out_len-1] */ uint8_t -ao_fec_decode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()); +ao_fec_decode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)(void)); /* * Interleave data packed in bytes. 'out' must be 'len' bytes long. diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index 64426d72..072a9e90 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -96,7 +96,7 @@ ao_next_state(uint8_t state, uint8_t bit) */ uint8_t -ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) +ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)(void)) { static uint32_t cost[2][NUM_STATE]; /* path cost */ static bits_t bits[2][NUM_STATE]; /* save bits to quickly output them */ -- cgit v1.2.3 From fb60d87b02c0fc83a0b4268212f0b6b740c984e3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 20:35:19 -0700 Subject: altos: Signal continuity over radio in pad mode (trac #40) This is especially useful for telemini which has no beeper, allowing you to hear the continuity signal while at the pad over the air. Signed-off-by: Keith Packard --- src/cc1111/ao_radio.c | 89 ++++++++++++++++++++++++++++++++++++++++--------- src/core/ao.h | 25 ++++++++++++-- src/core/ao_report.c | 10 ++++-- src/core/ao_telemetry.c | 14 +++++--- src/drivers/ao_cc1120.c | 69 +++++++++++++++++++++++++++++--------- 5 files changed, 167 insertions(+), 40 deletions(-) (limited to 'src/core') diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 2c4a661e..2071c47a 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -200,7 +200,7 @@ static __code uint8_t rdf_setup[] = { RF_MDMCFG3_OFF, (RDF_DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | RF_MDMCFG2_MOD_FORMAT_GFSK | - RF_MDMCFG2_SYNC_MODE_15_16_THRES), + RF_MDMCFG2_SYNC_MODE_NONE), RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_DIS | RF_MDMCFG1_NUM_PREAMBLE_2 | (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), @@ -366,29 +366,22 @@ ao_radio_recv_abort(void) ao_wakeup(&ao_radio_dma_done); } -__xdata ao_radio_rdf_value = 0x55; +__code ao_radio_rdf_value = 0x55; -void -ao_radio_rdf(uint8_t pkt_len) +static void +ao_radio_rdf_start(void) { uint8_t i; - ao_radio_abort = 0; - ao_radio_get(pkt_len); + ao_radio_get(AO_RADIO_RDF_LEN); ao_radio_done = 0; for (i = 0; i < sizeof (rdf_setup); i += 2) RF[rdf_setup[i]] = rdf_setup[i+1]; +} - ao_dma_set_transfer(ao_radio_dma, - &ao_radio_rdf_value, - &RFDXADDR, - pkt_len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_RADIO, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_HIGH); +static void +ao_radio_rdf_run(void) +{ ao_dma_start(ao_radio_dma); RFST = RFST_STX; __critical while (!ao_radio_done && !ao_radio_abort) @@ -401,6 +394,70 @@ ao_radio_rdf(uint8_t pkt_len) ao_radio_put(); } +void +ao_radio_rdf(void) +{ + ao_radio_rdf_start(); + + ao_dma_set_transfer(ao_radio_dma, + CODE_TO_XDATA(&ao_radio_rdf_value), + &RFDXADDR, + AO_RADIO_RDF_LEN, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_RADIO, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + ao_radio_rdf_run(); +} + +#define PA 0x00 +#define BE 0x55 + +#define CONT_PAUSE_8 PA, PA, PA, PA, PA, PA, PA, PA +#define CONT_PAUSE_16 CONT_PAUSE_8, CONT_PAUSE_8 +#define CONT_PAUSE_24 CONT_PAUSE_16, CONT_PAUSE_8 + +#define CONT_BEEP_8 BE, BE, BE, BE, BE, BE, BE, BE + +#if AO_RADIO_CONT_PAUSE_LEN == 24 +#define CONT_PAUSE CONT_PAUSE_24 +#endif + +#if AO_RADIO_CONT_TONE_LEN == 8 +#define CONT_BEEP CONT_BEEP_8 +#define CONT_PAUSE_SHORT CONT_PAUSE_8 +#endif + +#define CONT_ADDR(c) CODE_TO_XDATA(&ao_radio_cont[(3-(c)) * (AO_RADIO_CONT_PAUSE_LEN + AO_RADIO_CONT_TONE_LEN)]) + +__code uint8_t ao_radio_cont[] = { + CONT_PAUSE, CONT_BEEP, + CONT_PAUSE, CONT_BEEP, + CONT_PAUSE, CONT_BEEP, + CONT_PAUSE, CONT_PAUSE_SHORT, + CONT_PAUSE, CONT_PAUSE_SHORT, + CONT_PAUSE, +}; + +void +ao_radio_continuity(uint8_t c) +{ + ao_radio_rdf_start(); + ao_dma_set_transfer(ao_radio_dma, + CONT_ADDR(c), + &RFDXADDR, + AO_RADIO_CONT_TOTAL_LEN, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_RADIO, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + ao_radio_rdf_run(); +} + void ao_radio_rdf_abort(void) { diff --git a/src/core/ao.h b/src/core/ao.h index 861a0fd4..2e012f08 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -264,6 +264,26 @@ ao_cmd_filter(void); * ao_report.c */ +#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) +#define AO_RDF_LENGTH_MS 500 +#define AO_RDF_CONTINUITY_MS 32 +#define AO_RDF_CONTINUITY_PAUSE 96 +#define AO_RDF_CONTINUITY_TOTAL ((AO_RDF_CONTINUITY_PAUSE + AO_RDF_CONTINUITY_MS) * 3 + AO_RDF_CONTINUITY_PAUSE) + +/* This assumes that we're generating a 1kHz tone, which + * modulates the carrier at 2kbps, or 250kBps + */ +#define AO_MS_TO_RDF_LEN(ms) ((ms) / 4) + +#define AO_RADIO_RDF_LEN AO_MS_TO_RDF_LEN(AO_RDF_LENGTH_MS) +#define AO_RADIO_CONT_TONE_LEN AO_MS_TO_RDF_LEN(AO_RDF_CONTINUITY_MS) +#define AO_RADIO_CONT_PAUSE_LEN AO_MS_TO_RDF_LEN(AO_RDF_CONTINUITY_PAUSE) +#define AO_RADIO_CONT_TOTAL_LEN AO_MS_TO_RDF_LEN(AO_RDF_CONTINUITY_TOTAL) + +/* returns a value 0-3 to indicate igniter continuity */ +uint8_t +ao_report_igniter(void); + void ao_report_init(void); @@ -538,10 +558,11 @@ ao_radio_recv_abort(void); * 2 * ms bits, or ms / 4 bytes */ -#define AO_MS_TO_RDF_LEN(ms) ((ms) > 255 * 4 ? 255 : ((ms) >> 2)) +void +ao_radio_rdf(void); void -ao_radio_rdf(uint8_t pkt_len); +ao_radio_continuity(uint8_t c); void ao_radio_rdf_abort(void); diff --git a/src/core/ao_report.c b/src/core/ao_report.c index eb90a4f8..1104cd82 100644 --- a/src/core/ao_report.c +++ b/src/core/ao_report.c @@ -114,6 +114,13 @@ ao_report_igniter_ready(enum ao_igniter igniter) return ao_igniter_status(igniter) == ao_igniter_ready ? 1 : 0; } +uint8_t +ao_report_igniter(void) +{ + return (ao_report_igniter_ready(ao_igniter_drogue) | + (ao_report_igniter_ready(ao_igniter_main) << 1)); +} + static void ao_report_continuity(void) __reentrant { @@ -123,8 +130,7 @@ ao_report_continuity(void) __reentrant if (!ao_igniter_present) return; #endif - c = (ao_report_igniter_ready(ao_igniter_drogue) | - (ao_report_igniter_ready(ao_igniter_main) << 1)); + c = ao_report_igniter(); if (c) { while (c--) { high(AO_MS_TO_TICKS(25)); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 3c747520..583a6636 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -22,9 +22,6 @@ static __pdata uint16_t ao_telemetry_interval; static __pdata uint8_t ao_rdf = 0; static __pdata uint16_t ao_rdf_time; -#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) -#define AO_RDF_LENGTH_MS 500 - #if defined(MEGAMETRUM) #define AO_SEND_MEGA 1 #endif @@ -317,8 +314,16 @@ ao_telemetry(void) if (ao_rdf && (int16_t) (ao_time() - ao_rdf_time) >= 0) { +#if HAS_IGNITE_REPORT + uint8_t c; +#endif ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; - ao_radio_rdf(AO_MS_TO_RDF_LEN(AO_RDF_LENGTH_MS)); +#if HAS_IGNITE_REPORT + if (ao_flight_state == ao_flight_pad && (c = ao_report_igniter())) + ao_radio_continuity(c); + else +#endif + ao_radio_rdf(); } #endif time += ao_telemetry_interval; @@ -330,6 +335,7 @@ ao_telemetry(void) } else time = ao_time(); + bottom: ; } } } diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 1d28148b..a36d922c 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -160,7 +160,7 @@ ao_radio_fifo_read(uint8_t *data, uint8_t len) } static uint8_t -ao_radio_fifo_write(uint8_t *data, uint8_t len) +ao_radio_fifo_write_start(void) { uint8_t addr = ((0 << CC1120_READ) | (1 << CC1120_BURST) | @@ -169,24 +169,28 @@ ao_radio_fifo_write(uint8_t *data, uint8_t len) ao_radio_select(); ao_radio_duplex(&addr, &status, 1); - ao_radio_spi_send(data, len); + return status; +} + +static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) { ao_radio_deselect(); return status; } static uint8_t -ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) +ao_radio_fifo_write(uint8_t *data, uint8_t len) { - uint8_t addr = ((0 << CC1120_READ) | - (1 << CC1120_BURST) | - CC1120_FIFO); - uint8_t status; + uint8_t status = ao_radio_fifo_write_start(); + ao_radio_spi_send(data, len); + return ao_radio_fifo_write_stop(status); +} - ao_radio_select(); - ao_radio_duplex(&addr, &status, 1); +static uint8_t +ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) +{ + uint8_t status = ao_radio_fifo_write_start(); ao_radio_spi_send_fixed(data, len); - ao_radio_deselect(); - return status; + return ao_radio_fifo_write_stop(status); } static uint8_t @@ -446,19 +450,20 @@ ao_radio_get(uint8_t len) #define ao_radio_put() ao_mutex_put(&ao_radio_mutex) -void -ao_radio_rdf(uint8_t len) +static void +ao_rdf_start(uint8_t len) { - int i; - ao_radio_abort = 0; ao_radio_get(len); ao_radio_set_mode(AO_RADIO_MODE_RDF); ao_radio_wake = 0; - ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); +} +static void +ao_rdf_run(void) +{ ao_radio_start_tx(); cli(); @@ -470,6 +475,38 @@ ao_radio_rdf(uint8_t len) ao_radio_put(); } +void +ao_radio_rdf(void) +{ + ao_rdf_start(AO_RADIO_RDF_LEN); + + ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN); + + ao_rdf_run(); +} + +void +ao_radio_continuity(uint8_t c) +{ + uint8_t i; + uint8_t status; + + ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN); + + status = ao_radio_fifo_write_start(); + for (i = 0; i < 3; i++) { + ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN); + if (i < c) + ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN); + else + ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN); + } + ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN); + status = ao_radio_fifo_write_stop(status); + (void) status; + ao_rdf_run(); +} + void ao_radio_rdf_abort(void) { -- cgit v1.2.3 From 0b92164143aaf0d2aa3d5d742484391c16545289 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 22:08:28 -0700 Subject: altos: Set HAS_FLIGHT_DEBUG=1 to include the flight debugging commands This leaves USB enabled, and adds the 'F' command to dump internal flight state. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 39084fd0..c6786455 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -114,7 +114,7 @@ ao_flight(void) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; -#if HAS_USB && HAS_RADIO +#if HAS_USB && HAS_RADIO && !HAS_FLIGHT_DEBUG /* Disable the USB controller in flight mode * to save power */ @@ -358,7 +358,7 @@ ao_flight(void) } } -#if !HAS_RADIO +#if HAS_FLIGHT_DEBUG static inline int int_part(int16_t i) { return i >> 4; } static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; } @@ -378,6 +378,7 @@ ao_flight_dump(void) printf (" raw accel %d\n", ao_sample_accel); #endif printf (" ground pres %d\n", ao_ground_pres); + printf (" ground alt %d\n", ao_ground_height); #if HAS_ACCEL printf (" raw accel %d\n", ao_sample_accel); printf (" groundaccel %d\n", ao_ground_accel); @@ -413,7 +414,7 @@ void ao_flight_init(void) { ao_flight_state = ao_flight_startup; -#if !HAS_RADIO +#if HAS_FLIGHT_DEBUG ao_cmd_register(&ao_flight_cmds[0]); #endif ao_add_task(&flight_task, ao_flight, "flight"); -- cgit v1.2.3 From aa305da7e5dc182c99c09e422c053d85ed48d5d5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 22:09:44 -0700 Subject: altos: Continuously update ground state while on pad (trac #42) Average data for 5 seconds, wait 5 seconds and if still in pad mode, replace the existing data with the new data. This should avoid averaging in boost data while still keeping things reasonably current. Signed-off-by: Keith Packard --- src/core/ao_sample.c | 58 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 11 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c index ac11eef0..6461def0 100644 --- a/src/core/ao_sample.c +++ b/src/core/ao_sample.c @@ -61,6 +61,29 @@ __pdata int32_t ao_sample_pres_sum; __pdata int32_t ao_sample_accel_sum; #endif +static void +ao_sample_preflight_add(void) +{ +#if HAS_ACCEL + ao_sample_accel_sum += ao_sample_accel; +#endif + ao_sample_pres_sum += ao_sample_pres; + ++nsamples; +} + +static void +ao_sample_preflight_set(void) +{ +#if HAS_ACCEL + ao_ground_accel = ao_sample_accel_sum >> 9; + ao_sample_accel_sum = 0; +#endif + ao_ground_pres = ao_sample_pres_sum >> 9; + ao_ground_height = pres_to_altitude(ao_ground_pres); + nsamples = 0; + ao_sample_pres_sum = 0; +} + static void ao_sample_preflight(void) { @@ -70,29 +93,38 @@ ao_sample_preflight(void) * data and average them to find the resting values */ if (nsamples < 512) { -#if HAS_ACCEL - ao_sample_accel_sum += ao_sample_accel; -#endif - ao_sample_pres_sum += ao_sample_pres; - ++nsamples; + ao_sample_preflight_add(); } else { - ao_config_get(); #if HAS_ACCEL - ao_ground_accel = ao_sample_accel_sum >> 9; ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; #endif - ao_ground_pres = ao_sample_pres_sum >> 9; - ao_ground_height = pres_to_altitude(ao_ground_pres); + ao_sample_preflight_set(); ao_preflight = FALSE; } } +/* + * While in pad mode, constantly update the ground state by + * re-averaging the data. This tracks changes in orientation, which + * might be caused by adjustments to the rocket on the pad and + * pressure, which might be caused by changes in the weather. + */ + +static void +ao_sample_preflight_update(void) +{ + if (nsamples < 512) + ao_sample_preflight_add(); + else if (nsamples < 1024) + ++nsamples; + else + ao_sample_preflight_set(); +} uint8_t ao_sample(void) { - ao_config_get(); ao_wakeup(DATA_TO_XDATA(&ao_sample_data)); ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); while (ao_sample_data != ao_data_head) { @@ -116,8 +148,11 @@ ao_sample(void) if (ao_preflight) ao_sample_preflight(); - else + else { + if (ao_flight_state < ao_flight_boost) + ao_sample_preflight_update(); ao_kalman(); + } ao_sample_data = ao_data_ring_next(ao_sample_data); } return !ao_preflight; @@ -126,6 +161,7 @@ ao_sample(void) void ao_sample_init(void) { + ao_config_get(); nsamples = 0; ao_sample_pres_sum = 0; ao_sample_pres = 0; -- cgit v1.2.3 From 46407f7f3e4d2b6e74b3a2e90b38736a792cfc54 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 22:41:59 -0700 Subject: altos: Force 434.550Mhz by connecting debug gnd and clk (trac #41) Check for pin P2_2 low at startup and set the frequency to 434.550MHz. This value won't get written to flash, so rebooting again will restore the configured frequency. Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 1 + src/core/ao.h | 7 +++++++ src/core/ao_config.c | 4 ++++ src/product/ao_telemini.c | 13 +++++++++++++ 4 files changed, 25 insertions(+) (limited to 'src/core') diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index e28a7b65..fc6ed3ec 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -163,6 +163,7 @@ #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 + #define HAS_FORCE_FREQ 1 #define USE_INTERNAL_FLASH 1 #define HAS_DBG 0 #define IGNITE_ON_P2 0 diff --git a/src/core/ao.h b/src/core/ao.h index 2e012f08..06daf48f 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -682,6 +682,13 @@ ao_igniter_init(void); * ao_config.c */ +#if HAS_FORCE_FREQ +/* + * Set this to force the frequency to 434.550MHz + */ +extern __xdata uint8_t ao_force_freq; +#endif + #define AO_CONFIG_MAJOR 1 #define AO_CONFIG_MINOR 11 diff --git a/src/core/ao_config.c b/src/core/ao_config.c index e0dabcd9..ced8b1f2 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -135,6 +135,10 @@ _ao_config_get(void) ao_config_dirty = 1; } #if HAS_RADIO +#if HAS_FORCE_FREQ + if (ao_force_freq) + ao_config.frequency = 434550; +#endif ao_config_set_radio(); #endif ao_config_loaded = 1; diff --git a/src/product/ao_telemini.c b/src/product/ao_telemini.c index fa23de01..21551ee9 100644 --- a/src/product/ao_telemini.c +++ b/src/product/ao_telemini.c @@ -18,6 +18,8 @@ #include "ao.h" #include "ao_pins.h" +__xdata uint8_t ao_force_freq; + void main(void) { @@ -33,6 +35,17 @@ main(void) ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_RED); + /* A hack -- look at the debug clock pin, if it's sitting at + * ground, then we force the computer to idle mode instead of + * flight mode + */ + if (P2_2 == 0) { + ao_flight_force_idle = 1; + ao_force_freq = 1; + while (P2_2 == 0) + ; + } + ao_timer_init(); ao_adc_init(); ao_cmd_init(); -- cgit v1.2.3 From 726f47c8a07f060aed930e1d102a1e8b5a5c7aed Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:47:25 -0700 Subject: altos: remove optimization for 'help' that confuses cc1111 compiler The cc1111 compiler gets this very wrong and prints piles of garbage Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 05dbfb51..1814cecf 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -278,8 +278,10 @@ help(void) for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; - for (cmd = 0; (h = cs[cmd].help); cmd++) + for (cmd = 0; cs[cmd].func; cmd++) { + h = cs[cmd].help; printf("%-45s %s\n", h, h + 1 + strlen(h)); + } } } -- cgit v1.2.3 From fe70611c3c7d4b8cce3b5292f0ec549f3191bf86 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:50:56 -0700 Subject: altos: Create macros to convert from/to radio RSSI representation AO_RSSI_FROM_RADIO and AO_RADIO_FROM_RSSI. Removes a bunch of open-coded versions of the same function. Signed-off-by: Keith Packard --- src/core/ao.h | 6 ++++++ src/core/ao_monitor.c | 5 ++--- src/drivers/ao_cc1120.c | 4 ++-- src/product/ao_terraui.c | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index 06daf48f..eb2d47cf 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -487,6 +487,12 @@ struct ao_telemetry_tiny_recv { uint8_t status; }; +/* Unfortunately, we've exposed the CC1111 rssi units as the 'usual' method + * for reporting RSSI. So, now we use these values everywhere + */ +#define AO_RSSI_FROM_RADIO(radio) ((int16_t) ((int8_t) (radio) >> 1) - 74) +#define AO_RADIO_FROM_RSSI(rssi) (((int8_t) (rssi) + 74) << 1) + /* * ao_radio_recv tacks on rssi and status bytes */ diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 51d61425..d492e32a 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -141,8 +141,7 @@ ao_monitor_put(void) case AO_MONITORING_ORIG: state = recv_orig.telemetry_orig.flight_state; - /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ - rssi = (int16_t) (recv_orig.rssi >> 1) - 74; + rssi = (int16_t) AO_RSSI_FROM_RADIO(recv_orig.rssi); ao_xmemcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN); if (state > ao_flight_invalid) state = ao_flight_invalid; @@ -240,7 +239,7 @@ ao_monitor_put(void) putchar ('\n'); #if HAS_RSSI if (recv_raw.packet[ao_monitoring + 1] & PKT_APPEND_STATUS_1_CRC_OK) { - rssi = ((int16_t) recv_raw.packet[ao_monitoring] >> 1) - 74; + rssi = AO_RSSI_FROM_RADIO(recv_raw.packet[ao_monitoring]); ao_rssi_set(rssi); } #endif diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index a36d922c..569df3b7 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -729,7 +729,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) /* Convert from 'real' rssi to cc1111-style values */ - rssi = (((int8_t) ao_radio_reg_read(CC1120_RSSI1)) + 74) * 2; + rssi = AO_RADIO_FROM_RSSI(ao_radio_reg_read(CC1120_RSSI1)); ao_radio_put(); @@ -998,7 +998,7 @@ ao_radio_test_recv() printf ("CRC OK"); else printf ("CRC BAD"); - printf (" RSSI %d", (int16_t) ((int8_t) bytes[32] >> 1) - 74); + printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32])); for (b = 0; b < 32; b++) printf (" %02x", bytes[b]); printf ("\n"); diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 963c7be4..1866eb0c 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -594,7 +594,7 @@ ao_terramonitor(void) continue; if (!(ao_monitor_ring[monitor].all.status & PKT_APPEND_STATUS_1_CRC_OK)) continue; - ao_tel_rssi = (ao_monitor_ring[monitor].all.rssi >> 1) - 74; + ao_tel_rssi = AO_RSSI_FROM_RADIO(ao_monitor_ring[monitor].all.rssi); switch (ao_monitor_ring[monitor].all.telemetry.generic.type) { case AO_TELEMETRY_SENSOR_TELEMETRUM: case AO_TELEMETRY_SENSOR_TELEMINI: -- cgit v1.2.3 From cf44ea354c2d1780cee343132c6058e11e9eefa3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:52:32 -0700 Subject: altos: Fix gcc compiler warnings in GPS code unused variables and mis-matches in printf format codes. Signed-off-by: Keith Packard --- src/core/ao_gps_print.c | 4 ++-- src/drivers/ao_gps_skytraq.c | 2 +- src/test/ao_gps_test.c | 7 ++++++- src/test/ao_gps_test_skytraq.c | 12 +++++++++--- 4 files changed, 18 insertions(+), 7 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_gps_print.c b/src/core/ao_gps_print.c index fcdedd30..47c945d7 100644 --- a/src/core/ao_gps_print.c +++ b/src/core/ao_gps_print.c @@ -40,8 +40,8 @@ ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant printf(AO_TELEM_GPS_LATITUDE " %ld " AO_TELEM_GPS_LONGITUDE " %ld " AO_TELEM_GPS_ALTITUDE " %d ", - gps_data->latitude, - gps_data->longitude, + (long) gps_data->latitude, + (long) gps_data->longitude, gps_data->altitude); if (gps_data->flags & AO_GPS_DATE_VALID) diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 84616a05..d80da97c 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -480,7 +480,7 @@ gps_dump(void) __reentrant ao_mutex_get(&ao_gps_mutex); printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day); printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); - printf ("Lat/Lon: %ld %ld\n", ao_gps_data.latitude, ao_gps_data.longitude); + printf ("Lat/Lon: %ld %ld\n", (long) ao_gps_data.latitude, (long) ao_gps_data.longitude); printf ("Alt: %d\n", ao_gps_data.altitude); printf ("Flags: 0x%x\n", ao_gps_data.flags); printf ("Sats: %d", ao_gps_tracking_data.channels); diff --git a/src/test/ao_gps_test.c b/src/test/ao_gps_test.c index 4d4012df..d75a12ec 100644 --- a/src/test/ao_gps_test.c +++ b/src/test/ao_gps_test.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #define AO_GPS_NUM_SAT_MASK (0xf << 0) #define AO_GPS_NUM_SAT_SHIFT (0) @@ -220,6 +221,8 @@ check_sirf_message(char *from, uint8_t *msg, int len) get_u16(h_v_error); + (void) mag_var; + (void) id; printf ("Geodetic Navigation Data (41):\n"); printf ("\tNav valid %04x\n", nav_valid); printf ("\tNav type %04x\n", nav_type); @@ -257,6 +260,7 @@ check_sirf_message(char *from, uint8_t *msg, int len) get_u32(gps_tow); get_u8(channels); + (void) id; printf ("Measured Tracker Data (4):\n"); printf ("GPS week: %d\n", gps_week); printf ("GPS time of week: %d\n", gps_tow); @@ -368,10 +372,11 @@ ao_serial1_putchar(char c) i = write(ao_gps_fd, &c, 1); if (i == 1) { if ((uint8_t) c == 0xb3 || c == '\r') { - static const struct timespec delay = { +/* static const struct timespec delay = { .tv_sec = 0, .tv_nsec = 100 * 1000 * 1000 }; +*/ tcdrain(ao_gps_fd); // nanosleep(&delay, NULL); } diff --git a/src/test/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c index 88bed305..846daa94 100644 --- a/src/test/ao_gps_test_skytraq.c +++ b/src/test/ao_gps_test_skytraq.c @@ -22,6 +22,7 @@ #include #include #include +#include #define AO_GPS_NUM_SAT_MASK (0xf << 0) #define AO_GPS_NUM_SAT_SHIFT (0) @@ -87,6 +88,7 @@ ao_mutex_put(uint8_t *mutex) static int ao_gps_fd; +#if 0 static void ao_dbg_char(char c) { @@ -102,6 +104,7 @@ ao_dbg_char(char c) } write(1, line, strlen(line)); } +#endif #define QUEUE_LEN 4096 @@ -222,6 +225,8 @@ check_skytraq_message(char *from, uint8_t *msg, int len) get_u16(h_v_error); + (void) mag_var; + (void) id; printf ("Geodetic Navigation Data (41):\n"); printf ("\tNav valid %04x\n", nav_valid); printf ("\tNav type %04x\n", nav_type); @@ -259,6 +264,7 @@ check_skytraq_message(char *from, uint8_t *msg, int len) get_u32(gps_tow); get_u8(channels); + (void) id; printf ("Measured Tracker Data (4):\n"); printf ("GPS week: %d\n", gps_week); printf ("GPS time of week: %d\n", gps_tow); @@ -371,10 +377,11 @@ ao_serial1_putchar(char c) i = write(ao_gps_fd, &c, 1); if (i == 1) { if ((uint8_t) c == 0xb3 || c == '\r') { - static const struct timespec delay = { +/* static const struct timespec delay = { .tv_sec = 0, .tv_nsec = 100 * 1000 * 1000 }; +*/ tcdrain(ao_gps_fd); // nanosleep(&delay, NULL); } @@ -422,8 +429,6 @@ ao_serial1_set_speed(uint8_t speed) void ao_dump_state(void *wchan) { - double lat, lon; - int i; if (wchan == &ao_gps_data) ao_gps_print(&ao_gps_data); else @@ -487,4 +492,5 @@ main (int argc, char **argv) exit (1); } ao_gps(); + return 0; } -- cgit v1.2.3 From 846a6298e4a8bfbe87bb24d7b0802c0bf6f233be Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:53:30 -0700 Subject: Report RSSI values in monitor idle UI (trac #44) This adds a new 's' command to TeleDongle to report RSSI value from last received packet, and then has AltosUI request that value when closing the remote link. Signed-off-by: Keith Packard --- altosui/AltosIdleMonitorUI.java | 46 ++++++++++++++++++++++++++++------------- src/core/ao_packet.h | 2 ++ src/drivers/ao_packet.c | 11 ++++++---- src/drivers/ao_packet_master.c | 7 ++++++- 4 files changed, 47 insertions(+), 19 deletions(-) (limited to 'src/core') diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 949e3926..eb6ec5e7 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -178,8 +178,23 @@ class AltosIdleMonitor extends Thread { AltosADC adc; AltosGPS gps; + int AltosRSSI() throws TimeoutException, InterruptedException { + serial.printf("s\n"); + String line = serial.get_reply_no_dialog(5000); + if (line == null) + throw new TimeoutException(); + String[] items = line.split("\\s+"); + if (items.length < 2) + return 0; + if (!items[0].equals("RSSI:")) + return 0; + int rssi = Integer.parseInt(items[1]); + return rssi; + } + void update_state() throws InterruptedException, TimeoutException { - AltosRecord record = new AltosRecord(); + AltosRecordTM record = new AltosRecordTM(); + int rssi; try { if (remote) { @@ -191,31 +206,34 @@ class AltosIdleMonitor extends Thread { adc = new AltosADC(serial); gps = new AltosGPSQuery(serial, config_data); } finally { - if (remote) + if (remote) { serial.stop_remote(); + rssi = AltosRSSI(); + } else + rssi = 0; } record.version = 0; record.callsign = config_data.callsign; record.serial = config_data.serial; record.flight = config_data.log_available() > 0 ? 255 : 0; - record.rssi = 0; + record.rssi = rssi; record.status = 0; record.state = Altos.ao_flight_idle; record.tick = adc.tick; -// record.accel = adc.accel; -// record.pres = adc.pres; -// record.batt = adc.batt; -// record.temp = adc.temp; -// record.drogue = adc.drogue; -// record.main = adc.main; - -// record.ground_accel = record.accel; -// record.ground_pres = record.pres; -// record.accel_plus_g = config_data.accel_cal_plus; -// record.accel_minus_g = config_data.accel_cal_minus; + record.accel = adc.accel; + record.pres = adc.pres; + record.batt = adc.batt; + record.temp = adc.temp; + record.drogue = adc.drogue; + record.main = adc.main; + + record.ground_accel = record.accel; + record.ground_pres = record.pres; + record.accel_plus_g = config_data.accel_cal_plus; + record.accel_minus_g = config_data.accel_cal_minus; record.acceleration = 0; record.speed = 0; record.height = 0; diff --git a/src/core/ao_packet.h b/src/core/ao_packet.h index 618ccda4..f232a878 100644 --- a/src/core/ao_packet.h +++ b/src/core/ao_packet.h @@ -67,6 +67,8 @@ ao_packet_pollchar(void) __critical; #if PACKET_HAS_MASTER /* ao_packet_master.c */ +extern __xdata uint8_t ao_packet_last_rssi; + void ao_packet_master_init(void); #endif diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index e020c003..d813b25f 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -27,7 +27,11 @@ static __pdata uint8_t rx_seq; __xdata struct ao_task ao_packet_task; __xdata uint8_t ao_packet_enable; + +#if PACKET_HAS_MASTER __xdata uint8_t ao_packet_master_sleeping; +__xdata uint8_t ao_packet_last_rssi; +#endif void ao_packet_send(void) @@ -80,6 +84,9 @@ ao_packet_recv(void) if (!(ao_rx_packet.status & AO_RADIO_STATUS_CRC_OK)) return 0; +#if PACKET_HAS_MASTER + ao_packet_last_rssi = ao_rx_packet.rssi; +#endif /* Accept packets with matching call signs, or any packet if * our callsign hasn't been configured */ @@ -130,10 +137,6 @@ ao_packet_recv(void) return 1; } -#ifndef PACKET_HAS_MASTER -#define PACKET_HAS_MASTER 1 -#endif - #if PACKET_HAS_MASTER void ao_packet_flush(void) diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c index 66f94288..e97a6648 100644 --- a/src/drivers/ao_packet_master.c +++ b/src/drivers/ao_packet_master.c @@ -137,10 +137,15 @@ ao_packet_forward(void) __reentrant #endif } - +static void +ao_packet_signal(void) +{ + printf ("RSSI: %d\n", AO_RSSI_FROM_RADIO(ao_packet_last_rssi)); +} __code struct ao_cmds ao_packet_master_cmds[] = { { ao_packet_forward, "p\0Remote packet link." }, + { ao_packet_signal, "s\0Report signal strength." }, { 0, NULL }, }; -- cgit v1.2.3 From d90587535676f9492f0fde6b974353158104ef88 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jul 2012 01:26:38 -0700 Subject: altos: Add arbitrary pyro channel support Programmed by specifying a conjunction of flight conditions that trigger the igniter to fire. Signed-off-by: Keith Packard --- src/core/ao.h | 15 +- src/core/ao_config.c | 12 +- src/core/ao_flight.c | 6 + src/core/ao_flight.h | 4 + src/core/ao_pyro.c | 378 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/core/ao_pyro.h | 69 ++++++++++ 6 files changed, 481 insertions(+), 3 deletions(-) create mode 100644 src/core/ao_pyro.c create mode 100644 src/core/ao_pyro.h (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index eb2d47cf..d4be3be4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -688,6 +688,10 @@ ao_igniter_init(void); * ao_config.c */ +#if AO_PYRO_NUM +#include +#endif + #if HAS_FORCE_FREQ /* * Set this to force the frequency to 434.550MHz @@ -696,7 +700,7 @@ extern __xdata uint8_t ao_force_freq; #endif #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 11 +#define AO_CONFIG_MINOR 12 #define AO_AES_LEN 16 @@ -718,6 +722,9 @@ struct ao_config { uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */ uint32_t frequency; /* minor version 10 */ uint16_t apogee_lockout; /* minor version 11 */ +#if AO_PYRO_NUM + struct ao_pyro pyro[AO_PYRO_NUM]; /* minor version 12 */ +#endif }; #define AO_IGNITE_MODE_DUAL 0 @@ -731,6 +738,12 @@ extern __xdata struct ao_config ao_config; #define AO_CONFIG_MAX_SIZE 128 +void +_ao_config_edit_start(void); + +void +_ao_config_edit_finish(void); + void ao_config_get(void); diff --git a/src/core/ao_config.c b/src/core/ao_config.c index ced8b1f2..88fcc12d 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -131,6 +131,10 @@ _ao_config_get(void) ao_config.frequency = 434550; if (minor < 11) ao_config.apogee_lockout = 0; +#if AO_PYRO_NUM + if (minor < 12) + memset(&ao_config.pyro, '\0', sizeof (ao_config.pyro)); +#endif ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -144,14 +148,14 @@ _ao_config_get(void) ao_config_loaded = 1; } -static void +void _ao_config_edit_start(void) { ao_mutex_get(&ao_config_mutex); _ao_config_get(); } -static void +void _ao_config_edit_finish(void) { ao_config_dirty = 1; @@ -537,6 +541,10 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_AES { "k <32 hex digits>\0Set AES encryption key", ao_config_key_set, ao_config_key_show }, +#endif +#if AO_PYRO_NUM + { "P \0Configure pyro channels", + ao_pyro_set, ao_pyro_show }, #endif { "s\0Show", ao_config_show, 0 }, diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index c6786455..fc018f00 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -40,6 +40,9 @@ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ __pdata uint16_t ao_boost_tick; /* time of launch detect */ +#if AO_PYRO_NUM +__pdata uint16_t ao_motor_number; /* number of motors burned so far */ +#endif /* * track min/max data over a long interval to detect @@ -214,6 +217,9 @@ ao_flight(void) ao_coast_avg_accel = ao_accel; #else ao_flight_state = ao_flight_coast; +#endif +#if AO_PYRO_NUM + ++ao_motor_number; #endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } diff --git a/src/core/ao_flight.h b/src/core/ao_flight.h index aa5ab60d..c5c8af46 100644 --- a/src/core/ao_flight.h +++ b/src/core/ao_flight.h @@ -37,6 +37,10 @@ enum ao_flight_state { }; extern __pdata enum ao_flight_state ao_flight_state; +extern __pdata uint16_t ao_boost_tick; +#if AO_PYRO_NUM +extern __pdata uint16_t ao_motor_number; +#endif extern __pdata uint16_t ao_launch_time; extern __pdata uint8_t ao_flight_force_idle; diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c new file mode 100644 index 00000000..c060a866 --- /dev/null +++ b/src/core/ao_pyro.c @@ -0,0 +1,378 @@ +/* + * 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 + +#define ao_lowbit(x) ((x) & (-x)) + +/* + * Given a pyro structure, figure out + * if the current flight state satisfies all + * of the requirements + */ +static uint8_t +ao_pyro_ready(struct ao_pyro *pyro) +{ + enum ao_pyro_flag flag, flags; + + flags = pyro->flags; + while (flags != ao_pyro_none) { + flag = ao_lowbit(flags); + flags &= ~flag; + switch (flag) { + + case ao_pyro_accel_less: + if (ao_accel <= pyro->accel_less) + continue; + break; + case ao_pyro_accel_greater: + if (ao_accel >= pyro->accel_greater) + continue; + break; + + + case ao_pyro_speed_less: + if (ao_speed <= pyro->speed_less) + continue; + break; + case ao_pyro_speed_greater: + if (ao_speed >= pyro->speed_greater) + continue; + break; + + case ao_pyro_height_less: + if (ao_height <= pyro->height_less) + continue; + break; + case ao_pyro_height_greater: + if (ao_height >= pyro->height_greater) + continue; + break; + + case ao_pyro_orient_less: +// if (ao_orient <= pyro->orient_less) + continue; + break; + case ao_pyro_orient_greater: +// if (ao_orient >= pyro->orient_greater) + continue; + break; + + case ao_pyro_time_less: + if ((int16_t) (ao_time() - ao_boost_tick) <= pyro->time_less) + continue; + break; + case ao_pyro_time_greater: + if ((int16_t) (ao_time() - ao_boost_tick) >= pyro->time_greater) + continue; + break; + + case ao_pyro_ascending: + if (ao_speed > 0) + continue; + break; + case ao_pyro_descending: + if (ao_speed < 0) + continue; + break; + + case ao_pyro_after_motor: + if (ao_motor_number == pyro->motor) + continue; + break; + + case ao_pyro_delay: + /* handled separately */ + continue; + + } + return FALSE; + } + return TRUE; +} + +#define ao_pyro_fire_port(port, pin) do { \ + ao_gpio_set(port, pin, 1); \ + ao_delay(AO_MS_TO_TICKS(50)); \ + ao_gpio_set(port, pin, 0); \ + } while (0) + + +static void +ao_pyro_fire(uint8_t p) +{ + switch (p) { +#if AO_PYRO_NUM > 0 + case 0: ao_pyro_fire_port(AO_PYRO_PORT_0, AO_PYRO_PIN_0); break; +#endif +#if AO_PYRO_NUM > 1 + case 1: ao_pyro_fire_port(AO_PYRO_PORT_1, AO_PYRO_PIN_1); break; +#endif +#if AO_PYRO_NUM > 2 + case 2: ao_pyro_fire_port(AO_PYRO_PORT_2, AO_PYRO_PIN_2); break; +#endif +#if AO_PYRO_NUM > 3 + case 3: ao_pyro_fire_port(AO_PYRO_PORT_3, AO_PYRO_PIN_3); break; +#endif +#if AO_PYRO_NUM > 4 + case 4: ao_pyro_fire_port(AO_PYRO_PORT_4, AO_PYRO_PIN_4); break; +#endif +#if AO_PYRO_NUM > 5 + case 5: ao_pyro_fire_port(AO_PYRO_PORT_5, AO_PYRO_PIN_5); break; +#endif +#if AO_PYRO_NUM > 6 + case 6: ao_pyro_fire_port(AO_PYRO_PORT_6, AO_PYRO_PIN_6); break; +#endif +#if AO_PYRO_NUM > 7 + case 7: ao_pyro_fire_port(AO_PYRO_PORT_7, AO_PYRO_PIN_7); break; +#endif + default: break; + } + ao_delay(AO_MS_TO_TICKS(50)); +} + +static void +ao_pyro(void) +{ + uint8_t p; + struct ao_pyro *pyro; + + ao_config_get(); + while (ao_flight_state < ao_flight_boost) + ao_sleep(&ao_flight_state); + + for (;;) { + ao_delay(AO_MS_TO_TICKS(100)); + for (p = 0; p < AO_PYRO_NUM; p++) { + pyro = &ao_config.pyro[p]; + + /* Ignore igniters which have already fired + */ + if (pyro->fired) + continue; + + /* Ignore disabled igniters + */ + if (!pyro->flags) + continue; + + /* Check pyro state to see if it shoule fire + */ + if (!pyro->delay_done) { + if (!ao_pyro_ready(pyro)) + continue; + + /* If there's a delay set, then remember when + * it expires + */ + if (pyro->flags & ao_pyro_delay) + pyro->delay_done = ao_time() + pyro->delay; + } + + /* Check to see if we're just waiting for + * the delay to expire + */ + if (pyro->delay_done) { + if ((int16_t) (ao_time() - pyro->delay_done) < 0) + continue; + } + + ao_pyro_fire(p); + } + } +} + +__xdata struct ao_task ao_pyro_task; + +#define NO_VALUE 0xff + +#define AO_PYRO_NAME_LEN 3 + +const struct { + char name[AO_PYRO_NAME_LEN]; + enum ao_pyro_flag flag; + uint8_t offset; + char *help; +} ao_pyro_values[] = { + { "a<", ao_pyro_accel_less, offsetof(struct ao_pyro, accel_less), "accel less (m/ss * 16)" }, + { "a>", ao_pyro_accel_greater, offsetof(struct ao_pyro, accel_greater), "accel greater (m/ss * 16)" }, + + { "s<", ao_pyro_speed_less, offsetof(struct ao_pyro, speed_less), "speed less (m/s * 16)" }, + { "s>", ao_pyro_speed_greater, offsetof(struct ao_pyro, speed_greater), "speed greater (m/s * 16)" }, + + { "h<", ao_pyro_height_less, offsetof(struct ao_pyro, height_less), "height less (m)" }, + { "h>", ao_pyro_height_greater, offsetof(struct ao_pyro, height_greater), "height greater (m)" }, + + { "o<", ao_pyro_orient_less, offsetof(struct ao_pyro, orient_less), "orient less (deg)" }, + { "o>", ao_pyro_orient_greater, offsetof(struct ao_pyro, orient_greater), "orient greater (deg)" }, + + { "t<", ao_pyro_time_less, offsetof(struct ao_pyro, time_less), "time less (s * 100)" }, + { "t>", ao_pyro_time_greater, offsetof(struct ao_pyro, time_greater), "time greater (s * 100)" }, + + { "A", ao_pyro_ascending, NO_VALUE, "ascending" }, + { "D", ao_pyro_descending, NO_VALUE, "descending" }, + + { "m", ao_pyro_after_motor, offsetof(struct ao_pyro, motor), "after motor" }, + + { "d", ao_pyro_delay, offsetof(struct ao_pyro, delay), "delay before firing (s * 100)" }, + { "", ao_pyro_none, NO_VALUE, NULL }, +}; + +static void +ao_pyro_print_name(uint8_t v) +{ + const char *s = ao_pyro_values[v].name; + printf ("%s%s", s, " " + strlen(s)); +} + +static void +ao_pyro_help(void) +{ + uint8_t v; + for (v = 0; ao_pyro_values[v].flag != ao_pyro_none; v++) { + ao_pyro_print_name(v); + if (ao_pyro_values[v].offset != NO_VALUE) + printf (" "); + else + printf (" "); + printf ("%s\n", ao_pyro_values[v].help); + } +} + +void +ao_pyro_show(void) +{ + uint8_t p; + uint8_t v; + struct ao_pyro *pyro; + + for (p = 0; p < AO_PYRO_NUM; p++) { + printf ("Pyro %2d: ", p); + pyro = &ao_config.pyro[p]; + if (!pyro->flags) { + printf ("\n"); + continue; + } + for (v = 0; ao_pyro_values[v].flag != ao_pyro_none; v++) { + if (!(pyro->flags & ao_pyro_values[v].flag)) + continue; + ao_pyro_print_name(v); + if (ao_pyro_values[v].offset != NO_VALUE) { + int16_t value; + + value = *((int16_t *) ((char *) pyro + ao_pyro_values[v].offset)); + printf ("%6d ", value); + } else { + printf (" "); + } + } + printf ("\n"); + } +} + +void +ao_pyro_set(void) +{ + uint8_t p; + struct ao_pyro *pyro; + struct ao_pyro pyro_tmp; + char name[AO_PYRO_NAME_LEN]; + uint8_t c; + uint8_t v; + + ao_cmd_white(); + switch (ao_cmd_lex_c) { + case '?': + ao_pyro_help(); + return; + } + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + p = ao_cmd_lex_i; + if (p < 0 || AO_PYRO_NUM <= p) { + printf ("invalid pyro channel %d\n", p); + return; + } + pyro_tmp.flags = 0; + for (;;) { + ao_cmd_white(); + if (ao_cmd_lex_c == '\n') + break; + + for (c = 0; c < AO_PYRO_NAME_LEN - 1; c++) { + if (ao_cmd_is_white()) + break; + name[c] = ao_cmd_lex_c; + ao_cmd_lex(); + } + name[c] = '\0'; + for (v = 0; ao_pyro_values[v].flag != ao_pyro_none; v++) { + if (!strcmp (ao_pyro_values[v].name, name)) + break; + } + if (ao_pyro_values[v].flag == ao_pyro_none) { + printf ("invalid pyro field %s\n", name); + ao_cmd_status = ao_cmd_syntax_error; + return; + } + pyro_tmp.flags |= ao_pyro_values[v].flag; + if (ao_pyro_values[v].offset != NO_VALUE) { + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + *((int16_t *) ((char *) &pyro_tmp + ao_pyro_values[v].offset)) = ao_cmd_lex_i; + } + } + _ao_config_edit_start(); + ao_config.pyro[p] = pyro_tmp; + _ao_config_edit_finish(); +} + +void +ao_pyro_init(void) +{ +#if AO_PYRO_NUM > 0 + ao_enable_output(AO_PYRO_PORT_0, AO_PYRO_PIN_0, 0); +#endif +#if AO_PYRO_NUM > 1 + ao_enable_output(AO_PYRO_PORT_1, AO_PYRO_PIN_1, 0); +#endif +#if AO_PYRO_NUM > 2 + ao_enable_output(AO_PYRO_PORT_2, AO_PYRO_PIN_2, 0); +#endif +#if AO_PYRO_NUM > 3 + ao_enable_output(AO_PYRO_PORT_3, AO_PYRO_PIN_3, 0); +#endif +#if AO_PYRO_NUM > 4 + ao_enable_output(AO_PYRO_PORT_4, AO_PYRO_PIN_4, 0); +#endif +#if AO_PYRO_NUM > 5 + ao_enable_output(AO_PYRO_PORT_5, AO_PYRO_PIN_5, 0); +#endif +#if AO_PYRO_NUM > 6 + ao_enable_output(AO_PYRO_PORT_6, AO_PYRO_PIN_6, 0); +#endif +#if AO_PYRO_NUM > 7 + ao_enable_output(AO_PYRO_PORT_7, AO_PYRO_PIN_7, 0); +#endif + ao_add_task(&ao_pyro_task, ao_pyro, "pyro"); +} diff --git a/src/core/ao_pyro.h b/src/core/ao_pyro.h new file mode 100644 index 00000000..1989a9e5 --- /dev/null +++ b/src/core/ao_pyro.h @@ -0,0 +1,69 @@ +/* + * 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_PYRO_H_ +#define _AO_PYRO_H_ + +enum ao_pyro_flag { + ao_pyro_none = 0x00000000, + + ao_pyro_accel_less = 0x00000001, + ao_pyro_accel_greater = 0x00000002, + + ao_pyro_speed_less = 0x00000004, + ao_pyro_speed_greater = 0x00000008, + + ao_pyro_height_less = 0x00000010, + ao_pyro_height_greater = 0x00000020, + + ao_pyro_orient_less = 0x00000040, + ao_pyro_orient_greater = 0x00000080, + + ao_pyro_time_less = 0x00000100, + ao_pyro_time_greater = 0x00000200, + + ao_pyro_ascending = 0x00000400, + ao_pyro_descending = 0x00000800, + + ao_pyro_after_motor = 0x00001000, + + ao_pyro_delay = 0x00002000, +}; + +struct ao_pyro { + enum ao_pyro_flag flags; + int16_t accel_less, accel_greater; + int16_t speed_less, speed_greater; + int16_t height_less, height_greater; + int16_t orient_less, orient_greater; + int16_t time_less, time_greater; + int16_t delay; + int16_t motor; + uint16_t delay_done; + uint8_t fired; +}; + +void +ao_pyro_set(void); + +void +ao_pyro_show(void); + +void +ao_pyro_init(void); + +#endif -- cgit v1.2.3 From 0cfd22baa6af44e053428c30c1a95cf5551b68af Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jul 2012 02:44:17 -0700 Subject: src: Add explicit 'pin' argument to ao_enable_output This lets the cc1111 use the atomic bit operation instead of a mask, which is immune to interrupt issues as well as being a shorter code sequence. Signed-off-by: Keith Packard --- src/avr/ao_arch_funcs.h | 17 +++++++++++++++++ src/cc1111/ao_arch_funcs.h | 12 ++++++------ src/core/ao_ignite.c | 4 ++-- src/core/ao_pyro.c | 41 +++++++++++++++++++++-------------------- src/drivers/ao_25lc1024.c | 2 +- src/drivers/ao_companion.c | 2 +- src/stm/ao_arch_funcs.h | 8 ++++---- 7 files changed, 52 insertions(+), 34 deletions(-) (limited to 'src/core') diff --git a/src/avr/ao_arch_funcs.h b/src/avr/ao_arch_funcs.h index e400c98b..792ff744 100644 --- a/src/avr/ao_arch_funcs.h +++ b/src/avr/ao_arch_funcs.h @@ -41,12 +41,29 @@ extern __xdata uint8_t ao_spi_mutex; ao_mutex_put(&ao_spi_mutex); \ } while (0) + +#define ao_gpio_token_paster(x,y) x ## y +#define ao_gpio_token_evaluator(x,y) ao_gpio_token_paster(x,y) + +#define ao_gpio_set(port, bit, pin, v) do { \ + if (v) \ + (ao_gpio_token_evaluator(PORT,port)) |= (1 << bit); \ + else \ + (ao_gpio_token_evaluator(PORT,port)) &= ~(1 << bit); \ + } 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 */ +#define ao_enable_output(port, bit, pin, v) do { \ + ao_gpio_set(port, bit, pin, v); \ + ao_gpio_token_evaluator(DDR,port) |= (1 << bit); \ + } while (0) + + void ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant; diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index 0a322961..0737e7ab 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -77,14 +77,14 @@ ao_spi_init(void); SPI_CS_SEL &= ~mask; \ } while (0) -#define cc1111_enable_output(port,dir,sel,mask,v) do { \ - port = port & ~(mask) | v; \ - dir |= mask; \ - sel &= ~mask; \ -} while (0) +#define cc1111_enable_output(port,dir,sel,pin,bit,v) do { \ + pin = v; \ + dir |= (1 << bit); \ + sel &= ~(1 << bit); \ + } while (0) #define disable_unreachable _Pragma("disable_warning 126") #define token_paster(x,y) x ## y #define token_evaluator(x,y) token_paster(x,y) -#define ao_enable_output(port,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), 1 << pin, 1 << v) +#define ao_enable_output(port,bit,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), pin, bit, v) diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c index e82de355..c7829fc3 100644 --- a/src/core/ao_ignite.c +++ b/src/core/ao_ignite.c @@ -195,8 +195,8 @@ __xdata struct ao_task ao_igniter_task; void ao_ignite_set_pins(void) { - ao_enable_output(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, 0); - ao_enable_output(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, 0); + ao_enable_output(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, AO_IGNITER_DROGUE, 0); + ao_enable_output(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, AO_IGNITER_MAIN, 0); } void diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index c060a866..943413e6 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -102,16 +102,18 @@ ao_pyro_ready(struct ao_pyro *pyro) /* handled separately */ continue; + case ao_pyro_none: + break; } return FALSE; } return TRUE; } -#define ao_pyro_fire_port(port, pin) do { \ - ao_gpio_set(port, pin, 1); \ +#define ao_pyro_fire_port(port, bit, pin) do { \ + ao_gpio_set(port, bit, pin, 1); \ ao_delay(AO_MS_TO_TICKS(50)); \ - ao_gpio_set(port, pin, 0); \ + ao_gpio_set(port, bit, pin, 0); \ } while (0) @@ -120,28 +122,28 @@ ao_pyro_fire(uint8_t p) { switch (p) { #if AO_PYRO_NUM > 0 - case 0: ao_pyro_fire_port(AO_PYRO_PORT_0, AO_PYRO_PIN_0); break; + case 0: ao_pyro_fire_port(AO_PYRO_PORT_0, AO_PYRO_PIN_0, AO_PYRO_0); break; #endif #if AO_PYRO_NUM > 1 - case 1: ao_pyro_fire_port(AO_PYRO_PORT_1, AO_PYRO_PIN_1); break; + case 1: ao_pyro_fire_port(AO_PYRO_PORT_1, AO_PYRO_PIN_1, AO_PYRO_1); break; #endif #if AO_PYRO_NUM > 2 - case 2: ao_pyro_fire_port(AO_PYRO_PORT_2, AO_PYRO_PIN_2); break; + case 2: ao_pyro_fire_port(AO_PYRO_PORT_2, AO_PYRO_PIN_2, AO_PYRO_2); break; #endif #if AO_PYRO_NUM > 3 - case 3: ao_pyro_fire_port(AO_PYRO_PORT_3, AO_PYRO_PIN_3); break; + case 3: ao_pyro_fire_port(AO_PYRO_PORT_3, AO_PYRO_PIN_3, AO_PYRO_3); break; #endif #if AO_PYRO_NUM > 4 - case 4: ao_pyro_fire_port(AO_PYRO_PORT_4, AO_PYRO_PIN_4); break; + case 4: ao_pyro_fire_port(AO_PYRO_PORT_4, AO_PYRO_PIN_4, AO_PYRO_4); break; #endif #if AO_PYRO_NUM > 5 - case 5: ao_pyro_fire_port(AO_PYRO_PORT_5, AO_PYRO_PIN_5); break; + case 5: ao_pyro_fire_port(AO_PYRO_PORT_5, AO_PYRO_PIN_5, AO_PYRO_5); break; #endif #if AO_PYRO_NUM > 6 - case 6: ao_pyro_fire_port(AO_PYRO_PORT_6, AO_PYRO_PIN_6); break; + case 6: ao_pyro_fire_port(AO_PYRO_PORT_6, AO_PYRO_PIN_6, AO_PYRO_6); break; #endif #if AO_PYRO_NUM > 7 - case 7: ao_pyro_fire_port(AO_PYRO_PORT_7, AO_PYRO_PIN_7); break; + case 7: ao_pyro_fire_port(AO_PYRO_PORT_7, AO_PYRO_PIN_7, AO_PYRO_7); break; #endif default: break; } @@ -291,7 +293,6 @@ void ao_pyro_set(void) { uint8_t p; - struct ao_pyro *pyro; struct ao_pyro pyro_tmp; char name[AO_PYRO_NAME_LEN]; uint8_t c; @@ -351,28 +352,28 @@ void ao_pyro_init(void) { #if AO_PYRO_NUM > 0 - ao_enable_output(AO_PYRO_PORT_0, AO_PYRO_PIN_0, 0); + ao_enable_output(AO_PYRO_PORT_0, AO_PYRO_PIN_0, AO_PYRO_0, 0); #endif #if AO_PYRO_NUM > 1 - ao_enable_output(AO_PYRO_PORT_1, AO_PYRO_PIN_1, 0); + ao_enable_output(AO_PYRO_PORT_1, AO_PYRO_PIN_1, AO_PYRO_1, 0); #endif #if AO_PYRO_NUM > 2 - ao_enable_output(AO_PYRO_PORT_2, AO_PYRO_PIN_2, 0); + ao_enable_output(AO_PYRO_PORT_2, AO_PYRO_PIN_2, AO_PYRO_2, 0); #endif #if AO_PYRO_NUM > 3 - ao_enable_output(AO_PYRO_PORT_3, AO_PYRO_PIN_3, 0); + ao_enable_output(AO_PYRO_PORT_3, AO_PYRO_PIN_3, AO_PYRO_3, 0); #endif #if AO_PYRO_NUM > 4 - ao_enable_output(AO_PYRO_PORT_4, AO_PYRO_PIN_4, 0); + ao_enable_output(AO_PYRO_PORT_4, AO_PYRO_PIN_4, AO_PYRO_4, 0); #endif #if AO_PYRO_NUM > 5 - ao_enable_output(AO_PYRO_PORT_5, AO_PYRO_PIN_5, 0); + ao_enable_output(AO_PYRO_PORT_5, AO_PYRO_PIN_5, AO_PYRO_5, 0); #endif #if AO_PYRO_NUM > 6 - ao_enable_output(AO_PYRO_PORT_6, AO_PYRO_PIN_6, 0); + ao_enable_output(AO_PYRO_PORT_6, AO_PYRO_PIN_6, AO_PYRO_6, 0); #endif #if AO_PYRO_NUM > 7 - ao_enable_output(AO_PYRO_PORT_7, AO_PYRO_PIN_7, 0); + ao_enable_output(AO_PYRO_PORT_7, AO_PYRO_PIN_7, AO_PYRO_7, 0); #endif ao_add_task(&ao_pyro_task, ao_pyro, "pyro"); } diff --git a/src/drivers/ao_25lc1024.c b/src/drivers/ao_25lc1024.c index c5d811f7..fac0a430 100644 --- a/src/drivers/ao_25lc1024.c +++ b/src/drivers/ao_25lc1024.c @@ -236,5 +236,5 @@ void ao_storage_device_init(void) { /* set up CS */ - ao_enable_output(EE_CS_PORT, EE_CS_PIN,1); + ao_enable_output(EE_CS_PORT, EE_CS_PIN, EE_CS, 1); } diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index 85d68c44..a3167956 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -131,7 +131,7 @@ static __xdata struct ao_task ao_companion_task; void ao_companion_init(void) { - ao_enable_output(AO_COMPANION_CS_PORT, AO_COMPANION_CS_PIN, 1); + ao_enable_output(AO_COMPANION_CS_PORT, AO_COMPANION_CS_PIN, AO_COMPANION_CS, 1); ao_cmd_register(&ao_companion_cmds[0]); ao_add_task(&ao_companion_task, ao_companion, "companion"); } diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 4416bbab..d2c973f5 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -76,12 +76,12 @@ ao_spi_init(void); } while (0) -#define ao_gpio_set(port, pin, v) stm_gpio_set(port, pin, v) +#define ao_gpio_set(port, bit, pin, v) stm_gpio_set(port, bit, v) -#define ao_enable_output(port,pin,v) do { \ +#define ao_enable_output(port,bit,pin,v) do { \ ao_enable_port(port); \ - ao_gpio_set(port, pin, v); \ - stm_moder_set(port, pin, STM_MODER_OUTPUT); \ + ao_gpio_set(port, bit, pin, v); \ + stm_moder_set(port, bit, STM_MODER_OUTPUT);\ } while (0) #define ao_enable_cs(port,bit) do { \ -- cgit v1.2.3 From 366217e86a4c353012b5102322ee6927f7b27a21 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 14:39:05 -0700 Subject: altos: Remove unused 'func' from ao_config_set Signed-off-by: Keith Packard --- src/core/ao_config.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 88fcc12d..e2095e65 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -562,12 +562,10 @@ ao_config_set(void) { char c; uint8_t cmd; - void (*__xdata func)(void) __reentrant; ao_cmd_white(); c = ao_cmd_lex_c; ao_cmd_lex(); - func = 0; for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) if (ao_config_vars[cmd].str[0] == c) { (*ao_config_vars[cmd].set)(); -- cgit v1.2.3 From 2a23030031c31267fc4f14accd9220f285c03b61 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 14:40:49 -0700 Subject: altos: No space for pyro help on TP v0.1 AVR doesn't have enough ram to hold the help messages, and we can't use them in flash. Signed-off-by: Keith Packard --- src/core/ao_pyro.c | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index 943413e6..b0d45162 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -207,34 +207,48 @@ __xdata struct ao_task ao_pyro_task; #define AO_PYRO_NAME_LEN 3 +#if !DISABLE_HELP +#define ENABLE_HELP 1 +#endif + +#if ENABLE_HELP +#define HELP(s) (s) +#else +#define HELP(s) +#endif + const struct { char name[AO_PYRO_NAME_LEN]; enum ao_pyro_flag flag; uint8_t offset; +#if ENABLE_HELP char *help; +#endif } ao_pyro_values[] = { - { "a<", ao_pyro_accel_less, offsetof(struct ao_pyro, accel_less), "accel less (m/ss * 16)" }, - { "a>", ao_pyro_accel_greater, offsetof(struct ao_pyro, accel_greater), "accel greater (m/ss * 16)" }, + { "a<", ao_pyro_accel_less, offsetof(struct ao_pyro, accel_less), HELP("accel less (m/ss * 16)") }, + { "a>", ao_pyro_accel_greater, offsetof(struct ao_pyro, accel_greater), HELP("accel greater (m/ss * 16)") }, - { "s<", ao_pyro_speed_less, offsetof(struct ao_pyro, speed_less), "speed less (m/s * 16)" }, - { "s>", ao_pyro_speed_greater, offsetof(struct ao_pyro, speed_greater), "speed greater (m/s * 16)" }, + { "s<", ao_pyro_speed_less, offsetof(struct ao_pyro, speed_less), HELP("speed less (m/s * 16)") }, + { "s>", ao_pyro_speed_greater, offsetof(struct ao_pyro, speed_greater), HELP("speed greater (m/s * 16)") }, - { "h<", ao_pyro_height_less, offsetof(struct ao_pyro, height_less), "height less (m)" }, - { "h>", ao_pyro_height_greater, offsetof(struct ao_pyro, height_greater), "height greater (m)" }, + { "h<", ao_pyro_height_less, offsetof(struct ao_pyro, height_less), HELP("height less (m)") }, + { "h>", ao_pyro_height_greater, offsetof(struct ao_pyro, height_greater), HELP("height greater (m)") }, - { "o<", ao_pyro_orient_less, offsetof(struct ao_pyro, orient_less), "orient less (deg)" }, - { "o>", ao_pyro_orient_greater, offsetof(struct ao_pyro, orient_greater), "orient greater (deg)" }, +#if 0 + { "o<", ao_pyro_orient_less, offsetof(struct ao_pyro, orient_less), HELP("orient less (deg)") }, + { "o>", ao_pyro_orient_greater, offsetof(struct ao_pyro, orient_greater), HELP("orient greater (deg)") }, +#endif - { "t<", ao_pyro_time_less, offsetof(struct ao_pyro, time_less), "time less (s * 100)" }, - { "t>", ao_pyro_time_greater, offsetof(struct ao_pyro, time_greater), "time greater (s * 100)" }, + { "t<", ao_pyro_time_less, offsetof(struct ao_pyro, time_less), HELP("time less (s * 100)") }, + { "t>", ao_pyro_time_greater, offsetof(struct ao_pyro, time_greater), HELP("time greater (s * 100)") }, - { "A", ao_pyro_ascending, NO_VALUE, "ascending" }, - { "D", ao_pyro_descending, NO_VALUE, "descending" }, + { "A", ao_pyro_ascending, NO_VALUE, HELP("ascending") }, + { "D", ao_pyro_descending, NO_VALUE, HELP("descending") }, - { "m", ao_pyro_after_motor, offsetof(struct ao_pyro, motor), "after motor" }, + { "m", ao_pyro_after_motor, offsetof(struct ao_pyro, motor), HELP("after motor") }, - { "d", ao_pyro_delay, offsetof(struct ao_pyro, delay), "delay before firing (s * 100)" }, - { "", ao_pyro_none, NO_VALUE, NULL }, + { "d", ao_pyro_delay, offsetof(struct ao_pyro, delay), HELP("delay before firing (s * 100)") }, + { "", ao_pyro_none, NO_VALUE, HELP(NULL) }, }; static void @@ -244,6 +258,7 @@ ao_pyro_print_name(uint8_t v) printf ("%s%s", s, " " + strlen(s)); } +#if ENABLE_HELP static void ao_pyro_help(void) { @@ -257,6 +272,7 @@ ao_pyro_help(void) printf ("%s\n", ao_pyro_values[v].help); } } +#endif void ao_pyro_show(void) @@ -299,11 +315,14 @@ ao_pyro_set(void) uint8_t v; ao_cmd_white(); + +#if ENABLE_HELP switch (ao_cmd_lex_c) { case '?': ao_pyro_help(); return; } +#endif ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) -- cgit v1.2.3 From 4de789331098abc24abcb9390a35aef889a41784 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 14:47:53 -0700 Subject: altos: Make storage addresses datatype configurable No sense using 32 bits for tiny hardware Signed-off-by: Keith Packard --- src/core/ao_storage.c | 8 ++++---- src/core/ao_storage.h | 22 ++++++++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c index 66394e01..b2dd435b 100644 --- a/src/core/ao_storage.c +++ b/src/core/ao_storage.c @@ -18,7 +18,7 @@ #include uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +ao_storage_read(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant { uint16_t this_len; uint16_t this_off; @@ -48,7 +48,7 @@ ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant } uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +ao_storage_write(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant { uint16_t this_len; uint16_t this_off; @@ -161,8 +161,8 @@ void ao_storage_info(void) __reentrant { ao_storage_setup(); - printf("Storage size: %ld\n", ao_storage_total); - printf("Storage erase unit: %ld\n", ao_storage_block); + printf("Storage size: %ld\n", (long) ao_storage_total); + printf("Storage erase unit: %ld\n", (long) ao_storage_block); ao_storage_device_info(); } diff --git a/src/core/ao_storage.h b/src/core/ao_storage.h index 873fe097..ea946399 100644 --- a/src/core/ao_storage.h +++ b/src/core/ao_storage.h @@ -23,14 +23,20 @@ * drivers */ +#ifndef ao_storage_pos_t +#define ao_storage_pos_t uint32_t +#endif + +typedef ao_storage_pos_t ao_pos_t; + /* Total bytes of available storage */ -extern __pdata uint32_t ao_storage_total; +extern __pdata ao_pos_t ao_storage_total; /* Block size - device is erased in these units. At least 256 bytes */ -extern __pdata uint32_t ao_storage_block; +extern __pdata ao_pos_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ -extern __pdata uint32_t ao_storage_config; +extern __pdata ao_pos_t ao_storage_config; /* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ extern __pdata uint16_t ao_storage_unit; @@ -43,15 +49,15 @@ ao_storage_setup(void) __reentrant; /* Write data. Returns 0 on failure, 1 on success */ uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; +ao_storage_write(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant; /* Read data. Returns 0 on failure, 1 on success */ uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; +ao_storage_read(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant; /* Erase a block of storage. This always clears ao_storage_block bytes */ uint8_t -ao_storage_erase(uint32_t pos) __reentrant; +ao_storage_erase(ao_pos_t pos) __reentrant; /* Flush any pending writes to stable storage */ void @@ -67,11 +73,11 @@ ao_storage_init(void); /* Read data within a storage unit */ uint8_t -ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; +ao_storage_device_read(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant; /* Write data within a storage unit */ uint8_t -ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; +ao_storage_device_write(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant; /* Initialize low-level device bits */ void -- cgit v1.2.3 From 90507d4f7ef77b0870a032b1d9809898c2924721 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:24:21 -0700 Subject: altos: Make ao_tick_count visible Necessary to fetch it when interrupts are already disabled as we can't call ao_time then. Signed-off-by: Keith Packard --- src/avr/ao_timer.c | 2 +- src/cc1111/ao_timer.c | 2 +- src/core/ao.h | 2 ++ src/stm/ao_timer.c | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/avr/ao_timer.c b/src/avr/ao_timer.c index eef14345..cd81b163 100644 --- a/src/avr/ao_timer.c +++ b/src/avr/ao_timer.c @@ -17,7 +17,7 @@ #include "ao.h" -static volatile __data uint16_t ao_tick_count; +volatile __data uint16_t ao_tick_count; uint16_t ao_time(void) { diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c index aadee71e..602f98c8 100644 --- a/src/cc1111/ao_timer.c +++ b/src/cc1111/ao_timer.c @@ -17,7 +17,7 @@ #include "ao.h" -static volatile __data uint16_t ao_tick_count; +volatile __data uint16_t ao_tick_count; uint16_t ao_time(void) __critical { diff --git a/src/core/ao.h b/src/core/ao.h index d4be3be4..65b9eb18 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -125,6 +125,8 @@ ao_panic(uint8_t reason); * ao_timer.c */ +extern volatile __data uint16_t ao_tick_count; + /* Our timer runs at 100Hz */ #define AO_HERTZ 100 #define AO_MS_TO_TICKS(ms) ((ms) / (1000 / AO_HERTZ)) diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 936dc881..ebe75366 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -17,7 +17,7 @@ #include "ao.h" -static volatile __data uint16_t ao_tick_count; +volatile __data uint16_t ao_tick_count; uint16_t ao_time(void) { -- cgit v1.2.3 From 1887ca3d7d4a0259686f8c1e68d1e47c47b4ab84 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:25:47 -0700 Subject: altos: Pass flight dynamics to companion boards Necessary for TelePyro Signed-off-by: Keith Packard --- src/core/ao_companion.h | 4 ++++ src/core/ao_flight.c | 4 ---- src/core/ao_flight.h | 2 -- src/drivers/ao_companion.c | 4 ++++ 4 files changed, 8 insertions(+), 6 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_companion.h b/src/core/ao_companion.h index 47e0acf5..035325a3 100644 --- a/src/core/ao_companion.h +++ b/src/core/ao_companion.h @@ -30,6 +30,10 @@ struct ao_companion_command { uint16_t tick; uint16_t serial; uint16_t flight; + int16_t accel; + int16_t speed; + int16_t height; + int16_t motor_number; }; struct ao_companion_setup { diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index fc018f00..aa4f6961 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -40,9 +40,7 @@ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ __pdata uint16_t ao_boost_tick; /* time of launch detect */ -#if AO_PYRO_NUM __pdata uint16_t ao_motor_number; /* number of motors burned so far */ -#endif /* * track min/max data over a long interval to detect @@ -218,9 +216,7 @@ ao_flight(void) #else ao_flight_state = ao_flight_coast; #endif -#if AO_PYRO_NUM ++ao_motor_number; -#endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } break; diff --git a/src/core/ao_flight.h b/src/core/ao_flight.h index c5c8af46..b80202f0 100644 --- a/src/core/ao_flight.h +++ b/src/core/ao_flight.h @@ -38,9 +38,7 @@ enum ao_flight_state { extern __pdata enum ao_flight_state ao_flight_state; extern __pdata uint16_t ao_boost_tick; -#if AO_PYRO_NUM extern __pdata uint16_t ao_motor_number; -#endif extern __pdata uint16_t ao_launch_time; extern __pdata uint8_t ao_flight_force_idle; diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index a3167956..6e0bd2ec 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -53,6 +53,10 @@ ao_companion_send_command(uint8_t command) ao_companion_command.tick = ao_time(); ao_companion_command.serial = ao_serial_number; ao_companion_command.flight = ao_flight_number; + ao_companion_command.accel = ao_accel; + ao_companion_command.speed = ao_speed; + ao_companion_command.height = ao_height; + ao_companion_command.motor_number = ao_motor_number; ao_spi_send(&ao_companion_command, sizeof (ao_companion_command), AO_COMPANION_SPI_BUS); } -- cgit v1.2.3 From 6581eefbdbd8d3e94f615bdf11652a000d131c8e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:27:58 -0700 Subject: altos: Use 'HAS_ORIENT' to enable orientation selection in pyro code Don't expose orientation options when no orientation data is available Signed-off-by: Keith Packard --- src/core/ao_pyro.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index b0d45162..162f5e1e 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -66,14 +66,16 @@ ao_pyro_ready(struct ao_pyro *pyro) continue; break; +#if HAS_ORIENT case ao_pyro_orient_less: -// if (ao_orient <= pyro->orient_less) + if (ao_orient <= pyro->orient_less) continue; break; case ao_pyro_orient_greater: -// if (ao_orient >= pyro->orient_greater) + if (ao_orient >= pyro->orient_greater) continue; break; +#endif case ao_pyro_time_less: if ((int16_t) (ao_time() - ao_boost_tick) <= pyro->time_less) @@ -102,8 +104,8 @@ ao_pyro_ready(struct ao_pyro *pyro) /* handled separately */ continue; - case ao_pyro_none: - break; + default: + continue; } return FALSE; } @@ -234,7 +236,7 @@ const struct { { "h<", ao_pyro_height_less, offsetof(struct ao_pyro, height_less), HELP("height less (m)") }, { "h>", ao_pyro_height_greater, offsetof(struct ao_pyro, height_greater), HELP("height greater (m)") }, -#if 0 +#if HAS_ORIENT { "o<", ao_pyro_orient_less, offsetof(struct ao_pyro, orient_less), HELP("orient less (deg)") }, { "o>", ao_pyro_orient_greater, offsetof(struct ao_pyro, orient_greater), HELP("orient greater (deg)") }, #endif @@ -281,6 +283,7 @@ ao_pyro_show(void) uint8_t v; struct ao_pyro *pyro; + printf ("Pyro-count: %d\n", AO_PYRO_NUM); for (p = 0; p < AO_PYRO_NUM; p++) { printf ("Pyro %2d: ", p); pyro = &ao_config.pyro[p]; -- cgit v1.2.3 From 3ce645a79b54e22d7835c6e390a22a5ad501a339 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:30:29 -0700 Subject: altos: Add manual firing command for extra pyro channels In parallel with the existing igniter commands, this tests the programmable pyro channels Signed-off-by: Keith Packard --- src/core/ao_pyro.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index 162f5e1e..a1377d21 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -103,7 +103,7 @@ ao_pyro_ready(struct ao_pyro *pyro) case ao_pyro_delay: /* handled separately */ continue; - + default: continue; } @@ -117,7 +117,7 @@ ao_pyro_ready(struct ao_pyro *pyro) ao_delay(AO_MS_TO_TICKS(50)); \ ao_gpio_set(port, bit, pin, 0); \ } while (0) - + static void ao_pyro_fire(uint8_t p) @@ -246,7 +246,7 @@ const struct { { "A", ao_pyro_ascending, NO_VALUE, HELP("ascending") }, { "D", ao_pyro_descending, NO_VALUE, HELP("descending") }, - + { "m", ao_pyro_after_motor, offsetof(struct ao_pyro, motor), HELP("after motor") }, { "d", ao_pyro_delay, offsetof(struct ao_pyro, delay), HELP("delay before firing (s * 100)") }, @@ -275,7 +275,7 @@ ao_pyro_help(void) } } #endif - + void ao_pyro_show(void) { @@ -340,7 +340,7 @@ ao_pyro_set(void) ao_cmd_white(); if (ao_cmd_lex_c == '\n') break; - + for (c = 0; c < AO_PYRO_NAME_LEN - 1; c++) { if (ao_cmd_is_white()) break; @@ -370,6 +370,25 @@ ao_pyro_set(void) _ao_config_edit_finish(); } +static void +ao_pyro_manual(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + ao_cmd_white(); + ao_cmd_decimal(); + if (ao_cmd_lex_i < 0 || AO_PYRO_NUM <= ao_cmd_lex_i) + return; + ao_pyro_fire(ao_cmd_lex_i); + +} + +const struct ao_cmds ao_pyro_cmds[] = { + { ao_pyro_manual, "P DoIt \0Fire igniter" }, + { 0, NULL } +}; + void ao_pyro_init(void) { @@ -397,5 +416,6 @@ ao_pyro_init(void) #if AO_PYRO_NUM > 7 ao_enable_output(AO_PYRO_PORT_7, AO_PYRO_PIN_7, AO_PYRO_7, 0); #endif + ao_cmd_register(&ao_pyro_cmds[0]); ao_add_task(&ao_pyro_task, ao_pyro, "pyro"); } -- cgit v1.2.3 From 5860f75677ee20fcf35ab89a6b62f3e14a1c32f5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:32:26 -0700 Subject: altos: Enable pyro channel control in telepyro This should make the board actually work now. Signed-off-by: Keith Packard --- src/avr/ao_pins.h | 30 ++++++++++++++++++++++++++++++ src/core/ao_pyro.c | 15 ++++++++++++++- src/core/ao_pyro.h | 2 ++ src/drivers/ao_pyro_slave.c | 11 +++++++++++ src/product/ao_telepyro.c | 3 +++ 5 files changed, 60 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 3c9010a8..bc423ff7 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -59,6 +59,8 @@ #define SPI_SLAVE_PIN_0_3 1 #define SPI_SLAVE_PIN_2_5 0 + + #define IS_COMPANION 1 #endif #ifdef TELEPYRO @@ -77,6 +79,7 @@ #define DISABLE_HELP 1 #define HAS_STORAGE_DEBUG 0 #define IS_COMPANION 1 + #define HAS_ORIENT 0 #define ao_storage_pos_t uint16_t #define AVR_VCC_5V 0 @@ -89,6 +92,33 @@ #define SPI_SLAVE_PIN_0_3 1 #define SPI_SLAVE_PIN_2_5 0 + + #define AO_PYRO_NUM 8 + + #define AO_PYRO_PORT_0 B + #define AO_PYRO_PIN_0 5 + + #define AO_PYRO_PORT_1 B + #define AO_PYRO_PIN_1 6 + + #define AO_PYRO_PORT_2 B + #define AO_PYRO_PIN_2 7 + + #define AO_PYRO_PORT_3 C + #define AO_PYRO_PIN_3 6 + + #define AO_PYRO_PORT_4 C + #define AO_PYRO_PIN_4 7 + + #define AO_PYRO_PORT_5 D + #define AO_PYRO_PIN_5 5 + + #define AO_PYRO_PORT_6 D + #define AO_PYRO_PIN_6 3 + + #define AO_PYRO_PORT_7 D + #define AO_PYRO_PIN_7 2 + #endif #define AO_M25_SPI_CS_PORT SPI_CS_PORT diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index a1377d21..4f37e979 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -20,6 +20,15 @@ #include #include +#if IS_COMPANION +#include +#define ao_accel ao_companion_command.accel +#define ao_speed ao_companion_command.speed +#define ao_height ao_companion_command.height +#define ao_flight_state ao_companion_command.flight_state +#define ao_motor_number ao_companion_command.motor_number +#endif + #define ao_lowbit(x) ((x) & (-x)) /* @@ -152,6 +161,8 @@ ao_pyro_fire(uint8_t p) ao_delay(AO_MS_TO_TICKS(50)); } +uint8_t ao_pyro_wakeup; + static void ao_pyro(void) { @@ -163,7 +174,9 @@ ao_pyro(void) ao_sleep(&ao_flight_state); for (;;) { - ao_delay(AO_MS_TO_TICKS(100)); + ao_alarm(AO_MS_TO_TICKS(100)); + ao_sleep(&ao_pyro_wakeup); + ao_clear_alarm(); for (p = 0; p < AO_PYRO_NUM; p++) { pyro = &ao_config.pyro[p]; diff --git a/src/core/ao_pyro.h b/src/core/ao_pyro.h index 1989a9e5..5deb69d0 100644 --- a/src/core/ao_pyro.h +++ b/src/core/ao_pyro.h @@ -57,6 +57,8 @@ struct ao_pyro { uint8_t fired; }; +extern uint8_t ao_pyro_wakeup; + void ao_pyro_set(void); diff --git a/src/drivers/ao_pyro_slave.c b/src/drivers/ao_pyro_slave.c index 70206a00..f07c2cba 100644 --- a/src/drivers/ao_pyro_slave.c +++ b/src/drivers/ao_pyro_slave.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include struct ao_companion_command ao_companion_command; @@ -28,6 +30,11 @@ static const struct ao_companion_setup ao_telepyro_setup = { .channels = AO_TELEPYRO_NUM_ADC, }; +struct ao_config ao_config; + +extern volatile __data uint16_t ao_tick_count; +uint16_t ao_boost_tick; + void ao_spi_slave(void) { if (!ao_spi_slave_recv((uint8_t *) &ao_companion_command, @@ -45,6 +52,10 @@ void ao_spi_slave(void) AO_TELEPYRO_NUM_ADC * sizeof (uint16_t)); break; case AO_COMPANION_NOTIFY: + /* Can't use ao_time because we have interrupts suspended */ + if (ao_companion_command.flight_state < ao_flight_boost && ao_companion_command.flight_state >= ao_flight_boost) + ao_boost_tick = ao_tick_count; + ao_wakeup(&ao_pyro_wakeup); break; default: return; diff --git a/src/product/ao_telepyro.c b/src/product/ao_telepyro.c index a2b8f83c..79454fb7 100644 --- a/src/product/ao_telepyro.c +++ b/src/product/ao_telepyro.c @@ -31,6 +31,9 @@ main(void) ao_spi_slave_init(); ao_usb_init(); ao_adc_init(); + ao_storage_init(); + ao_config_init(); + ao_pyro_init(); ao_start_scheduler(); return 0; } -- cgit v1.2.3 From a5d873d47b3b16ca32559b4de668bf07b25eddb0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jul 2012 01:24:52 -0700 Subject: altos: Place STM config values at fixed addresses for re-use Just like cc1111, stick the serial number and radio calibration values at known fixed addresses so that when re-flashing the board, we can go find the existing values. Signed-off-by: Keith Packard --- ao-tools/ao-load/ao-load.c | 2 +- src/avr/ao_arch.h | 6 +++++- src/avr/ao_romconfig.c | 2 +- src/cc1111/ao_arch.h | 10 ++++++---- src/core/ao_product.c | 2 +- src/drivers/ao_cc1120.c | 2 +- src/drivers/ao_companion.c | 4 +++- src/megametrum-v0.1/Makefile | 2 +- src/megametrum-v0.1/ao_pins.h | 4 ++++ src/stm-bringup/Makefile | 4 ++-- src/stm/altos.ld | 21 +++++++++++---------- src/stm/ao_arch.h | 12 ++++++++++++ src/stm/ao_romconfig.c | 7 ++++++- 13 files changed, 54 insertions(+), 24 deletions(-) (limited to 'src/core') diff --git a/ao-tools/ao-load/ao-load.c b/ao-tools/ao-load/ao-load.c index 1b729d39..e3cef4a5 100644 --- a/ao-tools/ao-load/ao-load.c +++ b/ao-tools/ao-load/ao-load.c @@ -197,7 +197,7 @@ main (int argc, char **argv) serial = strtoul(serial_string, NULL, 0); if (!serial) -(argv[0]); + usage(argv[0]); serial_int[0] = serial & 0xff; serial_int[1] = (serial >> 8) & 0xff; diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index c775dab6..a14d0ade 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -67,7 +67,11 @@ extern void putchar(char c); extern char getchar(void); extern void ao_avr_stdio_init(void); -extern const uint16_t ao_serial_number; +#define AO_ROMCONFIG_VERSION 2 + +#define AO_ROMCONFIG_SYMBOL(a) const + +extern AO_ROMCONFIG_SYMBOL(0) uint16_t ao_serial_number; #define AVR_PUSH8(stack, val) (*((stack)--) = (val)) diff --git a/src/avr/ao_romconfig.c b/src/avr/ao_romconfig.c index bbb677e2..ecc19c76 100644 --- a/src/avr/ao_romconfig.c +++ b/src/avr/ao_romconfig.c @@ -17,4 +17,4 @@ #include "ao.h" -const uint16_t ao_serial_number = 0; +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_serial_number = 0; diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 8d9e4952..06b04b93 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -59,10 +59,12 @@ #define AO_ROMCONFIG_VERSION 2 -extern __code __at (0x00a0) uint16_t ao_romconfig_version; -extern __code __at (0x00a2) uint16_t ao_romconfig_check; -extern __code __at (0x00a4) uint16_t ao_serial_number; -extern __code __at (0x00a6) uint32_t ao_radio_cal; +#define AO_ROMCONFIG_SYMBOL(a) __code __at(a) + +extern AO_ROMCONFIG_SYMBOL(0x00a0) uint16_t ao_romconfig_version; +extern AO_ROMCONFIG_SYMBOL(0x00a2) uint16_t ao_romconfig_check; +extern AO_ROMCONFIG_SYMBOL(0x00a4) uint16_t ao_serial_number; +extern AO_ROMCONFIG_SYMBOL(0x00a6) uint32_t ao_radio_cal; #ifndef HAS_USB #error Please define HAS_USB diff --git a/src/core/ao_product.c b/src/core/ao_product.c index 67ec6793..ec91b978 100644 --- a/src/core/ao_product.c +++ b/src/core/ao_product.c @@ -29,7 +29,7 @@ const char ao_product[] = AO_iProduct_STRING; #if HAS_USB #include "ao_usb.h" /* USB descriptors in one giant block of bytes */ -__code __at(0x00aa) uint8_t ao_usb_descriptors [] = +AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] = { /* Device descriptor */ 0x12, diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 569df3b7..97a434d8 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -29,7 +29,7 @@ uint8_t ao_radio_in_recv; #define CC1120_DEBUG AO_FEC_DEBUG #define CC1120_TRACE 0 -const uint32_t ao_radio_cal = 0x6ca333; +extern const uint32_t ao_radio_cal; #define FOSC 32000000 diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index 6e0bd2ec..c749adea 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -68,7 +68,7 @@ ao_companion_get_setup(void) ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup), AO_COMPANION_SPI_BUS); COMPANION_DESELECT(); return (ao_companion_setup.board_id == - ~ao_companion_setup.board_id_inverse); + (uint16_t) ~ao_companion_setup.board_id_inverse); } static void @@ -116,6 +116,8 @@ ao_companion_status(void) __reentrant { uint8_t i; printf("Companion running: %d\n", ao_companion_running); + if (!ao_companion_running) + return; printf("device: %d\n", ao_companion_setup.board_id); printf("update period: %d\n", ao_companion_setup.update_period); printf("channels: %d\n", ao_companion_setup.channels); diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index a519609e..4a4c983a 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -92,7 +92,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) -$(PROG): Makefile $(OBJ) +$(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc ../altitude.h: make-altitude diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 2c438f6c..6b0f9832 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -268,6 +268,10 @@ struct ao_adc { * Radio (cc1120) */ +/* gets pretty close to 434.550 */ + +#define AO_RADIO_CAL_DEFAULT 0x6ca333 + #define AO_FEC_DEBUG 0 #define AO_CC1120_SPI_CS_PORT (&stm_gpioc) #define AO_CC1120_SPI_CS_PIN 5 diff --git a/src/stm-bringup/Makefile b/src/stm-bringup/Makefile index 01c80614..d45e836d 100644 --- a/src/stm-bringup/Makefile +++ b/src/stm-bringup/Makefile @@ -16,7 +16,7 @@ DEF_CFLAGS=-g -std=gnu99 -Os -mlittle-endian -mthumb -ffreestanding -nostdlib -I # to run from SRAM LD_FLAGS_RAM=-L../stm -Wl,-Taltos-ram.ld -LD_FLAGS=-L../stm -Wl,-Taltos.ld +LD_FLAGS=-L../stm -Wl,-Tbringup.ld CFLAGS=$(DEF_CFLAGS) -mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY @@ -28,7 +28,7 @@ all: bringup-ram.elf bringup.elf %.bin: %.elf $(OBJCOPY) -O binary $^ $@ -bringup.elf: $(OBJ) $(C_LIB) altos.ld +bringup.elf: $(OBJ) $(C_LIB) bringup.ld $(CC) $(CFLAGS) $(LD_FLAGS) -o $@ $(OBJ) $(C_LIB) -lgcc bringup-ram.elf: $(OBJ) $(C_LIB) altos-ram.ld diff --git a/src/stm/altos.ld b/src/stm/altos.ld index f5a84f4c..f78a45d6 100644 --- a/src/stm/altos.ld +++ b/src/stm/altos.ld @@ -25,18 +25,22 @@ INCLUDE registers.ld EXTERN (stm_interrupt_vector) SECTIONS { - . = ORIGIN(rom); - /* * Rom contents */ - __text_start__ = .; - - .text : { + .text ORIGIN(rom) : { + __text_start__ = .; *(.interrupt) /* Interrupt vectors */ + + . = ORIGIN(rom) + 0x100; + + ao_romconfig.o(.romconfig*) + ao_product.o(.romconfig*) + *(.text*) /* Executable code */ *(.rodata*) /* Constants */ + } > rom .ARM.exidx : { @@ -44,12 +48,10 @@ SECTIONS { __text_end__ = .; } > rom - . = ORIGIN(ram); - __data_start__ = .; - /* Data -- relocated to RAM, but written to ROM */ - .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + __data_start__ = .; *(.data) /* initialized data */ __data_end__ = .; __bss_start__ = .; @@ -63,7 +65,6 @@ SECTIONS { PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); PROVIDE(end = .); - } ENTRY(start); diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index d8fa3e89..484ce89e 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -59,7 +59,19 @@ extern void putchar(char c); extern char getchar(void); extern void ao_avr_stdio_init(void); + +/* + * ao_romconfig.c + */ + +#define AO_ROMCONFIG_VERSION 2 + +#define AO_ROMCONFIG_SYMBOL(a) __attribute__((section(".romconfig"))) const + +extern const uint16_t ao_romconfig_version; +extern const uint16_t ao_romconfig_check; extern const uint16_t ao_serial_number; +extern const uint32_t ao_radio_cal; #define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) diff --git a/src/stm/ao_romconfig.c b/src/stm/ao_romconfig.c index 84317458..cbb922ec 100644 --- a/src/stm/ao_romconfig.c +++ b/src/stm/ao_romconfig.c @@ -17,4 +17,9 @@ #include "ao.h" -const uint16_t ao_serial_number = 58; +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_version = AO_ROMCONFIG_VERSION; +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_check = ~AO_ROMCONFIG_VERSION; +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_serial_number = 0; +#ifdef AO_RADIO_CAL_DEFAULT +AO_ROMCONFIG_SYMBOL (0) uint32_t ao_radio_cal = AO_RADIO_CAL_DEFAULT; +#endif -- cgit v1.2.3 From b4be63627e146c7c868b5b3468d34880a561cfba Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jul 2012 20:44:55 -0700 Subject: altos: Megametrum ADC values are 12 bits, discard low 4 for telemetry We've only got space for 8 bits for the ADC values for pyro channels, discard the low 4 bits instead of the low 8 bits. Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 583a6636..52ac9489 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -138,9 +138,9 @@ ao_send_mega_data(void) telemetry.mega_data.v_batt = packet->adc.v_batt; telemetry.mega_data.v_pyro = packet->adc.v_pbatt; - /* XXX figure out right shift value; 4 might suffice */ + /* ADC range is 0-4095, so shift by four to save the high 8 bits */ for (i = 0; i < AO_ADC_NUM_SENSE; i++) - telemetry.mega_data.sense[i] = packet->adc.sense[i] >> 8; + telemetry.mega_data.sense[i] = packet->adc.sense[i] >> 4; telemetry.mega_data.ground_pres = ao_ground_pres; telemetry.mega_data.ground_accel = ao_ground_accel; -- cgit v1.2.3 From a698cd68968fc0be5f96b1729cdea2f65d2ccbf6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jul 2012 23:59:13 -0700 Subject: altos: Toggling telemetry monitoring would replay the telem queue Using the 'm' command to turn telem off and back on would end up going around the whole telemetry queue replaying everything there as the wait loop would exit when disabling monitoring even if the ring was empty. Signed-off-by: Keith Packard --- src/core/ao_monitor.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/core') diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index d492e32a..5876bef7 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -132,6 +132,8 @@ ao_monitor_put(void) ao_sleep(DATA_TO_XDATA(&ao_external_monitoring)); while (ao_monitor_tail == ao_monitor_head && ao_external_monitoring) ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + if (!ao_external_monitoring) + continue; m = &ao_monitor_ring[ao_monitor_tail]; ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail); switch (ao_monitoring) { -- cgit v1.2.3 From 52e920bc7a98edf5c6f2ad0bd59d581011dcd5c9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 22 Jul 2012 15:18:27 -0700 Subject: altos: Move ao_radio_cmac.c to core (it doesn't depend on hardware) Signed-off-by: Keith Packard --- src/ao_radio_cmac.c | 406 ----------------------------------------------- src/core/ao_radio_cmac.c | 406 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 406 insertions(+), 406 deletions(-) delete mode 100644 src/ao_radio_cmac.c create mode 100644 src/core/ao_radio_cmac.c (limited to 'src/core') diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c deleted file mode 100644 index e263f0db..00000000 --- a/src/ao_radio_cmac.c +++ /dev/null @@ -1,406 +0,0 @@ -/* - * 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 AO_CMAC_KEY_LEN AO_AES_LEN -#define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) - -static __xdata uint8_t ao_radio_cmac_mutex; -__pdata int16_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) -{ - 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 = (int16_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74; - if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & PKT_APPEND_STATUS_1_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); - memcpy(cmac_data, packet, len); - radio_cmac_send(len); - 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); - i = radio_cmac_recv(len, timeout); - if (i == AO_RADIO_CMAC_OK) - memcpy(packet, cmac_data, len); - ao_mutex_put(&ao_radio_cmac_mutex); - 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); -} - -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/core/ao_radio_cmac.c b/src/core/ao_radio_cmac.c new file mode 100644 index 00000000..e263f0db --- /dev/null +++ b/src/core/ao_radio_cmac.c @@ -0,0 +1,406 @@ +/* + * 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 AO_CMAC_KEY_LEN AO_AES_LEN +#define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) + +static __xdata uint8_t ao_radio_cmac_mutex; +__pdata int16_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) +{ + 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 = (int16_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74; + if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & PKT_APPEND_STATUS_1_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); + memcpy(cmac_data, packet, len); + radio_cmac_send(len); + 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); + i = radio_cmac_recv(len, timeout); + if (i == AO_RADIO_CMAC_OK) + memcpy(packet, cmac_data, len); + ao_mutex_put(&ao_radio_cmac_mutex); + 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); +} + +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]); +} -- cgit v1.2.3 From 59588ba34159b27c02e1a886b46497ecfa0cf4d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Jul 2012 16:22:23 -0700 Subject: Add ability to re-play telemetry through TeleDongle This adds a new command to TeleDongle to send arbitrary data, and then creates a new tool, 'ao-send-telem' that replays existing telemetry files through TeleDongle. Signed-off-by: Keith Packard --- ao-tools/Makefile.am | 2 +- ao-tools/ao-send-telem/Makefile.am | 12 ++ ao-tools/ao-send-telem/ao-send-telem.1 | 64 +++++++++ ao-tools/ao-send-telem/ao-send-telem.c | 238 +++++++++++++++++++++++++++++++++ configure.ac | 1 + src/core/ao_send_packet.c | 74 ++++++++++ src/core/ao_send_packet.h | 24 ++++ src/product/Makefile.teledongle | 1 + src/product/ao_teledongle.c | 2 + 9 files changed, 417 insertions(+), 1 deletion(-) create mode 100644 ao-tools/ao-send-telem/Makefile.am create mode 100644 ao-tools/ao-send-telem/ao-send-telem.1 create mode 100644 ao-tools/ao-send-telem/ao-send-telem.c create mode 100644 src/core/ao_send_packet.c create mode 100644 src/core/ao_send_packet.h (limited to 'src/core') diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index 6c315dd1..257fdaec 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -1 +1 @@ -SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list ao-load ao-telem ao-stmload +SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list ao-load ao-telem ao-stmload ao-send-telem diff --git a/ao-tools/ao-send-telem/Makefile.am b/ao-tools/ao-send-telem/Makefile.am new file mode 100644 index 00000000..bfddf131 --- /dev/null +++ b/ao-tools/ao-send-telem/Makefile.am @@ -0,0 +1,12 @@ +bin_PROGRAMS=ao-send-telem + +AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) +AO_POSTFLIGHT_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a + +ao_send_telem_DEPENDENCIES = $(AO_POSTFLIGHT_LIBS) + +ao_send_telem_LDADD=$(AO_POSTFLIGHT_LIBS) $(LIBUSB_LIBS) + +ao_send_telem_SOURCES = ao-send-telem.c + +man_MANS = ao-send-telem.1 diff --git a/ao-tools/ao-send-telem/ao-send-telem.1 b/ao-tools/ao-send-telem/ao-send-telem.1 new file mode 100644 index 00000000..fbdb2fe9 --- /dev/null +++ b/ao-tools/ao-send-telem/ao-send-telem.1 @@ -0,0 +1,64 @@ +.\" +.\" Copyright © 2009 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; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" 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. +.\" +.\" +.TH AO-SEND-TELEM 1 "ao-send-telem" "" +.SH NAME +ao-send-telem \- Re-transmit stored telemetry file +.SH SYNOPSIS +.B "ao-send-telem" +[\-T \fItty-device\fP] +[\--tty \fItty-device\fP] +[\-D \fIaltos-device\fP] +[\--device \fIaltos-device\fP] +[\-F \fIfrequency (kHz)\fP] +[\--frequency \fIfrequency (kHz)\fP] +[\-R] +[\--realtime] + +.SH OPTIONS +.TP +\-T tty-device | --tty tty-device +This selects which tty device ao-dumplog uses to communicate with +the target device. +.TP +\-D AltOS-device | --device AltOS-device +Search for a connected device. This requires an argument of one of the +following forms: +.IP +TeleDongle:2 +.br +TeleDongle +.br +2 +.IP +Leaving out the product name will cause the tool to select a suitable +product, leaving out the serial number will cause the tool to match +one of the available devices. +.TP +\-F kHz | --frequency kHz +This selects which frequency to send the specified packets on. +.TP +\-R | --realtime +This makes the program delay between packets in pad mode. Normally, +pad mode packets are sent as quickly as possible. +.SH DESCRIPTION +.I ao-send-telem +reads the specified flight telemetry log and re-transmits it via the +specified ground station device +.SH AUTHOR +Keith Packard diff --git a/ao-tools/ao-send-telem/ao-send-telem.c b/ao-tools/ao-send-telem/ao-send-telem.c new file mode 100644 index 00000000..c4c354e0 --- /dev/null +++ b/ao-tools/ao-send-telem/ao-send-telem.c @@ -0,0 +1,238 @@ +/* + * 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. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "cc.h" +#include "cc-usb.h" + +static const struct option options[] = { + { .name = "tty", .has_arg = 1, .val = 'T' }, + { .name = "device", .has_arg = 1, .val = 'D' }, + { .name = "frequency", .has_arg = 1, .val = 'F' }, + { .name = "realtime", .has_arg = 0, .val = 'R' }, + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s [--tty ] [--device ] [--frequency ] [--realtime] file.telem ...\n", program); + exit(1); +} + +#define bool(b) ((b) ? "true" : "false") + +struct ao_telem_list { + struct ao_telem_list *next; + union ao_telemetry_all telem; +}; + +static struct ao_telem_list *telem_list, **telem_last; + +static void +trim_telem(uint16_t time) +{ + while (telem_list && (int16_t) (time - telem_list->telem.generic.tick) > 0) { + struct ao_telem_list *next = telem_list->next; + free(telem_list); + telem_list = next; + } + if (!telem_list) + telem_last = &telem_list; +} + +static void +add_telem(union ao_telemetry_all *telem) +{ + struct ao_telem_list *new = malloc (sizeof (struct ao_telem_list)); + trim_telem((uint16_t) (telem->generic.tick - 20 * 100)); + new->telem = *telem; + new->next = 0; + *telem_last = new; + telem_last = &new->next; +} + +static enum ao_flight_state cur_state = ao_flight_invalid; +static enum ao_flight_state last_state = ao_flight_invalid; + +static enum ao_flight_state +packet_state(union ao_telemetry_all *telem) +{ + switch (telem->generic.type) { + case AO_TELEMETRY_SENSOR_TELEMETRUM: + case AO_TELEMETRY_SENSOR_TELEMINI: + case AO_TELEMETRY_SENSOR_TELENANO: + cur_state = telem->sensor.state; + break; + case AO_TELEMETRY_MEGA_DATA: + cur_state = telem->mega_data.state; + break; + } + return cur_state; +} + +static const char *state_names[] = { + "startup", + "idle", + "pad", + "boost", + "fast", + "coast", + "drogue", + "main", + "landed", + "invalid" +}; + +static void +send_telem(struct cc_usb *cc, union ao_telemetry_all *telem) +{ + int rssi = (int8_t) telem->generic.rssi / 2 - 74; + int i; + uint8_t *b; + + packet_state(telem); + if (cur_state != last_state) { + if (0 <= cur_state && cur_state < sizeof(state_names) / sizeof (state_names[0])) + printf ("%s\n", state_names[cur_state]); + last_state = cur_state; + } + cc_usb_printf(cc, "S 20\n"); + b = (uint8_t *) telem; + for (i = 0; i < 0x20; i++) + cc_usb_printf(cc, "%02x", b[i]); + cc_usb_sync(cc); +} + +static void +do_delay(uint16_t now, uint16_t then) +{ + int16_t delay = (int16_t) (now - then); + + if (delay > 0 && delay < 1000) + usleep(delay * 10 * 1000); +} + +static uint16_t +send_queued(struct cc_usb *cc, int pause) +{ + struct ao_telem_list *next; + uint16_t tick = 0; + int started = 0; + + while (telem_list) { + if (started && pause) + do_delay(telem_list->telem.generic.tick, tick); + tick = telem_list->telem.generic.tick; + started = 1; + send_telem(cc, &telem_list->telem); + + next = telem_list->next; + free(telem_list); + telem_list = next; + } + return tick; +} + +int +main (int argc, char **argv) +{ + struct cc_usb *cc; + char *tty = NULL; + char *device = NULL; + char line[80]; + int c, i, ret = 0; + int freq = 434550; + char *s; + FILE *file; + int serial; + uint16_t last_tick; + int started; + int realtime = 0; + + + while ((c = getopt_long(argc, argv, "RT:D:F:", options, NULL)) != -1) { + switch (c) { + case 'T': + tty = optarg; + break; + case 'D': + device = optarg; + break; + case 'F': + freq = atoi(optarg); + break; + case 'R': + realtime = 1; + default: + usage(argv[0]); + break; + } + } + if (!tty) + tty = cc_usbdevs_find_by_arg(device, "TeleDongle"); + if (!tty) + tty = getenv("ALTOS_TTY"); + if (!tty) + tty="/dev/ttyACM0"; + cc = cc_usb_open(tty); + if (!cc) + exit (1); + + cc_usb_printf(cc, "m 0\n"); + cc_usb_printf(cc, "F %d\n", freq); + for (i = optind; i < argc; i++) { + file = fopen(argv[i], "r"); + if (!file) { + perror(argv[i]); + ret++; + continue; + } + started = 0; + last_tick = 0; + while (fgets(line, sizeof (line), file)) { + union ao_telemetry_all telem; + + if (cc_telemetry_parse(line, &telem)) { + /* + * Skip packets with CRC errors. + */ + if ((telem.generic.status & (1 << 7)) == 0) + continue; + + if (started) { + do_delay(telem.generic.tick, last_tick); + last_tick = telem.generic.tick; + send_telem(cc, &telem); + } else { + add_telem(&telem); + if (packet_state(&telem) > ao_flight_pad) { + started = 1; + last_tick = send_queued(cc, realtime); + } + } + } + } + fclose (file); + + } + return ret; +} diff --git a/configure.ac b/configure.ac index bcd2dcac..c59261af 100644 --- a/configure.ac +++ b/configure.ac @@ -160,6 +160,7 @@ ao-tools/ao-list/Makefile ao-tools/ao-load/Makefile ao-tools/ao-telem/Makefile ao-tools/ao-stmload/Makefile +ao-tools/ao-send-telem/Makefile ao-utils/Makefile src/Version ]) 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 + * + * 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 \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 + * + * 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/product/Makefile.teledongle b/src/product/Makefile.teledongle index 5105b567..3101b777 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -43,6 +43,7 @@ CC1111_SRC = \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ + ao_send_packet.c \ ao_romconfig.c \ ao_string.c \ ao_timer.c \ diff --git a/src/product/ao_teledongle.c b/src/product/ao_teledongle.c index 0c829e97..25ebe73e 100644 --- a/src/product/ao_teledongle.c +++ b/src/product/ao_teledongle.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include void main(void) @@ -32,6 +33,7 @@ main(void) ao_rssi_init(AO_LED_RED); ao_radio_init(); ao_packet_master_init(); + ao_send_packet_init(); #if HAS_DBG ao_dbg_init(); #endif -- cgit v1.2.3 From e4d244eefa4c779cd9c8a91389bf998c54705b72 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Jul 2012 19:42:53 -0700 Subject: altos: Add software AES implementation This is untested Signed-off-by: Keith Packard --- src/aes/ao_aes.c | 390 ++++++++++++++++++++++++ src/aes/ao_aes_int.h | 64 ++++ src/aes/ao_aes_tables.c | 768 +++++++++++++++++++++++++++++++++++++++++++++++ src/aes/ao_aes_tables.h | 10 + src/core/ao_aes.h | 2 + src/core/ao_radio_cmac.c | 8 +- src/stm/Makefile.defs | 2 +- 7 files changed, 1239 insertions(+), 5 deletions(-) create mode 100644 src/aes/ao_aes.c create mode 100644 src/aes/ao_aes_int.h create mode 100644 src/aes/ao_aes_tables.c create mode 100644 src/aes/ao_aes_tables.h (limited to 'src/core') diff --git a/src/aes/ao_aes.c b/src/aes/ao_aes.c new file mode 100644 index 00000000..4977aaf8 --- /dev/null +++ b/src/aes/ao_aes.c @@ -0,0 +1,390 @@ +/* Copyright (C) 2000-2009 Peter Selinger. + This file is part of ccrypt. It is free software and it is covered + by the GNU general public license. See the file COPYING for details. */ + +/* rijndael.c - optimized version of the Rijndeal cipher */ +/* $Id: rijndael.c 258 2009-08-26 17:46:10Z selinger $ */ + +/* derived from original source: rijndael-alg-ref.c v2.0 August '99 + * Reference ANSI C code for NIST competition + * authors: Paulo Barreto + * Vincent Rijmen + */ + +#include +#include +#include "ao_aes_int.h" + +static const int xshifts[3][2][4] = { + {{0, 1, 2, 3}, + {0, 3, 2, 1}}, + + {{0, 1, 2, 3}, + {0, 5, 4, 3}}, + + {{0, 1, 3, 4}, + {0, 7, 5, 4}}, +}; + +/* Exor corresponding text input and round key input bytes */ +/* the result is written to res, which can be the same as a */ +static inline void xKeyAddition(word32 res[MAXBC], word32 a[MAXBC], + word32 rk[MAXBC], int BC) +{ + int j; + + for (j = 0; j < BC; j++) { + res[j] = a[j] ^ rk[j]; + } +} + +#if 0 /* code included for reference */ + +/* shift rows a, return result in res. This avoids having to copy a + tmp array back to a. res must not be a. */ +static inline void xShiftRow(word32 res[MAXBC], word32 a[MAXBC], int shift[4], + int BC) +{ + word8 (*a8)[4] = (word8 (*)[4]) a; + word8 (*res8)[4] = (word8 (*)[4]) res; + + /* Row 0 remains unchanged + * The other three rows are shifted a variable amount + */ + int i, j; + int s; + + for (j = 0; j < BC; j++) { + res8[j][0] = a8[j][0]; + } + for (i = 1; i < 4; i++) { + s = shift[i]; + for (j = 0; j < BC; j++) { + res8[j][i] = a8[(j + s) % BC][i]; + } + } +} + +static inline void xSubstitution(word32 a[MAXBC], word8 box[256], int BC) +{ + word8 (*a8)[4] = (word8 (*)[4]) a; + + /* Replace every byte of the input by the byte at that place + * in the nonlinear S-box + */ + int i, j; + + for (i = 0; i < 4; i++) { + for (j = 0; j < BC; j++) { + a8[j][i] = box[a[j][i]]; + } + } +} + +#endif /* code included for reference */ + +/* profiling shows that the ccrypt program spends about 50% of its + time in the function xShiftSubst. Splitting the inner "for" + statement into two parts - versus using the expensive "%" modulo + operation, makes this function about 44% faster, thereby making the + entire program about 28% faster. With -O3 optimization, the time + savings are even more dramatic - ccrypt runs between 55% and 65% + faster on most platforms. */ + +/* do ShiftRow and Substitution together. res must not be a. */ +static inline void xShiftSubst(word32 res[MAXBC], word32 a[MAXBC], + int shift[4], int BC, const word8 box[256]) +{ + int i, j; + int s; + word8 (*a8)[4] = (word8 (*)[4]) a; + word8 (*res8)[4] = (word8 (*)[4]) res; + + for (j = 0; j < BC; j++) { + res8[j][0] = box[a8[j][0]]; + } + for (i = 1; i < 4; i++) { + s = shift[i]; + for (j = 0; j < BC - s; j++) { + res8[j][i] = box[a8[(j + s)][i]]; + } + for (j = BC - s; j < BC; j++) { + res8[j][i] = box[a8[(j + s) - BC][i]]; + } + } +} + +#if 0 /* code included for reference */ + +/* Mix the four bytes of every column in a linear way */ +/* the result is written to res, which may equal a */ +static inline void xMixColumn(word32 res[MAXBC], word32 a[MAXBC], int BC) +{ + int j; + word32 b; + word8 (*a8)[4] = (word8 (*)[4]) a; + + for (j = 0; j < BC; j++) { + b = M0[0][a8[j][0]].w32; + b ^= M0[1][a8[j][1]].w32; + b ^= M0[2][a8[j][2]].w32; + b ^= M0[3][a8[j][3]].w32; + res[j] = b; + } +} + +#endif /* code included for reference */ + +/* do MixColumn and KeyAddition together */ +static inline void xMixAdd(word32 res[MAXBC], word32 a[MAXBC], + word32 rk[MAXBC], int BC) +{ + int j; + word32 b; + word8 (*a8)[4] = (word8 (*)[4]) a; + + for (j = 0; j < BC; j++) { + b = M0[0][a8[j][0]].w32; + b ^= M0[1][a8[j][1]].w32; + b ^= M0[2][a8[j][2]].w32; + b ^= M0[3][a8[j][3]].w32; + b ^= rk[j]; + res[j] = b; + } +} + +/* Mix the four bytes of every column in a linear way + * This is the opposite operation of xMixColumn */ +/* the result is written to res, which may equal a */ +static inline void xInvMixColumn(word32 res[MAXBC], word32 a[MAXBC], int BC) +{ + int j; + word32 b; + word8 (*a8)[4] = (word8 (*)[4]) a; + + for (j = 0; j < BC; j++) { + b = M1[0][a8[j][0]].w32; + b ^= M1[1][a8[j][1]].w32; + b ^= M1[2][a8[j][2]].w32; + b ^= M1[3][a8[j][3]].w32; + res[j] = b; + } +} + +#if 0 /* code included for reference */ + +/* do KeyAddition and InvMixColumn together */ +static inline void xAddInvMix(word32 res[MAXBC], word32 a[MAXBC], + word32 rk[MAXBC], int BC) +{ + int j; + word32 b; + word8 (*a8)[4] = (word8 (*)[4]) a; + + for (j = 0; j < BC; j++) { + a[j] = a[j] ^ rk[j]; + b = M1[0][a8[j][0]].w32; + b ^= M1[1][a8[j][1]].w32; + b ^= M1[2][a8[j][2]].w32; + b ^= M1[3][a8[j][3]].w32; + res[j] = b; + } +} + +#endif /* code included for reference */ + +int xrijndaelKeySched(word32 key[], int keyBits, int blockBits, + roundkey *rkk) +{ + /* Calculate the necessary round keys + * The number of calculations depends on keyBits and blockBits */ + int KC, BC, ROUNDS; + int i, j, t, rconpointer = 0; + word8 (*k8)[4] = (word8 (*)[4]) key; + + switch (keyBits) { + case 128: + KC = 4; + break; + case 192: + KC = 6; + break; + case 256: + KC = 8; + break; + default: + return -1; + } + + switch (blockBits) { + case 128: + BC = 4; + break; + case 192: + BC = 6; + break; + case 256: + BC = 8; + break; + default: + return -2; + } + + ROUNDS = KC > BC ? KC + 6 : BC + 6; + + t = 0; + /* copy values into round key array */ + for (j = 0; (j < KC) && (t < (ROUNDS + 1) * BC); j++, t++) + rkk->rk[t] = key[j]; + + while (t < (ROUNDS + 1) * BC) { /* while not enough round key material */ + /* calculate new values */ + for (i = 0; i < 4; i++) { + k8[0][i] ^= xS[k8[KC - 1][(i + 1) % 4]]; + } + k8[0][0] ^= xrcon[rconpointer++]; + + if (KC != 8) { + for (j = 1; j < KC; j++) { + key[j] ^= key[j - 1]; + } + } else { + for (j = 1; j < 4; j++) { + key[j] ^= key[j - 1]; + } + for (i = 0; i < 4; i++) { + k8[4][i] ^= xS[k8[3][i]]; + } + for (j = 5; j < 8; j++) { + key[j] ^= key[j - 1]; + } + } + /* copy values into round key array */ + for (j = 0; (j < KC) && (t < (ROUNDS + 1) * BC); j++, t++) { + rkk->rk[t] = key[j]; + } + } + + /* make roundkey structure */ + rkk->BC = BC; + rkk->KC = KC; + rkk->ROUNDS = ROUNDS; + for (i = 0; i < 2; i++) { + for (j = 0; j < 4; j++) { + rkk->shift[i][j] = xshifts[(BC - 4) >> 1][i][j]; + } + } + + return 0; +} + +/* Encryption of one block. */ + +void xrijndaelEncrypt(word32 block[], roundkey *rkk) +{ + word32 block2[MAXBC]; /* hold intermediate result */ + int r; + + int *shift = rkk->shift[0]; + int BC = rkk->BC; + int ROUNDS = rkk->ROUNDS; + word32 *rp = rkk->rk; + + /* begin with a key addition */ + xKeyAddition(block, block, rp, BC); + rp += BC; + + /* ROUNDS-1 ordinary rounds */ + for (r = 1; r < ROUNDS; r++) { + xShiftSubst(block2, block, shift, BC, xS); + xMixAdd(block, block2, rp, BC); + rp += BC; + } + + /* Last round is special: there is no xMixColumn */ + xShiftSubst(block2, block, shift, BC, xS); + xKeyAddition(block, block2, rp, BC); +} + +void xrijndaelDecrypt(word32 block[], roundkey *rkk) +{ + word32 block2[MAXBC]; /* hold intermediate result */ + int r; + + int *shift = rkk->shift[1]; + int BC = rkk->BC; + int ROUNDS = rkk->ROUNDS; + word32 *rp = rkk->rk + ROUNDS * BC; + + /* To decrypt: apply the inverse operations of the encrypt routine, + * in opposite order + * + * (xKeyAddition is an involution: it's equal to its inverse) + * (the inverse of xSubstitution with table S is xSubstitution with the + * inverse table of S) + * (the inverse of xShiftRow is xShiftRow over a suitable distance) + */ + + /* First the special round: + * without xInvMixColumn + * with extra xKeyAddition + */ + xKeyAddition(block2, block, rp, BC); + xShiftSubst(block, block2, shift, BC, xSi); + rp -= BC; + + /* ROUNDS-1 ordinary rounds + */ + for (r = ROUNDS - 1; r > 0; r--) { + xKeyAddition(block, block, rp, BC); + xInvMixColumn(block2, block, BC); + xShiftSubst(block, block2, shift, BC, xSi); + rp -= BC; + } + + /* End with the extra key addition + */ + + xKeyAddition(block, block, rp, BC); +} + +uint8_t ao_aes_mutex; +static roundkey rkk; + +static uint8_t iv[16]; + +void +ao_aes_set_mode(enum ao_aes_mode mode) +{ + /* we only do CBC_MAC anyways... */ +} + +void +ao_aes_set_key(__xdata uint8_t *in) +{ + xrijndaelKeySched((word32 *) in, 128, 128, &rkk); +} + +void +ao_aes_zero_iv(void) +{ + memset(iv, '\0', sizeof (iv)); +} + +void +ao_aes_run(__xdata uint8_t *in, + __xdata uint8_t *out) +{ + uint8_t i; + + for (i = 0; i < 16; i++) + iv[i] ^= in[i]; + xrijndaelEncrypt((word32 *) iv, &rkk); + if (out) + memcpy(out, iv, 16); +} + +void +ao_aes_init(void) +{ +} diff --git a/src/aes/ao_aes_int.h b/src/aes/ao_aes_int.h new file mode 100644 index 00000000..7990a2e1 --- /dev/null +++ b/src/aes/ao_aes_int.h @@ -0,0 +1,64 @@ +/* Copyright (C) 2000-2009 Peter Selinger. + This file is part of ccrypt. It is free software and it is covered + by the GNU general public license. See the file COPYING for details. */ + +/* rijndael.h */ +/* $Id: rijndael.h 258 2009-08-26 17:46:10Z selinger $ */ + +/* derived from original source: rijndael-alg-ref.h v2.0 August '99 + * Reference ANSI C code for NIST competition + * authors: Paulo Barreto + * Vincent Rijmen + */ + +#ifndef __RIJNDAEL_H +#define __RIJNDAEL_H + +#include + +typedef uint8_t word8; +typedef uint32_t word32; + +/* a type to hold 32 bits accessible as 1 integer or 4 bytes */ +union word8x4_u { + word8 w8[4]; + word32 w32; +}; +typedef union word8x4_u word8x4; + +#include "ao_aes_tables.h" + +#define MAXBC (256/32) +#define MAXKC (256/32) +#define MAXROUNDS 14 +#define MAXRK ((MAXROUNDS+1)*MAXBC) + +typedef struct { + int BC; + int KC; + int ROUNDS; + int shift[2][4]; + word32 rk[MAXRK]; +} roundkey; + +/* keys and blocks are externally treated as word32 arrays, to + make sure they are aligned on 4-byte boundaries on architectures + that require it. */ + +/* make a roundkey rkk from key. key must have appropriate size given + by keyBits. keyBits and blockBits may only be 128, 196, or + 256. Returns non-zero if arguments are invalid. */ + +int xrijndaelKeySched(word32 key[], int keyBits, int blockBits, + roundkey *rkk); + +/* encrypt, resp. decrypt, block using rijndael roundkey rkk. rkk must + have been created with xrijndaelKeySched. Size of block, in bits, + must be equal to blockBits parameter that was used to make rkk. In + all other cases, behavior is undefined - for reasons of speed, no + check for error conditions is done. */ + +void xrijndaelEncrypt(word32 block[], roundkey *rkk); +void xrijndaelDecrypt(word32 block[], roundkey *rkk); + +#endif /* __RIJNDAEL_H */ diff --git a/src/aes/ao_aes_tables.c b/src/aes/ao_aes_tables.c new file mode 100644 index 00000000..1bca227c --- /dev/null +++ b/src/aes/ao_aes_tables.c @@ -0,0 +1,768 @@ +/* Copyright (C) 2000-2009 Peter Selinger. + This file is part of ccrypt. It is free software and it is covered + by the GNU general public license. See the file COPYING for details. */ + +/* generated by maketables.c */ + +#include "ao_aes_int.h" + +const word8x4 M0[4][256] = { + { + {{ 0, 0, 0, 0}}, {{ 2, 1, 1, 3}}, {{ 4, 2, 2, 6}}, + {{ 6, 3, 3, 5}}, {{ 8, 4, 4, 12}}, {{ 10, 5, 5, 15}}, + {{ 12, 6, 6, 10}}, {{ 14, 7, 7, 9}}, {{ 16, 8, 8, 24}}, + {{ 18, 9, 9, 27}}, {{ 20, 10, 10, 30}}, {{ 22, 11, 11, 29}}, + {{ 24, 12, 12, 20}}, {{ 26, 13, 13, 23}}, {{ 28, 14, 14, 18}}, + {{ 30, 15, 15, 17}}, {{ 32, 16, 16, 48}}, {{ 34, 17, 17, 51}}, + {{ 36, 18, 18, 54}}, {{ 38, 19, 19, 53}}, {{ 40, 20, 20, 60}}, + {{ 42, 21, 21, 63}}, {{ 44, 22, 22, 58}}, {{ 46, 23, 23, 57}}, + {{ 48, 24, 24, 40}}, {{ 50, 25, 25, 43}}, {{ 52, 26, 26, 46}}, + {{ 54, 27, 27, 45}}, {{ 56, 28, 28, 36}}, {{ 58, 29, 29, 39}}, + {{ 60, 30, 30, 34}}, {{ 62, 31, 31, 33}}, {{ 64, 32, 32, 96}}, + {{ 66, 33, 33, 99}}, {{ 68, 34, 34, 102}}, {{ 70, 35, 35, 101}}, + {{ 72, 36, 36, 108}}, {{ 74, 37, 37, 111}}, {{ 76, 38, 38, 106}}, + {{ 78, 39, 39, 105}}, {{ 80, 40, 40, 120}}, {{ 82, 41, 41, 123}}, + {{ 84, 42, 42, 126}}, {{ 86, 43, 43, 125}}, {{ 88, 44, 44, 116}}, + {{ 90, 45, 45, 119}}, {{ 92, 46, 46, 114}}, {{ 94, 47, 47, 113}}, + {{ 96, 48, 48, 80}}, {{ 98, 49, 49, 83}}, {{100, 50, 50, 86}}, + {{102, 51, 51, 85}}, {{104, 52, 52, 92}}, {{106, 53, 53, 95}}, + {{108, 54, 54, 90}}, {{110, 55, 55, 89}}, {{112, 56, 56, 72}}, + {{114, 57, 57, 75}}, {{116, 58, 58, 78}}, {{118, 59, 59, 77}}, + {{120, 60, 60, 68}}, {{122, 61, 61, 71}}, {{124, 62, 62, 66}}, + {{126, 63, 63, 65}}, {{128, 64, 64, 192}}, {{130, 65, 65, 195}}, + {{132, 66, 66, 198}}, {{134, 67, 67, 197}}, {{136, 68, 68, 204}}, + {{138, 69, 69, 207}}, {{140, 70, 70, 202}}, {{142, 71, 71, 201}}, + {{144, 72, 72, 216}}, {{146, 73, 73, 219}}, {{148, 74, 74, 222}}, + {{150, 75, 75, 221}}, {{152, 76, 76, 212}}, {{154, 77, 77, 215}}, + {{156, 78, 78, 210}}, {{158, 79, 79, 209}}, {{160, 80, 80, 240}}, + {{162, 81, 81, 243}}, {{164, 82, 82, 246}}, {{166, 83, 83, 245}}, + {{168, 84, 84, 252}}, {{170, 85, 85, 255}}, {{172, 86, 86, 250}}, + {{174, 87, 87, 249}}, {{176, 88, 88, 232}}, {{178, 89, 89, 235}}, + {{180, 90, 90, 238}}, {{182, 91, 91, 237}}, {{184, 92, 92, 228}}, + {{186, 93, 93, 231}}, {{188, 94, 94, 226}}, {{190, 95, 95, 225}}, + {{192, 96, 96, 160}}, {{194, 97, 97, 163}}, {{196, 98, 98, 166}}, + {{198, 99, 99, 165}}, {{200, 100, 100, 172}}, {{202, 101, 101, 175}}, + {{204, 102, 102, 170}}, {{206, 103, 103, 169}}, {{208, 104, 104, 184}}, + {{210, 105, 105, 187}}, {{212, 106, 106, 190}}, {{214, 107, 107, 189}}, + {{216, 108, 108, 180}}, {{218, 109, 109, 183}}, {{220, 110, 110, 178}}, + {{222, 111, 111, 177}}, {{224, 112, 112, 144}}, {{226, 113, 113, 147}}, + {{228, 114, 114, 150}}, {{230, 115, 115, 149}}, {{232, 116, 116, 156}}, + {{234, 117, 117, 159}}, {{236, 118, 118, 154}}, {{238, 119, 119, 153}}, + {{240, 120, 120, 136}}, {{242, 121, 121, 139}}, {{244, 122, 122, 142}}, + {{246, 123, 123, 141}}, {{248, 124, 124, 132}}, {{250, 125, 125, 135}}, + {{252, 126, 126, 130}}, {{254, 127, 127, 129}}, {{ 27, 128, 128, 155}}, + {{ 25, 129, 129, 152}}, {{ 31, 130, 130, 157}}, {{ 29, 131, 131, 158}}, + {{ 19, 132, 132, 151}}, {{ 17, 133, 133, 148}}, {{ 23, 134, 134, 145}}, + {{ 21, 135, 135, 146}}, {{ 11, 136, 136, 131}}, {{ 9, 137, 137, 128}}, + {{ 15, 138, 138, 133}}, {{ 13, 139, 139, 134}}, {{ 3, 140, 140, 143}}, + {{ 1, 141, 141, 140}}, {{ 7, 142, 142, 137}}, {{ 5, 143, 143, 138}}, + {{ 59, 144, 144, 171}}, {{ 57, 145, 145, 168}}, {{ 63, 146, 146, 173}}, + {{ 61, 147, 147, 174}}, {{ 51, 148, 148, 167}}, {{ 49, 149, 149, 164}}, + {{ 55, 150, 150, 161}}, {{ 53, 151, 151, 162}}, {{ 43, 152, 152, 179}}, + {{ 41, 153, 153, 176}}, {{ 47, 154, 154, 181}}, {{ 45, 155, 155, 182}}, + {{ 35, 156, 156, 191}}, {{ 33, 157, 157, 188}}, {{ 39, 158, 158, 185}}, + {{ 37, 159, 159, 186}}, {{ 91, 160, 160, 251}}, {{ 89, 161, 161, 248}}, + {{ 95, 162, 162, 253}}, {{ 93, 163, 163, 254}}, {{ 83, 164, 164, 247}}, + {{ 81, 165, 165, 244}}, {{ 87, 166, 166, 241}}, {{ 85, 167, 167, 242}}, + {{ 75, 168, 168, 227}}, {{ 73, 169, 169, 224}}, {{ 79, 170, 170, 229}}, + {{ 77, 171, 171, 230}}, {{ 67, 172, 172, 239}}, {{ 65, 173, 173, 236}}, + {{ 71, 174, 174, 233}}, {{ 69, 175, 175, 234}}, {{123, 176, 176, 203}}, + {{121, 177, 177, 200}}, {{127, 178, 178, 205}}, {{125, 179, 179, 206}}, + {{115, 180, 180, 199}}, {{113, 181, 181, 196}}, {{119, 182, 182, 193}}, + {{117, 183, 183, 194}}, {{107, 184, 184, 211}}, {{105, 185, 185, 208}}, + {{111, 186, 186, 213}}, {{109, 187, 187, 214}}, {{ 99, 188, 188, 223}}, + {{ 97, 189, 189, 220}}, {{103, 190, 190, 217}}, {{101, 191, 191, 218}}, + {{155, 192, 192, 91}}, {{153, 193, 193, 88}}, {{159, 194, 194, 93}}, + {{157, 195, 195, 94}}, {{147, 196, 196, 87}}, {{145, 197, 197, 84}}, + {{151, 198, 198, 81}}, {{149, 199, 199, 82}}, {{139, 200, 200, 67}}, + {{137, 201, 201, 64}}, {{143, 202, 202, 69}}, {{141, 203, 203, 70}}, + {{131, 204, 204, 79}}, {{129, 205, 205, 76}}, {{135, 206, 206, 73}}, + {{133, 207, 207, 74}}, {{187, 208, 208, 107}}, {{185, 209, 209, 104}}, + {{191, 210, 210, 109}}, {{189, 211, 211, 110}}, {{179, 212, 212, 103}}, + {{177, 213, 213, 100}}, {{183, 214, 214, 97}}, {{181, 215, 215, 98}}, + {{171, 216, 216, 115}}, {{169, 217, 217, 112}}, {{175, 218, 218, 117}}, + {{173, 219, 219, 118}}, {{163, 220, 220, 127}}, {{161, 221, 221, 124}}, + {{167, 222, 222, 121}}, {{165, 223, 223, 122}}, {{219, 224, 224, 59}}, + {{217, 225, 225, 56}}, {{223, 226, 226, 61}}, {{221, 227, 227, 62}}, + {{211, 228, 228, 55}}, {{209, 229, 229, 52}}, {{215, 230, 230, 49}}, + {{213, 231, 231, 50}}, {{203, 232, 232, 35}}, {{201, 233, 233, 32}}, + {{207, 234, 234, 37}}, {{205, 235, 235, 38}}, {{195, 236, 236, 47}}, + {{193, 237, 237, 44}}, {{199, 238, 238, 41}}, {{197, 239, 239, 42}}, + {{251, 240, 240, 11}}, {{249, 241, 241, 8}}, {{255, 242, 242, 13}}, + {{253, 243, 243, 14}}, {{243, 244, 244, 7}}, {{241, 245, 245, 4}}, + {{247, 246, 246, 1}}, {{245, 247, 247, 2}}, {{235, 248, 248, 19}}, + {{233, 249, 249, 16}}, {{239, 250, 250, 21}}, {{237, 251, 251, 22}}, + {{227, 252, 252, 31}}, {{225, 253, 253, 28}}, {{231, 254, 254, 25}}, + {{229, 255, 255, 26}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 3, 2, 1, 1}}, {{ 6, 4, 2, 2}}, + {{ 5, 6, 3, 3}}, {{ 12, 8, 4, 4}}, {{ 15, 10, 5, 5}}, + {{ 10, 12, 6, 6}}, {{ 9, 14, 7, 7}}, {{ 24, 16, 8, 8}}, + {{ 27, 18, 9, 9}}, {{ 30, 20, 10, 10}}, {{ 29, 22, 11, 11}}, + {{ 20, 24, 12, 12}}, {{ 23, 26, 13, 13}}, {{ 18, 28, 14, 14}}, + {{ 17, 30, 15, 15}}, {{ 48, 32, 16, 16}}, {{ 51, 34, 17, 17}}, + {{ 54, 36, 18, 18}}, {{ 53, 38, 19, 19}}, {{ 60, 40, 20, 20}}, + {{ 63, 42, 21, 21}}, {{ 58, 44, 22, 22}}, {{ 57, 46, 23, 23}}, + {{ 40, 48, 24, 24}}, {{ 43, 50, 25, 25}}, {{ 46, 52, 26, 26}}, + {{ 45, 54, 27, 27}}, {{ 36, 56, 28, 28}}, {{ 39, 58, 29, 29}}, + {{ 34, 60, 30, 30}}, {{ 33, 62, 31, 31}}, {{ 96, 64, 32, 32}}, + {{ 99, 66, 33, 33}}, {{102, 68, 34, 34}}, {{101, 70, 35, 35}}, + {{108, 72, 36, 36}}, {{111, 74, 37, 37}}, {{106, 76, 38, 38}}, + {{105, 78, 39, 39}}, {{120, 80, 40, 40}}, {{123, 82, 41, 41}}, + {{126, 84, 42, 42}}, {{125, 86, 43, 43}}, {{116, 88, 44, 44}}, + {{119, 90, 45, 45}}, {{114, 92, 46, 46}}, {{113, 94, 47, 47}}, + {{ 80, 96, 48, 48}}, {{ 83, 98, 49, 49}}, {{ 86, 100, 50, 50}}, + {{ 85, 102, 51, 51}}, {{ 92, 104, 52, 52}}, {{ 95, 106, 53, 53}}, + {{ 90, 108, 54, 54}}, {{ 89, 110, 55, 55}}, {{ 72, 112, 56, 56}}, + {{ 75, 114, 57, 57}}, {{ 78, 116, 58, 58}}, {{ 77, 118, 59, 59}}, + {{ 68, 120, 60, 60}}, {{ 71, 122, 61, 61}}, {{ 66, 124, 62, 62}}, + {{ 65, 126, 63, 63}}, {{192, 128, 64, 64}}, {{195, 130, 65, 65}}, + {{198, 132, 66, 66}}, {{197, 134, 67, 67}}, {{204, 136, 68, 68}}, + {{207, 138, 69, 69}}, {{202, 140, 70, 70}}, {{201, 142, 71, 71}}, + {{216, 144, 72, 72}}, {{219, 146, 73, 73}}, {{222, 148, 74, 74}}, + {{221, 150, 75, 75}}, {{212, 152, 76, 76}}, {{215, 154, 77, 77}}, + {{210, 156, 78, 78}}, {{209, 158, 79, 79}}, {{240, 160, 80, 80}}, + {{243, 162, 81, 81}}, {{246, 164, 82, 82}}, {{245, 166, 83, 83}}, + {{252, 168, 84, 84}}, {{255, 170, 85, 85}}, {{250, 172, 86, 86}}, + {{249, 174, 87, 87}}, {{232, 176, 88, 88}}, {{235, 178, 89, 89}}, + {{238, 180, 90, 90}}, {{237, 182, 91, 91}}, {{228, 184, 92, 92}}, + {{231, 186, 93, 93}}, {{226, 188, 94, 94}}, {{225, 190, 95, 95}}, + {{160, 192, 96, 96}}, {{163, 194, 97, 97}}, {{166, 196, 98, 98}}, + {{165, 198, 99, 99}}, {{172, 200, 100, 100}}, {{175, 202, 101, 101}}, + {{170, 204, 102, 102}}, {{169, 206, 103, 103}}, {{184, 208, 104, 104}}, + {{187, 210, 105, 105}}, {{190, 212, 106, 106}}, {{189, 214, 107, 107}}, + {{180, 216, 108, 108}}, {{183, 218, 109, 109}}, {{178, 220, 110, 110}}, + {{177, 222, 111, 111}}, {{144, 224, 112, 112}}, {{147, 226, 113, 113}}, + {{150, 228, 114, 114}}, {{149, 230, 115, 115}}, {{156, 232, 116, 116}}, + {{159, 234, 117, 117}}, {{154, 236, 118, 118}}, {{153, 238, 119, 119}}, + {{136, 240, 120, 120}}, {{139, 242, 121, 121}}, {{142, 244, 122, 122}}, + {{141, 246, 123, 123}}, {{132, 248, 124, 124}}, {{135, 250, 125, 125}}, + {{130, 252, 126, 126}}, {{129, 254, 127, 127}}, {{155, 27, 128, 128}}, + {{152, 25, 129, 129}}, {{157, 31, 130, 130}}, {{158, 29, 131, 131}}, + {{151, 19, 132, 132}}, {{148, 17, 133, 133}}, {{145, 23, 134, 134}}, + {{146, 21, 135, 135}}, {{131, 11, 136, 136}}, {{128, 9, 137, 137}}, + {{133, 15, 138, 138}}, {{134, 13, 139, 139}}, {{143, 3, 140, 140}}, + {{140, 1, 141, 141}}, {{137, 7, 142, 142}}, {{138, 5, 143, 143}}, + {{171, 59, 144, 144}}, {{168, 57, 145, 145}}, {{173, 63, 146, 146}}, + {{174, 61, 147, 147}}, {{167, 51, 148, 148}}, {{164, 49, 149, 149}}, + {{161, 55, 150, 150}}, {{162, 53, 151, 151}}, {{179, 43, 152, 152}}, + {{176, 41, 153, 153}}, {{181, 47, 154, 154}}, {{182, 45, 155, 155}}, + {{191, 35, 156, 156}}, {{188, 33, 157, 157}}, {{185, 39, 158, 158}}, + {{186, 37, 159, 159}}, {{251, 91, 160, 160}}, {{248, 89, 161, 161}}, + {{253, 95, 162, 162}}, {{254, 93, 163, 163}}, {{247, 83, 164, 164}}, + {{244, 81, 165, 165}}, {{241, 87, 166, 166}}, {{242, 85, 167, 167}}, + {{227, 75, 168, 168}}, {{224, 73, 169, 169}}, {{229, 79, 170, 170}}, + {{230, 77, 171, 171}}, {{239, 67, 172, 172}}, {{236, 65, 173, 173}}, + {{233, 71, 174, 174}}, {{234, 69, 175, 175}}, {{203, 123, 176, 176}}, + {{200, 121, 177, 177}}, {{205, 127, 178, 178}}, {{206, 125, 179, 179}}, + {{199, 115, 180, 180}}, {{196, 113, 181, 181}}, {{193, 119, 182, 182}}, + {{194, 117, 183, 183}}, {{211, 107, 184, 184}}, {{208, 105, 185, 185}}, + {{213, 111, 186, 186}}, {{214, 109, 187, 187}}, {{223, 99, 188, 188}}, + {{220, 97, 189, 189}}, {{217, 103, 190, 190}}, {{218, 101, 191, 191}}, + {{ 91, 155, 192, 192}}, {{ 88, 153, 193, 193}}, {{ 93, 159, 194, 194}}, + {{ 94, 157, 195, 195}}, {{ 87, 147, 196, 196}}, {{ 84, 145, 197, 197}}, + {{ 81, 151, 198, 198}}, {{ 82, 149, 199, 199}}, {{ 67, 139, 200, 200}}, + {{ 64, 137, 201, 201}}, {{ 69, 143, 202, 202}}, {{ 70, 141, 203, 203}}, + {{ 79, 131, 204, 204}}, {{ 76, 129, 205, 205}}, {{ 73, 135, 206, 206}}, + {{ 74, 133, 207, 207}}, {{107, 187, 208, 208}}, {{104, 185, 209, 209}}, + {{109, 191, 210, 210}}, {{110, 189, 211, 211}}, {{103, 179, 212, 212}}, + {{100, 177, 213, 213}}, {{ 97, 183, 214, 214}}, {{ 98, 181, 215, 215}}, + {{115, 171, 216, 216}}, {{112, 169, 217, 217}}, {{117, 175, 218, 218}}, + {{118, 173, 219, 219}}, {{127, 163, 220, 220}}, {{124, 161, 221, 221}}, + {{121, 167, 222, 222}}, {{122, 165, 223, 223}}, {{ 59, 219, 224, 224}}, + {{ 56, 217, 225, 225}}, {{ 61, 223, 226, 226}}, {{ 62, 221, 227, 227}}, + {{ 55, 211, 228, 228}}, {{ 52, 209, 229, 229}}, {{ 49, 215, 230, 230}}, + {{ 50, 213, 231, 231}}, {{ 35, 203, 232, 232}}, {{ 32, 201, 233, 233}}, + {{ 37, 207, 234, 234}}, {{ 38, 205, 235, 235}}, {{ 47, 195, 236, 236}}, + {{ 44, 193, 237, 237}}, {{ 41, 199, 238, 238}}, {{ 42, 197, 239, 239}}, + {{ 11, 251, 240, 240}}, {{ 8, 249, 241, 241}}, {{ 13, 255, 242, 242}}, + {{ 14, 253, 243, 243}}, {{ 7, 243, 244, 244}}, {{ 4, 241, 245, 245}}, + {{ 1, 247, 246, 246}}, {{ 2, 245, 247, 247}}, {{ 19, 235, 248, 248}}, + {{ 16, 233, 249, 249}}, {{ 21, 239, 250, 250}}, {{ 22, 237, 251, 251}}, + {{ 31, 227, 252, 252}}, {{ 28, 225, 253, 253}}, {{ 25, 231, 254, 254}}, + {{ 26, 229, 255, 255}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 1, 3, 2, 1}}, {{ 2, 6, 4, 2}}, + {{ 3, 5, 6, 3}}, {{ 4, 12, 8, 4}}, {{ 5, 15, 10, 5}}, + {{ 6, 10, 12, 6}}, {{ 7, 9, 14, 7}}, {{ 8, 24, 16, 8}}, + {{ 9, 27, 18, 9}}, {{ 10, 30, 20, 10}}, {{ 11, 29, 22, 11}}, + {{ 12, 20, 24, 12}}, {{ 13, 23, 26, 13}}, {{ 14, 18, 28, 14}}, + {{ 15, 17, 30, 15}}, {{ 16, 48, 32, 16}}, {{ 17, 51, 34, 17}}, + {{ 18, 54, 36, 18}}, {{ 19, 53, 38, 19}}, {{ 20, 60, 40, 20}}, + {{ 21, 63, 42, 21}}, {{ 22, 58, 44, 22}}, {{ 23, 57, 46, 23}}, + {{ 24, 40, 48, 24}}, {{ 25, 43, 50, 25}}, {{ 26, 46, 52, 26}}, + {{ 27, 45, 54, 27}}, {{ 28, 36, 56, 28}}, {{ 29, 39, 58, 29}}, + {{ 30, 34, 60, 30}}, {{ 31, 33, 62, 31}}, {{ 32, 96, 64, 32}}, + {{ 33, 99, 66, 33}}, {{ 34, 102, 68, 34}}, {{ 35, 101, 70, 35}}, + {{ 36, 108, 72, 36}}, {{ 37, 111, 74, 37}}, {{ 38, 106, 76, 38}}, + {{ 39, 105, 78, 39}}, {{ 40, 120, 80, 40}}, {{ 41, 123, 82, 41}}, + {{ 42, 126, 84, 42}}, {{ 43, 125, 86, 43}}, {{ 44, 116, 88, 44}}, + {{ 45, 119, 90, 45}}, {{ 46, 114, 92, 46}}, {{ 47, 113, 94, 47}}, + {{ 48, 80, 96, 48}}, {{ 49, 83, 98, 49}}, {{ 50, 86, 100, 50}}, + {{ 51, 85, 102, 51}}, {{ 52, 92, 104, 52}}, {{ 53, 95, 106, 53}}, + {{ 54, 90, 108, 54}}, {{ 55, 89, 110, 55}}, {{ 56, 72, 112, 56}}, + {{ 57, 75, 114, 57}}, {{ 58, 78, 116, 58}}, {{ 59, 77, 118, 59}}, + {{ 60, 68, 120, 60}}, {{ 61, 71, 122, 61}}, {{ 62, 66, 124, 62}}, + {{ 63, 65, 126, 63}}, {{ 64, 192, 128, 64}}, {{ 65, 195, 130, 65}}, + {{ 66, 198, 132, 66}}, {{ 67, 197, 134, 67}}, {{ 68, 204, 136, 68}}, + {{ 69, 207, 138, 69}}, {{ 70, 202, 140, 70}}, {{ 71, 201, 142, 71}}, + {{ 72, 216, 144, 72}}, {{ 73, 219, 146, 73}}, {{ 74, 222, 148, 74}}, + {{ 75, 221, 150, 75}}, {{ 76, 212, 152, 76}}, {{ 77, 215, 154, 77}}, + {{ 78, 210, 156, 78}}, {{ 79, 209, 158, 79}}, {{ 80, 240, 160, 80}}, + {{ 81, 243, 162, 81}}, {{ 82, 246, 164, 82}}, {{ 83, 245, 166, 83}}, + {{ 84, 252, 168, 84}}, {{ 85, 255, 170, 85}}, {{ 86, 250, 172, 86}}, + {{ 87, 249, 174, 87}}, {{ 88, 232, 176, 88}}, {{ 89, 235, 178, 89}}, + {{ 90, 238, 180, 90}}, {{ 91, 237, 182, 91}}, {{ 92, 228, 184, 92}}, + {{ 93, 231, 186, 93}}, {{ 94, 226, 188, 94}}, {{ 95, 225, 190, 95}}, + {{ 96, 160, 192, 96}}, {{ 97, 163, 194, 97}}, {{ 98, 166, 196, 98}}, + {{ 99, 165, 198, 99}}, {{100, 172, 200, 100}}, {{101, 175, 202, 101}}, + {{102, 170, 204, 102}}, {{103, 169, 206, 103}}, {{104, 184, 208, 104}}, + {{105, 187, 210, 105}}, {{106, 190, 212, 106}}, {{107, 189, 214, 107}}, + {{108, 180, 216, 108}}, {{109, 183, 218, 109}}, {{110, 178, 220, 110}}, + {{111, 177, 222, 111}}, {{112, 144, 224, 112}}, {{113, 147, 226, 113}}, + {{114, 150, 228, 114}}, {{115, 149, 230, 115}}, {{116, 156, 232, 116}}, + {{117, 159, 234, 117}}, {{118, 154, 236, 118}}, {{119, 153, 238, 119}}, + {{120, 136, 240, 120}}, {{121, 139, 242, 121}}, {{122, 142, 244, 122}}, + {{123, 141, 246, 123}}, {{124, 132, 248, 124}}, {{125, 135, 250, 125}}, + {{126, 130, 252, 126}}, {{127, 129, 254, 127}}, {{128, 155, 27, 128}}, + {{129, 152, 25, 129}}, {{130, 157, 31, 130}}, {{131, 158, 29, 131}}, + {{132, 151, 19, 132}}, {{133, 148, 17, 133}}, {{134, 145, 23, 134}}, + {{135, 146, 21, 135}}, {{136, 131, 11, 136}}, {{137, 128, 9, 137}}, + {{138, 133, 15, 138}}, {{139, 134, 13, 139}}, {{140, 143, 3, 140}}, + {{141, 140, 1, 141}}, {{142, 137, 7, 142}}, {{143, 138, 5, 143}}, + {{144, 171, 59, 144}}, {{145, 168, 57, 145}}, {{146, 173, 63, 146}}, + {{147, 174, 61, 147}}, {{148, 167, 51, 148}}, {{149, 164, 49, 149}}, + {{150, 161, 55, 150}}, {{151, 162, 53, 151}}, {{152, 179, 43, 152}}, + {{153, 176, 41, 153}}, {{154, 181, 47, 154}}, {{155, 182, 45, 155}}, + {{156, 191, 35, 156}}, {{157, 188, 33, 157}}, {{158, 185, 39, 158}}, + {{159, 186, 37, 159}}, {{160, 251, 91, 160}}, {{161, 248, 89, 161}}, + {{162, 253, 95, 162}}, {{163, 254, 93, 163}}, {{164, 247, 83, 164}}, + {{165, 244, 81, 165}}, {{166, 241, 87, 166}}, {{167, 242, 85, 167}}, + {{168, 227, 75, 168}}, {{169, 224, 73, 169}}, {{170, 229, 79, 170}}, + {{171, 230, 77, 171}}, {{172, 239, 67, 172}}, {{173, 236, 65, 173}}, + {{174, 233, 71, 174}}, {{175, 234, 69, 175}}, {{176, 203, 123, 176}}, + {{177, 200, 121, 177}}, {{178, 205, 127, 178}}, {{179, 206, 125, 179}}, + {{180, 199, 115, 180}}, {{181, 196, 113, 181}}, {{182, 193, 119, 182}}, + {{183, 194, 117, 183}}, {{184, 211, 107, 184}}, {{185, 208, 105, 185}}, + {{186, 213, 111, 186}}, {{187, 214, 109, 187}}, {{188, 223, 99, 188}}, + {{189, 220, 97, 189}}, {{190, 217, 103, 190}}, {{191, 218, 101, 191}}, + {{192, 91, 155, 192}}, {{193, 88, 153, 193}}, {{194, 93, 159, 194}}, + {{195, 94, 157, 195}}, {{196, 87, 147, 196}}, {{197, 84, 145, 197}}, + {{198, 81, 151, 198}}, {{199, 82, 149, 199}}, {{200, 67, 139, 200}}, + {{201, 64, 137, 201}}, {{202, 69, 143, 202}}, {{203, 70, 141, 203}}, + {{204, 79, 131, 204}}, {{205, 76, 129, 205}}, {{206, 73, 135, 206}}, + {{207, 74, 133, 207}}, {{208, 107, 187, 208}}, {{209, 104, 185, 209}}, + {{210, 109, 191, 210}}, {{211, 110, 189, 211}}, {{212, 103, 179, 212}}, + {{213, 100, 177, 213}}, {{214, 97, 183, 214}}, {{215, 98, 181, 215}}, + {{216, 115, 171, 216}}, {{217, 112, 169, 217}}, {{218, 117, 175, 218}}, + {{219, 118, 173, 219}}, {{220, 127, 163, 220}}, {{221, 124, 161, 221}}, + {{222, 121, 167, 222}}, {{223, 122, 165, 223}}, {{224, 59, 219, 224}}, + {{225, 56, 217, 225}}, {{226, 61, 223, 226}}, {{227, 62, 221, 227}}, + {{228, 55, 211, 228}}, {{229, 52, 209, 229}}, {{230, 49, 215, 230}}, + {{231, 50, 213, 231}}, {{232, 35, 203, 232}}, {{233, 32, 201, 233}}, + {{234, 37, 207, 234}}, {{235, 38, 205, 235}}, {{236, 47, 195, 236}}, + {{237, 44, 193, 237}}, {{238, 41, 199, 238}}, {{239, 42, 197, 239}}, + {{240, 11, 251, 240}}, {{241, 8, 249, 241}}, {{242, 13, 255, 242}}, + {{243, 14, 253, 243}}, {{244, 7, 243, 244}}, {{245, 4, 241, 245}}, + {{246, 1, 247, 246}}, {{247, 2, 245, 247}}, {{248, 19, 235, 248}}, + {{249, 16, 233, 249}}, {{250, 21, 239, 250}}, {{251, 22, 237, 251}}, + {{252, 31, 227, 252}}, {{253, 28, 225, 253}}, {{254, 25, 231, 254}}, + {{255, 26, 229, 255}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 1, 1, 3, 2}}, {{ 2, 2, 6, 4}}, + {{ 3, 3, 5, 6}}, {{ 4, 4, 12, 8}}, {{ 5, 5, 15, 10}}, + {{ 6, 6, 10, 12}}, {{ 7, 7, 9, 14}}, {{ 8, 8, 24, 16}}, + {{ 9, 9, 27, 18}}, {{ 10, 10, 30, 20}}, {{ 11, 11, 29, 22}}, + {{ 12, 12, 20, 24}}, {{ 13, 13, 23, 26}}, {{ 14, 14, 18, 28}}, + {{ 15, 15, 17, 30}}, {{ 16, 16, 48, 32}}, {{ 17, 17, 51, 34}}, + {{ 18, 18, 54, 36}}, {{ 19, 19, 53, 38}}, {{ 20, 20, 60, 40}}, + {{ 21, 21, 63, 42}}, {{ 22, 22, 58, 44}}, {{ 23, 23, 57, 46}}, + {{ 24, 24, 40, 48}}, {{ 25, 25, 43, 50}}, {{ 26, 26, 46, 52}}, + {{ 27, 27, 45, 54}}, {{ 28, 28, 36, 56}}, {{ 29, 29, 39, 58}}, + {{ 30, 30, 34, 60}}, {{ 31, 31, 33, 62}}, {{ 32, 32, 96, 64}}, + {{ 33, 33, 99, 66}}, {{ 34, 34, 102, 68}}, {{ 35, 35, 101, 70}}, + {{ 36, 36, 108, 72}}, {{ 37, 37, 111, 74}}, {{ 38, 38, 106, 76}}, + {{ 39, 39, 105, 78}}, {{ 40, 40, 120, 80}}, {{ 41, 41, 123, 82}}, + {{ 42, 42, 126, 84}}, {{ 43, 43, 125, 86}}, {{ 44, 44, 116, 88}}, + {{ 45, 45, 119, 90}}, {{ 46, 46, 114, 92}}, {{ 47, 47, 113, 94}}, + {{ 48, 48, 80, 96}}, {{ 49, 49, 83, 98}}, {{ 50, 50, 86, 100}}, + {{ 51, 51, 85, 102}}, {{ 52, 52, 92, 104}}, {{ 53, 53, 95, 106}}, + {{ 54, 54, 90, 108}}, {{ 55, 55, 89, 110}}, {{ 56, 56, 72, 112}}, + {{ 57, 57, 75, 114}}, {{ 58, 58, 78, 116}}, {{ 59, 59, 77, 118}}, + {{ 60, 60, 68, 120}}, {{ 61, 61, 71, 122}}, {{ 62, 62, 66, 124}}, + {{ 63, 63, 65, 126}}, {{ 64, 64, 192, 128}}, {{ 65, 65, 195, 130}}, + {{ 66, 66, 198, 132}}, {{ 67, 67, 197, 134}}, {{ 68, 68, 204, 136}}, + {{ 69, 69, 207, 138}}, {{ 70, 70, 202, 140}}, {{ 71, 71, 201, 142}}, + {{ 72, 72, 216, 144}}, {{ 73, 73, 219, 146}}, {{ 74, 74, 222, 148}}, + {{ 75, 75, 221, 150}}, {{ 76, 76, 212, 152}}, {{ 77, 77, 215, 154}}, + {{ 78, 78, 210, 156}}, {{ 79, 79, 209, 158}}, {{ 80, 80, 240, 160}}, + {{ 81, 81, 243, 162}}, {{ 82, 82, 246, 164}}, {{ 83, 83, 245, 166}}, + {{ 84, 84, 252, 168}}, {{ 85, 85, 255, 170}}, {{ 86, 86, 250, 172}}, + {{ 87, 87, 249, 174}}, {{ 88, 88, 232, 176}}, {{ 89, 89, 235, 178}}, + {{ 90, 90, 238, 180}}, {{ 91, 91, 237, 182}}, {{ 92, 92, 228, 184}}, + {{ 93, 93, 231, 186}}, {{ 94, 94, 226, 188}}, {{ 95, 95, 225, 190}}, + {{ 96, 96, 160, 192}}, {{ 97, 97, 163, 194}}, {{ 98, 98, 166, 196}}, + {{ 99, 99, 165, 198}}, {{100, 100, 172, 200}}, {{101, 101, 175, 202}}, + {{102, 102, 170, 204}}, {{103, 103, 169, 206}}, {{104, 104, 184, 208}}, + {{105, 105, 187, 210}}, {{106, 106, 190, 212}}, {{107, 107, 189, 214}}, + {{108, 108, 180, 216}}, {{109, 109, 183, 218}}, {{110, 110, 178, 220}}, + {{111, 111, 177, 222}}, {{112, 112, 144, 224}}, {{113, 113, 147, 226}}, + {{114, 114, 150, 228}}, {{115, 115, 149, 230}}, {{116, 116, 156, 232}}, + {{117, 117, 159, 234}}, {{118, 118, 154, 236}}, {{119, 119, 153, 238}}, + {{120, 120, 136, 240}}, {{121, 121, 139, 242}}, {{122, 122, 142, 244}}, + {{123, 123, 141, 246}}, {{124, 124, 132, 248}}, {{125, 125, 135, 250}}, + {{126, 126, 130, 252}}, {{127, 127, 129, 254}}, {{128, 128, 155, 27}}, + {{129, 129, 152, 25}}, {{130, 130, 157, 31}}, {{131, 131, 158, 29}}, + {{132, 132, 151, 19}}, {{133, 133, 148, 17}}, {{134, 134, 145, 23}}, + {{135, 135, 146, 21}}, {{136, 136, 131, 11}}, {{137, 137, 128, 9}}, + {{138, 138, 133, 15}}, {{139, 139, 134, 13}}, {{140, 140, 143, 3}}, + {{141, 141, 140, 1}}, {{142, 142, 137, 7}}, {{143, 143, 138, 5}}, + {{144, 144, 171, 59}}, {{145, 145, 168, 57}}, {{146, 146, 173, 63}}, + {{147, 147, 174, 61}}, {{148, 148, 167, 51}}, {{149, 149, 164, 49}}, + {{150, 150, 161, 55}}, {{151, 151, 162, 53}}, {{152, 152, 179, 43}}, + {{153, 153, 176, 41}}, {{154, 154, 181, 47}}, {{155, 155, 182, 45}}, + {{156, 156, 191, 35}}, {{157, 157, 188, 33}}, {{158, 158, 185, 39}}, + {{159, 159, 186, 37}}, {{160, 160, 251, 91}}, {{161, 161, 248, 89}}, + {{162, 162, 253, 95}}, {{163, 163, 254, 93}}, {{164, 164, 247, 83}}, + {{165, 165, 244, 81}}, {{166, 166, 241, 87}}, {{167, 167, 242, 85}}, + {{168, 168, 227, 75}}, {{169, 169, 224, 73}}, {{170, 170, 229, 79}}, + {{171, 171, 230, 77}}, {{172, 172, 239, 67}}, {{173, 173, 236, 65}}, + {{174, 174, 233, 71}}, {{175, 175, 234, 69}}, {{176, 176, 203, 123}}, + {{177, 177, 200, 121}}, {{178, 178, 205, 127}}, {{179, 179, 206, 125}}, + {{180, 180, 199, 115}}, {{181, 181, 196, 113}}, {{182, 182, 193, 119}}, + {{183, 183, 194, 117}}, {{184, 184, 211, 107}}, {{185, 185, 208, 105}}, + {{186, 186, 213, 111}}, {{187, 187, 214, 109}}, {{188, 188, 223, 99}}, + {{189, 189, 220, 97}}, {{190, 190, 217, 103}}, {{191, 191, 218, 101}}, + {{192, 192, 91, 155}}, {{193, 193, 88, 153}}, {{194, 194, 93, 159}}, + {{195, 195, 94, 157}}, {{196, 196, 87, 147}}, {{197, 197, 84, 145}}, + {{198, 198, 81, 151}}, {{199, 199, 82, 149}}, {{200, 200, 67, 139}}, + {{201, 201, 64, 137}}, {{202, 202, 69, 143}}, {{203, 203, 70, 141}}, + {{204, 204, 79, 131}}, {{205, 205, 76, 129}}, {{206, 206, 73, 135}}, + {{207, 207, 74, 133}}, {{208, 208, 107, 187}}, {{209, 209, 104, 185}}, + {{210, 210, 109, 191}}, {{211, 211, 110, 189}}, {{212, 212, 103, 179}}, + {{213, 213, 100, 177}}, {{214, 214, 97, 183}}, {{215, 215, 98, 181}}, + {{216, 216, 115, 171}}, {{217, 217, 112, 169}}, {{218, 218, 117, 175}}, + {{219, 219, 118, 173}}, {{220, 220, 127, 163}}, {{221, 221, 124, 161}}, + {{222, 222, 121, 167}}, {{223, 223, 122, 165}}, {{224, 224, 59, 219}}, + {{225, 225, 56, 217}}, {{226, 226, 61, 223}}, {{227, 227, 62, 221}}, + {{228, 228, 55, 211}}, {{229, 229, 52, 209}}, {{230, 230, 49, 215}}, + {{231, 231, 50, 213}}, {{232, 232, 35, 203}}, {{233, 233, 32, 201}}, + {{234, 234, 37, 207}}, {{235, 235, 38, 205}}, {{236, 236, 47, 195}}, + {{237, 237, 44, 193}}, {{238, 238, 41, 199}}, {{239, 239, 42, 197}}, + {{240, 240, 11, 251}}, {{241, 241, 8, 249}}, {{242, 242, 13, 255}}, + {{243, 243, 14, 253}}, {{244, 244, 7, 243}}, {{245, 245, 4, 241}}, + {{246, 246, 1, 247}}, {{247, 247, 2, 245}}, {{248, 248, 19, 235}}, + {{249, 249, 16, 233}}, {{250, 250, 21, 239}}, {{251, 251, 22, 237}}, + {{252, 252, 31, 227}}, {{253, 253, 28, 225}}, {{254, 254, 25, 231}}, + {{255, 255, 26, 229}}, + }, +}; + +const word8x4 M1[4][256] = { + { + {{ 0, 0, 0, 0}}, {{ 14, 9, 13, 11}}, {{ 28, 18, 26, 22}}, + {{ 18, 27, 23, 29}}, {{ 56, 36, 52, 44}}, {{ 54, 45, 57, 39}}, + {{ 36, 54, 46, 58}}, {{ 42, 63, 35, 49}}, {{112, 72, 104, 88}}, + {{126, 65, 101, 83}}, {{108, 90, 114, 78}}, {{ 98, 83, 127, 69}}, + {{ 72, 108, 92, 116}}, {{ 70, 101, 81, 127}}, {{ 84, 126, 70, 98}}, + {{ 90, 119, 75, 105}}, {{224, 144, 208, 176}}, {{238, 153, 221, 187}}, + {{252, 130, 202, 166}}, {{242, 139, 199, 173}}, {{216, 180, 228, 156}}, + {{214, 189, 233, 151}}, {{196, 166, 254, 138}}, {{202, 175, 243, 129}}, + {{144, 216, 184, 232}}, {{158, 209, 181, 227}}, {{140, 202, 162, 254}}, + {{130, 195, 175, 245}}, {{168, 252, 140, 196}}, {{166, 245, 129, 207}}, + {{180, 238, 150, 210}}, {{186, 231, 155, 217}}, {{219, 59, 187, 123}}, + {{213, 50, 182, 112}}, {{199, 41, 161, 109}}, {{201, 32, 172, 102}}, + {{227, 31, 143, 87}}, {{237, 22, 130, 92}}, {{255, 13, 149, 65}}, + {{241, 4, 152, 74}}, {{171, 115, 211, 35}}, {{165, 122, 222, 40}}, + {{183, 97, 201, 53}}, {{185, 104, 196, 62}}, {{147, 87, 231, 15}}, + {{157, 94, 234, 4}}, {{143, 69, 253, 25}}, {{129, 76, 240, 18}}, + {{ 59, 171, 107, 203}}, {{ 53, 162, 102, 192}}, {{ 39, 185, 113, 221}}, + {{ 41, 176, 124, 214}}, {{ 3, 143, 95, 231}}, {{ 13, 134, 82, 236}}, + {{ 31, 157, 69, 241}}, {{ 17, 148, 72, 250}}, {{ 75, 227, 3, 147}}, + {{ 69, 234, 14, 152}}, {{ 87, 241, 25, 133}}, {{ 89, 248, 20, 142}}, + {{115, 199, 55, 191}}, {{125, 206, 58, 180}}, {{111, 213, 45, 169}}, + {{ 97, 220, 32, 162}}, {{173, 118, 109, 246}}, {{163, 127, 96, 253}}, + {{177, 100, 119, 224}}, {{191, 109, 122, 235}}, {{149, 82, 89, 218}}, + {{155, 91, 84, 209}}, {{137, 64, 67, 204}}, {{135, 73, 78, 199}}, + {{221, 62, 5, 174}}, {{211, 55, 8, 165}}, {{193, 44, 31, 184}}, + {{207, 37, 18, 179}}, {{229, 26, 49, 130}}, {{235, 19, 60, 137}}, + {{249, 8, 43, 148}}, {{247, 1, 38, 159}}, {{ 77, 230, 189, 70}}, + {{ 67, 239, 176, 77}}, {{ 81, 244, 167, 80}}, {{ 95, 253, 170, 91}}, + {{117, 194, 137, 106}}, {{123, 203, 132, 97}}, {{105, 208, 147, 124}}, + {{103, 217, 158, 119}}, {{ 61, 174, 213, 30}}, {{ 51, 167, 216, 21}}, + {{ 33, 188, 207, 8}}, {{ 47, 181, 194, 3}}, {{ 5, 138, 225, 50}}, + {{ 11, 131, 236, 57}}, {{ 25, 152, 251, 36}}, {{ 23, 145, 246, 47}}, + {{118, 77, 214, 141}}, {{120, 68, 219, 134}}, {{106, 95, 204, 155}}, + {{100, 86, 193, 144}}, {{ 78, 105, 226, 161}}, {{ 64, 96, 239, 170}}, + {{ 82, 123, 248, 183}}, {{ 92, 114, 245, 188}}, {{ 6, 5, 190, 213}}, + {{ 8, 12, 179, 222}}, {{ 26, 23, 164, 195}}, {{ 20, 30, 169, 200}}, + {{ 62, 33, 138, 249}}, {{ 48, 40, 135, 242}}, {{ 34, 51, 144, 239}}, + {{ 44, 58, 157, 228}}, {{150, 221, 6, 61}}, {{152, 212, 11, 54}}, + {{138, 207, 28, 43}}, {{132, 198, 17, 32}}, {{174, 249, 50, 17}}, + {{160, 240, 63, 26}}, {{178, 235, 40, 7}}, {{188, 226, 37, 12}}, + {{230, 149, 110, 101}}, {{232, 156, 99, 110}}, {{250, 135, 116, 115}}, + {{244, 142, 121, 120}}, {{222, 177, 90, 73}}, {{208, 184, 87, 66}}, + {{194, 163, 64, 95}}, {{204, 170, 77, 84}}, {{ 65, 236, 218, 247}}, + {{ 79, 229, 215, 252}}, {{ 93, 254, 192, 225}}, {{ 83, 247, 205, 234}}, + {{121, 200, 238, 219}}, {{119, 193, 227, 208}}, {{101, 218, 244, 205}}, + {{107, 211, 249, 198}}, {{ 49, 164, 178, 175}}, {{ 63, 173, 191, 164}}, + {{ 45, 182, 168, 185}}, {{ 35, 191, 165, 178}}, {{ 9, 128, 134, 131}}, + {{ 7, 137, 139, 136}}, {{ 21, 146, 156, 149}}, {{ 27, 155, 145, 158}}, + {{161, 124, 10, 71}}, {{175, 117, 7, 76}}, {{189, 110, 16, 81}}, + {{179, 103, 29, 90}}, {{153, 88, 62, 107}}, {{151, 81, 51, 96}}, + {{133, 74, 36, 125}}, {{139, 67, 41, 118}}, {{209, 52, 98, 31}}, + {{223, 61, 111, 20}}, {{205, 38, 120, 9}}, {{195, 47, 117, 2}}, + {{233, 16, 86, 51}}, {{231, 25, 91, 56}}, {{245, 2, 76, 37}}, + {{251, 11, 65, 46}}, {{154, 215, 97, 140}}, {{148, 222, 108, 135}}, + {{134, 197, 123, 154}}, {{136, 204, 118, 145}}, {{162, 243, 85, 160}}, + {{172, 250, 88, 171}}, {{190, 225, 79, 182}}, {{176, 232, 66, 189}}, + {{234, 159, 9, 212}}, {{228, 150, 4, 223}}, {{246, 141, 19, 194}}, + {{248, 132, 30, 201}}, {{210, 187, 61, 248}}, {{220, 178, 48, 243}}, + {{206, 169, 39, 238}}, {{192, 160, 42, 229}}, {{122, 71, 177, 60}}, + {{116, 78, 188, 55}}, {{102, 85, 171, 42}}, {{104, 92, 166, 33}}, + {{ 66, 99, 133, 16}}, {{ 76, 106, 136, 27}}, {{ 94, 113, 159, 6}}, + {{ 80, 120, 146, 13}}, {{ 10, 15, 217, 100}}, {{ 4, 6, 212, 111}}, + {{ 22, 29, 195, 114}}, {{ 24, 20, 206, 121}}, {{ 50, 43, 237, 72}}, + {{ 60, 34, 224, 67}}, {{ 46, 57, 247, 94}}, {{ 32, 48, 250, 85}}, + {{236, 154, 183, 1}}, {{226, 147, 186, 10}}, {{240, 136, 173, 23}}, + {{254, 129, 160, 28}}, {{212, 190, 131, 45}}, {{218, 183, 142, 38}}, + {{200, 172, 153, 59}}, {{198, 165, 148, 48}}, {{156, 210, 223, 89}}, + {{146, 219, 210, 82}}, {{128, 192, 197, 79}}, {{142, 201, 200, 68}}, + {{164, 246, 235, 117}}, {{170, 255, 230, 126}}, {{184, 228, 241, 99}}, + {{182, 237, 252, 104}}, {{ 12, 10, 103, 177}}, {{ 2, 3, 106, 186}}, + {{ 16, 24, 125, 167}}, {{ 30, 17, 112, 172}}, {{ 52, 46, 83, 157}}, + {{ 58, 39, 94, 150}}, {{ 40, 60, 73, 139}}, {{ 38, 53, 68, 128}}, + {{124, 66, 15, 233}}, {{114, 75, 2, 226}}, {{ 96, 80, 21, 255}}, + {{110, 89, 24, 244}}, {{ 68, 102, 59, 197}}, {{ 74, 111, 54, 206}}, + {{ 88, 116, 33, 211}}, {{ 86, 125, 44, 216}}, {{ 55, 161, 12, 122}}, + {{ 57, 168, 1, 113}}, {{ 43, 179, 22, 108}}, {{ 37, 186, 27, 103}}, + {{ 15, 133, 56, 86}}, {{ 1, 140, 53, 93}}, {{ 19, 151, 34, 64}}, + {{ 29, 158, 47, 75}}, {{ 71, 233, 100, 34}}, {{ 73, 224, 105, 41}}, + {{ 91, 251, 126, 52}}, {{ 85, 242, 115, 63}}, {{127, 205, 80, 14}}, + {{113, 196, 93, 5}}, {{ 99, 223, 74, 24}}, {{109, 214, 71, 19}}, + {{215, 49, 220, 202}}, {{217, 56, 209, 193}}, {{203, 35, 198, 220}}, + {{197, 42, 203, 215}}, {{239, 21, 232, 230}}, {{225, 28, 229, 237}}, + {{243, 7, 242, 240}}, {{253, 14, 255, 251}}, {{167, 121, 180, 146}}, + {{169, 112, 185, 153}}, {{187, 107, 174, 132}}, {{181, 98, 163, 143}}, + {{159, 93, 128, 190}}, {{145, 84, 141, 181}}, {{131, 79, 154, 168}}, + {{141, 70, 151, 163}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 11, 14, 9, 13}}, {{ 22, 28, 18, 26}}, + {{ 29, 18, 27, 23}}, {{ 44, 56, 36, 52}}, {{ 39, 54, 45, 57}}, + {{ 58, 36, 54, 46}}, {{ 49, 42, 63, 35}}, {{ 88, 112, 72, 104}}, + {{ 83, 126, 65, 101}}, {{ 78, 108, 90, 114}}, {{ 69, 98, 83, 127}}, + {{116, 72, 108, 92}}, {{127, 70, 101, 81}}, {{ 98, 84, 126, 70}}, + {{105, 90, 119, 75}}, {{176, 224, 144, 208}}, {{187, 238, 153, 221}}, + {{166, 252, 130, 202}}, {{173, 242, 139, 199}}, {{156, 216, 180, 228}}, + {{151, 214, 189, 233}}, {{138, 196, 166, 254}}, {{129, 202, 175, 243}}, + {{232, 144, 216, 184}}, {{227, 158, 209, 181}}, {{254, 140, 202, 162}}, + {{245, 130, 195, 175}}, {{196, 168, 252, 140}}, {{207, 166, 245, 129}}, + {{210, 180, 238, 150}}, {{217, 186, 231, 155}}, {{123, 219, 59, 187}}, + {{112, 213, 50, 182}}, {{109, 199, 41, 161}}, {{102, 201, 32, 172}}, + {{ 87, 227, 31, 143}}, {{ 92, 237, 22, 130}}, {{ 65, 255, 13, 149}}, + {{ 74, 241, 4, 152}}, {{ 35, 171, 115, 211}}, {{ 40, 165, 122, 222}}, + {{ 53, 183, 97, 201}}, {{ 62, 185, 104, 196}}, {{ 15, 147, 87, 231}}, + {{ 4, 157, 94, 234}}, {{ 25, 143, 69, 253}}, {{ 18, 129, 76, 240}}, + {{203, 59, 171, 107}}, {{192, 53, 162, 102}}, {{221, 39, 185, 113}}, + {{214, 41, 176, 124}}, {{231, 3, 143, 95}}, {{236, 13, 134, 82}}, + {{241, 31, 157, 69}}, {{250, 17, 148, 72}}, {{147, 75, 227, 3}}, + {{152, 69, 234, 14}}, {{133, 87, 241, 25}}, {{142, 89, 248, 20}}, + {{191, 115, 199, 55}}, {{180, 125, 206, 58}}, {{169, 111, 213, 45}}, + {{162, 97, 220, 32}}, {{246, 173, 118, 109}}, {{253, 163, 127, 96}}, + {{224, 177, 100, 119}}, {{235, 191, 109, 122}}, {{218, 149, 82, 89}}, + {{209, 155, 91, 84}}, {{204, 137, 64, 67}}, {{199, 135, 73, 78}}, + {{174, 221, 62, 5}}, {{165, 211, 55, 8}}, {{184, 193, 44, 31}}, + {{179, 207, 37, 18}}, {{130, 229, 26, 49}}, {{137, 235, 19, 60}}, + {{148, 249, 8, 43}}, {{159, 247, 1, 38}}, {{ 70, 77, 230, 189}}, + {{ 77, 67, 239, 176}}, {{ 80, 81, 244, 167}}, {{ 91, 95, 253, 170}}, + {{106, 117, 194, 137}}, {{ 97, 123, 203, 132}}, {{124, 105, 208, 147}}, + {{119, 103, 217, 158}}, {{ 30, 61, 174, 213}}, {{ 21, 51, 167, 216}}, + {{ 8, 33, 188, 207}}, {{ 3, 47, 181, 194}}, {{ 50, 5, 138, 225}}, + {{ 57, 11, 131, 236}}, {{ 36, 25, 152, 251}}, {{ 47, 23, 145, 246}}, + {{141, 118, 77, 214}}, {{134, 120, 68, 219}}, {{155, 106, 95, 204}}, + {{144, 100, 86, 193}}, {{161, 78, 105, 226}}, {{170, 64, 96, 239}}, + {{183, 82, 123, 248}}, {{188, 92, 114, 245}}, {{213, 6, 5, 190}}, + {{222, 8, 12, 179}}, {{195, 26, 23, 164}}, {{200, 20, 30, 169}}, + {{249, 62, 33, 138}}, {{242, 48, 40, 135}}, {{239, 34, 51, 144}}, + {{228, 44, 58, 157}}, {{ 61, 150, 221, 6}}, {{ 54, 152, 212, 11}}, + {{ 43, 138, 207, 28}}, {{ 32, 132, 198, 17}}, {{ 17, 174, 249, 50}}, + {{ 26, 160, 240, 63}}, {{ 7, 178, 235, 40}}, {{ 12, 188, 226, 37}}, + {{101, 230, 149, 110}}, {{110, 232, 156, 99}}, {{115, 250, 135, 116}}, + {{120, 244, 142, 121}}, {{ 73, 222, 177, 90}}, {{ 66, 208, 184, 87}}, + {{ 95, 194, 163, 64}}, {{ 84, 204, 170, 77}}, {{247, 65, 236, 218}}, + {{252, 79, 229, 215}}, {{225, 93, 254, 192}}, {{234, 83, 247, 205}}, + {{219, 121, 200, 238}}, {{208, 119, 193, 227}}, {{205, 101, 218, 244}}, + {{198, 107, 211, 249}}, {{175, 49, 164, 178}}, {{164, 63, 173, 191}}, + {{185, 45, 182, 168}}, {{178, 35, 191, 165}}, {{131, 9, 128, 134}}, + {{136, 7, 137, 139}}, {{149, 21, 146, 156}}, {{158, 27, 155, 145}}, + {{ 71, 161, 124, 10}}, {{ 76, 175, 117, 7}}, {{ 81, 189, 110, 16}}, + {{ 90, 179, 103, 29}}, {{107, 153, 88, 62}}, {{ 96, 151, 81, 51}}, + {{125, 133, 74, 36}}, {{118, 139, 67, 41}}, {{ 31, 209, 52, 98}}, + {{ 20, 223, 61, 111}}, {{ 9, 205, 38, 120}}, {{ 2, 195, 47, 117}}, + {{ 51, 233, 16, 86}}, {{ 56, 231, 25, 91}}, {{ 37, 245, 2, 76}}, + {{ 46, 251, 11, 65}}, {{140, 154, 215, 97}}, {{135, 148, 222, 108}}, + {{154, 134, 197, 123}}, {{145, 136, 204, 118}}, {{160, 162, 243, 85}}, + {{171, 172, 250, 88}}, {{182, 190, 225, 79}}, {{189, 176, 232, 66}}, + {{212, 234, 159, 9}}, {{223, 228, 150, 4}}, {{194, 246, 141, 19}}, + {{201, 248, 132, 30}}, {{248, 210, 187, 61}}, {{243, 220, 178, 48}}, + {{238, 206, 169, 39}}, {{229, 192, 160, 42}}, {{ 60, 122, 71, 177}}, + {{ 55, 116, 78, 188}}, {{ 42, 102, 85, 171}}, {{ 33, 104, 92, 166}}, + {{ 16, 66, 99, 133}}, {{ 27, 76, 106, 136}}, {{ 6, 94, 113, 159}}, + {{ 13, 80, 120, 146}}, {{100, 10, 15, 217}}, {{111, 4, 6, 212}}, + {{114, 22, 29, 195}}, {{121, 24, 20, 206}}, {{ 72, 50, 43, 237}}, + {{ 67, 60, 34, 224}}, {{ 94, 46, 57, 247}}, {{ 85, 32, 48, 250}}, + {{ 1, 236, 154, 183}}, {{ 10, 226, 147, 186}}, {{ 23, 240, 136, 173}}, + {{ 28, 254, 129, 160}}, {{ 45, 212, 190, 131}}, {{ 38, 218, 183, 142}}, + {{ 59, 200, 172, 153}}, {{ 48, 198, 165, 148}}, {{ 89, 156, 210, 223}}, + {{ 82, 146, 219, 210}}, {{ 79, 128, 192, 197}}, {{ 68, 142, 201, 200}}, + {{117, 164, 246, 235}}, {{126, 170, 255, 230}}, {{ 99, 184, 228, 241}}, + {{104, 182, 237, 252}}, {{177, 12, 10, 103}}, {{186, 2, 3, 106}}, + {{167, 16, 24, 125}}, {{172, 30, 17, 112}}, {{157, 52, 46, 83}}, + {{150, 58, 39, 94}}, {{139, 40, 60, 73}}, {{128, 38, 53, 68}}, + {{233, 124, 66, 15}}, {{226, 114, 75, 2}}, {{255, 96, 80, 21}}, + {{244, 110, 89, 24}}, {{197, 68, 102, 59}}, {{206, 74, 111, 54}}, + {{211, 88, 116, 33}}, {{216, 86, 125, 44}}, {{122, 55, 161, 12}}, + {{113, 57, 168, 1}}, {{108, 43, 179, 22}}, {{103, 37, 186, 27}}, + {{ 86, 15, 133, 56}}, {{ 93, 1, 140, 53}}, {{ 64, 19, 151, 34}}, + {{ 75, 29, 158, 47}}, {{ 34, 71, 233, 100}}, {{ 41, 73, 224, 105}}, + {{ 52, 91, 251, 126}}, {{ 63, 85, 242, 115}}, {{ 14, 127, 205, 80}}, + {{ 5, 113, 196, 93}}, {{ 24, 99, 223, 74}}, {{ 19, 109, 214, 71}}, + {{202, 215, 49, 220}}, {{193, 217, 56, 209}}, {{220, 203, 35, 198}}, + {{215, 197, 42, 203}}, {{230, 239, 21, 232}}, {{237, 225, 28, 229}}, + {{240, 243, 7, 242}}, {{251, 253, 14, 255}}, {{146, 167, 121, 180}}, + {{153, 169, 112, 185}}, {{132, 187, 107, 174}}, {{143, 181, 98, 163}}, + {{190, 159, 93, 128}}, {{181, 145, 84, 141}}, {{168, 131, 79, 154}}, + {{163, 141, 70, 151}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 13, 11, 14, 9}}, {{ 26, 22, 28, 18}}, + {{ 23, 29, 18, 27}}, {{ 52, 44, 56, 36}}, {{ 57, 39, 54, 45}}, + {{ 46, 58, 36, 54}}, {{ 35, 49, 42, 63}}, {{104, 88, 112, 72}}, + {{101, 83, 126, 65}}, {{114, 78, 108, 90}}, {{127, 69, 98, 83}}, + {{ 92, 116, 72, 108}}, {{ 81, 127, 70, 101}}, {{ 70, 98, 84, 126}}, + {{ 75, 105, 90, 119}}, {{208, 176, 224, 144}}, {{221, 187, 238, 153}}, + {{202, 166, 252, 130}}, {{199, 173, 242, 139}}, {{228, 156, 216, 180}}, + {{233, 151, 214, 189}}, {{254, 138, 196, 166}}, {{243, 129, 202, 175}}, + {{184, 232, 144, 216}}, {{181, 227, 158, 209}}, {{162, 254, 140, 202}}, + {{175, 245, 130, 195}}, {{140, 196, 168, 252}}, {{129, 207, 166, 245}}, + {{150, 210, 180, 238}}, {{155, 217, 186, 231}}, {{187, 123, 219, 59}}, + {{182, 112, 213, 50}}, {{161, 109, 199, 41}}, {{172, 102, 201, 32}}, + {{143, 87, 227, 31}}, {{130, 92, 237, 22}}, {{149, 65, 255, 13}}, + {{152, 74, 241, 4}}, {{211, 35, 171, 115}}, {{222, 40, 165, 122}}, + {{201, 53, 183, 97}}, {{196, 62, 185, 104}}, {{231, 15, 147, 87}}, + {{234, 4, 157, 94}}, {{253, 25, 143, 69}}, {{240, 18, 129, 76}}, + {{107, 203, 59, 171}}, {{102, 192, 53, 162}}, {{113, 221, 39, 185}}, + {{124, 214, 41, 176}}, {{ 95, 231, 3, 143}}, {{ 82, 236, 13, 134}}, + {{ 69, 241, 31, 157}}, {{ 72, 250, 17, 148}}, {{ 3, 147, 75, 227}}, + {{ 14, 152, 69, 234}}, {{ 25, 133, 87, 241}}, {{ 20, 142, 89, 248}}, + {{ 55, 191, 115, 199}}, {{ 58, 180, 125, 206}}, {{ 45, 169, 111, 213}}, + {{ 32, 162, 97, 220}}, {{109, 246, 173, 118}}, {{ 96, 253, 163, 127}}, + {{119, 224, 177, 100}}, {{122, 235, 191, 109}}, {{ 89, 218, 149, 82}}, + {{ 84, 209, 155, 91}}, {{ 67, 204, 137, 64}}, {{ 78, 199, 135, 73}}, + {{ 5, 174, 221, 62}}, {{ 8, 165, 211, 55}}, {{ 31, 184, 193, 44}}, + {{ 18, 179, 207, 37}}, {{ 49, 130, 229, 26}}, {{ 60, 137, 235, 19}}, + {{ 43, 148, 249, 8}}, {{ 38, 159, 247, 1}}, {{189, 70, 77, 230}}, + {{176, 77, 67, 239}}, {{167, 80, 81, 244}}, {{170, 91, 95, 253}}, + {{137, 106, 117, 194}}, {{132, 97, 123, 203}}, {{147, 124, 105, 208}}, + {{158, 119, 103, 217}}, {{213, 30, 61, 174}}, {{216, 21, 51, 167}}, + {{207, 8, 33, 188}}, {{194, 3, 47, 181}}, {{225, 50, 5, 138}}, + {{236, 57, 11, 131}}, {{251, 36, 25, 152}}, {{246, 47, 23, 145}}, + {{214, 141, 118, 77}}, {{219, 134, 120, 68}}, {{204, 155, 106, 95}}, + {{193, 144, 100, 86}}, {{226, 161, 78, 105}}, {{239, 170, 64, 96}}, + {{248, 183, 82, 123}}, {{245, 188, 92, 114}}, {{190, 213, 6, 5}}, + {{179, 222, 8, 12}}, {{164, 195, 26, 23}}, {{169, 200, 20, 30}}, + {{138, 249, 62, 33}}, {{135, 242, 48, 40}}, {{144, 239, 34, 51}}, + {{157, 228, 44, 58}}, {{ 6, 61, 150, 221}}, {{ 11, 54, 152, 212}}, + {{ 28, 43, 138, 207}}, {{ 17, 32, 132, 198}}, {{ 50, 17, 174, 249}}, + {{ 63, 26, 160, 240}}, {{ 40, 7, 178, 235}}, {{ 37, 12, 188, 226}}, + {{110, 101, 230, 149}}, {{ 99, 110, 232, 156}}, {{116, 115, 250, 135}}, + {{121, 120, 244, 142}}, {{ 90, 73, 222, 177}}, {{ 87, 66, 208, 184}}, + {{ 64, 95, 194, 163}}, {{ 77, 84, 204, 170}}, {{218, 247, 65, 236}}, + {{215, 252, 79, 229}}, {{192, 225, 93, 254}}, {{205, 234, 83, 247}}, + {{238, 219, 121, 200}}, {{227, 208, 119, 193}}, {{244, 205, 101, 218}}, + {{249, 198, 107, 211}}, {{178, 175, 49, 164}}, {{191, 164, 63, 173}}, + {{168, 185, 45, 182}}, {{165, 178, 35, 191}}, {{134, 131, 9, 128}}, + {{139, 136, 7, 137}}, {{156, 149, 21, 146}}, {{145, 158, 27, 155}}, + {{ 10, 71, 161, 124}}, {{ 7, 76, 175, 117}}, {{ 16, 81, 189, 110}}, + {{ 29, 90, 179, 103}}, {{ 62, 107, 153, 88}}, {{ 51, 96, 151, 81}}, + {{ 36, 125, 133, 74}}, {{ 41, 118, 139, 67}}, {{ 98, 31, 209, 52}}, + {{111, 20, 223, 61}}, {{120, 9, 205, 38}}, {{117, 2, 195, 47}}, + {{ 86, 51, 233, 16}}, {{ 91, 56, 231, 25}}, {{ 76, 37, 245, 2}}, + {{ 65, 46, 251, 11}}, {{ 97, 140, 154, 215}}, {{108, 135, 148, 222}}, + {{123, 154, 134, 197}}, {{118, 145, 136, 204}}, {{ 85, 160, 162, 243}}, + {{ 88, 171, 172, 250}}, {{ 79, 182, 190, 225}}, {{ 66, 189, 176, 232}}, + {{ 9, 212, 234, 159}}, {{ 4, 223, 228, 150}}, {{ 19, 194, 246, 141}}, + {{ 30, 201, 248, 132}}, {{ 61, 248, 210, 187}}, {{ 48, 243, 220, 178}}, + {{ 39, 238, 206, 169}}, {{ 42, 229, 192, 160}}, {{177, 60, 122, 71}}, + {{188, 55, 116, 78}}, {{171, 42, 102, 85}}, {{166, 33, 104, 92}}, + {{133, 16, 66, 99}}, {{136, 27, 76, 106}}, {{159, 6, 94, 113}}, + {{146, 13, 80, 120}}, {{217, 100, 10, 15}}, {{212, 111, 4, 6}}, + {{195, 114, 22, 29}}, {{206, 121, 24, 20}}, {{237, 72, 50, 43}}, + {{224, 67, 60, 34}}, {{247, 94, 46, 57}}, {{250, 85, 32, 48}}, + {{183, 1, 236, 154}}, {{186, 10, 226, 147}}, {{173, 23, 240, 136}}, + {{160, 28, 254, 129}}, {{131, 45, 212, 190}}, {{142, 38, 218, 183}}, + {{153, 59, 200, 172}}, {{148, 48, 198, 165}}, {{223, 89, 156, 210}}, + {{210, 82, 146, 219}}, {{197, 79, 128, 192}}, {{200, 68, 142, 201}}, + {{235, 117, 164, 246}}, {{230, 126, 170, 255}}, {{241, 99, 184, 228}}, + {{252, 104, 182, 237}}, {{103, 177, 12, 10}}, {{106, 186, 2, 3}}, + {{125, 167, 16, 24}}, {{112, 172, 30, 17}}, {{ 83, 157, 52, 46}}, + {{ 94, 150, 58, 39}}, {{ 73, 139, 40, 60}}, {{ 68, 128, 38, 53}}, + {{ 15, 233, 124, 66}}, {{ 2, 226, 114, 75}}, {{ 21, 255, 96, 80}}, + {{ 24, 244, 110, 89}}, {{ 59, 197, 68, 102}}, {{ 54, 206, 74, 111}}, + {{ 33, 211, 88, 116}}, {{ 44, 216, 86, 125}}, {{ 12, 122, 55, 161}}, + {{ 1, 113, 57, 168}}, {{ 22, 108, 43, 179}}, {{ 27, 103, 37, 186}}, + {{ 56, 86, 15, 133}}, {{ 53, 93, 1, 140}}, {{ 34, 64, 19, 151}}, + {{ 47, 75, 29, 158}}, {{100, 34, 71, 233}}, {{105, 41, 73, 224}}, + {{126, 52, 91, 251}}, {{115, 63, 85, 242}}, {{ 80, 14, 127, 205}}, + {{ 93, 5, 113, 196}}, {{ 74, 24, 99, 223}}, {{ 71, 19, 109, 214}}, + {{220, 202, 215, 49}}, {{209, 193, 217, 56}}, {{198, 220, 203, 35}}, + {{203, 215, 197, 42}}, {{232, 230, 239, 21}}, {{229, 237, 225, 28}}, + {{242, 240, 243, 7}}, {{255, 251, 253, 14}}, {{180, 146, 167, 121}}, + {{185, 153, 169, 112}}, {{174, 132, 187, 107}}, {{163, 143, 181, 98}}, + {{128, 190, 159, 93}}, {{141, 181, 145, 84}}, {{154, 168, 131, 79}}, + {{151, 163, 141, 70}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 9, 13, 11, 14}}, {{ 18, 26, 22, 28}}, + {{ 27, 23, 29, 18}}, {{ 36, 52, 44, 56}}, {{ 45, 57, 39, 54}}, + {{ 54, 46, 58, 36}}, {{ 63, 35, 49, 42}}, {{ 72, 104, 88, 112}}, + {{ 65, 101, 83, 126}}, {{ 90, 114, 78, 108}}, {{ 83, 127, 69, 98}}, + {{108, 92, 116, 72}}, {{101, 81, 127, 70}}, {{126, 70, 98, 84}}, + {{119, 75, 105, 90}}, {{144, 208, 176, 224}}, {{153, 221, 187, 238}}, + {{130, 202, 166, 252}}, {{139, 199, 173, 242}}, {{180, 228, 156, 216}}, + {{189, 233, 151, 214}}, {{166, 254, 138, 196}}, {{175, 243, 129, 202}}, + {{216, 184, 232, 144}}, {{209, 181, 227, 158}}, {{202, 162, 254, 140}}, + {{195, 175, 245, 130}}, {{252, 140, 196, 168}}, {{245, 129, 207, 166}}, + {{238, 150, 210, 180}}, {{231, 155, 217, 186}}, {{ 59, 187, 123, 219}}, + {{ 50, 182, 112, 213}}, {{ 41, 161, 109, 199}}, {{ 32, 172, 102, 201}}, + {{ 31, 143, 87, 227}}, {{ 22, 130, 92, 237}}, {{ 13, 149, 65, 255}}, + {{ 4, 152, 74, 241}}, {{115, 211, 35, 171}}, {{122, 222, 40, 165}}, + {{ 97, 201, 53, 183}}, {{104, 196, 62, 185}}, {{ 87, 231, 15, 147}}, + {{ 94, 234, 4, 157}}, {{ 69, 253, 25, 143}}, {{ 76, 240, 18, 129}}, + {{171, 107, 203, 59}}, {{162, 102, 192, 53}}, {{185, 113, 221, 39}}, + {{176, 124, 214, 41}}, {{143, 95, 231, 3}}, {{134, 82, 236, 13}}, + {{157, 69, 241, 31}}, {{148, 72, 250, 17}}, {{227, 3, 147, 75}}, + {{234, 14, 152, 69}}, {{241, 25, 133, 87}}, {{248, 20, 142, 89}}, + {{199, 55, 191, 115}}, {{206, 58, 180, 125}}, {{213, 45, 169, 111}}, + {{220, 32, 162, 97}}, {{118, 109, 246, 173}}, {{127, 96, 253, 163}}, + {{100, 119, 224, 177}}, {{109, 122, 235, 191}}, {{ 82, 89, 218, 149}}, + {{ 91, 84, 209, 155}}, {{ 64, 67, 204, 137}}, {{ 73, 78, 199, 135}}, + {{ 62, 5, 174, 221}}, {{ 55, 8, 165, 211}}, {{ 44, 31, 184, 193}}, + {{ 37, 18, 179, 207}}, {{ 26, 49, 130, 229}}, {{ 19, 60, 137, 235}}, + {{ 8, 43, 148, 249}}, {{ 1, 38, 159, 247}}, {{230, 189, 70, 77}}, + {{239, 176, 77, 67}}, {{244, 167, 80, 81}}, {{253, 170, 91, 95}}, + {{194, 137, 106, 117}}, {{203, 132, 97, 123}}, {{208, 147, 124, 105}}, + {{217, 158, 119, 103}}, {{174, 213, 30, 61}}, {{167, 216, 21, 51}}, + {{188, 207, 8, 33}}, {{181, 194, 3, 47}}, {{138, 225, 50, 5}}, + {{131, 236, 57, 11}}, {{152, 251, 36, 25}}, {{145, 246, 47, 23}}, + {{ 77, 214, 141, 118}}, {{ 68, 219, 134, 120}}, {{ 95, 204, 155, 106}}, + {{ 86, 193, 144, 100}}, {{105, 226, 161, 78}}, {{ 96, 239, 170, 64}}, + {{123, 248, 183, 82}}, {{114, 245, 188, 92}}, {{ 5, 190, 213, 6}}, + {{ 12, 179, 222, 8}}, {{ 23, 164, 195, 26}}, {{ 30, 169, 200, 20}}, + {{ 33, 138, 249, 62}}, {{ 40, 135, 242, 48}}, {{ 51, 144, 239, 34}}, + {{ 58, 157, 228, 44}}, {{221, 6, 61, 150}}, {{212, 11, 54, 152}}, + {{207, 28, 43, 138}}, {{198, 17, 32, 132}}, {{249, 50, 17, 174}}, + {{240, 63, 26, 160}}, {{235, 40, 7, 178}}, {{226, 37, 12, 188}}, + {{149, 110, 101, 230}}, {{156, 99, 110, 232}}, {{135, 116, 115, 250}}, + {{142, 121, 120, 244}}, {{177, 90, 73, 222}}, {{184, 87, 66, 208}}, + {{163, 64, 95, 194}}, {{170, 77, 84, 204}}, {{236, 218, 247, 65}}, + {{229, 215, 252, 79}}, {{254, 192, 225, 93}}, {{247, 205, 234, 83}}, + {{200, 238, 219, 121}}, {{193, 227, 208, 119}}, {{218, 244, 205, 101}}, + {{211, 249, 198, 107}}, {{164, 178, 175, 49}}, {{173, 191, 164, 63}}, + {{182, 168, 185, 45}}, {{191, 165, 178, 35}}, {{128, 134, 131, 9}}, + {{137, 139, 136, 7}}, {{146, 156, 149, 21}}, {{155, 145, 158, 27}}, + {{124, 10, 71, 161}}, {{117, 7, 76, 175}}, {{110, 16, 81, 189}}, + {{103, 29, 90, 179}}, {{ 88, 62, 107, 153}}, {{ 81, 51, 96, 151}}, + {{ 74, 36, 125, 133}}, {{ 67, 41, 118, 139}}, {{ 52, 98, 31, 209}}, + {{ 61, 111, 20, 223}}, {{ 38, 120, 9, 205}}, {{ 47, 117, 2, 195}}, + {{ 16, 86, 51, 233}}, {{ 25, 91, 56, 231}}, {{ 2, 76, 37, 245}}, + {{ 11, 65, 46, 251}}, {{215, 97, 140, 154}}, {{222, 108, 135, 148}}, + {{197, 123, 154, 134}}, {{204, 118, 145, 136}}, {{243, 85, 160, 162}}, + {{250, 88, 171, 172}}, {{225, 79, 182, 190}}, {{232, 66, 189, 176}}, + {{159, 9, 212, 234}}, {{150, 4, 223, 228}}, {{141, 19, 194, 246}}, + {{132, 30, 201, 248}}, {{187, 61, 248, 210}}, {{178, 48, 243, 220}}, + {{169, 39, 238, 206}}, {{160, 42, 229, 192}}, {{ 71, 177, 60, 122}}, + {{ 78, 188, 55, 116}}, {{ 85, 171, 42, 102}}, {{ 92, 166, 33, 104}}, + {{ 99, 133, 16, 66}}, {{106, 136, 27, 76}}, {{113, 159, 6, 94}}, + {{120, 146, 13, 80}}, {{ 15, 217, 100, 10}}, {{ 6, 212, 111, 4}}, + {{ 29, 195, 114, 22}}, {{ 20, 206, 121, 24}}, {{ 43, 237, 72, 50}}, + {{ 34, 224, 67, 60}}, {{ 57, 247, 94, 46}}, {{ 48, 250, 85, 32}}, + {{154, 183, 1, 236}}, {{147, 186, 10, 226}}, {{136, 173, 23, 240}}, + {{129, 160, 28, 254}}, {{190, 131, 45, 212}}, {{183, 142, 38, 218}}, + {{172, 153, 59, 200}}, {{165, 148, 48, 198}}, {{210, 223, 89, 156}}, + {{219, 210, 82, 146}}, {{192, 197, 79, 128}}, {{201, 200, 68, 142}}, + {{246, 235, 117, 164}}, {{255, 230, 126, 170}}, {{228, 241, 99, 184}}, + {{237, 252, 104, 182}}, {{ 10, 103, 177, 12}}, {{ 3, 106, 186, 2}}, + {{ 24, 125, 167, 16}}, {{ 17, 112, 172, 30}}, {{ 46, 83, 157, 52}}, + {{ 39, 94, 150, 58}}, {{ 60, 73, 139, 40}}, {{ 53, 68, 128, 38}}, + {{ 66, 15, 233, 124}}, {{ 75, 2, 226, 114}}, {{ 80, 21, 255, 96}}, + {{ 89, 24, 244, 110}}, {{102, 59, 197, 68}}, {{111, 54, 206, 74}}, + {{116, 33, 211, 88}}, {{125, 44, 216, 86}}, {{161, 12, 122, 55}}, + {{168, 1, 113, 57}}, {{179, 22, 108, 43}}, {{186, 27, 103, 37}}, + {{133, 56, 86, 15}}, {{140, 53, 93, 1}}, {{151, 34, 64, 19}}, + {{158, 47, 75, 29}}, {{233, 100, 34, 71}}, {{224, 105, 41, 73}}, + {{251, 126, 52, 91}}, {{242, 115, 63, 85}}, {{205, 80, 14, 127}}, + {{196, 93, 5, 113}}, {{223, 74, 24, 99}}, {{214, 71, 19, 109}}, + {{ 49, 220, 202, 215}}, {{ 56, 209, 193, 217}}, {{ 35, 198, 220, 203}}, + {{ 42, 203, 215, 197}}, {{ 21, 232, 230, 239}}, {{ 28, 229, 237, 225}}, + {{ 7, 242, 240, 243}}, {{ 14, 255, 251, 253}}, {{121, 180, 146, 167}}, + {{112, 185, 153, 169}}, {{107, 174, 132, 187}}, {{ 98, 163, 143, 181}}, + {{ 93, 128, 190, 159}}, {{ 84, 141, 181, 145}}, {{ 79, 154, 168, 131}}, + {{ 70, 151, 163, 141}}, + }, +}; + +const int xrcon[30] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, + 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, + 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, +}; + +const word8 xS[256] = { + 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, + 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, + 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, + 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, + 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, + 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237, + 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, + 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, + 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, + 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, + 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, + 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, + 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, + 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37, 46, + 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, + 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, + 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, + 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, + 176, 84, 187, 22, +}; + +const word8 xSi[256] = { + 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, + 215, 251, 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, + 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, + 149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, + 118, 91, 162, 73, 109, 139, 209, 37, 114, 248, 246, 100, 134, 104, + 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, 108, 112, 72, 80, + 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, 144, 216, + 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, + 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, + 138, 107, 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, + 240, 180, 230, 115, 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, + 55, 232, 28, 117, 223, 110, 71, 241, 26, 113, 29, 41, 197, 137, + 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75, 198, 210, + 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168, 51, + 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, 96, 81, + 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, + 160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, + 153, 97, 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, + 85, 33, 12, 125, +}; + diff --git a/src/aes/ao_aes_tables.h b/src/aes/ao_aes_tables.h new file mode 100644 index 00000000..73bcf3fb --- /dev/null +++ b/src/aes/ao_aes_tables.h @@ -0,0 +1,10 @@ +/* Copyright (C) 2000-2009 Peter Selinger. + This file is part of ccrypt. It is free software and it is covered + by the GNU general public license. See the file COPYING for details. */ + +extern const word8x4 M0[4][256]; +extern const word8x4 M1[4][256]; +extern const int xrcon[30]; +extern const word8 xS[256]; +extern const word8 xSi[256]; + diff --git a/src/core/ao_aes.h b/src/core/ao_aes.h index 7f67374d..ab3e367e 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); diff --git a/src/core/ao_radio_cmac.c b/src/core/ao_radio_cmac.c index e263f0db..7a377002 100644 --- a/src/core/ao_radio_cmac.c +++ b/src/core/ao_radio_cmac.c @@ -121,7 +121,7 @@ radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant } ao_radio_cmac_rssi = (int16_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74; - if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & PKT_APPEND_STATUS_1_CRC_OK)) + if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & AO_RADIO_STATUS_CRC_OK)) return AO_RADIO_CMAC_CRC_ERROR; ao_config_get(); @@ -233,9 +233,9 @@ radio_cmac_recv_cmd(void) __reentrant 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 __pdata uint16_t launch_serial; +static __pdata uint8_t launch_channel; +static __pdata uint16_t tick_offset; static void launch_args(void) __reentrant diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 3edfa41d..04404cdc 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -1,4 +1,4 @@ -vpath % ../stm:../product:../drivers:../core:../util:../kalman:.. +vpath % ../stm:../product:../drivers:../core:../util:../kalman:../aes:.. vpath make-altitude ../util vpath make-kalman ../util vpath kalman.5c ../kalman -- cgit v1.2.3 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/Makefile | 3 +- src/cc1111/ao_adc.c | 20 ++++ src/cc1111/ao_arch.h | 12 --- src/cc1111/ao_pins.h | 12 +++ src/core/ao.h | 7 ++ src/core/ao_config.c | 3 + src/core/ao_storage.c | 1 + 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 ++++++++++++++ src/telefire-v0.1/Makefile | 101 ++++++++++++++++++ src/telefire-v0.1/ao_pins.h | 94 +++++++++++++++++ src/telefire-v0.1/ao_telefire.c | 41 ++++++++ 15 files changed, 720 insertions(+), 13 deletions(-) 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 create mode 100644 src/telefire-v0.1/Makefile create mode 100644 src/telefire-v0.1/ao_pins.h create mode 100644 src/telefire-v0.1/ao_telefire.c (limited to 'src/core') diff --git a/src/Makefile b/src/Makefile index 491618f6..99ea8f85 100644 --- a/src/Makefile +++ b/src/Makefile @@ -21,7 +21,8 @@ ifneq ($(shell which sdcc),) telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ telelaunch-v0.1 tidongle test \ - teleterra-v0.2 teleshield-v0.1 + teleterra-v0.2 teleshield-v0.1 \ + telefire-v0.1 endif ifneq ($(shell which avr-gcc),) diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index ce827e25..f7b52281 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -140,6 +140,15 @@ ao_adc_isr(void) __interrupt 1 } #endif /* telemini || telenano */ +#ifdef TELEFIRE_V_0_1 + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.sense[0] + sequence); + a[0] = ADCL; + a[1] = ADCH; + if (sequence < 5) + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1); +#define GOT_ADC +#endif /* TELEFIRE_V_0_1 */ + #ifndef GOT_ADC #error No known ADC configuration set #endif @@ -157,9 +166,13 @@ ao_adc_dump(void) __reentrant { static __xdata struct ao_data packet; ao_data_get(&packet); +#ifndef AO_ADC_DUMP printf("tick: %5u accel: %5d pres: %5d temp: %5d batt: %5d drogue: %5d main: %5d\n", packet.tick, packet.adc.accel, packet.adc.pres, packet.adc.temp, packet.adc.v_batt, packet.adc.sense_d, packet.adc.sense_m); +#else + AO_ADC_DUMP(&packet); +#endif } __code struct ao_cmds ao_adc_cmds[] = { @@ -170,6 +183,11 @@ __code struct ao_cmds ao_adc_cmds[] = { void ao_adc_init(void) { +#ifdef AO_ADC_PINS + ADCCFG = AO_ADC_PINS; + +#else + #if IGNITE_ON_P2 /* TeleMetrum configuration */ ADCCFG = ((1 << 0) | /* acceleration */ @@ -190,6 +208,8 @@ ao_adc_init(void) (1 << 3)); /* battery voltage */ #endif +#endif /* else AO_ADC_PINS */ + /* enable interrupts */ ADCIF = 0; IEN0 |= IEN0_ADCIE; diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 06b04b93..a97515a7 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -200,18 +200,6 @@ extern AO_ROMCONFIG_SYMBOL(0x00a6) uint32_t ao_radio_cal; #define ao_arch_critical(b) __critical { b } -struct ao_adc { - int16_t accel; /* accelerometer */ - int16_t pres; /* pressure sensor */ - int16_t temp; /* temperature sensor */ - int16_t v_batt; /* battery voltage */ - int16_t sense_d; /* drogue continuity sense */ - int16_t sense_m; /* main continuity sense */ -#if HAS_ACCEL_REF - uint16_t accel_ref; /* acceleration reference */ -#endif -}; - #define AO_DATA_RING 32 /* ao_button.c */ diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index fc6ed3ec..2f0e2884 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -560,4 +560,16 @@ #define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) #define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) +struct ao_adc { + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +#if HAS_ACCEL_REF + uint16_t accel_ref; /* acceleration reference */ +#endif +}; + #endif /* _AO_PINS_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 65b9eb18..1032dd33 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -432,6 +432,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 +490,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 */ @@ -582,6 +585,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 +623,8 @@ ao_monitor_enable(void); void ao_monitor_init(void) __reentrant; +#endif + /* * ao_stdio.c */ 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 +#if HAS_FLIGHT #include #include +#endif __xdata struct ao_config ao_config; __pdata uint8_t ao_config_loaded; 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 +#include uint8_t ao_storage_read(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant 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); +} diff --git a/src/telefire-v0.1/Makefile b/src/telefire-v0.1/Makefile new file mode 100644 index 00000000..09cb88fb --- /dev/null +++ b/src/telefire-v0.1/Makefile @@ -0,0 +1,101 @@ +# +# TeleFire build file +# + +TELEFIRE_VER=0.1 +TELEFIRE_DEF=0_1 + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_convert.c \ + ao_mutex.c \ + ao_panic.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c \ + ao_freq.c + +CC1111_SRC = \ + ao_adc.c \ + ao_aes.c \ + ao_beep.c \ + ao_dma.c \ + ao_intflash.c \ + ao_radio.c \ + ao_radio_cmac.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_spi.c \ + ao_string.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = \ + ao_pca9922.c \ + ao_74hc497.c \ + ao_pad.c + +PRODUCT_SRC = \ + ao_telefire.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROGNAME = telefire-v$(TELEFIRE_VER) +PROG = $(PROGNAME)-$(VERSION).ihx +PRODUCT=TeleFire-v$(TELEFIRE_VER) +PRODUCT_DEF=-DTELEFIRE_V_$(TELEFIRE_DEF) +IDPRODUCT=0x000f +CODESIZE=0x6700 + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: clean-cc1111 + +install: + +uninstall: + diff --git a/src/telefire-v0.1/ao_pins.h b/src/telefire-v0.1/ao_pins.h new file mode 100644 index 00000000..4cf523fc --- /dev/null +++ b/src/telefire-v0.1/ao_pins.h @@ -0,0 +1,94 @@ +/* + * Copyright © 2010 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_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_RADIO 1 + +#define HAS_FLIGHT 0 +#define HAS_USB 1 +#define HAS_BEEP 1 +#define HAS_GPS 0 +#define HAS_SERIAL_1 0 +#define HAS_ADC 1 +#define HAS_DBG 0 +#define HAS_EEPROM 1 +#define HAS_LOG 0 +#define USE_INTERNAL_FLASH 1 +#define DBG_ON_P1 0 +#define IGNITE_ON_P2 0 +#define IGNITE_ON_P1 1 +#define IGNITE_ON_P0 0 +#define PACKET_HAS_MASTER 0 +#define PACKET_HAS_SLAVE 0 +#define AO_LED_RED 2 +#define AO_LED_GREEN 1 +#define LEDS_AVAILABLE (0xff) +#define HAS_EXTERNAL_TEMP 0 +#define HAS_ACCEL_REF 0 +#define SPI_CS_ON_P1 1 +#define HAS_AES 1 + +#define SPI_CS_PORT P1 +#define SPI_CS_SEL P1SEL +#define SPI_CS_DIR P1DIR + +#define AO_74HC497_CS_PORT P1 +#define AO_74HC497_CS_PIN 4 +#define AO_74HC497_CS P1_4 + +#define AO_PCA9922_CS_PORT P1 +#define AO_PCA9922_CS_PIN 4 +#define AO_PCA9922_CS P1_4 + +#define AO_PAD_NUM 4 +#define AO_PAD_PORT P1 +#define AO_PAD_DIR P1DIR +#define AO_PAD_PIN_0 0 +#define AO_PAD_0 P1_0 +#define AO_PAD_PIN_1 1 +#define AO_PAD_1 P1_1 +#define AO_PAD_PIN_2 2 +#define AO_PAD_2 P1_2 +#define AO_PAD_PIN_3 3 +#define AO_PAD_3 P1_3 +#define AO_PAD_ALL_PINS ((1 << AO_PAD_PIN_0) | (1 << AO_PAD_PIN_1) | (1 << AO_PAD_PIN_2) | (1 << AO_PAD_PIN_3)) + +/* test these values with real igniters */ +#define AO_PAD_RELAY_CLOSED 3524 +#define AO_PAD_NO_IGNITER 16904 +#define AO_PAD_GOOD_IGNITER 22514 + +struct ao_adc { + int16_t sense[4]; + int16_t pyro; + int16_t batt; +}; + +#define AO_ADC_DUMP(p) \ + printf ("tick: %5u 0: %5d 1: %5d 2: %5d 3: %5d pyro: %5d batt %5d\n", \ + (p)->adc.sense[0], \ + (p)->adc.sense[1], \ + (p)->adc.sense[2], \ + (p)->adc.sense[3], \ + (p)->adc.pyro, \ + (p)->adc.batt) + +#define AO_ADC_PINS ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5)) + +#endif /* _AO_PINS_H_ */ diff --git a/src/telefire-v0.1/ao_telefire.c b/src/telefire-v0.1/ao_telefire.c new file mode 100644 index 00000000..96413a63 --- /dev/null +++ b/src/telefire-v0.1/ao_telefire.c @@ -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. + */ + +#include "ao.h" +#include "ao_pins.h" + +void +main(void) +{ + ao_clock_init(); + + ao_led_init(LEDS_AVAILABLE); + + ao_timer_init(); + ao_adc_init(); + ao_beep_init(); + ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); + ao_usb_init(); + ao_radio_init(); + ao_aes_init(); + ao_radio_cmac_init(); + ao_pad_init(); + ao_config_init(); + ao_start_scheduler(); +} -- 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/core') 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 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/core') 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 c64999c39d6d9242f98bdc9312436c3333115bfd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Aug 2012 00:39:46 -0700 Subject: altos: Have radio_cmac turn on LEDs as appropriate Use AO_LED_RX and AO_LED_TX defines if present to control LEDs during radio operations. Signed-off-by: Keith Packard --- src/core/ao_radio_cmac.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_radio_cmac.c b/src/core/ao_radio_cmac.c index 7a377002..32ce8793 100644 --- a/src/core/ao_radio_cmac.c +++ b/src/core/ao_radio_cmac.c @@ -159,8 +159,14 @@ 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); - memcpy(cmac_data, packet, len); + 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; } @@ -172,9 +178,15 @@ ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentr 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) - memcpy(packet, cmac_data, len); + ao_xmemcpy(packet, cmac_data, len); ao_mutex_put(&ao_radio_cmac_mutex); return i; } -- 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/core') 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 d13d0fbfcb0fd6d8a1af46f6270a968d746c830e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 Aug 2012 09:49:34 -0700 Subject: altos: Make ao_cur_task_index track ao_cur_task in ao_yield This keeps the two main task references (index and pointer) in agreement during task switching, avoiding an extra assignment at the end of the task switching loop. Signed-off-by: Keith Packard --- src/core/ao_task.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'src/core') 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++) { -- 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/core') 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 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/core') 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 31b42b99edbb976534ac432c07e218f13d1f5f9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Aug 2012 18:03:52 -0700 Subject: altos: Fix ao_delay function and move from per-chip code to ao_task.c ao_delay hasn't been chip-specific for a long time, and it had a bug in not calling ao_clear_alarm. Signed-off-by: Keith Packard --- src/avr/ao_timer.c | 9 --------- src/cc1111/ao_timer.c | 10 ---------- src/core/ao_task.c | 11 +++++++++++ src/stm/ao_timer.c | 9 --------- 4 files changed, 11 insertions(+), 28 deletions(-) (limited to 'src/core') diff --git a/src/avr/ao_timer.c b/src/avr/ao_timer.c index cd81b163..d2ea2be7 100644 --- a/src/avr/ao_timer.c +++ b/src/avr/ao_timer.c @@ -28,15 +28,6 @@ uint16_t ao_time(void) return v; } -static __xdata uint8_t ao_forever; - -void -ao_delay(uint16_t ticks) -{ - ao_alarm(ticks); - ao_sleep(&ao_forever); -} - #define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ #define T1_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c index 602f98c8..a64b5aba 100644 --- a/src/cc1111/ao_timer.c +++ b/src/cc1111/ao_timer.c @@ -24,16 +24,6 @@ uint16_t ao_time(void) __critical return ao_tick_count; } -static __xdata uint8_t ao_forever; - -void -ao_delay(uint16_t ticks) -{ - ao_alarm(ticks); - ao_sleep(&ao_forever); - ao_clear_alarm(); -} - #define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ #define T1_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 4593bd79..65654731 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -125,6 +125,7 @@ ao_sleep(__xdata void *wchan) ao_yield(); if (ao_cur_task->wchan) { ao_cur_task->wchan = NULL; + ao_cur_task->alarm = 0; return 1; } return 0; @@ -157,6 +158,16 @@ ao_clear_alarm(void) ao_cur_task->alarm = 0; } +static __xdata uint8_t ao_forever; + +void +ao_delay(uint16_t ticks) +{ + ao_alarm(ticks); + ao_sleep(&ao_forever); + ao_clear_alarm(); +} + void ao_exit(void) { diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 78228e65..f561e6b5 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -28,15 +28,6 @@ uint16_t ao_time(void) return v; } -static __xdata uint8_t ao_forever; - -void -ao_delay(uint16_t ticks) -{ - ao_alarm(ticks); - ao_sleep(&ao_forever); -} - #if AO_DATA_ALL volatile __data uint8_t ao_data_interval = 1; volatile __data uint8_t ao_data_count; -- cgit v1.2.3 From 78cd26eec77adda23ef1b5ca2d91027f1e059868 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Aug 2012 18:07:05 -0700 Subject: altos: Move radio_cmac test funcs from ao_lco_cmd.c to new file These are useful in the firing node for testing as well, so move them to be shared. Signed-off-by: Keith Packard --- src/core/ao_radio_cmac_cmd.c | 104 +++++++++++++++++++++++++++++++++++++++++++ src/core/ao_radio_cmac_cmd.h | 24 ++++++++++ src/drivers/ao_lco_cmd.c | 74 ------------------------------ 3 files changed, 128 insertions(+), 74 deletions(-) create mode 100644 src/core/ao_radio_cmac_cmd.c create mode 100644 src/core/ao_radio_cmac_cmd.h (limited to 'src/core') diff --git a/src/core/ao_radio_cmac_cmd.c b/src/core/ao_radio_cmac_cmd.c new file mode 100644 index 00000000..64410921 --- /dev/null +++ b/src/core/ao_radio_cmac_cmd.c @@ -0,0 +1,104 @@ +/* + * 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 uint8_t cmac_data[AO_CMAC_MAX_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 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_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" }, + { 0, NULL }, +}; + +void +ao_radio_cmac_cmd_init(void) +{ + ao_cmd_register(&ao_radio_cmac_cmds[0]); +} diff --git a/src/core/ao_radio_cmac_cmd.h b/src/core/ao_radio_cmac_cmd.h new file mode 100644 index 00000000..6b8782de --- /dev/null +++ b/src/core/ao_radio_cmac_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_RADIO_CMAC_CMD_H_ +#define _AO_RADIO_CMAC_CMD_H_ + +void +ao_radio_cmac_cmd_init(void); + +#endif /* _AO_RADIO_CMAC_CMD_H_ */ diff --git a/src/drivers/ao_lco_cmd.c b/src/drivers/ao_lco_cmd.c index 3fe0d9cc..cce7a259 100644 --- a/src/drivers/ao_lco_cmd.c +++ b/src/drivers/ao_lco_cmd.c @@ -177,81 +177,7 @@ launch_ignite_cmd(void) __reentrant 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" }, -- cgit v1.2.3 From 7f64e62356bcfcd6ba8a88b09251793481bcd56c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 29 Aug 2012 11:19:17 -0700 Subject: altos: Note changes to configured AES key for SPI radio convenience Keep a sequence number to mark when the AES key is changed so that the radio code can avoid sending the key before every CMAC radio operation. Signed-off-by: Keith Packard --- src/core/ao.h | 2 ++ src/core/ao_config.c | 4 ++++ 2 files changed, 6 insertions(+) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index b8bedd85..66c0881f 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -718,6 +718,8 @@ extern __xdata uint8_t ao_force_freq; #define AO_AES_LEN 16 +extern __xdata uint8_t ao_config_aes_seq; + struct ao_config { uint8_t major; uint8_t minor; diff --git a/src/core/ao_config.c b/src/core/ao_config.c index f19dd9cd..ce855ad1 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -463,6 +463,9 @@ ao_config_radio_enable_set(void) __reentrant #endif /* HAS_RADIO */ #if HAS_AES + +__xdata uint8_t ao_config_aes_seq = 1; + void ao_config_key_show(void) __reentrant { @@ -485,6 +488,7 @@ ao_config_key_set(void) __reentrant break; ao_config.aes_key[i] = ao_cmd_lex_i; } + ++ao_config_aes_seq; _ao_config_edit_finish(); } #endif -- cgit v1.2.3 From f9af7819de086d9179c3a4d1df7c88ab67a7d7c7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 31 Aug 2012 21:01:21 -0500 Subject: altos: Add custom panic noise for self-test failures Make it easier to tell which component is failing self test Signed-off-by: Keith Packard --- src/core/ao.h | 5 ++++- src/core/ao_panic.c | 10 +++++++++- src/drivers/ao_cc1120.c | 4 ++-- src/drivers/ao_mpu6000.c | 2 +- src/drivers/ao_ms5607.c | 35 ++++++++++++++++++----------------- 5 files changed, 34 insertions(+), 22 deletions(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index 66c0881f..4f4779ec 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -115,7 +115,10 @@ ao_start_scheduler(void); #define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ #define AO_PANIC_STACK 12 /* Stack overflow */ #define AO_PANIC_SPI 13 /* SPI communication failure */ -#define AO_PANIC_SELF_TEST 14 /* Self test failure */ +#define AO_PANIC_SELF_TEST_CC1120 0x40 | 1 /* Self test failure */ +#define AO_PANIC_SELF_TEST_HMC5883 0x40 | 2 /* Self test failure */ +#define AO_PANIC_SELF_TEST_MPU6000 0x40 | 3 /* Self test failure */ +#define AO_PANIC_SELF_TEST_MS5607 0x40 | 4 /* Self test failure */ /* Stop the operating system, beeping and blinking the reason */ void diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index 25dc145e..52433044 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -65,7 +65,15 @@ ao_panic(uint8_t reason) #ifdef SDCC #pragma disable_warning 126 #endif - for (n = 0; n < reason; n++) { + if (reason & 0x40) { + ao_led_on(AO_LED_RED); + ao_beep(AO_BEEP_HIGH); + ao_panic_delay(40); + ao_led_off(AO_LED_RED); + ao_beep(AO_BEEP_OFF); + ao_panic_delay(10); + } + for (n = 0; n < (reason & 0x3f); n++) { ao_led_on(AO_LED_RED); ao_beep(AO_BEEP_MID); ao_panic_delay(10); diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 4df931b5..2f9c296f 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -1028,12 +1028,12 @@ ao_radio_init(void) AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN)); for (i = 0; i < 10000; i++) { - if ((SPI_2_GPIO->idr & (1 << SPI_2_MISO)) == 0) + if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0) break; } AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN); if (i == 10000) - ao_panic(AO_PANIC_SELF_TEST); + ao_panic(AO_PANIC_SELF_TEST_CC1120); /* Enable the EXTI interrupt for the appropriate pin */ ao_enable_port(AO_CC1120_INT_PORT); diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index e8c80f12..b3e284e0 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -225,7 +225,7 @@ ao_mpu6000_setup(void) errors += ao_mpu6000_gyro_check(normal_mode.gyro_z, test_mode.gyro_z, "z"); if (errors) - ao_panic(AO_PANIC_SELF_TEST); + ao_panic(AO_PANIC_SELF_TEST_MPU6000); /* Filter to about 100Hz, which also sets the gyro rate to 1000Hz */ ao_mpu6000_reg_write(MPU6000_CONFIG, diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index ec0d2202..704b4583 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -27,12 +27,12 @@ static uint8_t ms5607_configured; static void ao_ms5607_start(void) { ao_spi_get(AO_MS5607_SPI_INDEX,AO_SPI_SPEED_FAST); - stm_gpio_set(AO_MS5607_CS_GPIO, AO_MS5607_CS, 0); + stm_gpio_set(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, 0); } static void ao_ms5607_stop(void) { - stm_gpio_set(AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); + stm_gpio_set(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, 1); ao_spi_put(AO_MS5607_SPI_INDEX); } @@ -92,7 +92,7 @@ ao_ms5607_prom_read(struct ao_ms5607_prom *prom) printf ("MS5607 PROM CRC error (computed %x actual %x)\n", crc, (((uint8_t *) prom)[15] & 0xf)); flush(); - ao_panic(AO_PANIC_SELF_TEST); +// ao_panic(AO_PANIC_SELF_TEST_MS5607); } #if __BYTE_ORDER == __LITTLE_ENDIAN @@ -120,7 +120,7 @@ static uint8_t ao_ms5607_done; static void ao_ms5607_isr(void) { - ao_exti_disable(AO_MS5607_MISO_GPIO, AO_MS5607_MISO); + ao_exti_disable(AO_MS5607_MISO_PORT, AO_MS5607_MISO_PIN); ao_ms5607_done = 1; ao_wakeup(&ao_ms5607_done); } @@ -135,7 +135,7 @@ 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); + ao_exti_enable(AO_MS5607_MISO_PORT, AO_MS5607_MISO_PIN); #if AO_MS5607_PRIVATE_PINS ao_spi_put(AO_MS5607_SPI_INDEX); #endif @@ -144,7 +144,7 @@ ao_ms5607_get_sample(uint8_t cmd) { ao_sleep(&ao_ms5607_done); sei(); #if AO_MS5607_PRIVATE_PINS - stm_gpio_set(AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); + stm_gpio_set(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, 1); #else ao_ms5607_stop(); #endif @@ -235,13 +235,14 @@ ao_ms5607_info(void) static void ao_ms5607_dump(void) { - struct ao_data sample; + struct ao_ms5607_sample sample; struct ao_ms5607_value value; - 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); + ao_ms5607_setup(); + ao_ms5607_sample(&sample); + ao_ms5607_convert(&sample, &value); + printf ("Pressure: %8u %8d\n", sample.pres, value.pres); + printf ("Temperature: %8u %8d\n", sample.temp, value.temp); printf ("Altitude: %ld\n", ao_pa_to_altitude(value.pres)); } @@ -255,24 +256,24 @@ ao_ms5607_init(void) { ms5607_configured = 0; ao_cmd_register(&ao_ms5607_cmds[0]); - ao_spi_init_cs(AO_MS5607_CS_GPIO, (1 << AO_MS5607_CS)); + ao_spi_init_cs(AO_MS5607_CS_PORT, (1 << AO_MS5607_CS_PIN)); - ao_add_task(&ao_ms5607_task, ao_ms5607, "ms5607"); +// ao_add_task(&ao_ms5607_task, ao_ms5607, "ms5607"); /* Configure the MISO pin as an interrupt; when the * conversion is complete, the MS5607 will raise this * pin as a signal */ - ao_exti_setup(AO_MS5607_MISO_GPIO, - AO_MS5607_MISO, + ao_exti_setup(AO_MS5607_MISO_PORT, + AO_MS5607_MISO_PIN, AO_EXTI_MODE_RISING, ao_ms5607_isr); /* Reset the pin from INPUT to ALTERNATE so that SPI works * This needs an abstraction at some point... */ - stm_moder_set(AO_MS5607_MISO_GPIO, - AO_MS5607_MISO, + stm_moder_set(AO_MS5607_MISO_PORT, + AO_MS5607_MISO_PIN, STM_MODER_ALTERNATE); } -- cgit v1.2.3 From e053da3e7cb5a4c9ebbffd245cb5d83932183b22 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Sep 2012 13:11:57 -0700 Subject: altos: Allow products without MS5607 The define for a missing MS5607 was wrong, so anything using the fancy multi-sensor data code would break without an MS5607 in place. Signed-off-by: Keith Packard --- src/core/ao_data.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 3b66ef5d..5412febe 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -28,7 +28,7 @@ #include #define AO_DATA_MS5607 (1 << 1) #else -#define AO_DATA_MS5607 (1 << 1) +#define AO_DATA_MS5607 0 #endif #if HAS_MPU6000 -- cgit v1.2.3 From ced6a020d6d94b1c63837a7ab5b0091b7b8ea3c9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Sep 2012 13:43:45 -0700 Subject: altos: include ao_arch_funcs.h at the very end of ao.h Move it below the definition of the ms5607 init function Signed-off-by: Keith Packard --- src/core/ao.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/ao.h b/src/core/ao.h index 4f4779ec..31ec4686 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -22,7 +22,7 @@ #include #include #include -#include "ao_pins.h" +#include #include #define TRUE 1 @@ -981,12 +981,12 @@ ao_sqrt(uint32_t op); int32_t ao_freq_to_set(int32_t freq, int32_t cal) __reentrant; -#include - /* * ao_ms5607.c */ void ao_ms5607_init(void); +#include + #endif /* _AO_H_ */ -- cgit v1.2.3 From 27ab744c6eec9243b7aa14161eec2fbf7003531e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Sep 2012 13:46:23 -0700 Subject: altos: Clean up flight data definitions These just shuffle the various definitions of data macros around to make the include files more sensible looking. Signed-off-by: Keith Packard --- src/core/ao_data.h | 64 +++++++++++++++++++++++++++++++++++------------ src/core/ao_sample.c | 2 ++ src/core/ao_sample.h | 17 +++++++------ src/test/ao_flight_test.c | 22 ++++++++-------- 4 files changed, 72 insertions(+), 33 deletions(-) (limited to 'src/core') diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 5412febe..2b9ef5ac 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -95,15 +95,19 @@ extern volatile __data uint8_t ao_data_count; } while (0); /* - * Wait for data to be completed by looking at the - * indicated bit + * Wait until it is time to write a sensor sample; this is + * signaled by the timer tick */ #define AO_DATA_WAIT() do { \ ao_sleep((void *) &ao_data_count); \ } while (0) +#if !HAS_BARO && HAS_MS5607 -#if HAS_MS5607 +/* Either an MS5607 or an MS5611 hooked to a SPI port + */ + +#define HAS_BARO 1 typedef int32_t pres_t; typedef int32_t alt_t; @@ -115,7 +119,11 @@ typedef int32_t alt_t; #define pres_to_altitude(p) ao_pa_to_altitude(p) -#else /* HAS_MS5607 */ +#endif + +#if !HAS_BARO && HAS_ADC + +#define HAS_BARO 1 typedef int16_t pres_t; typedef int16_t alt_t; @@ -125,7 +133,7 @@ typedef int16_t alt_t; #define pres_to_altitude(p) ao_pres_to_altitude(p) #define ao_data_pres_cook(p) -#endif /* else HAS_MS5607 */ +#endif /* * Need a few macros to pull data from the sensors: @@ -136,17 +144,12 @@ typedef int16_t alt_t; * ao_data_accel_invert - flip rocket ends for positive acceleration */ -#if HAS_MPU6000 && !HAS_HIGHG_ACCEL - -typedef int16_t accel_t; - -/* MPU6000 is hooked up so that positive y is positive acceleration */ -#define ao_data_accel(packet) ((packet)->mpu6000.accel_y) -#define ao_data_accel_cook(packet) (-(packet)->mpu6000.accel_y) -#define ao_data_set_accel(packet, accel) ((packet)->mpu6000.accel_y = (accel)) -#define ao_data_accel_invert(a) (-(a)) +#if HAS_ACCEL -#else /* HAS_MPU6000 && !HAS_HIGHG_ACCEL */ +/* This section is for an analog accelerometer hooked to one of the ADC pins. As + * those are 5V parts, this also requires that the 5V supply be hooked to to anothe ADC + * pin so that the both can be measured to correct for changes between the 3.3V and 5V rails + */ typedef int16_t accel_t; #define ao_data_accel(packet) ((packet)->adc.accel) @@ -245,6 +248,35 @@ typedef int16_t accel_t; #endif /* HAS_ACCEL_REF */ -#endif /* else some other accel sensor */ +#endif /* HAS_ACCEL */ + +#if !HAS_ACCEL && HAS_MMA655X + +#define HAS_ACCEL 1 + +typedef int16_t accel_t; + +/* MMA655X is hooked up so that positive values represent negative acceleration */ + +#define ao_data_accel(packet) ((packet)->mma655x) +#define ao_data_accel_cook(packet) ((packet)->mma655x) +#define ao_data_set_accel(packet, accel) ((packet)->mma655x = (accel)) +#define ao_data_accel_invert(accel) (4095 - (accel)) + +#endif + +#if !HAS_ACCEL && HAS_MPU6000 + +#define HAS_ACCEL 1 + +typedef int16_t accel_t; + +/* MPU6000 is hooked up so that positive y is positive acceleration */ +#define ao_data_accel(packet) ((packet)->mpu6000.accel_y) +#define ao_data_accel_cook(packet) (-(packet)->mpu6000.accel_y) +#define ao_data_set_accel(packet, accel) ((packet)->mpu6000.accel_y = (accel)) +#define ao_data_accel_invert(a) (-(a)) + +#endif #endif /* _AO_DATA_H_ */ diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c index 6461def0..985c0940 100644 --- a/src/core/ao_sample.c +++ b/src/core/ao_sample.c @@ -134,10 +134,12 @@ ao_sample(void) ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data]; ao_sample_tick = ao_data->tick; +#if HAS_BARO ao_data_pres_cook(ao_data); ao_sample_pres = ao_data_pres(ao_data); ao_sample_alt = pres_to_altitude(ao_sample_pres); ao_sample_height = ao_sample_alt - ao_ground_height; +#endif #if HAS_ACCEL ao_sample_accel = ao_data_accel_cook(ao_data); diff --git a/src/core/ao_sample.h b/src/core/ao_sample.h index 189b2019..9336bdf9 100644 --- a/src/core/ao_sample.h +++ b/src/core/ao_sample.h @@ -69,7 +69,11 @@ /* * Above this height, the baro sensor doesn't work */ +#if HAS_MS5607 +#define AO_MAX_BARO_HEIGHT 30000 +#else #define AO_MAX_BARO_HEIGHT 12000 +#endif /* * Above this speed, baro measurements are unreliable @@ -90,20 +94,19 @@ #define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) extern __pdata uint16_t ao_sample_tick; /* time of last data */ -extern __pdata pres_t ao_sample_pres; /* most recent pressure sensor reading */ -extern __pdata alt_t ao_sample_alt; /* MSL of ao_sample_pres */ -extern __pdata alt_t ao_sample_height; /* AGL of ao_sample_pres */ extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ extern __data uint8_t ao_sample_data; /* Ring position of last processed sample */ -#if HAS_ACCEL -extern __pdata accel_t ao_sample_accel; /* most recent accel sensor reading */ -#endif - +#if HAS_BARO +extern __pdata pres_t ao_sample_pres; /* most recent pressure sensor reading */ +extern __pdata alt_t ao_sample_alt; /* MSL of ao_sample_pres */ +extern __pdata alt_t ao_sample_height; /* AGL of ao_sample_pres */ extern __pdata pres_t ao_ground_pres; /* startup pressure */ extern __pdata alt_t ao_ground_height; /* MSL of ao_ground_pres */ +#endif #if HAS_ACCEL +extern __pdata accel_t ao_sample_accel; /* most recent accel sensor reading */ extern __pdata accel_t ao_ground_accel; /* startup acceleration */ extern __pdata accel_t ao_accel_2g; /* factory accel calibration */ extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index a4ef8dc0..b9e291ce 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -54,6 +54,15 @@ struct ao_adc { #define __code #define __reentrant +#define HAS_FLIGHT 1 +#define HAS_IGNITE 1 +#define HAS_USB 1 +#define HAS_GPS 1 +#ifndef HAS_ACCEL +#define HAS_ACCEL 1 +#define HAS_ACCEL_REF 0 +#endif + #include #define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) @@ -200,24 +209,17 @@ struct ao_config ao_config; #define DATA_TO_XDATA(x) (x) -#define HAS_FLIGHT 1 -#define HAS_IGNITE 1 -#define HAS_ADC 1 -#define HAS_USB 1 -#define HAS_GPS 1 -#ifndef HAS_ACCEL -#define HAS_ACCEL 1 -#define HAS_ACCEL_REF 0 -#endif #define GRAVITY 9.80665 extern int16_t ao_ground_accel, ao_flight_accel; extern int16_t ao_accel_2g; +typedef int16_t accel_t; + extern uint16_t ao_sample_tick; extern int16_t ao_sample_height; -extern int16_t ao_sample_accel; +extern accel_t ao_sample_accel; extern int32_t ao_accel_scale; extern int16_t ao_ground_height; extern int16_t ao_sample_alt; -- cgit v1.2.3