diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/micropeak/Makefile | 14 | ||||
| -rw-r--r-- | src/micropeak/ao_async.c | 43 | ||||
| -rw-r--r-- | src/micropeak/ao_async.h | 6 | ||||
| -rw-r--r-- | src/micropeak/ao_log_micro.c | 116 | ||||
| -rw-r--r-- | src/micropeak/ao_log_micro.h | 19 | ||||
| -rw-r--r-- | src/micropeak/ao_micropeak.c | 134 | ||||
| -rw-r--r-- | src/micropeak/ao_micropeak.h | 56 | 
7 files changed, 226 insertions, 162 deletions
| diff --git a/src/micropeak/Makefile b/src/micropeak/Makefile index 0c48ed66..ff0a4499 100644 --- a/src/micropeak/Makefile +++ b/src/micropeak/Makefile @@ -20,13 +20,6 @@ ifndef VERSION  include ../Version  endif -# Support for a logging EEPROM -# -#EEPROM_SRC=ao_async.c \ -#	ao_i2c_attiny.c \ -#	ao_at24c.c -# -  ALTOS_SRC = \  	ao_micropeak.c \  	ao_spi_attiny.c \ @@ -39,7 +32,8 @@ ALTOS_SRC = \  	ao_notask.c \  	ao_eeprom_tiny.c \  	ao_panic.c \ -	$(EEPROM_SRC) +	ao_log_micro.c \ +	ao_async.c  INC=\  	ao.h \ @@ -48,13 +42,15 @@ INC=\  	ao_arch_funcs.h \  	ao_exti.h \  	ao_ms5607.h \ +	ao_log_micro.h \ +	ao_micropeak.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 +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTINY  NICKLE=nickle diff --git a/src/micropeak/ao_async.c b/src/micropeak/ao_async.c index 04bba9e8..3556f54c 100644 --- a/src/micropeak/ao_async.c +++ b/src/micropeak/ao_async.c @@ -21,20 +21,51 @@  #define AO_ASYNC_BAUD	38400l  #define AO_ASYNC_DELAY	(uint8_t) (1000000l / AO_ASYNC_BAUD) +#define LED_PORT	PORTB + +void +ao_async_start(void) +{ +	LED_PORT |= (1 << AO_LED_SERIAL); +} + +void +ao_async_stop(void) +{ +	LED_PORT &= ~(1 << AO_LED_SERIAL); +} +  void  ao_async_byte(uint8_t byte)  {  	uint8_t		b;  	uint16_t	w; -	/* start bit */ - -	/* start     data         stop */ -	w = 0x001 | (byte << 1) | 0x000; +	/*    start           data           stop */ +	w = (0x000 << 0) | (byte << 1) | (0x001 << 9); +	ao_arch_block_interrupts();  	for (b = 0; b < 10; b++) { -		ao_led_set((w & 1) << AO_LED_SERIAL); +		uint8_t	v = LED_PORT & ~(1 << AO_LED_SERIAL); +		v |= (w & 1) << AO_LED_SERIAL; +		LED_PORT = v;  		w >>= 1; -		ao_delay_us(26); + +		/* Carefully timed to hit around 9600 baud */ +		asm volatile ("nop"); +		asm volatile ("nop"); + +		asm volatile ("nop"); +		asm volatile ("nop"); +		asm volatile ("nop"); +		asm volatile ("nop"); +		asm volatile ("nop"); + +		asm volatile ("nop"); +		asm volatile ("nop"); +		asm volatile ("nop"); +		asm volatile ("nop"); +		asm volatile ("nop");  	} +	ao_arch_release_interrupts();  } diff --git a/src/micropeak/ao_async.h b/src/micropeak/ao_async.h index a06d2e1a..1b239712 100644 --- a/src/micropeak/ao_async.h +++ b/src/micropeak/ao_async.h @@ -19,6 +19,12 @@  #define _AO_ASYNC_H_  void +ao_async_start(void); + +void +ao_async_stop(void); + +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 index eda0d1d2..d665efb5 100644 --- a/src/micropeak/ao_log_micro.c +++ b/src/micropeak/ao_log_micro.c @@ -16,58 +16,106 @@   */  #include <ao.h> +#include <ao_micropeak.h>  #include <ao_log_micro.h>  #include <ao_async.h> -#if HAS_EEPROM - -ao_pos_t	ao_log_micro_pos; +static uint16_t ao_log_offset = STARTING_LOG_OFFSET;  void -ao_log_micro_data(uint32_t data) +ao_log_micro_save(void)  { -	ao_storage_write(ao_log_micro_pos, &data, sizeof (data)); -	ao_log_micro_pos += sizeof (data); +	uint16_t	n_samples = (ao_log_offset - STARTING_LOG_OFFSET) / sizeof (uint16_t); +	ao_eeprom_write(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground)); +	ao_eeprom_write(PA_MIN_OFFSET, &pa_min, sizeof (pa_min)); +	ao_eeprom_write(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples));  } -uint32_t	ao_log_last_ground; -uint32_t	ao_log_last_done; +void +ao_log_micro_restore(void) +{ +	ao_eeprom_read(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground)); +	ao_eeprom_read(PA_MIN_OFFSET, &pa_min, sizeof (pa_min)); +} -uint8_t -ao_log_micro_scan(void) +void +ao_log_micro_data(void)  { -	uint32_t	data; -	ao_pos_t	pos; +	uint16_t	low_bits = pa; -	ao_storage_read(0, &data, sizeof (data)); -	if ((data & AO_LOG_MICRO_MASK) != AO_LOG_MICRO_GROUND) -		return 0; +	if (ao_log_offset < MAX_LOG_OFFSET) { +		ao_eeprom_write(ao_log_offset, &low_bits, sizeof (low_bits)); +		ao_log_offset += sizeof (low_bits); +	} +} + +#define POLY 0x8408 + +static uint16_t +ao_log_micro_crc(uint16_t crc, uint8_t byte) +{ +	uint8_t	i; -	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; -		} +	for (i = 0; i < 8; i++) { +		if ((crc & 0x0001) ^ (byte & 0x0001)) +			crc = (crc >> 1) ^ POLY; +		else +			crc = crc >> 1; +		byte >>= 1;  	} -	return 0; +	return crc; +} + +static void +ao_log_hex_nibble(uint8_t b) +{ +	if (b < 10) +		ao_async_byte('0' + b); +	else +		ao_async_byte('a' - 10 + b); +} + +static void +ao_log_hex(uint8_t b) +{ +	ao_log_hex_nibble(b>>4); +	ao_log_hex_nibble(b&0xf); +} + +static void +ao_log_newline(void) +{ +	ao_async_byte('\r'); +	ao_async_byte('\n');  }  void  ao_log_micro_dump(void)  { -	ao_pos_t	pos; -	uint8_t		data[4]; -	uint8_t		i; +	uint16_t	n_samples; +	uint16_t	nbytes; +	uint8_t		byte; +	uint16_t	b; +	uint16_t	crc = 0xffff; -	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; +	ao_eeprom_read(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples)); +	if (n_samples == 0xffff) +		n_samples = 0; +	nbytes = STARTING_LOG_OFFSET + sizeof (uint16_t) * n_samples; +	ao_async_start(); +	ao_async_byte('M'); +	ao_async_byte('P'); +	for (b = 0; b < nbytes; b++) { +		if ((b & 0xf) == 0) +			ao_log_newline(); +		ao_eeprom_read(b, &byte, 1); +		ao_log_hex(byte); +		crc = ao_log_micro_crc(crc, byte);  	} +	ao_log_newline(); +	crc = ~crc; +	ao_log_hex(crc >> 8); +	ao_log_hex(crc); +	ao_log_newline(); +	ao_async_stop();  } - -#endif diff --git a/src/micropeak/ao_log_micro.h b/src/micropeak/ao_log_micro.h index 15b2d178..976852ee 100644 --- a/src/micropeak/ao_log_micro.h +++ b/src/micropeak/ao_log_micro.h @@ -18,19 +18,20 @@  #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) +#define PA_GROUND_OFFSET	0 +#define PA_MIN_OFFSET		4 +#define N_SAMPLES_OFFSET	8 +#define STARTING_LOG_OFFSET	10 +#define MAX_LOG_OFFSET		512  void -ao_log_micro_data(uint32_t data); +ao_log_micro_save(void); -extern uint32_t	ao_log_last_ground; -extern uint32_t	ao_log_last_done; +void +ao_log_micro_restore(void); -uint8_t -ao_log_micro_scan(void); +void +ao_log_micro_data(void);  void  ao_log_micro_dump(void); diff --git a/src/micropeak/ao_micropeak.c b/src/micropeak/ao_micropeak.c index 525cfa42..82012800 100644 --- a/src/micropeak/ao_micropeak.c +++ b/src/micropeak/ao_micropeak.c @@ -16,22 +16,23 @@   */  #include <ao.h> +#include <ao_micropeak.h>  #include <ao_ms5607.h>  #include <ao_log_micro.h> +#include <ao_async.h>  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; +uint32_t	pa; +uint32_t	pa_avg; +uint32_t	pa_ground; +uint32_t	pa_min; +alt_t		ground_alt, max_alt;  alt_t		ao_max_height; +static uint32_t	pa_sum; +  static void  ao_pa_get(void)  { @@ -40,22 +41,6 @@ ao_pa_get(void)  	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) - -/* Pressure change (in Pa) to detect boost */ -#define BOOST_DETECT		120	/* 10m at sea level, 12m at 2000m */ - -/* Wait after power on before doing anything to give the user time to assemble the rocket */ -#define BOOST_DELAY		AO_SEC_TO_TICKS(30) - -/* Pressure change (in Pa) to detect landing */ -#define LAND_DETECT		12	/* 1m at sea level, 1.2m at 2000m */ -  static void  ao_compute_height(void)  { @@ -64,90 +49,42 @@ ao_compute_height(void)  	ao_max_height = max_alt - ground_alt;  } -#if !HAS_EEPROM - -#define PA_GROUND_OFFSET	0 -#define PA_MIN_OFFSET		4 -#define N_SAMPLES_OFFSET	8 -#define STARTING_LOG_OFFSET	10 -#define MAX_LOG_OFFSET		512 - -static uint16_t ao_log_offset = STARTING_LOG_OFFSET; - -void -ao_save_flight(void) -{ -	uint16_t	n_samples = (ao_log_offset - STARTING_LOG_OFFSET) / sizeof (uint16_t); -	ao_eeprom_write(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground)); -	ao_eeprom_write(PA_MIN_OFFSET, &pa_min, sizeof (pa_min)); -	ao_eeprom_write(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples)); -} - -void -ao_restore_flight(void) -{ -	ao_eeprom_read(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground)); -	ao_eeprom_read(PA_MIN_OFFSET, &pa_min, sizeof (pa_min)); -} - -void -ao_log_micro(void) +static void +ao_pips(void)  { -	uint16_t	low_bits = pa; - -	if (ao_log_offset < MAX_LOG_OFFSET) { -		ao_eeprom_write(ao_log_offset, &low_bits, sizeof (low_bits)); -		ao_log_offset += sizeof (low_bits); +	uint8_t	i; +	for (i = 0; i < 10; i++) { +		ao_led_toggle(AO_LED_REPORT); +		ao_delay(AO_MS_TO_TICKS(80));  	} +	ao_delay(AO_MS_TO_TICKS(200));  } -#endif  int  main(void)  {  	int16_t		sample_count;  	uint16_t	time; -#if HAS_EEPROM -	uint8_t	dump_eeprom = 0; -#endif +	uint32_t	pa_interval_min, pa_interval_max; +	int32_t		pa_diff; +  	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(); -	/* Give the person a second to get their finger out of the way */ -	ao_delay(AO_MS_TO_TICKS(1000)); -	ao_report_altitude(); -	 +	/* Init external hardware */  	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	 +	/* Give the person a second to get their finger out of the way */ +	ao_delay(AO_MS_TO_TICKS(1000)); +	ao_log_micro_restore(); +	ao_compute_height(); +	ao_report_altitude(); +	ao_pips(); +	ao_log_micro_dump(); +	  	ao_delay(BOOST_DELAY);  	/* Wait for motion, averaging values to get ground pressure */  	time = ao_time(); @@ -182,10 +119,6 @@ main(void)  	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; @@ -200,12 +133,8 @@ main(void)  		ao_pa_get();  		if ((sample_count & 3) == 0)  			ao_led_off(AO_LED_REPORT); -#if HAS_EEPROM -		ao_log_micro_data(AO_LOG_MICRO_DATA | pa); -#else  		if (sample_count & 1) -			ao_log_micro(); -#endif +			ao_log_micro_data();  		pa_avg = pa_avg - (pa_avg >> FILTER_SHIFT) + pa;  		if (pa_avg < pa_min)  			pa_min = pa_avg; @@ -228,10 +157,7 @@ main(void)  		}  	}  	pa_min >>= FILTER_SHIFT; -#if HAS_EEPROM -	ao_log_micro_data(AO_LOG_MICRO_DONE | pa_min); -#endif -	ao_save_flight(); +	ao_log_micro_save();  	ao_compute_height();  	ao_report_altitude();  	for (;;) { diff --git a/src/micropeak/ao_micropeak.h b/src/micropeak/ao_micropeak.h new file mode 100644 index 00000000..e408d7c5 --- /dev/null +++ b/src/micropeak/ao_micropeak.h @@ -0,0 +1,56 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_MICROPEAK_H_ +#define _AO_MICROPEAK_H_ + +#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) + +/* Pressure change (in Pa) to detect boost */ +#define BOOST_DETECT		120	/* 10m at sea level, 12m at 2000m */ + +/* Wait after power on before doing anything to give the user time to assemble the rocket */ +#define BOOST_DELAY		AO_SEC_TO_TICKS(30) + +/* Pressure change (in Pa) to detect landing */ +#define LAND_DETECT		12	/* 1m at sea level, 1.2m at 2000m */ + +/* Current sensor pressure value */ +extern uint32_t	pa; + +/* IIR filtered pressure value */ +extern uint32_t	pa_avg; + +/* Average pressure value on ground */ +extern uint32_t	pa_ground; + +/* Minimum recorded filtered pressure value */ +extern uint32_t	pa_min; + +/* Pressure values converted to altitudes */ +extern alt_t	ground_alt, max_alt; + +/* max_alt - ground_alt */ +extern alt_t	ao_max_height; + +#endif + | 
