From d4b1dffeef3e9ea96e143f74782e4da7d116c0d4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 6 Oct 2012 18:25:15 -0700 Subject: altos/telefire: Make sure armed alarm goes off on time Instead of turning the alarm off when a packet is received after the deadline, just do it in the thread which is awake all of the time. This prevents the alarm from sticking on when the LCO box is turned off while the arming key is on. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 55e6289d..120ce539 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -139,6 +139,9 @@ ao_pad_monitor(void) prev = cur; } + if (ao_pad_armed && (int16_t) (ao_time() - ao_pad_arm_time) > AO_PAD_ARM_TIME) + ao_pad_armed = 0; + if (ao_pad_armed) { if (sample & 2) ao_beep(AO_BEEP_HIGH); @@ -197,9 +200,6 @@ ao_pad(void) PRINTD ("tick %d box %d cmd %d channels %02x\n", command.tick, command.box, command.cmd, command.channels); - if (ao_pad_armed && (int16_t) (ao_time() - ao_pad_arm_time) > AO_PAD_ARM_TIME) - ao_pad_armed = 0; - switch (command.cmd) { case AO_LAUNCH_ARM: if (command.box != ao_pad_box) { -- cgit v1.2.3 From 422799d9be36ef71b63c1c0fd80d5e76da802949 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Oct 2012 21:59:55 -0700 Subject: altos: Compute desired frequency when upgrading from pre-1.1 Instead of just smashing the frequency to 434.550, compute the frequency from the old radio channel value Signed-off-by: Keith Packard --- src/core/ao_config.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index ce855ad1..e8ff95b7 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -102,6 +102,7 @@ _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._legacy_radio_channel = 0; } minor = ao_config.minor; if (minor != AO_CONFIG_MINOR) { @@ -131,7 +132,7 @@ _ao_config_get(void) if (minor < 9) ao_xmemset(&ao_config.aes_key, '\0', AO_AES_LEN); if (minor < 10) - ao_config.frequency = 434550; + ao_config.frequency = 434550 + ao_config._legacy_radio_channel * 100; if (minor < 11) ao_config.apogee_lockout = 0; #if AO_PYRO_NUM -- cgit v1.2.3 From 3f059f8878a79b3154a19b6803fbc367eda80dc9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 10 Oct 2012 14:28:07 -0700 Subject: altos/telefire: Add siren/strobe support This also involved hacking up the code to allow for non-zero offsets for the pad firing and continuity pins. Signed-off-by: Keith Packard --- src/cc1111/ao_adc.c | 8 ++++-- src/drivers/ao_pad.c | 63 ++++++++++++++++++++++++++++++++++++++------- src/telefire-v0.1/ao_pins.h | 49 +++++++++++++++++++++++------------ 3 files changed, 92 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index f7b52281..f8000410 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -20,6 +20,10 @@ volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; volatile __data uint8_t ao_data_head; +#ifndef AO_ADC_FIRST_PIN +#define AO_ADC_FIRST_PIN 0 +#endif + void ao_adc_poll(void) { @@ -29,7 +33,7 @@ ao_adc_poll(void) # ifdef TELENANO_V_0_1 ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1; # else - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0; + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | AO_ADC_FIRST_PIN; # endif #endif } @@ -141,7 +145,7 @@ 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 = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.sense[0] + sequence - AO_ADC_FIRST_PIN); a[0] = ADCL; a[1] = ADCH; if (sequence < 5) diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 120ce539..36905136 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -39,25 +39,63 @@ static __pdata uint8_t ao_pad_debug; #define FLUSHD() #endif +static void +ao_siren(uint8_t v) +{ +#ifdef AO_SIREN + ao_gpio_set(AO_SIREN_PORT, AO_SIREN_PIN, AO_SIREN, v); +#else + ao_beep(v ? AO_BEEP_MID : 0); +#endif +} + +static void +ao_strobe(uint8_t v) +{ +#ifdef AO_STROBE + ao_gpio_set(AO_STROBE_PORT, AO_STROBE_PIN, AO_STROBE, v); +#endif +} + static void ao_pad_run(void) { + uint8_t pins; + 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; + pins = 0; +#if AO_PAD_NUM > 0 + if (ao_pad_ignite & (1 << 0)) + pins |= (1 << AO_PAD_PIN_0); +#endif +#if AO_PAD_NUM > 1 + if (ao_pad_ignite & (1 << 1)) + pins |= (1 << AO_PAD_PIN_1); +#endif +#if AO_PAD_NUM > 2 + if (ao_pad_ignite & (1 << 2)) + pins |= (1 << AO_PAD_PIN_2); +#endif +#if AO_PAD_NUM > 3 + if (ao_pad_ignite & (1 << 3)) + pins |= (1 << AO_PAD_PIN_3); +#endif + AO_PAD_PORT = (AO_PAD_PORT & (~AO_PAD_ALL_PINS)) | pins; while (ao_pad_ignite) { ao_pad_ignite = 0; + ao_delay(AO_PAD_FIRE_TIME); } AO_PAD_PORT &= ~(AO_PAD_ALL_PINS); } } -#define AO_PAD_ARM_BEEP_INTERVAL 200 +#define AO_PAD_ARM_SIREN_INTERVAL 200 static void ao_pad_monitor(void) @@ -143,21 +181,23 @@ ao_pad_monitor(void) ao_pad_armed = 0; if (ao_pad_armed) { + ao_strobe(1); if (sample & 2) - ao_beep(AO_BEEP_HIGH); + ao_siren(1); else - ao_beep(AO_BEEP_LOW); + ao_siren(0); beeping = 1; } else if (query.arm_status == AO_PAD_ARM_STATUS_ARMED && !beeping) { if (arm_beep_time == 0) { - arm_beep_time = AO_PAD_ARM_BEEP_INTERVAL; + arm_beep_time = AO_PAD_ARM_SIREN_INTERVAL; beeping = 1; - ao_beep(AO_BEEP_HIGH); + ao_siren(1); } --arm_beep_time; } else if (beeping) { beeping = 0; - ao_beep(0); + ao_siren(0); + ao_strobe(0); } } } @@ -184,7 +224,6 @@ ao_pad(void) int16_t time_difference; int8_t ret; - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); ao_pad_box = 0; ao_led_set(0); ao_led_on(AO_LED_POWER); @@ -207,7 +246,7 @@ ao_pad(void) break; } - if (command.channels & ~(AO_PAD_ALL_PINS)) + if (command.channels & ~(AO_PAD_ALL_CHANNELS)) break; time_difference = command.tick - ao_time(); @@ -348,6 +387,12 @@ ao_pad_init(void) #endif #if AO_PAD_NUM > 3 ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_3, AO_PAD_3, 0); +#endif +#ifdef AO_STROBE + ao_enable_output(AO_STROBE_PORT, AO_STROBE_PIN, AO_STROBE, 0); +#endif +#ifdef AO_SIREN + ao_enable_output(AO_SIREN_PORT, AO_SIREN_PIN, AO_SIREN, 0); #endif ao_cmd_register(&ao_pad_cmds[0]); ao_add_task(&ao_pad_task, ao_pad, "pad listener"); diff --git a/src/telefire-v0.1/ao_pins.h b/src/telefire-v0.1/ao_pins.h index eecf783e..774d59f4 100644 --- a/src/telefire-v0.1/ao_pins.h +++ b/src/telefire-v0.1/ao_pins.h @@ -38,8 +38,8 @@ #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 0 -#define AO_LED_CONTINUITY(c) (1 << (c)) -#define AO_LED_CONTINUITY_MASK (0xf) +#define AO_LED_CONTINUITY(c) (1 << ((c) + 2)) +#define AO_LED_CONTINUITY_MASK (0xc) #define AO_LED_RX 0x10 #define AO_LED_TX 0x20 #define AO_LED_ARMED 0x40 @@ -74,40 +74,55 @@ #define AO_PCA9922_CS_PIN 4 #define AO_PCA9922_CS P1_4 -#define AO_PAD_NUM 4 +#define AO_PAD_NUM 2 #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)) + +#define AO_PAD_PIN_0 2 +#define AO_PAD_0 P1_2 +#define AO_PAD_ADC_0 2 + +#define AO_PAD_PIN_1 3 +#define AO_PAD_1 P1_3 +#define AO_PAD_ADC_1 3 + +#define AO_PAD_ALL_PINS ((1 << AO_PAD_PIN_0) | (1 << AO_PAD_PIN_1)) +#define AO_PAD_ALL_CHANNELS ((1 << 0) | (1 << 1)) + +#define AO_SIREN_PORT P1 +#define AO_SIREN_DIR P1DIR +#define AO_SIREN_PIN 0 +#define AO_SIREN P1_0 + +#define AO_STROBE_PORT P1 +#define AO_STROBE_DIR P1DIR +#define AO_STROBE_PIN 1 +#define AO_STROBE P1_1 /* test these values with real igniters */ #define AO_PAD_RELAY_CLOSED 3524 #define AO_PAD_NO_IGNITER 16904 #define AO_PAD_GOOD_IGNITER 22514 +#define AO_PAD_ADC_PYRO 4 +#define AO_PAD_ADC_BATT 5 + +#define AO_ADC_FIRST_PIN 2 + struct ao_adc { - int16_t sense[4]; + int16_t sense[AO_PAD_NUM]; 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", \ + printf ("tick: %5u 0: %5d 1: %5d pyro: %5d batt %5d\n", \ (p)->tick, \ (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)) +#define AO_ADC_PINS ((1 << AO_PAD_ADC_0) | (1 << AO_PAD_ADC_1) | (1 << AO_PAD_ADC_PYRO) | (1 << AO_PAD_ADC_BATT)) #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From a07b8ba166e05e7d1722c59651ef00e9fb7580d5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Oct 2012 13:31:17 -0700 Subject: altos: Split task definitions out to ao_task.h And only include them if using tasks Signed-off-by: Keith Packard --- src/core/ao.h | 63 ++++-------------------------------------- src/core/ao_task.h | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 57 deletions(-) create mode 100644 src/core/ao_task.h (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 31ec4686..711b3533 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -39,64 +39,13 @@ #define CODE_TO_XDATA(a) (a) #endif -/* An AltOS task */ -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 */ - 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); - -/* Clear any pending alarm */ -void -ao_clear_alarm(void); - -/* Yield the processor to another task */ -void -ao_yield(void) ao_arch_naked_declare; - -/* 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); +#ifndef HAS_TASK +#define HAS_TASK 1 +#endif -/* Start the scheduler. This will not return */ -void -ao_start_scheduler(void); +#if HAS_TASK +#include +#endif /* * ao_panic.c diff --git a/src/core/ao_task.h b/src/core/ao_task.h new file mode 100644 index 00000000..18edd866 --- /dev/null +++ b/src/core/ao_task.h @@ -0,0 +1,80 @@ +/* + * 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_TASK_H_ +#define _AO_TASK_H_ + +/* An AltOS task */ +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 */ + 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); + +/* Clear any pending alarm */ +void +ao_clear_alarm(void); + +/* Yield the processor to another task */ +void +ao_yield(void) ao_arch_naked_declare; + +/* 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); + +#endif -- cgit v1.2.3 From 7795d8309b3e1147bc37d31a0adde42d7dee6cd1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Oct 2012 13:37:07 -0700 Subject: altos: Prepare ms5607 driver for use in non-tasking products Micropeak doesn't have tasking, prepare the ms5607 driver for that Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.c | 30 ++++++++++++++++++------------ src/drivers/ao_ms5607.h | 3 +++ 2 files changed, 21 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 76931b4b..1e69cccb 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -17,7 +17,7 @@ #include #include -#include "ao_ms5607.h" +#include #if HAS_MS5607 || HAS_MS5611 @@ -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_PORT, AO_MS5607_CS_PIN, 0); + ao_gpio_set(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, 0); } static void ao_ms5607_stop(void) { - stm_gpio_set(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, 1); + ao_gpio_set(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, 1); ao_spi_put(AO_MS5607_SPI_INDEX); } @@ -53,7 +53,6 @@ ao_ms5607_crc(uint8_t *prom) uint8_t crc_byte = prom[15]; uint8_t cnt; uint16_t n_rem = 0; - uint16_t crc_read; uint8_t n_bit; prom[15] = 0; @@ -89,9 +88,11 @@ ao_ms5607_prom_read(struct ao_ms5607_prom *prom) } crc = ao_ms5607_crc((uint8_t *) prom); if (crc != (((uint8_t *) prom)[15] & 0xf)) { +#if HAS_TASK printf ("MS5607 PROM CRC error (computed %x actual %x)\n", crc, (((uint8_t *) prom)[15] & 0xf)); flush(); +#endif ao_panic(AO_PANIC_SELF_TEST_MS5607); } @@ -105,7 +106,7 @@ ao_ms5607_prom_read(struct ao_ms5607_prom *prom) #endif } -static void +void ao_ms5607_setup(void) { if (ms5607_configured) @@ -115,33 +116,34 @@ ao_ms5607_setup(void) ao_ms5607_prom_read(&ms5607_prom); } -static uint8_t ao_ms5607_done; +static volatile uint8_t ao_ms5607_done; static void ao_ms5607_isr(void) { ao_exti_disable(AO_MS5607_MISO_PORT, AO_MS5607_MISO_PIN); ao_ms5607_done = 1; - ao_wakeup(&ao_ms5607_done); + ao_wakeup((void *) &ao_ms5607_done); } static uint32_t 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_PORT, AO_MS5607_MISO_PIN); + #if AO_MS5607_PRIVATE_PINS ao_spi_put(AO_MS5607_SPI_INDEX); #endif cli(); while (!ao_ms5607_done) - ao_sleep(&ao_ms5607_done); + ao_sleep((void *) &ao_ms5607_done); sei(); #if AO_MS5607_PRIVATE_PINS stm_gpio_set(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, 1); @@ -168,12 +170,10 @@ ao_ms5607_sample(struct ao_ms5607_sample *sample) void ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value) { - uint8_t addr; int32_t dT; int32_t TEMP; int64_t OFF; int64_t SENS; - int32_t P; dT = sample->temp - ((int32_t) ms5607_prom.tref << 8); @@ -207,6 +207,7 @@ ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value value->temp = TEMP; } +#if HAS_TASK static void ao_ms5607(void) { @@ -254,15 +255,18 @@ __code struct ao_cmds ao_ms5607_cmds[] = { { ao_ms5607_dump, "B\0Display MS5607 data" }, { 0, NULL }, }; +#endif /* HAS_TASK */ void ao_ms5607_init(void) { ms5607_configured = 0; - ao_cmd_register(&ao_ms5607_cmds[0]); ao_spi_init_cs(AO_MS5607_CS_PORT, (1 << AO_MS5607_CS_PIN)); +#if HAS_TASK + ao_cmd_register(&ao_ms5607_cmds[0]); ao_add_task(&ao_ms5607_task, ao_ms5607, "ms5607"); +#endif /* Configure the MISO pin as an interrupt; when the * conversion is complete, the MS5607 will raise this @@ -273,12 +277,14 @@ ao_ms5607_init(void) AO_EXTI_MODE_RISING, ao_ms5607_isr); +#ifdef STM_MODER_ALTERNATE /* Reset the pin from INPUT to ALTERNATE so that SPI works * This needs an abstraction at some point... */ stm_moder_set(AO_MS5607_MISO_PORT, AO_MS5607_MISO_PIN, STM_MODER_ALTERNATE); +#endif } #endif diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index e9c364d9..5c31fd8b 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -56,6 +56,9 @@ struct ao_ms5607_value { int32_t temp; /* in °C * 100 */ }; +void +ao_ms5607_setup(void); + void ao_ms5607_init(void); -- cgit v1.2.3 From 6a3ee911353291b04e161d50a181ed4211d467a2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Oct 2012 13:54:37 -0700 Subject: altos: Allow projects to specify clock at other than 100Hz Leave the default at 100Hz, but allow it to be overridden Signed-off-by: Keith Packard --- src/core/ao.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 711b3533..9d801489 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -85,7 +85,9 @@ ao_panic(uint8_t reason); extern volatile __data AO_TICK_TYPE ao_tick_count; /* Our timer runs at 100Hz */ +#ifndef AO_HERTZ #define AO_HERTZ 100 +#endif #define AO_MS_TO_TICKS(ms) ((ms) / (1000 / AO_HERTZ)) #define AO_SEC_TO_TICKS(s) ((s) * AO_HERTZ) -- cgit v1.2.3 From be0a28ee7a6fbd98fc8113db8501bb791a112fa0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Oct 2012 13:55:33 -0700 Subject: altos: Allow for other mutex implementations Allow projects to replace ao_mutex_get and ao_mutex_put with macros Signed-off-by: Keith Packard --- src/core/ao.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 9d801489..200d4bc4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -119,11 +119,13 @@ ao_clock_init(void); * ao_mutex.c */ +#ifndef ao_mutex_get void ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant; void ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant; +#endif /* * ao_cmd.c -- cgit v1.2.3 From 175380a436efa35bbfae2ee5e29e12e9ef86fbde Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Oct 2012 13:57:49 -0700 Subject: altos: Use alt_t for all Pascal-based altitude data This allows alt_t to be overridden for systems using the MS5607/MS5611 sensors Signed-off-by: Keith Packard --- src/core/ao.h | 6 ++++-- src/core/ao_convert_pa.c | 6 +++--- src/core/ao_convert_pa_test.c | 1 + src/core/ao_data.h | 11 ++++++++++- 4 files changed, 18 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 200d4bc4..e559e876 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -272,11 +272,13 @@ ao_temp_to_dC(int16_t temp) __reentrant; * Convert between pressure in Pa and altitude in meters */ -int32_t +#include + +alt_t ao_pa_to_altitude(int32_t pa); int32_t -ao_altitude_to_pa(int32_t alt); +ao_altitude_to_pa(alt_t alt); #if HAS_DBG #include diff --git a/src/core/ao_convert_pa.c b/src/core/ao_convert_pa.c index 0c93caea..1413681d 100644 --- a/src/core/ao_convert_pa.c +++ b/src/core/ao_convert_pa.c @@ -26,7 +26,7 @@ static const int32_t altitude_table[] = { #define ALT_SCALE (1 << ALT_SHIFT) #define ALT_MASK (ALT_SCALE - 1) -int32_t +alt_t ao_pa_to_altitude(int32_t pa) { int16_t o; @@ -40,8 +40,8 @@ ao_pa_to_altitude(int32_t pa) 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); + low = (alt_t) FETCH_ALT(o) * (ALT_SCALE - part); + high = (alt_t) FETCH_ALT(o+1) * part + (ALT_SCALE >> 1); return (low + high) >> ALT_SHIFT; } diff --git a/src/core/ao_convert_pa_test.c b/src/core/ao_convert_pa_test.c index 972a4d4c..143ce958 100644 --- a/src/core/ao_convert_pa_test.c +++ b/src/core/ao_convert_pa_test.c @@ -17,6 +17,7 @@ #include #define AO_CONVERT_TEST +typedef int32_t alt_t; #include "ao_host.h" #include "ao_convert_pa.c" diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 2b9ef5ac..90182b12 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -110,7 +110,12 @@ extern volatile __data uint8_t ao_data_count; #define HAS_BARO 1 typedef int32_t pres_t; -typedef int32_t alt_t; + +#ifndef AO_ALT_TYPE +#define AO_ALT_TYPE int32_t +#endif + +typedef AO_ALT_TYPE alt_t; #define ao_data_pres_cook(packet) ao_ms5607_convert(&packet->ms5607_raw, &packet->ms5607_cooked) @@ -135,6 +140,10 @@ typedef int16_t alt_t; #endif +#if !HAS_BARO +typedef int16_t alt_t; +#endif + /* * Need a few macros to pull data from the sensors: * -- cgit v1.2.3 From 68308908afbd1f04b17056d2be408c89b3578c86 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Oct 2012 13:59:50 -0700 Subject: altos: Parameterize altitude table access and initialization This allows projects to store the altitude data in different representations or with different access modes. By default, altitude data is stored in meters, but the initializers include decimeter values so those can be used instead if desired. Signed-off-by: Keith Packard --- src/core/ao_convert_pa.c | 10 +++++++++- src/util/make-altitude-pa | 10 +++++----- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/ao_convert_pa.c b/src/core/ao_convert_pa.c index 1413681d..2793b77c 100644 --- a/src/core/ao_convert_pa.c +++ b/src/core/ao_convert_pa.c @@ -19,10 +19,18 @@ #include "ao.h" #endif -static const int32_t altitude_table[] = { +#ifndef AO_CONST_ATTRIB +#define AO_CONST_ATTRIB +#endif + +static const alt_t altitude_table[] AO_CONST_ATTRIB = { #include "altitude-pa.h" }; +#ifndef FETCH_ALT +#define FETCH_ALT(o) altitude_table[o] +#endif + #define ALT_SCALE (1 << ALT_SHIFT) #define ALT_MASK (ALT_SCALE - 1) diff --git a/src/util/make-altitude-pa b/src/util/make-altitude-pa index eae5ebe9..22831d50 100644 --- a/src/util/make-altitude-pa +++ b/src/util/make-altitude-pa @@ -239,8 +239,8 @@ real sample_to_fit_altitude(int sample) { real i_v; r_v = sample * l.m + l.b; - i_v = (round(alt_part[sub]) * (seg_len - off) + round(alt_part[sub+1]) * off) / seg_len; - return i_v; + i_v = (round(alt_part[sub]*10) * (seg_len - off) + round(alt_part[sub+1]*10) * off) / seg_len; + return i_v/10; } real max_error = 0; @@ -279,11 +279,11 @@ printf ("/*max error %f at %7.3f kPa. Average error %f*/\n", printf ("#define NALT %d\n", dim(alt_part)); printf ("#define ALT_SHIFT %d\n", pa_part_shift + pa_sample_shift); -printf ("#ifndef SATURATE\n#define SATURATE(x) (x)\n#endif\n"); +printf ("#ifndef AO_ALT_VALUE\n#define AO_ALT_VALUE(x) (alt_t) (x)\n#endif\n"); for (int part = 0; part < dim(alt_part); part++) { real kPa = sample_to_Pa(part_to_sample(part)) / 1000; - printf ("SATURATE(%9d), /* %6.2f kPa error %6.2fm */\n", - round (alt_part[part]), kPa, + printf ("AO_ALT_VALUE(%10.1f), /* %6.2f kPa error %6.2fm */\n", + round (alt_part[part]*10) / 10, kPa, alt_error[part]); } -- cgit v1.2.3 From 866d10b3faa96f6c5a2c495a2c12a0d2bc8259ef Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Oct 2012 14:01:16 -0700 Subject: altos: Elide ao_altitude_to_pa in flight firmware Only the conversion testing code needs to get back from altitude to pressure, so don't include that code in other environments. Signed-off-by: Keith Packard --- src/core/ao_convert_pa.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/core/ao_convert_pa.c b/src/core/ao_convert_pa.c index 2793b77c..55fe6e7d 100644 --- a/src/core/ao_convert_pa.c +++ b/src/core/ao_convert_pa.c @@ -53,6 +53,7 @@ ao_pa_to_altitude(int32_t pa) return (low + high) >> ALT_SHIFT; } +#ifdef AO_CONVERT_TEST int32_t ao_altitude_to_pa(int32_t alt) { @@ -78,3 +79,4 @@ ao_altitude_to_pa(int32_t alt) pa = 0; return pa; } +#endif -- cgit v1.2.3 From 7751c9cbc630f7251b8988f8da68be9a54ff552c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Oct 2012 14:02:29 -0700 Subject: altos: Clean up types in Pa conversion testing code. Only test to 40km A couple of missing 'int' declarations. Only test to 40km as above that there aren't enough data points to do anything reasonable Signed-off-by: Keith Packard --- src/core/ao_convert_pa_test.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/core/ao_convert_pa_test.c b/src/core/ao_convert_pa_test.c index 143ce958..7d5b1922 100644 --- a/src/core/ao_convert_pa_test.c +++ b/src/core/ao_convert_pa_test.c @@ -24,9 +24,10 @@ typedef int32_t alt_t; #define STEP_P 1 #define STEP_A 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; int32_t p_to_a, p_to_a_to_p; @@ -50,9 +51,7 @@ main () // 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; + for (i = -1450; i < 40000 + STEP_A; i += STEP_A) { 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); -- cgit v1.2.3 From 16bad3b6ab65cf31b19152127cb6af69142c5c12 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Oct 2012 14:03:28 -0700 Subject: altos: Include struct ao_data declaration only when used Leave it out for products that don't have a ring of sensor data Signed-off-by: Keith Packard --- src/core/ao_data.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 90182b12..1153d433 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -52,6 +52,8 @@ #define AO_DATA_MMA655X 0 #endif +#ifdef AO_DATA_RING + #define AO_DATA_ALL (AO_DATA_ADC|AO_DATA_MS5607|AO_DATA_MPU6000|AO_DATA_HMC5883|AO_DATA_MMA655X) struct ao_data { @@ -102,6 +104,8 @@ extern volatile __data uint8_t ao_data_count; ao_sleep((void *) &ao_data_count); \ } while (0) +#endif /* AO_DATA_RING */ + #if !HAS_BARO && HAS_MS5607 /* Either an MS5607 or an MS5611 hooked to a SPI port -- cgit v1.2.3 From 64500ab11ab76d2309608f8e02a1dd9658963b3e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Oct 2012 14:04:57 -0700 Subject: altos: Add attiny architecture files These are designed to work with the ATtiny85 processor, but can presuambly be easily adapted to others in that series Signed-off-by: Keith Packard --- src/attiny/ao_arch.h | 82 +++++++++++++++ src/attiny/ao_arch_funcs.h | 125 +++++++++++++++++++++++ src/attiny/ao_clock.c | 114 +++++++++++++++++++++ src/attiny/ao_eeprom_tiny.c | 71 +++++++++++++ src/attiny/ao_exti.c | 37 +++++++ src/attiny/ao_exti.h | 34 +++++++ src/attiny/ao_i2c_attiny.c | 238 ++++++++++++++++++++++++++++++++++++++++++++ src/attiny/ao_led.c | 63 ++++++++++++ src/attiny/ao_spi_attiny.c | 123 +++++++++++++++++++++++ 9 files changed, 887 insertions(+) create mode 100644 src/attiny/ao_arch.h create mode 100644 src/attiny/ao_arch_funcs.h create mode 100644 src/attiny/ao_clock.c create mode 100644 src/attiny/ao_eeprom_tiny.c create mode 100644 src/attiny/ao_exti.c create mode 100644 src/attiny/ao_exti.h create mode 100644 src/attiny/ao_i2c_attiny.c create mode 100644 src/attiny/ao_led.c create mode 100644 src/attiny/ao_spi_attiny.c (limited to 'src') diff --git a/src/attiny/ao_arch.h b/src/attiny/ao_arch.h new file mode 100644 index 00000000..c34206e6 --- /dev/null +++ b/src/attiny/ao_arch.h @@ -0,0 +1,82 @@ +/* + * 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 +#include +#include +#include + +#define F_CPU 8000000UL // 8 MHz + +/* + * AVR definitions and code fragments for AltOS + */ + +#define AO_STACK_SIZE 116 + +/* Various definitions to make GCC look more like SDCC */ + +#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 __at(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 + +#define ao_arch_cpu_idle() do { \ + sleep_enable(); \ + sei(); \ + sleep_cpu(); \ + sleep_disable(); \ + } while (0) + +#define ao_arch_critical(b) do { cli(); do { b } while (0); sei(); } while (0) + +#define ao_mutex_get(m) +#define ao_mutex_put(m) + +void +ao_delay_until(uint16_t target); + +/* We can't hit 100 Hz, but we can hit 125 */ +#define AO_HERTZ 125 + +void +ao_eeprom_read(uint16_t addr, void *buf, uint16_t len); + +void +ao_eeprom_write(uint16_t addr, void *buf, uint16_t len); + +#endif /* _AO_ARCH_H_ */ diff --git a/src/attiny/ao_arch_funcs.h b/src/attiny/ao_arch_funcs.h new file mode 100644 index 00000000..8c9d1ae6 --- /dev/null +++ b/src/attiny/ao_arch_funcs.h @@ -0,0 +1,125 @@ +/* + * 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 + */ + +#define ao_spi_get_mask(reg,mask,bus,speed) do { \ + (reg) &= ~(mask); \ + } while (0) + +#define ao_spi_put_mask(reg,mask,bus) do { \ + (reg) |= (mask); \ + } while (0) + +#define ao_spi_get_bit(reg,bit,pin,bus,speed) do { \ + (pin) = 0; \ + } while (0) + +#define ao_spi_put_bit(reg,bit,pin,bus) do { \ + (pin) = 1; \ + } 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) \ + PORTB |= (1 << bit); \ + else \ + PORTB &= ~(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; + +void +ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant; + +#define ao_spi_send(block, len, bus) ao_spi_send_bus(block, len) +#define ao_spi_recv(block, len, bus) ao_spi_recv_bus(block, len) + +void +ao_spi_init(void); + +#define ao_spi_get(bus, speed) +#define ao_spi_put(bus) + +#define ao_spi_init_cs(port, mask) do { \ + PORTB |= (mask); \ + DDRB |= (mask); \ + } while (0) + +/* I2C */ + +void +ao_i2c_get(uint8_t i2c_index); + +uint8_t +ao_i2c_start_bus(uint8_t address); + +#define ao_i2c_start(i,a) ao_i2c_start_bus(a) + +void +ao_i2c_put(uint8_t i2c_index); + +uint8_t +ao_i2c_send_bus(void *block, uint16_t len, uint8_t stop); + +#define ao_i2c_send(b,l,i,s) ao_i2c_send_bus(b,l.s) + +uint8_t +ao_i2c_send_fixed_bus(uint8_t value, uint16_t len, uint8_t stop); + +#define ao_i2c_send_fixed(v,l,i,s) ao_i2c_send_fixed_bus(v,l.s) + +uint8_t +ao_i2c_recv_bus(void *block, uint16_t len, uint8_t stop); + +#define ao_i2c_recv(b,l,i,s) ao_i2c_recv_bus(b,l.s) + +void +ao_i2c_init(void); + +/* notask.c */ + +uint8_t +ao_sleep(__xdata void *wchan); + +void +ao_wakeup(__xdata void *wchan); + +extern alt_t ao_max_height; + +extern void ao_report_altitude(void); + +void ao_delay_us(uint16_t us); + diff --git a/src/attiny/ao_clock.c b/src/attiny/ao_clock.c new file mode 100644 index 00000000..a381b47f --- /dev/null +++ b/src/attiny/ao_clock.c @@ -0,0 +1,114 @@ +/* + * 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 + +volatile AO_TICK_TYPE ao_tick_count; +static volatile AO_TICK_TYPE ao_wakeup_count; + +ISR(TIMER1_COMPA_vect) +{ + PORTB ^= 2; + ++ao_tick_count; + if ((int16_t) (ao_tick_count - ao_wakeup_count) >= 0) + ao_wakeup((void *) &ao_tick_count); +} + +uint16_t +ao_time(void) +{ + uint16_t r; + + cli(); + r = ao_tick_count; + sei(); + return r; +} + +void +ao_timer_init(void) +{ + cli(); + CLKPR = (1 << CLKPCE); + CLKPR = 0; + sei(); + + /* Overall division ratio is 512 * 125, + * so our 8MHz base clock ends up as a 125Hz + * clock + */ + TCCR1 = ((1 << CTC1) | /* Clear timer on match */ + (0 << PWM1A) | /* Not PWM mode */ + (0 << COM1A0) | /* Don't change output pins */ + (0 << COM1A1) | /* ... */ + (1 << CS13) | /* Prescale by 512 */ + (0 << CS12) | /* ... */ + (1 << CS11) | /* ... */ + (0 << CS10)); /* ... */ + GTCCR = ((0 << PWM1B) | /* Not PWM mode */ + (0 << COM1B1) | /* Don't change output pins */ + (0 << COM1B0) | /* ... */ + (0 << FOC1B) | /* Don't force output compare */ + (0 << FOC1A) | /* ... */ + (0 << PSR1)); /* Don't bother to reset scaler */ + + OCR1A = 0; + OCR1B = 0; + OCR1C = 124; /* Divide by as many 5s as we can (5^3 = 125) */ + + TIMSK = ((1 << OCIE1A) | /* Enable TIMER1_COMPA interrupt */ + (0 << OCIE1B) | /* Disable TIMER1_COMPB interrupt */ + (0 << TOIE1)); /* Disable TIMER1_OVF interrupt */ + DDRB |= 2; +} + +#define PER_LOOP 8 +#define US_LOOPS ((AVR_CLOCK / 1000000) / PER_LOOP) + +void ao_delay_us(uint16_t us) +{ +#if US_LOOPS > 1 + us *= US_LOOPS; +#endif + for (;;) { + ao_arch_nop(); + ao_arch_nop(); + ao_arch_nop(); + --us; + /* A bit funky to keep the optimizer + * from short-circuiting the test */ + if (!((uint8_t) (us | (us >> 8)))) + break; + } +} + +void +ao_delay_until(uint16_t target) +{ + cli(); + ao_wakeup_count = target; + while ((int16_t) (target - ao_tick_count) > 0) + ao_sleep((void *) &ao_tick_count); + sei(); +} + +void +ao_delay(uint16_t ticks) +{ + ao_delay_until(ao_time() + ticks); +} + diff --git a/src/attiny/ao_eeprom_tiny.c b/src/attiny/ao_eeprom_tiny.c new file mode 100644 index 00000000..83014183 --- /dev/null +++ b/src/attiny/ao_eeprom_tiny.c @@ -0,0 +1,71 @@ +/* + * 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 + +static void +ao_eeprom_wait(void) +{ + /* Wait for previous write to complete */ + while (EECR & (1 << EEPE)) + ; +} + +static uint8_t +ao_eeprom_read_byte(uint16_t addr) +{ + uint8_t v; + + ao_eeprom_wait(); + EEAR = addr; + cli(); + EECR |= (1 << EERE); + v = EEDR; + sei(); + return v; +} + +static void +ao_eeprom_write_byte(uint16_t addr, uint8_t v) +{ + ao_eeprom_wait(); + EECR = (0 << EEPM1) | (0 << EEPM0); + EEAR = addr; + EEDR = v; + cli(); + EECR |= (1 << EEMPE); + EECR |= (1 << EEPE); + sei(); +} + +void +ao_eeprom_read(uint16_t addr, void *buf, uint16_t len) +{ + uint8_t *b = buf; + + while (len--) + *b++ = ao_eeprom_read_byte(addr++); +} + +void +ao_eeprom_write(uint16_t addr, void *buf, uint16_t len) +{ + uint8_t *b = buf; + + while (len--) + ao_eeprom_write_byte(addr++, *b++); +} diff --git a/src/attiny/ao_exti.c b/src/attiny/ao_exti.c new file mode 100644 index 00000000..0ca10ca4 --- /dev/null +++ b/src/attiny/ao_exti.c @@ -0,0 +1,37 @@ +/* + * 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 void (*pcint_callback)(void); +static uint8_t pcint_mask; + +ISR(PCINT0_vect) +{ + if (PINB & pcint_mask) + (*pcint_callback)(); +} + +void +ao_exti_setup_port(uint8_t pin, uint8_t mode, void (*callback)(void)) +{ + pcint_callback = callback; + pcint_mask = (1 << pin); + ao_exti_disable(PORTB, pin); + GIMSK |= (1 << PCIE); +} diff --git a/src/attiny/ao_exti.h b/src/attiny/ao_exti.h new file mode 100644 index 00000000..2ea4f47d --- /dev/null +++ b/src/attiny/ao_exti.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_EXTI_H_ +#define _AO_EXTI_H_ + +void +ao_exti_setup_port(uint8_t pin, uint8_t mode, void (*callback)(void)); + +#define ao_exti_setup(port, pin, mode, callback) ao_exti_setup_port(pin, mode, callback) + +#define ao_exti_enable(gpio, pin) (PCMSK |= (1 << (pin))) + +#define ao_exti_disable(gpio, pin) (PCMSK &= ~(1 << (pin))) + +#define ao_exti_init() + +#define AO_EXTI_MODE_RISING 1 + +#endif /* _AO_EXTI_H_ */ diff --git a/src/attiny/ao_i2c_attiny.c b/src/attiny/ao_i2c_attiny.c new file mode 100644 index 00000000..2ee44fd2 --- /dev/null +++ b/src/attiny/ao_i2c_attiny.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. + */ + +#include + +/* + * ATtiny USI as an I2C interface + */ + +#define I2C_USICR ((0 << USISIE) | /* No start condition interrupt */ \ + (0 << USIOIE) | /* No counter overflow interrupt */ \ + (1 << USIWM1) | /* Two-wire mode */ \ + (0 << USIWM0) | /* ... */ \ + (1 << USICS1) | /* Software clock strobe */ \ + (0 << USICS0) | /* ... */ \ + (1 << USICLK)) /* ... */ \ + +#define I2C_USICR_TICK (I2C_USICR | (1 << USITC)) /* Toggle the clock on every write */ + +#define I2C_USISR_1BIT ((1<4.7μs */ +#define T4_TWI 4 /* >4.0μs */ + +static inline void ao_i2c_transfer(uint8_t sr) +{ + USISR = sr; + for (;;) { + ao_delay_us(T2_TWI); + + /* Clock high */ + USICR = I2C_USICR_TICK; + + /* Wait for clock high (clock stretching) */ + ao_delay_us(T4_TWI); + while(!(I2C_PIN & (1< + * + * 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; + LED_PORT &= ~enable; + LED_DDR |= enable; +} diff --git a/src/attiny/ao_spi_attiny.c b/src/attiny/ao_spi_attiny.c new file mode 100644 index 00000000..064876d7 --- /dev/null +++ b/src/attiny/ao_spi_attiny.c @@ -0,0 +1,123 @@ +/* + * 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 + +/* + * ATtiny USI as a SPI interface + */ + +/* + * Transfer one byte in/out of the USI interface + */ + +/* Three wire mode */ +#define SPI_USICR_WM ((0 << USIWM1) | (1 << USIWM0)) +#define SPI_USICR_CS ((1 << USICS1) | (0 << USICS0) | (1 << USICLK)) + +#define SPI_USICR_FAST_2 ((1 << USIWM0) | (1 << USITC)) +#define SPI_USICR_FAST_1 ((1 << USIWM0) | (1 << USITC) | (1 << USICLK)) + + +static uint8_t +ao_spi_transfer(uint8_t i) +{ + /* Load data register */ + USIDR = i; + +#if 1 + USISR = (1 << USIOIF); + do { + USICR = SPI_USICR_WM | SPI_USICR_CS | (1 << USITC); + } while ((USISR & (1 << USIOIF)) == 0); +#else + /* 8 clocks */ + USICR = SPI_USICR_FAST_1; + USICR = SPI_USICR_FAST_2; + + USICR = SPI_USICR_FAST_1; + USICR = SPI_USICR_FAST_2; + + USICR = SPI_USICR_FAST_1; + USICR = SPI_USICR_FAST_2; + + USICR = SPI_USICR_FAST_1; + USICR = SPI_USICR_FAST_2; + + USICR = SPI_USICR_FAST_1; + USICR = SPI_USICR_FAST_2; + + USICR = SPI_USICR_FAST_1; + USICR = SPI_USICR_FAST_2; + + USICR = SPI_USICR_FAST_1; + USICR = SPI_USICR_FAST_2; + + USICR = SPI_USICR_FAST_1; + USICR = SPI_USICR_FAST_2; +#endif + + /* Pull data from the port */ + return USIDR; +} + +/* 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_bus(void __xdata *block, uint16_t len) __reentrant +{ + uint8_t *d = block; + + while (len--) + ao_spi_transfer (*d++); +} + +/* Receive bytes over SPI. + * + * Poll, sending zeros and reading data back + */ +void +ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant +{ + uint8_t *d = block; + + while (len--) + *d++ = ao_spi_transfer (0xff); +} + +/* + * Initialize USI + * + * Chip select is the responsibility of the caller + */ + +void +ao_spi_init(void) +{ +#if 1 + USICR = (1 << USIWM0) | (1 << USICS1) | (1 << USICLK); +#else + USICR = SPI_USICR_FAST_2; +#endif + SPI_DIR &= ~(1 << DDB0); /* DI */ + SPI_DIR |= (1 << DDB1); /* DO */ + SPI_DIR |= (1 << DDB2); /* SCLK */ + SPI_DIR |= (1 << DDB3); /* CS */ +} -- cgit v1.2.3 From 767b74e1466ad4e31746340081d6d60e40359425 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Oct 2012 14:08:19 -0700 Subject: altos: Megametrum uses altitude-pa.h, not altitude.h Make sure megametrum gets rebuilt as needed when the various altitude-pa related files change Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index a93f6f17..0e0534a5 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -13,7 +13,7 @@ INC = \ ao_data.h \ ao_sample.h \ ao_pins.h \ - altitude.h \ + altitude-pa.h \ ao_kalman.h \ ao_product.h \ ao_ms5607.h \ @@ -99,7 +99,7 @@ all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc -../altitude.h: make-altitude +../altitude-pa.h: make-altitude-pa nickle $< > $@ $(OBJ): $(INC) -- cgit v1.2.3 From 9c732effeb2ef4a4d8bc9599febed74a6ec2f466 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Oct 2012 14:18:37 -0700 Subject: altos: Allow products to define which LED to panic with Continue to use AO_LED_RED by default. Signed-off-by: Keith Packard --- src/core/ao_panic.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index 52433044..3c0b471e 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -29,6 +29,10 @@ #define ao_led_off(x) #endif +#ifndef AO_LED_PANIC +#define AO_LED_PANIC AO_LED_RED +#endif + static void ao_panic_delay(uint8_t n) { @@ -52,10 +56,10 @@ ao_panic(uint8_t reason) __critical for (;;) { ao_panic_delay(20); for (n = 0; n < 5; n++) { - ao_led_on(AO_LED_RED); + ao_led_on(AO_LED_PANIC); ao_beep(AO_BEEP_HIGH); ao_panic_delay(1); - ao_led_off(AO_LED_RED); + ao_led_off(AO_LED_PANIC); ao_beep(AO_BEEP_LOW); ao_panic_delay(1); } @@ -66,18 +70,18 @@ ao_panic(uint8_t reason) #pragma disable_warning 126 #endif if (reason & 0x40) { - ao_led_on(AO_LED_RED); + ao_led_on(AO_LED_PANIC); ao_beep(AO_BEEP_HIGH); ao_panic_delay(40); - ao_led_off(AO_LED_RED); + ao_led_off(AO_LED_PANIC); ao_beep(AO_BEEP_OFF); ao_panic_delay(10); } for (n = 0; n < (reason & 0x3f); n++) { - ao_led_on(AO_LED_RED); + ao_led_on(AO_LED_PANIC); ao_beep(AO_BEEP_MID); ao_panic_delay(10); - ao_led_off(AO_LED_RED); + ao_led_off(AO_LED_PANIC); ao_beep(AO_BEEP_OFF); ao_panic_delay(10); } -- cgit v1.2.3 From b9bf8e01e243508297f28b102cb2477dc1bc74df Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Oct 2012 14:22:41 -0700 Subject: altos: Add initial micropeak implementation Blinks out max height in decimeters, stores previous flight data to internal eeprom. Signed-off-by: Keith Packard --- src/micropeak/Makefile | 105 +++++++++++++++++++++ src/micropeak/ao_async.c | 40 ++++++++ src/micropeak/ao_async.h | 24 +++++ src/micropeak/ao_log_micro.c | 73 +++++++++++++++ src/micropeak/ao_log_micro.h | 38 ++++++++ src/micropeak/ao_micropeak.c | 207 +++++++++++++++++++++++++++++++++++++++++ src/micropeak/ao_morse.c | 95 +++++++++++++++++++ src/micropeak/ao_notask.c | 45 +++++++++ src/micropeak/ao_pins.h | 60 ++++++++++++ src/micropeak/ao_report_tiny.c | 57 ++++++++++++ 10 files changed, 744 insertions(+) create mode 100644 src/micropeak/Makefile create mode 100644 src/micropeak/ao_async.c create mode 100644 src/micropeak/ao_async.h create mode 100644 src/micropeak/ao_log_micro.c create mode 100644 src/micropeak/ao_log_micro.h create mode 100644 src/micropeak/ao_micropeak.c create mode 100644 src/micropeak/ao_morse.c create mode 100644 src/micropeak/ao_notask.c create mode 100644 src/micropeak/ao_pins.h create mode 100644 src/micropeak/ao_report_tiny.c (limited to 'src') diff --git a/src/micropeak/Makefile b/src/micropeak/Makefile new file mode 100644 index 00000000..e0b2b80d --- /dev/null +++ b/src/micropeak/Makefile @@ -0,0 +1,105 @@ +# +# Tiny AltOS build +# +# +vpath % ../attiny:../drivers:../core:.. +vpath ao-make-product.5c ../util +vpath make-altitude-pa ../util + +MCU=attiny85 +DUDECPUTYPE=t85 +#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 + +ALTOS_SRC = \ + ao_micropeak.c \ + ao_spi_attiny.c \ + ao_led.c \ + ao_clock.c \ + ao_ms5607.c \ + ao_exti.c \ + ao_convert_pa.c \ + ao_i2c_attiny.c \ + ao_at24c.c \ + ao_report_tiny.c \ + ao_async.c \ + ao_notask.c \ + ao_eeprom_tiny.c \ + ao_panic.c + +INC=\ + ao.h \ + ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_exti.h \ + ao_ms5607.h \ + altitude-pa.h + +IDPRODUCT=0 +PRODUCT=MicroPeak-v0.1 +PRODUCT_DEF=-DMICROPEAK +CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../core -I.. -I../drivers +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DATTINY + +NICKLE=nickle + +PROG=micropeak-v0.1 + +SRC=$(ALTOS_SRC) +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).hex + +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 + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.o: ao_product.c ao_product.h + +%.o : %.c $(INC) + $(call quiet,CC) -c $(CFLAGS) $< + +distclean: clean + +clean: + rm -f *.o $(PROG) $(PROG).hex + rm -f ao_product.h + +../altitude-pa.h: make-altitude-pa + nickle $< > $@ + +install: + +uninstall: + +$(OBJ): ao_product.h $(INC) diff --git a/src/micropeak/ao_async.c b/src/micropeak/ao_async.c new file mode 100644 index 00000000..04bba9e8 --- /dev/null +++ b/src/micropeak/ao_async.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. + */ + +#include +#include + +#define AO_ASYNC_BAUD 38400l +#define AO_ASYNC_DELAY (uint8_t) (1000000l / AO_ASYNC_BAUD) + +void +ao_async_byte(uint8_t byte) +{ + uint8_t b; + uint16_t w; + + /* start bit */ + + /* start data stop */ + w = 0x001 | (byte << 1) | 0x000; + + for (b = 0; b < 10; b++) { + ao_led_set((w & 1) << AO_LED_SERIAL); + w >>= 1; + ao_delay_us(26); + } +} diff --git a/src/micropeak/ao_async.h b/src/micropeak/ao_async.h new file mode 100644 index 00000000..a06d2e1a --- /dev/null +++ b/src/micropeak/ao_async.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_ASYNC_H_ +#define _AO_ASYNC_H_ + +void +ao_async_byte(uint8_t byte); + +#endif /* _AO_ASYNC_H_ */ diff --git a/src/micropeak/ao_log_micro.c b/src/micropeak/ao_log_micro.c new file mode 100644 index 00000000..eda0d1d2 --- /dev/null +++ b/src/micropeak/ao_log_micro.c @@ -0,0 +1,73 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +#if HAS_EEPROM + +ao_pos_t ao_log_micro_pos; + +void +ao_log_micro_data(uint32_t data) +{ + ao_storage_write(ao_log_micro_pos, &data, sizeof (data)); + ao_log_micro_pos += sizeof (data); +} + +uint32_t ao_log_last_ground; +uint32_t ao_log_last_done; + +uint8_t +ao_log_micro_scan(void) +{ + uint32_t data; + ao_pos_t pos; + + ao_storage_read(0, &data, sizeof (data)); + if ((data & AO_LOG_MICRO_MASK) != AO_LOG_MICRO_GROUND) + return 0; + + ao_log_last_ground = data & ~(AO_LOG_MICRO_MASK); + for (pos = 4; pos < ao_storage_total; pos += 4) { + ao_storage_read(pos, &data, sizeof (data)); + if ((data & AO_LOG_MICRO_MASK) == AO_LOG_MICRO_GROUND) { + ao_log_last_done = data & ~(AO_LOG_MICRO_MASK); + return 1; + } + } + return 0; +} + +void +ao_log_micro_dump(void) +{ + ao_pos_t pos; + uint8_t data[4]; + uint8_t i; + + for (pos = 0; pos < ao_storage_total; pos += 4) { + ao_storage_read(pos, data, 4); + for (i = 0; i < 4; i++) + ao_async_byte(data[i]); + if (data[3] == (uint8_t) (AO_LOG_MICRO_GROUND >> 24)) + break; + } +} + +#endif diff --git a/src/micropeak/ao_log_micro.h b/src/micropeak/ao_log_micro.h new file mode 100644 index 00000000..15b2d178 --- /dev/null +++ b/src/micropeak/ao_log_micro.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_LOG_MICRO_H_ +#define _AO_LOG_MICRO_H_ + +#define AO_LOG_MICRO_GROUND (0l << 24) +#define AO_LOG_MICRO_DATA (1l << 24) +#define AO_LOG_MICRO_DONE (0xaal << 24) +#define AO_LOG_MICRO_MASK (0xffl << 24) + +void +ao_log_micro_data(uint32_t data); + +extern uint32_t ao_log_last_ground; +extern uint32_t ao_log_last_done; + +uint8_t +ao_log_micro_scan(void); + +void +ao_log_micro_dump(void); + +#endif /* _AO_LOG_MICRO_H_ */ diff --git a/src/micropeak/ao_micropeak.c b/src/micropeak/ao_micropeak.c new file mode 100644 index 00000000..6ceec3b5 --- /dev/null +++ b/src/micropeak/ao_micropeak.c @@ -0,0 +1,207 @@ +/* + * 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 struct ao_ms5607_sample sample; +static struct ao_ms5607_value value; + +static uint32_t pa; +static uint32_t pa_sum; +static uint32_t pa_avg; +static int32_t pa_diff; +static uint32_t pa_ground; +static uint32_t pa_min; +static uint32_t pa_interval_min, pa_interval_max; +static alt_t ground_alt, max_alt; +alt_t ao_max_height; + +static void +ao_pa_get(void) +{ + ao_ms5607_sample(&sample); + ao_ms5607_convert(&sample, &value); + pa = value.pres; +} + +#define FILTER_SHIFT 3 +#define SAMPLE_SLEEP AO_MS_TO_TICKS(96) + +/* 16 sample, or about two seconds worth */ +#define GROUND_AVG_SHIFT 4 +#define GROUND_AVG (1 << GROUND_AVG_SHIFT) + +static void +ao_compute_height(void) +{ + ground_alt = ao_pa_to_altitude(pa_ground); + max_alt = ao_pa_to_altitude(pa_min); + ao_max_height = max_alt - ground_alt; +} + +#if !HAS_EEPROM +void +ao_save_flight(void) +{ + ao_eeprom_write(0, &pa_ground, sizeof (pa_ground)); + ao_eeprom_write(sizeof (pa_ground), &pa_min, sizeof (pa_min)); +} + +void +ao_restore_flight(void) +{ + ao_eeprom_read(0, &pa_ground, sizeof (pa_ground)); + ao_eeprom_read(sizeof (pa_ground), &pa_min, sizeof (pa_min)); +} +#endif + +int +main(void) +{ + int16_t sample_count; + uint16_t time; +#if HAS_EEPROM + uint8_t dump_eeprom = 0; +#endif + ao_led_init(LEDS_AVAILABLE); + ao_timer_init(); + +#if HAS_EEPROM + + /* Set MOSI and CLK as inputs with pull-ups */ + DDRB &= ~(1 << 0) | (1 << 2); + PORTB |= (1 << 0) | (1 << 2); + + /* Check to see if either MOSI or CLK are pulled low by the + * user shorting them to ground. If so, dump the eeprom out + * via the LED. Wait for the shorting wire to go away before + * continuing. + */ + while ((PINB & ((1 << 0) | (1 << 2))) != ((1 << 0) | (1 << 2))) + dump_eeprom = 1; + PORTB &= ~(1 << 0) | (1 << 2); + + ao_i2c_init(); +#endif + ao_restore_flight(); + ao_compute_height(); + ao_report_altitude(); + + ao_spi_init(); + ao_ms5607_init(); + ao_ms5607_setup(); + +#if HAS_EEPROM + ao_storage_init(); + + /* Check to see if there's a flight recorded in memory */ + if (dump_eeprom && ao_log_micro_scan()) + ao_log_micro_dump(); +#endif + + /* Wait for motion, averaging values to get ground pressure */ + time = ao_time(); + ao_pa_get(); + pa_avg = pa_ground = pa << FILTER_SHIFT; + sample_count = 0; + for (;;) { + time += SAMPLE_SLEEP; + ao_delay_until(time); + if (sample_count == 0) + ao_led_on(AO_LED_BLUE); + ao_pa_get(); + if (sample_count == 0) + ao_led_off(AO_LED_BLUE); + pa_avg = pa_avg - (pa_avg >> FILTER_SHIFT) + pa; + pa_diff = pa_ground - pa_avg; + if (pa_diff < 0) + pa_diff = -pa_diff; + + /* about 2 meters at sea level, more if you're higher */ + if (pa_diff > (24 << FILTER_SHIFT)) + break; + + if (sample_count < GROUND_AVG * 2) { + ao_led_off(AO_LED_BLUE); + if (sample_count < GROUND_AVG) + pa_sum += pa; + ++sample_count; + } else { + pa_ground = pa_sum >> (GROUND_AVG_SHIFT - FILTER_SHIFT); + pa_sum = 0; + sample_count = 0; + } + } + + pa_ground >>= FILTER_SHIFT; + +#if HAS_EEPROM + ao_log_micro_data(AO_LOG_MICRO_GROUND | pa_ground); +#endif + + /* Now sit around until the pressure is stable again and record the max */ + + sample_count = 0; + pa_min = pa_avg; + pa_interval_min = pa_avg; + pa_interval_max = pa_avg; + for (;;) { + time += SAMPLE_SLEEP; + ao_delay_until(time); + if ((sample_count & 3) == 0) + ao_led_on(AO_LED_BLUE); + ao_pa_get(); + if ((sample_count & 3) == 0) + ao_led_off(AO_LED_BLUE); +#if HAS_EEPROM + ao_log_micro_data(AO_LOG_MICRO_DATA | pa); +#endif + pa_avg = pa_avg - (pa_avg >> FILTER_SHIFT) + pa; + if (pa_avg < pa_min) + pa_min = pa_avg; + + if (sample_count == (GROUND_AVG - 1)) { + pa_diff = pa_interval_max - pa_interval_min; + /* About 1m at sea level */ + if (pa_diff < (12 << FILTER_SHIFT)) + break; + sample_count = 0; + pa_interval_min = pa_avg; + pa_interval_max = pa_avg; + } else { + if (pa_avg < pa_interval_min) + pa_interval_min = pa_avg; + if (pa_avg > pa_interval_max) + pa_interval_max = pa_avg; + ++sample_count; + } + } + pa_min >>= FILTER_SHIFT; +#if HAS_EEPROM + ao_log_micro_data(AO_LOG_MICRO_DONE | pa_min); +#endif + ao_save_flight(); + ao_compute_height(); + ao_report_altitude(); + for (;;) { + cli(); + set_sleep_mode(SLEEP_MODE_PWR_DOWN); + sleep_mode(); + } +} diff --git a/src/micropeak/ao_morse.c b/src/micropeak/ao_morse.c new file mode 100644 index 00000000..9a7f88e5 --- /dev/null +++ b/src/micropeak/ao_morse.c @@ -0,0 +1,95 @@ +static void +pause(uint8_t j) +{ + int64_t i; + + while (j--) { + for (i = 0; i < 2000; i++) + ao_arch_nop(); + } +} + +#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)) + +#define ___ 1 +#define _ 0 + +static const uint8_t morse[26] = { + MORSE2(0,1), /* A */ + MORSE4(1,0,0,0), /* B */ + MORSE4(1,0,1,0), /* C */ + MORSE3(1,0,0), /* D */ + MORSE1(0), /* E */ + MORSE4(0,0,1,0), /* F */ + MORSE3(1,1,0), /* G */ + MORSE4(0,0,0,0), /* H */ + MORSE2(0,0), /* I */ + MORSE4(0,1,1,1), /* J */ + MORSE3(1,0,1), /* K */ + MORSE4(0,1,0,0), /* L */ + MORSE2(1,1), /* M */ + MORSE2(1,1), /* N */ + MORSE3(1,1,1), /* O */ + MORSE4(0,1,1,0), /* P */ + MORSE4(1,1,0,1), /* Q */ + MORSE3(0,1,0), /* R */ + MORSE3(0,0,0), /* S */ + MORSE1(1), /* T */ + MORSE3(0,0,1), /* U */ + MORSE4(0,0,0,1), /* V */ + MORSE3(0,1,1), /* W */ + MORSE4(1,0,0,1), /* X */ + MORSE4(1,0,1,1), /* Y */ + MORSE4(1,1,0,0), /* Z */ +}; + +static void +on(void) +{ + PORTB |= (1 << 4); +} + +static void +off(void) +{ + PORTB &= ~(1 << 4); +} + +static void +morse_char (char c) +{ + uint8_t r = morse[c - 'a']; + uint8_t l = r & 7; + + if (!r) + return; + while (l--) { + on(); + if (r & 8) + pause(3); + else + pause(1); + off(); + pause(1); + r >>= 1; + } + pause(2); +} + +static void +morse_string(char *s) { + char c; + + while ((c = *s++)) { + if (c == ' ') + pause(5); + else + morse_char(c); + } +} + diff --git a/src/micropeak/ao_notask.c b/src/micropeak/ao_notask.c new file mode 100644 index 00000000..0aef9cf3 --- /dev/null +++ b/src/micropeak/ao_notask.c @@ -0,0 +1,45 @@ +/* + * 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 + +static volatile void *ao_wchan; + +uint8_t +ao_sleep(__xdata void *wchan) +{ +#if 1 + ao_wchan = wchan; + ao_arch_cpu_idle(); +#else + uint8_t sreg; + + ao_wchan = wchan; + asm("in %0,__SREG__" : "=&r" (sreg)); + sei(); + while (ao_wchan) + ao_arch_cpu_idle(); + asm("out __SREG__,%0" : : "r" (sreg)); +#endif + return 0; +} + +void +ao_wakeup(__xdata void *wchan) +{ + ao_wchan = 0; +} diff --git a/src/micropeak/ao_pins.h b/src/micropeak/ao_pins.h new file mode 100644 index 00000000..de9fc7f2 --- /dev/null +++ b/src/micropeak/ao_pins.h @@ -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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ +#include + +#define AO_LED_BLUE (1<<4) +#define AO_LED_SERIAL 4 +#define AO_LED_PANIC AO_LED_BLUE +#define LEDS_AVAILABLE (AO_LED_BLUE) +#define USE_SERIAL_1_STDIN 0 +#define HAS_USB 0 +#define PACKET_HAS_SLAVE 0 +#define HAS_SERIAL_1 0 +#define HAS_TASK 0 +#define HAS_MS5607 1 +#define HAS_MS5611 1 +#define HAS_EEPROM 0 +#define HAS_BEEP 0 +#define AVR_CLOCK 8000000UL + +/* SPI */ +#define SPI_PORT PORTB +#define SPI_PIN PINB +#define SPI_DIR DDRB +#define AO_MS5607_CS_PORT PORTB +#define AO_MS5607_CS_PIN 3 + +#define AO_MS5607_SPI_INDEX 0 +#define AO_MS5607_MISO_PORT PORTB +#define AO_MS5607_MISO_PIN 0 + +/* I2C */ +#define I2C_PORT PORTB +#define I2C_PIN PINB +#define I2C_DIR DDRB +#define I2C_PIN_SCL PINB2 +#define I2C_PIN_SDA PINB0 + +#define AO_CONST_ATTRIB PROGMEM +#define FETCH_ALT(o) ((alt_t) pgm_read_dword(&altitude_table[o])) + +#define AO_ALT_VALUE(x) ((x) * 10) + +#endif /* _AO_PINS_H_ */ diff --git a/src/micropeak/ao_report_tiny.c b/src/micropeak/ao_report_tiny.c new file mode 100644 index 00000000..5937508b --- /dev/null +++ b/src/micropeak/ao_report_tiny.c @@ -0,0 +1,57 @@ +/* + * 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 mid(time) ao_led_for(AO_LED_BLUE, time) +#define pause(time) ao_delay(time) + +static void +ao_report_digit(uint8_t digit) __reentrant +{ + if (!digit) { + mid(AO_MS_TO_TICKS(600)); + 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)); +} + +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); + + i = ndigits; + do + ao_report_digit(digits[--i]); + while (i != 0); +} -- cgit v1.2.3 From 6cfb2d3b1c75916ee69d069519edc675e37e1aa1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Oct 2012 14:26:08 -0700 Subject: altos: Add (untested) driver for AT24C i2c flash parts Signed-off-by: Keith Packard --- src/drivers/ao_at24c.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/drivers/ao_at24c.c (limited to 'src') diff --git a/src/drivers/ao_at24c.c b/src/drivers/ao_at24c.c new file mode 100644 index 00000000..2a23be3a --- /dev/null +++ b/src/drivers/ao_at24c.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 + +#if HAS_EEPROM +#define AO_AT24C_ADDR 0xa0 +#define AO_AT24C_ADDR_WRITE (AO_AT24C_ADDR|0) +#define AO_AT24C_ADDR_READ (AO_AT24C_ADDR|1) +#define AO_AT24C_PAGE_LEN 128 + +/* Total bytes of available storage */ +__pdata ao_pos_t ao_storage_total = 64l * 1024l; + +/* Storage unit size - device reads and writes must be within blocks of this size. */ +__pdata uint16_t ao_storage_unit = 128; + +static void +ao_at24c_set_address(uint8_t addr, ao_pos_t pos) +{ + uint8_t a[2]; + + a[0] = pos >> 8; + a[1] = pos; + ao_i2c_start_bus(addr); + ao_i2c_send_bus(a, 2, 0); +} + +/* + * Erase the specified sector + */ +uint8_t +ao_storage_erase(ao_pos_t pos) __reentrant +{ + if (pos >= ao_storage_total || pos + AO_AT24C_PAGE_LEN > ao_storage_total) + return 0; + + ao_mutex_get(&ao_at24c_mutex); + ao_at24c_set_address(AO_AT24C_ADDR_WRITE, pos); + ao_i2c_send_fixed_bus(0xff, AO_AT24C_PAGE_LEN, 1); + ao_mutex_put(&ao_at24c_mutex); + return 1; +} + +/* + * Write to flash + */ +uint8_t +ao_storage_device_write(ao_pos_t pos, __xdata void *d, uint16_t len) __reentrant +{ + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + + ao_mutex_get(&ao_m25_mutex); + ao_at24c_set_address(AO_AT24C_ADDR_WRITE, pos); + ao_i2c_send_bus(d, len, 1); + ao_mutex_put(&ao_m25_mutex); + return 1; +} + +/* + * Read from flash + */ +uint8_t +ao_storage_device_read(ao_pos_t pos, __xdata void *d, uint16_t len) __reentrant +{ + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + ao_mutex_get(&ao_m25_mutex); + ao_at24c_set_address(AO_AT24C_ADDR_READ, pos); + ao_i2c_recv_bus(d, len, 1); + ao_mutex_put(&ao_m25_mutex); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ +} + +void +ao_storage_device_init(void) +{ +} +#endif -- cgit v1.2.3 From 162a21dc423c2883a54f7d2a154871ae714d1552 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Oct 2012 14:27:14 -0700 Subject: altos: Add .gitignore for micropeak Signed-off-by: Keith Packard --- src/micropeak/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/micropeak/.gitignore (limited to 'src') diff --git a/src/micropeak/.gitignore b/src/micropeak/.gitignore new file mode 100644 index 00000000..91468368 --- /dev/null +++ b/src/micropeak/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +micropeak-* -- cgit v1.2.3 From eea1c8da986f9dbd0ca58c926a2bbe01721c1bda Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Oct 2012 13:33:45 -0700 Subject: altos: Document a few member offsets in struct ao_log_record Incomplete, but useful even so Signed-off-by: Keith Packard --- src/core/ao_log.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/core/ao_log.h b/src/core/ao_log.h index 04abeb7e..30ef03f2 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -138,17 +138,17 @@ ao_log_full(void); #define AO_LOG_POS_NONE (~0UL) struct ao_log_record { - char type; - uint8_t csum; - uint16_t tick; + char type; /* 0 */ + uint8_t csum; /* 1 */ + uint16_t tick; /* 2 */ union { struct { - int16_t ground_accel; - uint16_t flight; + int16_t ground_accel; /* 4 */ + uint16_t flight; /* 6 */ } flight; struct { - int16_t accel; - int16_t pres; + int16_t accel; /* 4 */ + int16_t pres; /* 6 */ } sensor; struct { int16_t temp; -- cgit v1.2.3 From 46abd248fb2eb84f161672ffce121b2203d42be0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Oct 2012 13:34:28 -0700 Subject: altos: struct ao_log_mega doesn't have a ground temp value There's no averaged ground temperature recorded in the flight system to save there, so just remove the field Signed-off-by: Keith Packard --- src/core/ao_log.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/ao_log.h b/src/core/ao_log.h index 30ef03f2..eaaca444 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -201,8 +201,7 @@ struct ao_log_mega { uint16_t flight; /* 4 */ int16_t ground_accel; /* 6 */ uint32_t ground_pres; /* 8 */ - uint32_t ground_temp; /* 12 */ - } flight; /* 16 */ + } flight; /* 12 */ struct { uint16_t state; uint16_t reason; -- cgit v1.2.3 From 2733d1b71bbac2c5ef4a2c3a1992ba448e981267 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Oct 2012 13:35:42 -0700 Subject: altos: Split out ms5607 conversion code for use in ao_flight_test Makes the conversion code available even where the driver isn't needed Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.c | 40 +--------------------------- src/drivers/ao_ms5607_convert.c | 58 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 39 deletions(-) create mode 100644 src/drivers/ao_ms5607_convert.c (limited to 'src') diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 1e69cccb..fdd2c31e 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -167,45 +167,7 @@ ao_ms5607_sample(struct ao_ms5607_sample *sample) 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) -{ - int32_t dT; - int32_t TEMP; - int64_t OFF; - int64_t SENS; - - dT = sample->temp - ((int32_t) ms5607_prom.tref << 8); - - TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23); - -#if HAS_MS5611 - OFF = ((int64_t) ms5607_prom.off << 16) + (((int64_t) ms5607_prom.tco * dT) >> 7); - SENS = ((int64_t) ms5607_prom.sens << 15) + (((int64_t) ms5607_prom.tcs * dT) >> 8); -#else - 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); -#endif - - 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; - if (TEMP < 1500) { - int32_t TEMPP = TEMP + 1500; - int64_t TEMPP2 = TEMPP * TEMPP; - OFF2 = OFF2 + 15 * TEMPP2; - SENS2 = SENS2 + 8 * TEMPP2; - } - TEMP -= T2; - OFF -= OFF2; - SENS -= SENS2; - } - - value->pres = ((((int64_t) sample->pres * SENS) >> 21) - OFF) >> 15; - value->temp = TEMP; -} +#include "ao_ms5607_convert.c" #if HAS_TASK static void diff --git a/src/drivers/ao_ms5607_convert.c b/src/drivers/ao_ms5607_convert.c new file mode 100644 index 00000000..e61d19ed --- /dev/null +++ b/src/drivers/ao_ms5607_convert.c @@ -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. + */ + +#include + +void +ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value) +{ + int32_t dT; + int32_t TEMP; + int64_t OFF; + int64_t SENS; + + dT = sample->temp - ((int32_t) ms5607_prom.tref << 8); + + TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23); + +#if HAS_MS5611 + OFF = ((int64_t) ms5607_prom.off << 16) + (((int64_t) ms5607_prom.tco * dT) >> 7); + SENS = ((int64_t) ms5607_prom.sens << 15) + (((int64_t) ms5607_prom.tcs * dT) >> 8); +#else + 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); +#endif + + 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; + if (TEMP < 1500) { + int32_t TEMPP = TEMP + 1500; + int64_t TEMPP2 = TEMPP * TEMPP; + OFF2 = OFF2 + 15 * TEMPP2; + SENS2 = SENS2 + 8 * TEMPP2; + } + TEMP -= T2; + OFF -= OFF2; + SENS -= SENS2; + } + + value->pres = ((((int64_t) sample->pres * SENS) >> 21) - OFF) >> 15; + value->temp = TEMP; +} -- cgit v1.2.3 From 0ec77f5c90e0b930488ae2ab75efcbba8a3bd1d8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Oct 2012 13:37:29 -0700 Subject: altos: Eliminate implicit 1 byte offset in uint16/int16 functions Make callers explicitly compute the full offset Signed-off-by: Keith Packard --- src/test/ao_flight_test.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index b9e291ce..3231194d 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -469,7 +469,6 @@ union ao_telemetry_all { uint16_t uint16(uint8_t *bytes, int off) { - off++; return (uint16_t) bytes[off] | (((uint16_t) bytes[off+1]) << 8); } @@ -608,22 +607,22 @@ ao_sleep(void *wchan) } } else if (len == 99) { ao_flight_started = 1; - tick = uint16(bytes, 21); - ao_flight_ground_accel = int16(bytes, 7); - ao_config.accel_plus_g = int16(bytes, 17); - ao_config.accel_minus_g = int16(bytes, 19); + tick = uint16(bytes+1, 21); + ao_flight_ground_accel = int16(bytes+1, 7); + ao_config.accel_plus_g = int16(bytes+1, 17); + ao_config.accel_minus_g = int16(bytes+1, 19); type = 'A'; - a = int16(bytes, 23); - b = int16(bytes, 25); + a = int16(bytes+1, 23); + b = int16(bytes+1, 25); } else if (len == 98) { ao_flight_started = 1; - tick = uint16(bytes, 20); - ao_flight_ground_accel = int16(bytes, 6); - ao_config.accel_plus_g = int16(bytes, 16); - ao_config.accel_minus_g = int16(bytes, 18); + tick = uint16(bytes+1, 20); + ao_flight_ground_accel = int16(bytes+1, 6); + ao_config.accel_plus_g = int16(bytes+1, 16); + ao_config.accel_minus_g = int16(bytes+1, 18); type = 'A'; - a = int16(bytes, 22); - b = int16(bytes, 24); + a = int16(bytes+1, 22); + b = int16(bytes+1, 24); } else { printf("unknown len %d\n", len); continue; -- cgit v1.2.3 From 321d0f68c04a5a9c6ea7874081e6245d44c48bb4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Oct 2012 13:39:03 -0700 Subject: altos/test: Add ao_flight_test_mm This reads mega metrum eeprom files and runs the flight code over it Signed-off-by: Keith Packard --- src/test/Makefile | 10 +++- src/test/ao_flight_test.c | 149 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 132 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/test/Makefile b/src/test/Makefile index db3cc04b..37949e86 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,10 +1,11 @@ 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_test +PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_flight_test_mm \ + ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test ao_fec_test KALMAN=make-kalman -CFLAGS=-I.. -I. -I../core -I../drivers -O3 -g -Wall +CFLAGS=-I.. -I. -I../core -I../drivers -O0 -g -Wall all: $(PROGS) @@ -16,7 +17,7 @@ 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 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.c ao_sample.c ao_kalman.c altitude-pa.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 @@ -25,6 +26,9 @@ ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalm ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc $(CFLAGS) -o $@ -DFORCE_ACCEL=1 ao_flight_test.c +ao_flight_test_mm: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h + cc -DMEGAMETRUM=1 $(CFLAGS) -o $@ $< + ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h cc $(CFLAGS) -o $@ $< diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 3231194d..6c0bb4da 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -35,6 +35,21 @@ #define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) #define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) +#if MEGAMETRUM +#define AO_ADC_NUM_SENSE 6 +#define HAS_MS5607 1 +#define HAS_MPU6000 1 +#define HAS_MMA655X 0 + +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; +}; +#else /* * One set of samples read from the A/D converter */ @@ -48,6 +63,13 @@ struct ao_adc { int16_t sense_m; /* main continuity sense */ }; +#ifndef HAS_ACCEL +#define HAS_ACCEL 1 +#define HAS_ACCEL_REF 0 +#endif + +#endif + #define __pdata #define __data #define __xdata @@ -58,12 +80,9 @@ struct ao_adc { #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 +#include #define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) #define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) @@ -72,7 +91,6 @@ struct ao_adc { /* * Above this height, the baro sensor doesn't work */ -#define AO_MAX_BARO_HEIGHT 12000 #define AO_BARO_SATURATE 13000 #define AO_MIN_BARO_VALUE ao_altitude_to_pres(AO_BARO_SATURATE) @@ -83,19 +101,6 @@ struct ao_adc { #define ACCEL_NOSE_UP (ao_accel_2g >> 2) -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 enum ao_flight_state ao_flight_state; #define FALSE 0 @@ -190,7 +195,14 @@ struct ao_cmds { #define ao_xmemcmp(d,s,c) memcmp(d,s,c) #define AO_NEED_ALTITUDE_TO_PRES 1 +#if MEGAMETRUM +#include "ao_convert_pa.c" +#include +struct ao_ms5607_prom ms5607_prom; +#include "ao_ms5607_convert.c" +#else #include "ao_convert.c" +#endif struct ao_config { uint16_t main_deploy; @@ -218,11 +230,11 @@ typedef int16_t accel_t; extern uint16_t ao_sample_tick; -extern int16_t ao_sample_height; +extern alt_t ao_sample_height; extern accel_t ao_sample_accel; extern int32_t ao_accel_scale; -extern int16_t ao_ground_height; -extern int16_t ao_sample_alt; +extern alt_t ao_ground_height; +extern alt_t ao_sample_alt; int ao_sample_prev_tick; uint16_t prev_tick; @@ -293,9 +305,20 @@ ao_insert(void) 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_data_static.adc.pres_real) - ao_ground_height; - double accel = ((ao_flight_ground_accel - ao_data_static.adc.accel) * GRAVITY * 2.0) / +#if HAS_ACCEL + double accel = ((ao_flight_ground_accel - ao_data_accel_cook(&ao_data_static)) * GRAVITY * 2.0) / (ao_config.accel_minus_g - ao_config.accel_plus_g); +#else + double accel = 0.0; +#endif +#if MEGAMETRUM + double height; + + ao_ms5607_convert(&ao_data_static.ms5607_raw, &ao_data_static.ms5607_cooked); + height = ao_pa_to_altitude(ao_data_static.ms5607_cooked.pres) - ao_ground_height; +#else + double height = ao_pres_to_altitude(ao_data_static.adc.pres_real) - ao_ground_height; +#endif if (!tick_offset) tick_offset = -ao_data_static.tick; @@ -478,6 +501,22 @@ int16(uint8_t *bytes, int off) return (int16_t) uint16(bytes, off); } +uint32_t +uint32(uint8_t *bytes, int off) +{ + return (uint32_t) bytes[off] | (((uint32_t) bytes[off+1]) << 8) | + (((uint32_t) bytes[off+2]) << 16) | + (((uint32_t) bytes[off+3]) << 24); +} + +int32_t +int32(uint8_t *bytes, int off) +{ + return (int32_t) uint32(bytes, off); +} + +static int log_format; + void ao_sleep(void *wchan) { @@ -496,7 +535,10 @@ ao_sleep(void *wchan) for (;;) { if (ao_records_read > 2 && ao_flight_state == ao_flight_startup) { +#if MEGAMETRUM +#else ao_data_static.adc.accel = ao_flight_ground_accel; +#endif ao_insert(); return; } @@ -518,13 +560,69 @@ ao_sleep(void *wchan) if (words[nword] == NULL) break; } - if (nword == 4) { +#if MEGAMETRUM + if (log_format == AO_LOG_FORMAT_MEGAMETRUM && nword == 30 && strlen(words[0]) == 1) { + int i; + struct ao_ms5607_value value; + + type = words[0][0]; + tick = strtoul(words[1], NULL, 16); +// printf ("%c %04x", type, tick); + for (i = 2; i < nword; i++) { + bytes[i - 2] = strtoul(words[i], NULL, 16); +// printf(" %02x", bytes[i-2]); + } +// printf ("\n"); + switch (type) { + case 'F': + ao_flight_ground_accel = int16(bytes, 2); + ao_flight_started = 1; + ao_ground_pres = int32(bytes, 4); + ao_ground_height = ao_pa_to_altitude(ao_ground_pres); + break; + case 'A': + ao_data_static.tick = tick; + ao_data_static.ms5607_raw.pres = int32(bytes, 0); + ao_data_static.ms5607_raw.temp = int32(bytes, 4); + ao_ms5607_convert(&ao_data_static.ms5607_raw, &value); + ao_data_set_accel(&ao_data_static, -int16(bytes, 10)); +// printf ("accel %d pres %d\n", ao_data_accel_cook(&ao_data_static), value.pres); + ao_records_read++; + ao_insert(); + return; + } + continue; + } else if (nword == 3 && strcmp(words[0], "ms5607") == 0) { + if (strcmp(words[1], "reserved:") == 0) + ms5607_prom.reserved = strtoul(words[2], NULL, 10); + else if (strcmp(words[1], "sens:") == 0) + ms5607_prom.sens = strtoul(words[2], NULL, 10); + else if (strcmp(words[1], "off:") == 0) + ms5607_prom.off = strtoul(words[2], NULL, 10); + else if (strcmp(words[1], "tcs:") == 0) + ms5607_prom.tcs = strtoul(words[2], NULL, 10); + else if (strcmp(words[1], "tco:") == 0) + ms5607_prom.tco = strtoul(words[2], NULL, 10); + else if (strcmp(words[1], "tref:") == 0) + ms5607_prom.tref = strtoul(words[2], NULL, 10); + else if (strcmp(words[1], "tempsens:") == 0) + ms5607_prom.tempsens = strtoul(words[2], NULL, 10); + else if (strcmp(words[1], "crc:") == 0) + ms5607_prom.crc = strtoul(words[2], NULL, 10); + continue; + } +#else + if (nword == 4 && log_format != AO_LOG_FORMAT_MEGAMETRUM) { type = words[0][0]; tick = strtoul(words[1], NULL, 16); a = strtoul(words[2], NULL, 16); b = strtoul(words[3], NULL, 16); if (type == 'P') type = 'A'; + } +#endif + else if (nword == 2 && strcmp(words[0], "log-format") == 0) { + log_format = strtoul(words[1], NULL, 10); } else if (nword >= 6 && strcmp(words[0], "Accel") == 0) { ao_config.accel_plus_g = atoi(words[3]); ao_config.accel_minus_g = atoi(words[5]); @@ -631,6 +729,8 @@ ao_sleep(void *wchan) if (type != 'F' && !ao_flight_started) continue; +#if MEGAMETRUM +#else switch (type) { case 'F': ao_flight_ground_accel = a; @@ -666,6 +766,7 @@ ao_sleep(void *wchan) case 'H': break; } +#endif } } -- cgit v1.2.3 From 5caf56e89678637c1afa79700a2fa09aa67dea9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Oct 2012 15:02:42 -0700 Subject: altos: When missing MMA655x, create fake Z accel value This avoids overwriting the MPU6000 y acceleration value so that other computations using that value can work unmodified. Signed-off-by: Keith Packard --- src/core/ao_data.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 1153d433..86acd48f 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -67,6 +67,9 @@ struct ao_data { #endif #if HAS_MPU6000 struct ao_mpu6000_sample mpu6000; +#if !HAS_MMA655X + int16_t z_accel; +#endif #endif #if HAS_HMC5883 struct ao_hmc5883_sample hmc5883; @@ -285,9 +288,9 @@ typedef int16_t accel_t; 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(packet) ((packet)->z_accel) #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_set_accel(packet, accel) ((packet)->z_accel = (accel)) #define ao_data_accel_invert(a) (-(a)) #endif -- cgit v1.2.3 From c6eec0bec06d2e246ea3c9552818ad3180c1e318 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Oct 2012 15:04:00 -0700 Subject: altos: Define full-scale gyro and accel values for MPU6000 This lets other code convert MPU6000 readings into canonical units Signed-off-by: Keith Packard --- src/drivers/ao_mpu6000.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h index ca76b081..5c0cee1b 100644 --- a/src/drivers/ao_mpu6000.h +++ b/src/drivers/ao_mpu6000.h @@ -145,6 +145,9 @@ /* Self test gyro is approximately 50°/s */ #define MPU6000_ST_GYRO(full_scale) ((int16_t) (((int32_t) 32767 * (int32_t) 50) / (full_scale))) +#define MPU6000_GYRO_FULLSCALE 2000 +#define MPU6000_ACCEL_FULLSCALE 16 + struct ao_mpu6000_sample { int16_t accel_x; int16_t accel_y; -- cgit v1.2.3 From 91b8c8b20cead2836ec835f44b4ca0cf06cbf518 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Oct 2012 15:04:46 -0700 Subject: altos/test: Display MPU6000 values in ao_flight_test_mm output No computation yet, just making the values visible in the output Signed-off-by: Keith Packard --- src/test/Makefile | 12 ++++++----- src/test/ao_flight_test.c | 52 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/test/Makefile b/src/test/Makefile index 37949e86..44cee904 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -3,6 +3,8 @@ vpath % ..:../core:../drivers:../util PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_flight_test_mm \ ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test ao_fec_test +INCS=ao_kalman.h ao_ms5607.h ao_log.h ao_data.h altitude-pa.h altitude.h + KALMAN=make-kalman CFLAGS=-I.. -I. -I../core -I../drivers -O0 -g -Wall @@ -14,19 +16,19 @@ 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.c ao_sample.c ao_kalman.c altitude.h $(INCS) 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-pa.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 $(INCS) 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 +ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c $(INCS) cc $(CFLAGS) -o $@ -DHAS_ACCEL=0 ao_flight_test.c -ao_flight_test_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_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c $(INCS) cc $(CFLAGS) -o $@ -DFORCE_ACCEL=1 ao_flight_test.c -ao_flight_test_mm: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h +ao_flight_test_mm: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c $(INCS) cc -DMEGAMETRUM=1 $(CFLAGS) -o $@ $< ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 6c0bb4da..0df9a5d7 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -260,6 +260,10 @@ static int landed_set; static double landed_time; static double landed_height; +#if HAS_MPU6000 +static struct ao_mpu6000_sample ao_ground_mpu6000; +#endif + void ao_test_exit(void) { @@ -297,6 +301,20 @@ ao_test_exit(void) exit(0); } +#if HAS_MPU6000 +static double +ao_mpu6000_accel(int16_t sensor) +{ + return sensor / 32767.0 * MPU6000_ACCEL_FULLSCALE * GRAVITY; +} + +static double +ao_mpu6000_gyro(int16_t sensor) +{ + return sensor / 32767.0 * MPU6000_GYRO_FULLSCALE; +} +#endif + void ao_insert(void) { @@ -350,10 +368,22 @@ ao_insert(void) } if (!ao_summary) { - printf("%7.2f height %8.2f accel %8.3f state %-8.8s k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d\n", + printf("%7.2f height %8.2f accel %8.3f " +#if MEGAMETRUM + "accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f " +#endif + "state %-8.8s k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d\n", time, height, accel, +#if MEGAMETRUM + ao_mpu6000_accel(ao_data_static.mpu6000.accel_x), + ao_mpu6000_accel(ao_data_static.mpu6000.accel_y), + ao_mpu6000_accel(ao_data_static.mpu6000.accel_z), + ao_mpu6000_gyro(ao_data_static.mpu6000.gyro_x - ao_ground_mpu6000.gyro_x), + ao_mpu6000_gyro(ao_data_static.mpu6000.gyro_y - ao_ground_mpu6000.gyro_y), + ao_mpu6000_gyro(ao_data_static.mpu6000.gyro_z - ao_ground_mpu6000.gyro_z), +#endif ao_state_names[ao_flight_state], ao_k_height / 65536.0, ao_k_speed / 65536.0 / 16.0, @@ -536,6 +566,7 @@ ao_sleep(void *wchan) if (ao_records_read > 2 && ao_flight_state == ao_flight_startup) { #if MEGAMETRUM + ao_data_static.mpu6000 = ao_ground_mpu6000; #else ao_data_static.adc.accel = ao_flight_ground_accel; #endif @@ -585,8 +616,23 @@ ao_sleep(void *wchan) ao_data_static.ms5607_raw.pres = int32(bytes, 0); ao_data_static.ms5607_raw.temp = int32(bytes, 4); ao_ms5607_convert(&ao_data_static.ms5607_raw, &value); - ao_data_set_accel(&ao_data_static, -int16(bytes, 10)); -// printf ("accel %d pres %d\n", ao_data_accel_cook(&ao_data_static), value.pres); + ao_data_static.mpu6000.accel_x = int16(bytes, 8); + ao_data_static.mpu6000.accel_y = -int16(bytes, 10); + ao_data_static.mpu6000.accel_z = int16(bytes, 12); + ao_data_static.mpu6000.gyro_x = int16(bytes, 14); + ao_data_static.mpu6000.gyro_y = -int16(bytes, 16); + ao_data_static.mpu6000.gyro_z = int16(bytes, 18); + if (ao_records_read == 0) + ao_ground_mpu6000 = ao_data_static.mpu6000; + else if (ao_records_read < 10) { +#define f(f) ao_ground_mpu6000.f = ao_ground_mpu6000.f + ((ao_data_static.mpu6000.f - ao_ground_mpu6000.f) >> 2) + f(accel_x); + f(accel_y); + f(accel_z); + f(gyro_x); + f(gyro_y); + f(gyro_z); + } ao_records_read++; ao_insert(); return; -- cgit v1.2.3 From 84c56b1e92fca181207c468ea6351db3c2f196fb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 14 Oct 2012 23:04:44 -0700 Subject: altos/telefire: Report valid channels instead of valid pins Now that pins don't match channels 1:1, make sure that the report back to the LCO names the channels instead of the pin numbers. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 36905136..6cec98ab 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -271,7 +271,7 @@ ao_pad(void) query.tick = ao_time(); query.box = ao_pad_box; - query.channels = AO_PAD_ALL_PINS; + query.channels = AO_PAD_ALL_CHANNELS; query.armed = ao_pad_armed; PRINTD ("query tick %d box %d channels %02x arm %d arm_status %d igniter %d,%d,%d,%d\n", query.tick, query.box, query.channels, query.armed, -- cgit v1.2.3 From 56ebb0a2f50fd56f4f0b0c695e516bee8fae36fb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 14 Oct 2012 23:16:45 -0700 Subject: altos/telelco: Only present valid pads Limit pad display to valid pads, skipping missing ones. Signed-off-by: Keith Packard --- src/telelco-v0.1/ao_lco.c | 82 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/telelco-v0.1/ao_lco.c b/src/telelco-v0.1/ao_lco.c index 41bba0ba..3421e1df 100644 --- a/src/telelco-v0.1/ao_lco.c +++ b/src/telelco-v0.1/ao_lco.c @@ -43,6 +43,9 @@ static uint8_t ao_lco_box; static uint8_t ao_lco_armed; static uint8_t ao_lco_firing; static uint8_t ao_lco_valid; +static uint16_t ao_lco_tick_offset; + +static struct ao_pad_query ao_pad_query; static void ao_lco_set_pad(void) @@ -71,11 +74,32 @@ ao_lco_box_present(uint8_t box) return (ao_lco_box_mask[MASK_ID(box)] >> MASK_SHIFT(box)) & 1; } +static uint8_t +ao_lco_pad_present(uint8_t pad) +{ + if (!ao_lco_valid || !ao_pad_query.channels) + return pad == 0; + if (pad >= AO_PAD_MAX_CHANNELS) + return 0; + return (ao_pad_query.channels >> pad) & 1; +} + +static uint8_t +ao_lco_pad_first(void) +{ + uint8_t pad; + + for (pad = 0; pad < AO_PAD_MAX_CHANNELS; pad++) + if (ao_lco_pad_present(pad)) + return pad; + return 0; +} + static void ao_lco_input(void) { static struct ao_event event; - int8_t dir; + int8_t dir, new_box; ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); ao_lco_set_pad(); @@ -89,7 +113,17 @@ ao_lco_input(void) switch (event.unit) { case AO_QUADRATURE_PAD: if (!ao_lco_armed) { - ao_lco_pad = event.value & 3; + if (event.value == ao_lco_pad) + break; + dir = ((int8_t) event.value - (int8_t) ao_lco_pad) > 0 ? 1 : -1; + ao_lco_pad = event.value; + while (!ao_lco_pad_present(ao_lco_pad)) { + ao_lco_pad += dir; + if ((int8_t) ao_lco_pad > AO_PAD_MAX_CHANNELS) + ao_lco_pad = 0; + else if ((int8_t) ao_lco_pad < 0) + ao_lco_pad = AO_PAD_MAX_CHANNELS - 1; + } ao_quadrature_count[AO_QUADRATURE_PAD] = ao_lco_pad; ao_lco_set_pad(); } @@ -98,17 +132,21 @@ ao_lco_input(void) if (!ao_lco_armed) { if (event.value == ao_lco_box) break; - dir = (event.value - ao_lco_box) > 0 ? 1 : -1; - ao_lco_box = event.value; - while (!ao_lco_box_present(ao_lco_box)) { - ao_lco_box += dir; - if (ao_lco_box > ao_lco_max_box) - ao_lco_box = ao_lco_min_box; - else if (ao_lco_box < ao_lco_min_box) - ao_lco_box = ao_lco_min_box; + dir = ((int8_t) event.value - (int8_t) ao_lco_box) > 0 ? 1 : -1; + new_box = event.value; + while (!ao_lco_box_present(new_box)) { + new_box += dir; + if (new_box > ao_lco_max_box) + new_box = ao_lco_min_box; + else if (new_box < ao_lco_min_box) + new_box = ao_lco_min_box; + } + ao_quadrature_count[AO_QUADRATURE_PAD] = new_box; + if (ao_lco_box != new_box) { + ao_lco_box = new_box; + ao_lco_valid = 0; + ao_lco_set_box(); } - ao_quadrature_count[AO_QUADRATURE_PAD] = ao_lco_box; - ao_lco_set_box(); } break; } @@ -160,10 +198,6 @@ static AO_LED_TYPE continuity_led[AO_LED_CONTINUITY_NUM] = { #endif }; -static uint16_t ao_lco_tick_offset; - -static struct ao_pad_query ao_pad_query; - static void ao_lco_update(void) { @@ -171,8 +205,14 @@ ao_lco_update(void) uint8_t c; r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset); - if (r == AO_RADIO_CMAC_OK) + if (r == AO_RADIO_CMAC_OK) { + c = ao_lco_valid; ao_lco_valid = 1; + if (!c) { + ao_lco_pad = ao_lco_pad_first(); + ao_lco_set_pad(); + } + } #if 0 PRINTD("lco_query success arm_status %d i0 %d i1 %d i2 %d i3 %d\n", @@ -213,7 +253,11 @@ ao_lco_search(void) ao_lco_box_set_present(ao_lco_box); } } - ao_lco_box = ao_lco_min_box; + if (ao_lco_min_box <= ao_lco_max_box) + ao_lco_box = ao_lco_min_box; + else + ao_lco_box = 0; + ao_lco_valid = 0; ao_lco_pad = 0; } @@ -233,7 +277,7 @@ ao_lco_igniter_status(void) continue; } PRINTD("RSSI %d\n", ao_radio_cmac_rssi); - if (ao_radio_cmac_rssi < -70) + if (ao_radio_cmac_rssi < -90) ao_led_on(AO_LED_RED|AO_LED_GREEN); else { ao_led_on(AO_LED_GREEN); -- cgit v1.2.3 From b042f3d6e6b3241cd5e55cf893242ea599d3c0e9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 14 Oct 2012 23:24:49 -0700 Subject: altos/telelco: Handle case where no boxes are present Don't infinite loop looking for something which isn't there Signed-off-by: Keith Packard --- src/telelco-v0.1/ao_lco.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/telelco-v0.1/ao_lco.c b/src/telelco-v0.1/ao_lco.c index 3421e1df..1bf2a825 100644 --- a/src/telelco-v0.1/ao_lco.c +++ b/src/telelco-v0.1/ao_lco.c @@ -99,7 +99,7 @@ static void ao_lco_input(void) { static struct ao_event event; - int8_t dir, new_box; + int8_t dir, new_box, new_pad; ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); ao_lco_set_pad(); @@ -116,16 +116,20 @@ ao_lco_input(void) if (event.value == ao_lco_pad) break; dir = ((int8_t) event.value - (int8_t) ao_lco_pad) > 0 ? 1 : -1; - ao_lco_pad = event.value; - while (!ao_lco_pad_present(ao_lco_pad)) { - ao_lco_pad += dir; - if ((int8_t) ao_lco_pad > AO_PAD_MAX_CHANNELS) - ao_lco_pad = 0; - else if ((int8_t) ao_lco_pad < 0) - ao_lco_pad = AO_PAD_MAX_CHANNELS - 1; + new_pad = event.value; + while (!ao_lco_pad_present(new_pad)) { + new_pad += dir; + if (new_pad > AO_PAD_MAX_CHANNELS) + new_pad = 0; + else if (new_pad < 0) + new_pad = AO_PAD_MAX_CHANNELS - 1; + if (new_pad == ao_lco_pad) + break; + } + if (new_pad != ao_lco_pad) { + ao_quadrature_count[AO_QUADRATURE_PAD] = ao_lco_pad; + ao_lco_set_pad(); } - ao_quadrature_count[AO_QUADRATURE_PAD] = ao_lco_pad; - ao_lco_set_pad(); } break; case AO_QUADRATURE_BOX: @@ -140,6 +144,8 @@ ao_lco_input(void) new_box = ao_lco_min_box; else if (new_box < ao_lco_min_box) new_box = ao_lco_min_box; + if (new_box == ao_lco_box) + break; } ao_quadrature_count[AO_QUADRATURE_PAD] = new_box; if (ao_lco_box != new_box) { @@ -256,7 +262,7 @@ ao_lco_search(void) if (ao_lco_min_box <= ao_lco_max_box) ao_lco_box = ao_lco_min_box; else - ao_lco_box = 0; + ao_lco_min_box = ao_lco_max_box = ao_lco_box = 0; ao_lco_valid = 0; ao_lco_pad = 0; } -- cgit v1.2.3 From 44c13005f34fdf7d4831e86e1f3e8729e9b67a68 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 14 Oct 2012 23:40:58 -0700 Subject: altos/telelco: Actually set pad when it changes Oops. Lost the actual assignment to the current pad Signed-off-by: Keith Packard --- src/telelco-v0.1/ao_lco.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/telelco-v0.1/ao_lco.c b/src/telelco-v0.1/ao_lco.c index 1bf2a825..ab9f6747 100644 --- a/src/telelco-v0.1/ao_lco.c +++ b/src/telelco-v0.1/ao_lco.c @@ -127,6 +127,7 @@ ao_lco_input(void) break; } if (new_pad != ao_lco_pad) { + ao_lco_pad = new_pad; ao_quadrature_count[AO_QUADRATURE_PAD] = ao_lco_pad; ao_lco_set_pad(); } -- cgit v1.2.3 From 80227c08444d5c82fd43320644cdeec6f34fee1b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 15 Oct 2012 00:06:10 -0700 Subject: altos/stm: Declare all SPI bus speeds Just list them all so users can pick what they like Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index d4fbea37..e66d20d7 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -21,9 +21,22 @@ /* ao_spi_stm.c */ -#define AO_SPI_SPEED_FAST STM_SPI_CR1_BR_PCLK_4 +/* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */ + +#define AO_SPI_SPEED_8MHz STM_SPI_CR1_BR_PCLK_2 /* This doesn't appear to work */ +#define AO_SPI_SPEED_4MHz STM_SPI_CR1_BR_PCLK_4 +#define AO_SPI_SPEED_2MHz STM_SPI_CR1_BR_PCLK_8 #define AO_SPI_SPEED_1MHz STM_SPI_CR1_BR_PCLK_16 -#define AO_SPI_SPEED_200kHz STM_SPI_CR1_BR_PCLK_256 +#define AO_SPI_SPEED_500kHz STM_SPI_CR1_BR_PCLK_32 +#define AO_SPI_SPEED_250kHz STM_SPI_CR1_BR_PCLK_64 +#define AO_SPI_SPEED_125kHz STM_SPI_CR1_BR_PCLK_128 +#define AO_SPI_SPEED_62500Hz STM_SPI_CR1_BR_PCLK_256 + +#define AO_SPI_SPEED_FAST AO_SPI_SPEED_4MHz + +/* Companion bus wants something no faster than 200kHz */ + +#define AO_SPI_SPEED_200kHz AO_SPI_SPEED_125kHz #define AO_SPI_CONFIG_1 0x00 #define AO_SPI_1_CONFIG_PA5_PA6_PA7 AO_SPI_CONFIG_1 -- cgit v1.2.3 From c6069e38d6d2f9b37aa8671c41b4a470d92996a4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 15 Oct 2012 00:06:57 -0700 Subject: altos/telelco: Crank up SPI speed to cc1111 The cc1111 can handle up to 3MHz, so use 2MHz. Also, crank down the packet wait time to 10ms, which should be plenty long for the remote box to receive and return a packet. Signed-off-by: Keith Packard --- src/drivers/ao_lco_func.c | 2 +- src/drivers/ao_radio_master.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_lco_func.c b/src/drivers/ao_lco_func.c index 99e58b76..4af17fd6 100644 --- a/src/drivers/ao_lco_func.c +++ b/src/drivers/ao_lco_func.c @@ -37,7 +37,7 @@ ao_lco_query(uint16_t box, struct ao_pad_query *query, uint16_t *tick_offset) command.channels = 0; ao_radio_cmac_send(&command, sizeof (command)); sent_time = ao_time(); - r = ao_radio_cmac_recv(query, sizeof (*query), AO_MS_TO_TICKS(20)); + r = ao_radio_cmac_recv(query, sizeof (*query), AO_MS_TO_TICKS(10)); if (r == AO_RADIO_CMAC_OK) *tick_offset = sent_time - query->tick; ao_mutex_put(&ao_lco_mutex); diff --git a/src/drivers/ao_radio_master.c b/src/drivers/ao_radio_master.c index 73ac3c03..4a37ace0 100644 --- a/src/drivers/ao_radio_master.c +++ b/src/drivers/ao_radio_master.c @@ -53,7 +53,7 @@ ao_radio_master_start(void) { ao_spi_get_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS, AO_RADIO_SPI_BUS, - AO_SPI_SPEED_200kHz); + AO_SPI_SPEED_2MHz); } static void -- cgit v1.2.3 From fdc00ec143022356bf8cdbb28812f045b439c549 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 15 Oct 2012 00:07:57 -0700 Subject: altos/telelco: Only display every 10th box number during scan This reduces the scan time to about 4 seconds, which seems tolerable Signed-off-by: Keith Packard --- src/telelco-v0.1/ao_lco.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/telelco-v0.1/ao_lco.c b/src/telelco-v0.1/ao_lco.c index ab9f6747..df7f865b 100644 --- a/src/telelco-v0.1/ao_lco.c +++ b/src/telelco-v0.1/ao_lco.c @@ -250,7 +250,8 @@ ao_lco_search(void) ao_lco_min_box = 0xff; ao_lco_max_box = 0x00; for (ao_lco_box = 0; ao_lco_box < AO_PAD_MAX_BOXES; ao_lco_box++) { - ao_lco_set_box(); + if ((ao_lco_box % 10) == 0) + ao_lco_set_box(); r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset); if (r == AO_RADIO_CMAC_OK) { if (ao_lco_box < ao_lco_min_box) -- cgit v1.2.3 From 5f31f6652f4b0898214d06d009af823a1ed3b96a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 15 Oct 2012 00:24:28 -0700 Subject: altos/telelco: 10ms is not enough time to get a packet back Not reliable, so bump to 20ms Signed-off-by: Keith Packard --- src/drivers/ao_lco_func.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_lco_func.c b/src/drivers/ao_lco_func.c index 4af17fd6..99e58b76 100644 --- a/src/drivers/ao_lco_func.c +++ b/src/drivers/ao_lco_func.c @@ -37,7 +37,7 @@ ao_lco_query(uint16_t box, struct ao_pad_query *query, uint16_t *tick_offset) command.channels = 0; ao_radio_cmac_send(&command, sizeof (command)); sent_time = ao_time(); - r = ao_radio_cmac_recv(query, sizeof (*query), AO_MS_TO_TICKS(10)); + r = ao_radio_cmac_recv(query, sizeof (*query), AO_MS_TO_TICKS(20)); if (r == AO_RADIO_CMAC_OK) *tick_offset = sent_time - query->tick; ao_mutex_put(&ao_lco_mutex); -- cgit v1.2.3 From 60880bda2153ba3122c7102cd2bacbcca73b9e0d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 15 Oct 2012 00:24:57 -0700 Subject: altos/telelco: Make the RSSI led turn red when no packet is received This involved splitting out the notion of ever having received an answer and having received an answer from the last query. Signed-off-by: Keith Packard --- src/telelco-v0.1/ao_lco.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/telelco-v0.1/ao_lco.c b/src/telelco-v0.1/ao_lco.c index df7f865b..79f3896b 100644 --- a/src/telelco-v0.1/ao_lco.c +++ b/src/telelco-v0.1/ao_lco.c @@ -43,6 +43,7 @@ static uint8_t ao_lco_box; static uint8_t ao_lco_armed; static uint8_t ao_lco_firing; static uint8_t ao_lco_valid; +static uint8_t ao_lco_got_channels; static uint16_t ao_lco_tick_offset; static struct ao_pad_query ao_pad_query; @@ -77,7 +78,7 @@ ao_lco_box_present(uint8_t box) static uint8_t ao_lco_pad_present(uint8_t pad) { - if (!ao_lco_valid || !ao_pad_query.channels) + if (!ao_lco_got_channels || !ao_pad_query.channels) return pad == 0; if (pad >= AO_PAD_MAX_CHANNELS) return 0; @@ -151,7 +152,7 @@ ao_lco_input(void) ao_quadrature_count[AO_QUADRATURE_PAD] = new_box; if (ao_lco_box != new_box) { ao_lco_box = new_box; - ao_lco_valid = 0; + ao_lco_got_channels = 0; ao_lco_set_box(); } } @@ -213,13 +214,15 @@ ao_lco_update(void) r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset); if (r == AO_RADIO_CMAC_OK) { - c = ao_lco_valid; + c = ao_lco_got_channels; + ao_lco_got_channels = 1; ao_lco_valid = 1; if (!c) { ao_lco_pad = ao_lco_pad_first(); ao_lco_set_pad(); } - } + } else + ao_lco_valid = 0; #if 0 PRINTD("lco_query success arm_status %d i0 %d i1 %d i2 %d i3 %d\n", @@ -266,6 +269,7 @@ ao_lco_search(void) else ao_lco_min_box = ao_lco_max_box = ao_lco_box = 0; ao_lco_valid = 0; + ao_lco_got_channels = 0; ao_lco_pad = 0; } -- cgit v1.2.3 From 4d6d90e15db30991bf81060a0876ae8adb843c75 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 16 Oct 2012 21:08:58 -0700 Subject: altos/avr: Use ISR_BLOCK to disable interrupts during slave ISR This avoids enabling and then immediatly disabling them Signed-off-by: Keith Packard --- src/avr/ao_spi_slave.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c index b742d29a..a400b8a0 100644 --- a/src/avr/ao_spi_slave.c +++ b/src/avr/ao_spi_slave.c @@ -44,9 +44,8 @@ ao_spi_slave_send(uint8_t *buf, uint8_t len) static uint8_t ao_spi_slave_running; -ISR(PCINT0_vect) +ISR(PCINT0_vect, ISR_BLOCK) { - cli(); #if SPI_SLAVE_PIN_0_3 if ((PINB & (1 << PORTB0)) == 0) #endif @@ -61,7 +60,6 @@ ISR(PCINT0_vect) } else { ao_spi_slave_running = 0; } - sei(); } void -- cgit v1.2.3