diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/ao_data.h | 4 | ||||
| -rw-r--r-- | src/core/ao_gps_report_metrum.c | 110 | ||||
| -rw-r--r-- | src/core/ao_log.h | 66 | ||||
| -rw-r--r-- | src/core/ao_log_metrum.c | 175 | ||||
| -rw-r--r-- | src/core/ao_sample_profile.c | 6 | ||||
| -rw-r--r-- | src/core/ao_task.c | 3 | ||||
| -rw-r--r-- | src/core/ao_telemetry.c | 88 | ||||
| -rw-r--r-- | src/core/ao_telemetry.h | 44 | ||||
| -rw-r--r-- | src/drivers/ao_gps_ublox.c | 123 | ||||
| -rw-r--r-- | src/stm/Makefile-flash.defs | 2 | ||||
| -rw-r--r-- | src/stm/ao_arch.h | 2 | ||||
| -rw-r--r-- | src/stm/ao_arch_funcs.h | 15 | ||||
| -rw-r--r-- | src/stm/ao_beep_stm.c | 48 | ||||
| -rw-r--r-- | src/stm/ao_timer.c | 25 | ||||
| -rw-r--r-- | src/stm/stm32l.h | 2 | ||||
| -rw-r--r-- | src/telemetrum-v2.0/.gitignore | 2 | ||||
| -rw-r--r-- | src/telemetrum-v2.0/Makefile | 122 | ||||
| -rw-r--r-- | src/telemetrum-v2.0/ao_pins.h | 290 | ||||
| -rw-r--r-- | src/telemetrum-v2.0/ao_telemetrum.c | 90 | ||||
| -rw-r--r-- | src/telemetrum-v2.0/flash-loader/Makefile | 8 | ||||
| -rw-r--r-- | src/telemetrum-v2.0/flash-loader/ao_pins.h | 34 | 
21 files changed, 1196 insertions, 63 deletions
| diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 080a534f..339afe69 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -272,7 +272,11 @@ typedef int16_t accel_t;  /* MMA655X is hooked up so that positive values represent negative acceleration */  #define ao_data_accel(packet)			((packet)->mma655x) +#if AO_MMA655X_INVERT +#define ao_data_accel_cook(packet)		(4095 - (packet)->mma655x) +#else  #define ao_data_accel_cook(packet)		((packet)->mma655x) +#endif  #define ao_data_set_accel(packet, accel)	((packet)->mma655x = (accel))  #define ao_data_accel_invert(accel)		(4095 - (accel)) diff --git a/src/core/ao_gps_report_metrum.c b/src/core/ao_gps_report_metrum.c new file mode 100644 index 00000000..4fefe223 --- /dev/null +++ b/src/core/ao_gps_report_metrum.c @@ -0,0 +1,110 @@ +/* + * Copyright © 2009 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_log.h" + +void +ao_gps_report_metrum(void) +{ +	static __xdata struct ao_log_metrum		gps_log; +	static __xdata struct ao_telemetry_location	gps_data; +	uint8_t	date_reported = 0; + +	for (;;) { +		ao_sleep(&ao_gps_data); +		ao_mutex_get(&ao_gps_mutex); +		ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); +		ao_mutex_put(&ao_gps_mutex); + +		if (!(gps_data.flags & AO_GPS_VALID)) +			continue; + +		gps_log.tick = ao_gps_tick; +		gps_log.type = AO_LOG_GPS_POS; +		gps_log.u.gps.latitude = gps_data.latitude; +		gps_log.u.gps.longitude = gps_data.longitude; +		gps_log.u.gps.altitude = gps_data.altitude; +		ao_log_metrum(&gps_log); + +		gps_log.type = AO_LOG_GPS_TIME; +		gps_log.u.gps_time.hour = gps_data.hour; +		gps_log.u.gps_time.minute = gps_data.minute; +		gps_log.u.gps_time.second = gps_data.second; +		gps_log.u.gps_time.flags = gps_data.flags; +		gps_log.u.gps_time.year = gps_data.year; +		gps_log.u.gps_time.month = gps_data.month; +		gps_log.u.gps_time.day = gps_data.day; +		ao_log_metrum(&gps_log); +	} +} + +void +ao_gps_tracking_report_metrum(void) +{ +	static __xdata struct ao_log_metrum		gps_log; +	static __xdata struct ao_telemetry_satellite	gps_tracking_data; +	uint8_t	c, n, i, p, valid, packets; +	uint8_t svid; + +	for (;;) { +		ao_sleep(&ao_gps_tracking_data); +		ao_mutex_get(&ao_gps_mutex); +		ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); +		ao_mutex_put(&ao_gps_mutex); + +		if (!(n = gps_tracking_data.channels)) +			continue; + +		gps_log.type = AO_LOG_GPS_SAT; +		gps_log.tick = ao_gps_tick; +		i = 0; +		for (c = 0; c < n; c++) { +			svid = gps_tracking_data.sats[c].svid; +			if (svid != 0) { +				if (i == 4) { +					gps_log.u.gps_sat.channels = i; +					gps_log.u.gps_sat.more = 1; +					ao_log_metrum(&gps_log); +					i = 0; +				} +				gps_log.u.gps_sat.sats[i].svid = svid; +				gps_log.u.gps_sat.sats[i].c_n = gps_tracking_data.sats[c].c_n_1; +				i++; +			} +		} +		if (i) { +			gps_log.u.gps_sat.channels = i; +			gps_log.u.gps_sat.more = 0; +			ao_log_metrum(&gps_log); +		} +	} +} + +__xdata struct ao_task ao_gps_report_metrum_task; +__xdata struct ao_task ao_gps_tracking_report_metrum_task; + +void +ao_gps_report_metrum_init(void) +{ +	ao_add_task(&ao_gps_report_metrum_task, +		    ao_gps_report_metrum, +		    "gps_report"); +	ao_add_task(&ao_gps_tracking_report_metrum_task, +		    ao_gps_tracking_report_metrum, +		    "gps_tracking_report"); +} diff --git a/src/core/ao_log.h b/src/core/ao_log.h index dce12f02..f6ab4520 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -45,6 +45,7 @@ extern __pdata enum ao_flight_state ao_log_state;  #define AO_LOG_FORMAT_TELESCIENCE	4	/* 32 byte typed telescience records */  #define AO_LOG_FORMAT_TELEMEGA		5	/* 32 byte typed telemega records */  #define AO_LOG_FORMAT_MINI		6	/* 16-byte MS5607 baro only */ +#define AO_LOG_FORMAT_TELEMETRUM	7	/* 16-byte typed telemetrum records */  #define AO_LOG_FORMAT_NONE		127	/* No log at all */  extern __code uint8_t ao_log_format; @@ -135,6 +136,7 @@ ao_log_full(void);  #define AO_LOG_GPS_ALT		'H'  #define AO_LOG_GPS_SAT		'V'  #define AO_LOG_GPS_DATE		'Y' +#define AO_LOG_GPS_POS		'P'  #define AO_LOG_POS_NONE		(~0UL) @@ -263,6 +265,64 @@ struct ao_log_mega {  	} u;  }; +struct ao_log_metrum { +	char			type;			/* 0 */ +	uint8_t			csum;			/* 1 */ +	uint16_t		tick;			/* 2 */ +	union {						/* 4 */ +		/* AO_LOG_FLIGHT */ +		struct { +			uint16_t	flight;		/* 4 */ +			int16_t		ground_accel;	/* 6 */ +			uint32_t	ground_pres;	/* 8 */ +		} flight;	/* 12 */ +		/* AO_LOG_STATE */ +		struct { +			uint16_t	state;		/* 4 */ +			uint16_t	reason;		/* 6 */ +		} state;	/* 8 */ +		/* AO_LOG_SENSOR */ +		struct { +			uint32_t	pres;		/* 4 */ +			uint32_t	temp;		/* 8 */ +			int16_t		accel;		/* 12 */ +		} sensor;	/* 14 */ +		/* AO_LOG_TEMP_VOLT */ +		struct { +			int16_t		v_batt;		/* 4 */ +			int16_t		sense_a;	/* 6 */ +			int16_t		sense_m;	/* 8 */ +		} volt;		/* 10 */ +		/* AO_LOG_GPS_POS */ +		struct { +			int32_t		latitude;	/* 4 */ +			int32_t		longitude;	/* 8 */ +			int16_t		altitude;	/* 12 */ +		} gps;		/* 14 */ +		/* AO_LOG_GPS_TIME */ +		struct { +			uint8_t		hour;		/* 4 */ +			uint8_t		minute;		/* 5 */ +			uint8_t		second;		/* 6 */ +			uint8_t		flags;		/* 7 */ +			uint8_t		year;		/* 8 */ +			uint8_t		month;		/* 9 */ +			uint8_t		day;		/* 10 */ +			uint8_t		pad;		/* 11 */ +		} gps_time;	/* 12 */ +		/* AO_LOG_GPS_SAT (up to three packets) */ +		struct { +			uint8_t	channels;		/* 4 */ +			uint8_t	more;			/* 5 */ +			struct { +				uint8_t	svid; +				uint8_t c_n; +			} sats[4];			/* 6 */ +		} gps_sat;				/* 14 */ +		uint8_t		raw[12];		/* 4 */ +	} u;	/* 16 */ +}; +  struct ao_log_mini {  	char		type;				/* 0 */  	uint8_t		csum;				/* 1 */ @@ -304,9 +364,15 @@ uint8_t  ao_log_mega(__xdata struct ao_log_mega *log) __reentrant;  uint8_t +ao_log_metrum(__xdata struct ao_log_metrum *log) __reentrant; + +uint8_t  ao_log_mini(__xdata struct ao_log_mini *log) __reentrant;  void  ao_log_flush(void); +void +ao_gps_report_metrum_init(void); +  #endif /* _AO_LOG_H_ */ diff --git a/src/core/ao_log_metrum.c b/src/core/ao_log_metrum.c new file mode 100644 index 00000000..43441e7a --- /dev/null +++ b/src/core/ao_log_metrum.c @@ -0,0 +1,175 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include <ao_log.h> +#include <ao_data.h> +#include <ao_flight.h> + +static __xdata uint8_t	ao_log_mutex; +static __xdata struct ao_log_metrum log; + +__code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRUM; + +static uint8_t +ao_log_csum(__xdata uint8_t *b) __reentrant +{ +	uint8_t	sum = 0x5a; +	uint8_t	i; + +	for (i = 0; i < sizeof (struct ao_log_metrum); i++) +		sum += *b++; +	return -sum; +} + +uint8_t +ao_log_metrum(__xdata struct ao_log_metrum *log) __reentrant +{ +	uint8_t wrote = 0; +	/* set checksum */ +	log->csum = 0; +	log->csum = ao_log_csum((__xdata uint8_t *) log); +	ao_mutex_get(&ao_log_mutex); { +		if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) +			ao_log_stop(); +		if (ao_log_running) { +			wrote = 1; +			ao_storage_write(ao_log_current_pos, +					 log, +					 sizeof (struct ao_log_metrum)); +			ao_log_current_pos += sizeof (struct ao_log_metrum); +		} +	} ao_mutex_put(&ao_log_mutex); +	return wrote; +} + +static uint8_t +ao_log_dump_check_data(void) +{ +	if (ao_log_csum((uint8_t *) &log) != 0) +		return 0; +	return 1; +} + +#if HAS_ADC +static __data uint8_t	ao_log_data_pos; + +/* a hack to make sure that ao_log_metrums fill the eeprom block in even units */ +typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_metrum))] ; + +#ifndef AO_SENSOR_INTERVAL_ASCENT +#define AO_SENSOR_INTERVAL_ASCENT	1 +#define AO_SENSOR_INTERVAL_DESCENT	10 +#define AO_OTHER_INTERVAL		32 +#endif + +void +ao_log(void) +{ +	__pdata uint16_t	next_sensor, next_other; +	uint8_t			i; + +	ao_storage_setup(); + +	ao_log_scan(); + +	while (!ao_log_running) +		ao_sleep(&ao_log_running); + +#if HAS_FLIGHT +	log.type = AO_LOG_FLIGHT; +	log.tick = ao_sample_tick; +#if HAS_ACCEL +	log.u.flight.ground_accel = ao_ground_accel; +#endif +	log.u.flight.ground_pres = ao_ground_pres; +	log.u.flight.flight = ao_flight_number; +	ao_log_metrum(&log); +#endif + +	/* Write the whole contents of the ring to the log +	 * when starting up. +	 */ +	ao_log_data_pos = ao_data_ring_next(ao_data_head); +	next_other = next_sensor = ao_data_ring[ao_log_data_pos].tick; +	ao_log_state = ao_flight_startup; +	for (;;) { +		/* Write samples to EEPROM */ +		while (ao_log_data_pos != ao_data_head) { +			log.tick = ao_data_ring[ao_log_data_pos].tick; +			if ((int16_t) (log.tick - next_sensor) >= 0) { +				log.type = AO_LOG_SENSOR; +#if HAS_MS5607 +				log.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607_raw.pres; +				log.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607_raw.temp; +#endif +				log.u.sensor.accel = ao_data_accel(&ao_data_ring[ao_log_data_pos]); +				ao_log_metrum(&log); +				if (ao_log_state <= ao_flight_coast) +					next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; +				else +					next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT; +			} +			if ((int16_t) (log.tick - next_other) >= 0) { +				log.type = AO_LOG_TEMP_VOLT; +				log.u.volt.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt; +				log.u.volt.sense_a = ao_data_ring[ao_log_data_pos].adc.sense_a; +				log.u.volt.sense_m = ao_data_ring[ao_log_data_pos].adc.sense_m; +				ao_log_metrum(&log); +				next_other = log.tick + AO_OTHER_INTERVAL; +			} +			ao_log_data_pos = ao_data_ring_next(ao_log_data_pos); +		} +#if HAS_FLIGHT +		/* Write state change to EEPROM */ +		if (ao_flight_state != ao_log_state) { +			ao_log_state = ao_flight_state; +			log.type = AO_LOG_STATE; +			log.tick = ao_time(); +			log.u.state.state = ao_log_state; +			log.u.state.reason = 0; +			ao_log_metrum(&log); + +			if (ao_log_state == ao_flight_landed) +				ao_log_stop(); +		} +#endif + +		ao_log_flush(); + +		/* Wait for a while */ +		ao_delay(AO_MS_TO_TICKS(100)); + +		/* Stop logging when told to */ +		while (!ao_log_running) +			ao_sleep(&ao_log_running); +	} +} +#endif + +uint16_t +ao_log_flight(uint8_t slot) +{ +	if (!ao_storage_read(ao_log_pos(slot), +			     &log, +			     sizeof (struct ao_log_metrum))) +		return 0; + +	if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) +		return log.u.flight.flight; +	return 0; +} diff --git a/src/core/ao_sample_profile.c b/src/core/ao_sample_profile.c index 1d9ed414..e682bd98 100644 --- a/src/core/ao_sample_profile.c +++ b/src/core/ao_sample_profile.c @@ -20,15 +20,15 @@  #include <ao_task.h>  #ifndef AO_SAMPLE_PROFILE_LOW_PC -#define AO_SAMPLE_PROFILE_LOW_PC	0x08000000 +#define AO_SAMPLE_PROFILE_LOW_PC	0x08002000  #endif  #ifndef AO_SAMPLE_PROFILE_HIGH_PC -#define AO_SAMPLE_PROFILE_HIGH_PC	(AO_SAMPLE_PROFILE_LOW_PC + 44 * 1024) +#define AO_SAMPLE_PROFILE_HIGH_PC	0x08003000  #endif  #ifndef AO_SAMPLE_PROFILE_SHIFT -#define AO_SAMPLE_PROFILE_SHIFT		6 +#define AO_SAMPLE_PROFILE_SHIFT		3  #endif  #define AO_SAMPLE_PROFILE_RANGE		(AO_SAMPLE_PROFILE_HIGH_PC - AO_SAMPLE_PROFILE_LOW_PC) diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 18315b1f..bafb4943 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -109,6 +109,8 @@ ao_task_validate_alarm_queue(void)  				ao_panic(3);  		}  	} +	if (ao_task_alarm_tick != ao_list_first_entry(&alarm_queue, struct ao_task, alarm_queue)->alarm) +		ao_panic(4);  }  #else  #define ao_task_validate_alarm_queue() @@ -123,6 +125,7 @@ ao_task_to_alarm_queue(struct ao_task *task)  	ao_list_for_each_entry(alarm, &alarm_queue, struct ao_task, alarm_queue) {  		if ((int16_t) (alarm->alarm - task->alarm) >= 0) {  			ao_list_insert(&task->alarm_queue, alarm->alarm_queue.prev); +			ao_task_alarm_tick = ao_list_first_entry(&alarm_queue, struct ao_task, alarm_queue)->alarm;  			ao_task_validate_alarm_queue();  			return;  		} diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 9c673030..cd95aa6b 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -40,6 +40,10 @@ static __pdata uint16_t ao_aprs_time;  #define AO_SEND_MEGA	1  #endif +#if defined (TELEMETRUM_V_2_0) +#define AO_SEND_METRUM	1 +#endif +  #if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) || defined(TELEMETRUM_V_1_2)  #define AO_TELEMETRY_SENSOR	AO_TELEMETRY_SENSOR_TELEMETRUM  #endif @@ -171,6 +175,56 @@ ao_send_mega_data(void)  }  #endif /* AO_SEND_MEGA */ +#ifdef AO_SEND_METRUM +/* Send telemetrum sensor packet */ +static void +ao_send_metrum_sensor(void) +{ +	__xdata	struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; + +	telemetry.generic.type = AO_TELEMETRY_METRUM_SENSOR; + +	telemetry.metrum_sensor.state = ao_flight_state; +	telemetry.metrum_sensor.accel = ao_data_accel(packet); +	telemetry.metrum_sensor.pres = ao_data_pres(packet); +	telemetry.metrum_sensor.temp = ao_data_temp(packet); + +	telemetry.metrum_sensor.acceleration = ao_accel; +	telemetry.metrum_sensor.speed = ao_speed; +	telemetry.metrum_sensor.height = ao_height; + +	telemetry.metrum_sensor.v_batt = packet->adc.v_batt; +	telemetry.metrum_sensor.sense_a = packet->adc.sense_a; +	telemetry.metrum_sensor.sense_m = packet->adc.sense_m; + +	ao_radio_send(&telemetry, sizeof (telemetry)); +} + +static __pdata int8_t ao_telemetry_metrum_data_max; +static __pdata int8_t ao_telemetry_metrum_data_cur; + +/* Send telemetrum data packet */ +static void +ao_send_metrum_data(void) +{ +	if (--ao_telemetry_metrum_data_cur <= 0) { +		__xdata	struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; +		uint8_t	i; + +		telemetry.generic.tick = packet->tick; +		telemetry.generic.type = AO_TELEMETRY_METRUM_DATA; + +		telemetry.metrum_data.ground_pres = ao_ground_pres; +		telemetry.metrum_data.ground_accel = ao_ground_accel; +		telemetry.metrum_data.accel_plus_g = ao_config.accel_plus_g; +		telemetry.metrum_data.accel_minus_g = ao_config.accel_minus_g; + +		ao_radio_send(&telemetry, sizeof (telemetry)); +		ao_telemetry_metrum_data_cur = ao_telemetry_metrum_data_max; +	} +} +#endif /* AO_SEND_METRUM */ +  #ifdef AO_SEND_MINI  static void @@ -199,7 +253,7 @@ ao_send_mini(void)  	ao_radio_send(&telemetry, sizeof (telemetry));  } -#endif +#endif /* AO_SEND_MINI */  #ifdef AO_SEND_ALL_BARO  static uint8_t		ao_baro_sample; @@ -344,7 +398,6 @@ ao_telemetry(void)  		ao_aprs_time = time;  #endif  		while (ao_telemetry_interval) { -  #if HAS_APRS  			if (!(ao_config.radio_enable & AO_RADIO_DISABLE_TELEMETRY))  #endif @@ -352,18 +405,23 @@ ao_telemetry(void)  #ifdef AO_SEND_ALL_BARO  				ao_send_baro();  #endif +  #if HAS_FLIGHT  # ifdef AO_SEND_MEGA  				ao_send_mega_sensor();  				ao_send_mega_data(); -# else -#  ifdef AO_SEND_MINI +# endif +# ifdef AO_SEND_METRUM +				ao_send_metrum_sensor(); +				ao_send_metrum_data(); +# endif +# ifdef AO_SEND_MINI  				ao_send_mini(); -#  else +# endif +# ifdef AO_TELEMETRY_SENSOR  				ao_send_sensor(); -#  endif  # endif -#endif +#endif /* HAS_FLIGHT */  #if HAS_COMPANION  				if (ao_companion_running) @@ -380,18 +438,18 @@ ao_telemetry(void)  			if (ao_rdf &&  #if HAS_APRS  			    !(ao_config.radio_enable & AO_RADIO_DISABLE_RDF) && -#endif +#endif /* HAS_APRS */  			    (int16_t) (ao_time() - ao_rdf_time) >= 0)  			{  #if HAS_IGNITE_REPORT  				uint8_t	c; -#endif +#endif /* HAS_IGNITE_REPORT */  				ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS;  #if HAS_IGNITE_REPORT  				if (ao_flight_state == ao_flight_pad && (c = ao_report_igniter()))  					ao_radio_continuity(c);  				else -#endif +#endif /* HAS_IGNITE_REPORT*/  					ao_radio_rdf();  			}  #endif /* HAS_RDF */ @@ -402,8 +460,8 @@ ao_telemetry(void)  				ao_aprs_time = ao_time() + AO_SEC_TO_TICKS(ao_config.aprs_interval);  				ao_aprs_send();  			} -#endif -#endif +#endif /* HAS_APRS */ +#endif /* !AO_SEND_ALL_BARO */  			time += ao_telemetry_interval;  			delay = time - ao_time();  			if (delay > 0) { @@ -433,6 +491,12 @@ ao_telemetry_set_interval(uint16_t interval)  		cur++;  	ao_telemetry_mega_data_cur = cur;  #endif +#if AO_SEND_METRUM +	ao_telemetry_metrum_data_max = AO_SEC_TO_TICKS(1) / interval; +	if (ao_telemetry_metrum_data_max > cur) +		cur++; +	ao_telemetry_metrum_data_cur = cur; +#endif  #if HAS_COMPANION  	if (!ao_companion_setup.update_period) diff --git a/src/core/ao_telemetry.h b/src/core/ao_telemetry.h index 77601529..fd6b76b3 100644 --- a/src/core/ao_telemetry.h +++ b/src/core/ao_telemetry.h @@ -207,6 +207,47 @@ struct ao_telemetry_mega_data {  }; +#define AO_TELEMETRY_METRUM_SENSOR	0x0A + +struct ao_telemetry_metrum_sensor { +	uint16_t	serial;		/*  0 */ +	uint16_t	tick;		/*  2 */ +	uint8_t		type;		/*  4 */ + +	uint8_t         state;          /*  5 flight state */ +	int16_t		accel;		/*  6 Z axis */ + +	int32_t		pres;		/*  8 Pa * 10 */ +	int16_t		temp;		/* 12 °C * 100 */ + +	int16_t         acceleration;   /* 14 m/s² * 16 */ +	int16_t         speed;          /* 16 m/s * 16 */ +	int16_t         height;         /* 18 m */ + +	int16_t		v_batt;		/* 20 battery voltage */ +	int16_t		sense_a;	/* 22 apogee continuity sense */ +	int16_t		sense_m;	/* 24 main continuity sense */ + +	uint8_t		pad[6];		/* 26 */ +	/* 32 */ +}; +	 +#define AO_TELEMETRY_METRUM_DATA	0x0B + +struct ao_telemetry_metrum_data { +	uint16_t	serial;		/*  0 */ +	uint16_t	tick;		/*  2 */ +	uint8_t		type;		/*  4 */ + +	int32_t		ground_pres;	/* 8 average pres on pad */ +	int16_t		ground_accel;	/* 12 average accel on pad */ +	int16_t		accel_plus_g;	/* 14 accel calibration at +1g */ +	int16_t		accel_minus_g;	/* 16 accel calibration at -1g */ + +	uint8_t		pad[14];	/* 18 */ +	/* 32 */ +}; +  #define AO_TELEMETRY_MINI		0x10  struct ao_telemetry_mini { @@ -215,7 +256,6 @@ struct ao_telemetry_mini {  	uint8_t		type;		/*  4 */  	uint8_t         state;          /*  5 flight state */ -  	int16_t		v_batt;		/*  6 battery voltage */  	int16_t		sense_a;	/*  8 apogee continuity */  	int16_t		sense_m;	/* 10 main continuity */ @@ -266,6 +306,8 @@ union ao_telemetry_all {  	struct ao_telemetry_companion		companion;  	struct ao_telemetry_mega_sensor		mega_sensor;  	struct ao_telemetry_mega_data		mega_data; +	struct ao_telemetry_metrum_sensor	metrum_sensor; +	struct ao_telemetry_metrum_data		metrum_data;  	struct ao_telemetry_mini		mini;  	struct ao_telemetry_baro		baro;  }; diff --git a/src/drivers/ao_gps_ublox.c b/src/drivers/ao_gps_ublox.c index fa6ff0e0..1bc2a68f 100644 --- a/src/drivers/ao_gps_ublox.c +++ b/src/drivers/ao_gps_ublox.c @@ -21,26 +21,36 @@  #include "ao_gps_ublox.h" +#define AO_UBLOX_DEBUG 1 + +#include <stdarg.h> +  __xdata uint8_t ao_gps_mutex;  __pdata uint16_t ao_gps_tick;  __xdata struct ao_telemetry_location	ao_gps_data;  __xdata struct ao_telemetry_satellite	ao_gps_tracking_data; +#undef AO_SERIAL_SPEED_UBLOX +  #ifndef AO_SERIAL_SPEED_UBLOX -#define AO_SERIAL_SPEED_UBLOX AO_SERIAL_SPEED_57600 +#define AO_SERIAL_SPEED_UBLOX AO_SERIAL_SPEED_9600  #endif  #if AO_SERIAL_SPEED_UBLOX == AO_SERIAL_SPEED_57600  #define SERIAL_SPEED_STRING	"57600" +#define SERIAL_SPEED_CHECKSUM	"2d"  #endif  #if AO_SERIAL_SPEED_UBLOX == AO_SERIAL_SPEED_19200  #define SERIAL_SPEED_STRING	"19200" +#define SERIAL_SPEED_CHECKSUM	"23"  #endif  #if AO_SERIAL_SPEED_UBLOX == AO_SERIAL_SPEED_9600  #define SERIAL_SPEED_STRING	"9600" +#define SERIAL_SPEED_CHECKSUM	"16"  #endif -static const char ao_gps_set_nmea[] = "\r\n$PUBX,41,1,3,1," SERIAL_SPEED_STRING ",0*2d\r\n"; +static const char ao_gps_set_nmea[] = +	"\r\n$PUBX,41,1,3,1," SERIAL_SPEED_STRING ",0*" SERIAL_SPEED_CHECKSUM "\r\n";  struct ao_ublox_cksum {  	uint8_t	a, b; @@ -49,7 +59,34 @@ struct ao_ublox_cksum {  static __pdata struct ao_ublox_cksum ao_ublox_cksum;  static __pdata uint16_t ao_ublox_len; -#define ao_ublox_byte()	((uint8_t) ao_gps_getchar()) +#if AO_UBLOX_DEBUG + +static uint8_t ao_gps_dbg_enable; + +#define DBG_PROTO	1 +#define DBG_CHAR	2 +#define DBG_INIT	4 + +static void ao_gps_dbg(int level, char *format, ...) { +	va_list a; + +	if (level & ao_gps_dbg_enable) { +		va_start(a, format); +		vprintf(format, a); +		va_end(a); +		flush(); +	} +} + +#else +#define ao_gps_dbg(fmt, ...) +#endif + +static inline uint8_t ao_ublox_byte(void) { +	uint8_t	c = (uint8_t) ao_gps_getchar(); +	ao_gps_dbg(DBG_CHAR, " %02x", c); +	return c; +}  static inline void add_cksum(struct ao_ublox_cksum *cksum, uint8_t c)  { @@ -65,6 +102,7 @@ static void ao_ublox_init_cksum(void)  static void ao_ublox_put_u8(uint8_t c)  {  	add_cksum(&ao_ublox_cksum, c); +	ao_gps_dbg(DBG_CHAR, " (%02x)", c);  	ao_gps_putchar(c);  } @@ -187,6 +225,7 @@ ao_ublox_parse(void __xdata *target, const struct ublox_packet_parse *parse) __r  			break;  		}  	} +	ao_gps_dbg(DBG_PROTO, "\n");  }  /* @@ -330,6 +369,7 @@ ao_ublox_parse_nav_svinfo(void)  {  	uint8_t	nsat;  	nav_svinfo_nsat = 0; +  	ao_ublox_parse(&nav_svinfo, nav_svinfo_packet);  	for (nsat = 0; nsat < nav_svinfo.num_ch && ao_ublox_len >= 12; nsat++) {  		if (nsat < NAV_SVINFO_MAX_SAT) { @@ -338,6 +378,17 @@ ao_ublox_parse_nav_svinfo(void)  			ublox_discard(12);  		}  	} +#if AO_UBLOX_DEBUG +	ao_gps_dbg(DBG_PROTO, "svinfo num_ch %d flags %02x\n", nav_svinfo.num_ch, nav_svinfo.flags); +	for (nsat = 0; nsat < nav_svinfo.num_ch; nsat++) +		ao_gps_dbg(DBG_PROTO, "\t%d: chn %d svid %d flags %02x quality %d cno %d\n", +			    nsat, +			    nav_svinfo_sat[nsat].chn, +			    nav_svinfo_sat[nsat].svid, +			    nav_svinfo_sat[nsat].flags, +			    nav_svinfo_sat[nsat].quality, +			    nav_svinfo_sat[nsat].cno); +#endif  }  /* @@ -406,42 +457,52 @@ ao_ublox_parse_nav_velned(void)   */  static void -ao_gps_setup(void) +ao_gps_delay(void)  { -	uint8_t	i, k; - -	ao_delay(AO_SEC_TO_TICKS(3)); - -	ao_gps_set_speed(AO_SERIAL_SPEED_9600); +	uint8_t i;  	/*  	 * A bunch of nulls so the start bit  	 * is clear  	 */ +  	for (i = 0; i < 64; i++)  		ao_gps_putchar(0x00); +} + +static void +ao_gps_setup(void) +{ +	uint8_t	i, k; + +	ao_delay(AO_SEC_TO_TICKS(3)); + +	ao_gps_dbg(DBG_INIT, "Set speed 9600\n"); +	ao_gps_set_speed(AO_SERIAL_SPEED_9600);  	/*  	 * Send the baud-rate setting and protocol-setting  	 * command three times  	 */ -	for (k = 0; k < 3; k++) +	for (k = 0; k < 3; k++) { +		ao_gps_delay(); + +		ao_gps_dbg(DBG_INIT, "Send initial setting\n");  		for (i = 0; i < sizeof (ao_gps_set_nmea); i++)  			ao_gps_putchar(ao_gps_set_nmea[i]); +	} + +	ao_gps_delay();  #if AO_SERIAL_SPEED_UBLOX != AO_SERIAL_SPEED_9600 +	ao_gps_dbg(DBG_INIT, "Set speed high\n");  	/*  	 * Increase the baud rate  	 */  	ao_gps_set_speed(AO_SERIAL_SPEED_UBLOX);  #endif -	/* -	 * Pad with nulls to give the chip -	 * time to see the baud rate switch -	 */ -	for (i = 0; i < 64; i++) -		ao_gps_putchar(0x00); +	ao_gps_delay();  }  static void @@ -556,7 +617,7 @@ ao_gps(void) __reentrant  	/* Enable all of the messages we want */  	for (i = 0; i < sizeof (ublox_enable_nav); i++)  		ao_ublox_set_message_rate(UBLOX_NAV, ublox_enable_nav[i], 1); -	 +  	ao_ublox_set_navigation_settings((1 << UBLOX_CFG_NAV5_MASK_DYN) | (1 << UBLOX_CFG_NAV5_MASK_FIXMODE),  					 UBLOX_CFG_NAV5_DYNMODEL_AIRBORNE_4G,  					 UBLOX_CFG_NAV5_FIXMODE_3D, @@ -587,6 +648,8 @@ ao_gps(void) __reentrant  		ao_ublox_len = header_byte();  		ao_ublox_len |= header_byte() << 8; +		ao_gps_dbg(DBG_PROTO, "class %02x id %02x len %d\n", class, id, ao_ublox_len); +  		if (ao_ublox_len > 1023)  			continue; @@ -627,8 +690,10 @@ ao_gps(void) __reentrant  			break;  		} -		if (ao_ublox_len != 0) +		if (ao_ublox_len != 0) { +			ao_gps_dbg(DBG_PROTO, "len left %d\n", ao_ublox_len);  			continue; +		}  		/* verify checksum and end sequence */  		cksum.a = ao_ublox_byte(); @@ -654,7 +719,7 @@ ao_gps(void) __reentrant  				}  				if (nav_timeutc.valid & (1 << NAV_TIMEUTC_VALID_UTC))  					ao_gps_data.flags |= AO_GPS_DATE_VALID; -				 +  				ao_gps_data.altitude = nav_posllh.alt_msl / 1000;  				ao_gps_data.latitude = nav_posllh.lat;  				ao_gps_data.longitude = nav_posllh.lon; @@ -676,7 +741,7 @@ ao_gps(void) __reentrant  				ao_gps_data.ground_speed = nav_velned.g_speed;  				ao_gps_data.climb_rate = -nav_velned.vel_d;  				ao_gps_data.course = nav_velned.heading / 200000; -				 +  				ao_gps_tracking_data.channels = 0;  				struct ao_telemetry_satellite_info *dst = &ao_gps_tracking_data.sats[0]; @@ -704,8 +769,24 @@ ao_gps(void) __reentrant  	}  } +#if AO_UBLOX_DEBUG +static void ao_gps_option(void) +{ +	ao_cmd_hex(); +	if (ao_cmd_status != ao_cmd_success) { +		ao_cmd_status = ao_cmd_success; +		ao_gps_show(); +	} else { +		ao_gps_dbg_enable = ao_cmd_lex_i; +		printf ("gps debug set to %d\n", ao_gps_dbg_enable); +	} +} +#else +#define ao_gps_option ao_gps_show +#endif +  __code struct ao_cmds ao_gps_cmds[] = { -	{ ao_gps_show, 	"g\0Display GPS" }, +	{ ao_gps_option, 	"g\0Display GPS" },  	{ 0, NULL },  }; diff --git a/src/stm/Makefile-flash.defs b/src/stm/Makefile-flash.defs index 016bb7e7..86f76d46 100644 --- a/src/stm/Makefile-flash.defs +++ b/src/stm/Makefile-flash.defs @@ -6,7 +6,7 @@ vpath ao-make-product.5c $(TOPDIR)/util  .elf.ihx:  	objcopy -O ihex $*.elf $@ -CC=arm-none-eabi-gcc +CC=/opt/cortex/bin/arm-none-eabi-gcc  SAT=/opt/cortex  SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a  SAT_CFLAGS=-I$(SAT)/include diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index adc288c3..42fe727a 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -34,6 +34,8 @@  #define AO_TICK_SIGNED	int16_t  #endif +#define AO_PORT_TYPE	uint16_t +  /* Various definitions to make GCC look more like SDCC */  #define ao_arch_naked_declare	__attribute__((naked)) diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 6fe86e62..9bb2d7cd 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -338,6 +338,11 @@ static inline void ao_arch_restore_stack(void) {  	asm("bx lr");  } +#ifndef HAS_SAMPLE_PROFILE +#define HAS_SAMPLE_PROFILE 0 +#endif + +#if !HAS_SAMPLE_PROFILE  #define HAS_ARCH_START_SCHEDULER	1  static inline void ao_arch_start_scheduler(void) { @@ -350,15 +355,17 @@ static inline void ao_arch_start_scheduler(void) {  	control |= (1 << 1);  	asm("msr control,%0" : : "r" (control));  } +#endif  #define ao_arch_isr_stack()  #endif -#define ao_arch_wait_interrupt() do {			\ -		asm(".global ao_idle_loc\n\twfi\nao_idle_loc:");	\ -		ao_arch_release_interrupts();				\ -		ao_arch_block_interrupts();				\ +#define ao_arch_wait_interrupt() do {				\ +		asm("\twfi\n");					\ +		ao_arch_release_interrupts();			\ +		asm(".global ao_idle_loc\nao_idle_loc:");	\ +		ao_arch_block_interrupts();			\  	} while (0)  #define ao_arch_critical(b) do {				\ diff --git a/src/stm/ao_beep_stm.c b/src/stm/ao_beep_stm.c index 4761fbfc..a95d869b 100644 --- a/src/stm/ao_beep_stm.c +++ b/src/stm/ao_beep_stm.c @@ -17,6 +17,10 @@  #include "ao.h" +#ifndef BEEPER_CHANNEL +#define BEEPER_CHANNEL	1 +#endif +  void  ao_beep(uint8_t beep)  { @@ -56,6 +60,7 @@ ao_beep(uint8_t beep)  		 *  is enabled and active high.  		 */ +#if BEEPER_CHANNEL == 1  		stm_tim3.ccmr1 = ((0 << STM_TIM234_CCMR1_OC2CE) |  				  (STM_TIM234_CCMR1_OC2M_FROZEN << STM_TIM234_CCMR1_OC2M) |  				  (0 << STM_TIM234_CCMR1_OC2PE) | @@ -68,7 +73,6 @@ ao_beep(uint8_t beep)  				  (0 << STM_TIM234_CCMR1_OC1FE) |  				  (STM_TIM234_CCMR1_CC1S_OUTPUT << STM_TIM234_CCMR1_CC1S)); -  		stm_tim3.ccer = ((0 << STM_TIM234_CCER_CC4NP) |  				 (0 << STM_TIM234_CCER_CC4P) |  				 (0 << STM_TIM234_CCER_CC4E) | @@ -81,6 +85,33 @@ ao_beep(uint8_t beep)  				 (0 << STM_TIM234_CCER_CC1NP) |  				 (0 << STM_TIM234_CCER_CC1P) |  				 (1 << STM_TIM234_CCER_CC1E)); +#endif +#if BEEPER_CHANNEL == 4 +		stm_tim3.ccmr2 = ((0 << STM_TIM234_CCMR2_OC4CE) | +				  (STM_TIM234_CCMR2_OC4M_TOGGLE << STM_TIM234_CCMR2_OC4M) | +				  (0 << STM_TIM234_CCMR2_OC4PE) | +				  (0 << STM_TIM234_CCMR2_OC4FE) | +				  (STM_TIM234_CCMR2_CC4S_OUTPUT << STM_TIM234_CCMR2_CC4S) | + +				  (0 << STM_TIM234_CCMR2_OC3CE) | +				  (STM_TIM234_CCMR2_OC3M_FROZEN << STM_TIM234_CCMR2_OC3M) | +				  (0 << STM_TIM234_CCMR2_OC3PE) | +				  (0 << STM_TIM234_CCMR2_OC3FE) | +				  (STM_TIM234_CCMR2_CC3S_OUTPUT << STM_TIM234_CCMR2_CC3S)); + +		stm_tim3.ccer = ((0 << STM_TIM234_CCER_CC4NP) | +				 (0 << STM_TIM234_CCER_CC4P) | +				 (1 << STM_TIM234_CCER_CC4E) | +				 (0 << STM_TIM234_CCER_CC3NP) | +				 (0 << STM_TIM234_CCER_CC3P) | +				 (0 << STM_TIM234_CCER_CC3E) | +				 (0 << STM_TIM234_CCER_CC2NP) | +				 (0 << STM_TIM234_CCER_CC2P) | +				 (0 << STM_TIM234_CCER_CC2E) | +				 (0 << STM_TIM234_CCER_CC1NP) | +				 (0 << STM_TIM234_CCER_CC1P) | +				 (0 << STM_TIM234_CCER_CC1E)); +#endif  		/* 5. Enable the counter by setting the CEN bit in the TIMx_CR1 register. */ @@ -110,13 +141,22 @@ ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant  void  ao_beep_init(void)  { -	/* Our beeper is on PC6, which is hooked to TIM3_CH1, -	 * which is on PC6 -	 */ +#if BEEPER_CHANNEL == 1 +	/* Our beeper is on PC6, which is hooked to TIM3_CH1. +	 */  	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN);  	stm_afr_set(&stm_gpioc, 6, STM_AFR_AF2); +#endif +#if BEEPER_CHANNEL == 4 + +	/* Our beeper is on PB1, which is hooked to TIM3_CH4. +	 */ +	stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + +	stm_afr_set(&stm_gpiob, 1, STM_AFR_AF2); +#endif  	/* Leave the timer off until requested */ diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index daf2f400..34f9edb9 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -67,20 +67,6 @@ ao_timer_set_adc_interval(uint8_t interval)  }  #endif -/* - * According to the STM clock-configuration, timers run - * twice as fast as the APB1 clock *if* the APB1 prescaler - * is greater than 1. - */ - -#if AO_APB1_PRESCALER > 1 -#define TIMER_23467_SCALER 2 -#else -#define TIMER_23467_SCALER 1 -#endif - -#define TIMER_10kHz	((AO_PCLK1 * TIMER_23467_SCALER) / 10000) -  #define SYSTICK_RELOAD (AO_SYSTICK / 100 - 1)  void @@ -104,7 +90,15 @@ ao_clock_init(void)  	/* Switch to MSI while messing about */  	stm_rcc.cr |= (1 << STM_RCC_CR_MSION);  	while (!(stm_rcc.cr & (1 << STM_RCC_CR_MSIRDY))) -		asm("nop"); +		ao_arch_nop(); + +	stm_rcc.cfgr = (stm_rcc.cfgr & ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW)) | +		(STM_RCC_CFGR_SW_MSI << STM_RCC_CFGR_SW); + +	/* wait for system to switch to MSI */ +	while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != +	       (STM_RCC_CFGR_SWS_MSI << STM_RCC_CFGR_SWS)) +		ao_arch_nop();  	/* reset SW, HPRE, PPRE1, PPRE2, MCOSEL and MCOPRE */  	stm_rcc.cfgr &= (uint32_t)0x88FFC00C; @@ -155,7 +149,6 @@ ao_clock_init(void)  	stm_flash.acr |= (1 << STM_FLASH_ACR_PRFEN);  	/* Enable 1 wait state so the CPU can run at 32MHz */ -	/* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */  	stm_flash.acr |= (1 << STM_FLASH_ACR_LATENCY);  	/* Enable power interface clock */ diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 1868468f..ff3f5336 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1739,7 +1739,7 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4;  #define  STM_TIM234_CCMR1_CC1S_INPUT_TRC		3  #define  STM_TIM234_CCMR1_CC1S_MASK			3 -#define STM_TIM234_CCMR2_OC2CE	15 +#define STM_TIM234_CCMR2_OC4CE	15  #define STM_TIM234_CCMR2_OC4M	12  #define  STM_TIM234_CCMR2_OC4M_FROZEN			0  #define  STM_TIM234_CCMR2_OC4M_SET_HIGH_ON_MATCH	1 diff --git a/src/telemetrum-v2.0/.gitignore b/src/telemetrum-v2.0/.gitignore new file mode 100644 index 00000000..35ce24d4 --- /dev/null +++ b/src/telemetrum-v2.0/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +telemetrum-*.elf diff --git a/src/telemetrum-v2.0/Makefile b/src/telemetrum-v2.0/Makefile new file mode 100644 index 00000000..c03a5539 --- /dev/null +++ b/src/telemetrum-v2.0/Makefile @@ -0,0 +1,122 @@ +# +# AltOS build +# +# + +include ../stm/Makefile.defs + +INC = \ +	ao.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_companion.h \ +	ao_data.h \ +	ao_sample.h \ +	ao_pins.h \ +	altitude-pa.h \ +	ao_kalman.h \ +	ao_product.h \ +	ao_ms5607.h \ +	ao_mma655x.h \ +	ao_cc1120_CC1120.h \ +	ao_profile.h \ +	ao_task.h \ +	ao_whiten.h \ +	ao_sample_profile.h \ +	ao_mpu.h \ +	stm32l.h \ +	Makefile + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +#SAMPLE_PROFILE=ao_sample_profile.c \ +#	ao_sample_profile_timer.c +#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1 + +#STACK_GUARD=ao_mpu_stm.c +#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 + +ALTOS_SRC = \ +	ao_boot_chain.c \ +	ao_interrupt.c \ +	ao_product.c \ +	ao_romconfig.c \ +	ao_cmd.c \ +	ao_config.c \ +	ao_task.c \ +	ao_led.c \ +	ao_stdio.c \ +	ao_panic.c \ +	ao_timer.c \ +	ao_mutex.c \ +	ao_serial_stm.c \ +	ao_gps_ublox.c \ +	ao_gps_show.c \ +	ao_gps_report_metrum.c \ +	ao_ignite.c \ +	ao_freq.c \ +	ao_dma_stm.c \ +	ao_spi_stm.c \ +	ao_cc1120.c \ +	ao_fec_tx.c \ +	ao_fec_rx.c \ +	ao_data.c \ +	ao_ms5607.c \ +	ao_mma655x.c \ +	ao_adc_stm.c \ +	ao_beep_stm.c \ +	ao_storage.c \ +	ao_m25.c \ +	ao_usb_stm.c \ +	ao_exti_stm.c \ +	ao_report.c \ +	ao_convert_pa.c \ +	ao_log.c \ +	ao_log_metrum.c \ +	ao_sample.c \ +	ao_kalman.c \ +	ao_flight.c \ +	ao_telemetry.c \ +	ao_packet_slave.c \ +	ao_packet.c \ +	ao_companion.c \ +	ao_aprs.c \ +	$(PROFILE) \ +	$(SAMPLE_PROFILE) \ +	$(STACK_GUARD) + +PRODUCT=TeleMetrum-v2.0 +PRODUCT_DEF=-DTELEMETRUM_V_2_0 +IDPRODUCT=0x000b + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g + +PROGNAME=telemetrum-v2.0 +PROG=$(PROGNAME)-$(VERSION).elf + +SRC=$(ALTOS_SRC) ao_telemetrum.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) + +$(PROG): Makefile $(OBJ) altos.ld +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + +../altitude-pa.h: make-altitude-pa +	nickle $< > $@ + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean:	clean + +clean: +	rm -f *.o $(PROGNAME)-*.elf +	rm -f ao_product.h + +install: + +uninstall: diff --git a/src/telemetrum-v2.0/ao_pins.h b/src/telemetrum-v2.0/ao_pins.h new file mode 100644 index 00000000..a7236b80 --- /dev/null +++ b/src/telemetrum-v2.0/ao_pins.h @@ -0,0 +1,290 @@ +/* + * 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_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_TASK_QUEUE		1 + +/* 8MHz High speed external crystal */ +#define AO_HSE			8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL		12 +#define AO_RCC_CFGR_PLLMUL	(STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV		3 +#define AO_RCC_CFGR_PLLDIV	(STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER	1 +#define AO_RCC_CFGR_HPRE_DIV	STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER	2 +#define AO_RCC_CFGR_PPRE1_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER	2 +#define AO_RCC_CFGR_PPRE2_DIV	STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_SERIAL_1		0 +#define USE_SERIAL_1_STDIN	0 +#define SERIAL_1_PB6_PB7	0 +#define SERIAL_1_PA9_PA10	1 + +#define HAS_SERIAL_2		0 +#define USE_SERIAL_2_STDIN	0 +#define SERIAL_2_PA2_PA3	0 +#define SERIAL_2_PD5_PD6	0 + +#define HAS_SERIAL_3		1 +#define USE_SERIAL_3_STDIN	0 +#define SERIAL_3_PB10_PB11	1 +#define SERIAL_3_PC10_PC11	0 +#define SERIAL_3_PD8_PD9	0 + +#define HAS_EEPROM		1 +#define USE_INTERNAL_FLASH	0 +#define HAS_USB			1 +#define HAS_BEEP		1 +#define BEEPER_CHANNEL		4 +#define HAS_RADIO		1 +#define HAS_TELEMETRY		1 +#define HAS_APRS		1 + +#define HAS_SPI_1		1 +#define SPI_1_PA5_PA6_PA7	1	/* Barometer */ +#define SPI_1_PB3_PB4_PB5	1	/* Accelerometer */ +#define SPI_1_PE13_PE14_PE15	0 +#define SPI_1_OSPEEDR		STM_OSPEEDR_10MHz + +#define HAS_SPI_2		1 +#define SPI_2_PB13_PB14_PB15	1	/* Flash, Companion, Radio */ +#define SPI_2_PD1_PD3_PD4	0 +#define SPI_2_OSPEEDR		STM_OSPEEDR_10MHz + +#define SPI_2_PORT		(&stm_gpiob) +#define SPI_2_SCK_PIN		13 +#define SPI_2_MISO_PIN		14 +#define SPI_2_MOSI_PIN		15 + +#define HAS_I2C_1		0 +#define I2C_1_PB8_PB9		0 + +#define HAS_I2C_2		0 +#define I2C_2_PB10_PB11		0 + +#define PACKET_HAS_SLAVE	1 +#define PACKET_HAS_MASTER	0 + +#define LOW_LEVEL_DEBUG		0 + +#define LED_PORT_ENABLE		STM_RCC_AHBENR_GPIOCEN +#define LED_PORT		(&stm_gpioc) +#define LED_PIN_RED		14 +#define LED_PIN_GREEN		15 +#define AO_LED_RED		(1 << LED_PIN_RED) +#define AO_LED_GREEN		(1 << LED_PIN_GREEN) + +#define LEDS_AVAILABLE		(AO_LED_RED | AO_LED_GREEN) + +#define HAS_GPS			1 +#define HAS_FLIGHT		1 +#define HAS_ADC			1 +#define HAS_ADC_TEMP		1 +#define HAS_LOG			1 + +/* + * Igniter + */ + +#define HAS_IGNITE		1 +#define HAS_IGNITE_REPORT	1 + +#define AO_SENSE_DROGUE(p)	((p)->adc.sense_a) +#define AO_SENSE_MAIN(p)	((p)->adc.sense_m) +#define AO_IGNITER_CLOSED	400 +#define AO_IGNITER_OPEN		60 + +/* Drogue */ +#define AO_IGNITER_DROGUE_PORT	(&stm_gpioa) +#define AO_IGNITER_DROGUE_PIN	8 + +/* Main */ +#define AO_IGNITER_MAIN_PORT	(&stm_gpioa) +#define AO_IGNITER_MAIN_PIN	9 + +#define AO_IGNITER_SET_DROGUE(v)	stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v) +#define AO_IGNITER_SET_MAIN(v)		stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v) + +/* + * ADC + */ +#define AO_DATA_RING		32 +#define AO_ADC_NUM_SENSE	2 + +struct ao_adc { +	int16_t			sense_a; +	int16_t			sense_m; +	int16_t			v_batt; +	int16_t			temp; +}; + +#define AO_ADC_DUMP(p) \ +	printf("tick: %5u drogue: %5d main: %5d batt: %5d\n", \ +	       (p)->tick, \ +	       (p)->adc.sense_a, (p)->adc.sense_m, \ +	       (p)->adc.v_batt); + +#define AO_ADC_SENSE_DROGUE	0 +#define AO_ADC_SENSE_DROGUE_PORT	(&stm_gpioa) +#define AO_ADC_SENSE_DROGUE_PIN	0 + +#define AO_ADC_SENSE_MAIN	1 +#define AO_ADC_SENSE_MAIN_PORT	(&stm_gpioa) +#define AO_ADC_SENSE_MAIN_PIN	1 + +#define AO_ADC_V_BATT		8 +#define AO_ADC_V_BATT_PORT	(&stm_gpiob) +#define AO_ADC_V_BATT_PIN	0 + +#define AO_ADC_TEMP		16 + +#define AO_ADC_RCC_AHBENR	((1 << STM_RCC_AHBENR_GPIOAEN) | \ +				 (1 << STM_RCC_AHBENR_GPIOEEN) | \ +				 (1 << STM_RCC_AHBENR_GPIOBEN)) + +#define AO_NUM_ADC_PIN		3 + +#define AO_ADC_PIN0_PORT	AO_ADC_SENSE_DROGUE_PORT +#define AO_ADC_PIN0_PIN		AO_ADC_SENSE_DROGUE_PIN +#define AO_ADC_PIN1_PORT	AO_ADC_SENSE_MAIN_PORT +#define AO_ADC_PIN1_PIN		AO_ADC_SENSE_MAIN_PIN +#define AO_ADC_PIN2_PORT	AO_ADC_V_BATT_PORT +#define AO_ADC_PIN2_PIN		AO_ADC_V_BATT_PIN + +#define AO_NUM_ADC	       	(AO_NUM_ADC_PIN + 1) + +#define AO_ADC_SQ1		AO_ADC_SENSE_DROGUE +#define AO_ADC_SQ2		AO_ADC_SENSE_MAIN +#define AO_ADC_SQ3		AO_ADC_V_BATT +#define AO_ADC_SQ4		AO_ADC_TEMP + +/* + * GPS + */ + +#define AO_SERIAL_SPEED_UBLOX	AO_SERIAL_SPEED_9600 + +#define ao_gps_getchar		ao_serial3_getchar +#define ao_gps_putchar		ao_serial3_putchar +#define ao_gps_set_speed	ao_serial3_set_speed +#define ao_gps_fifo		(ao_stm_usart3.rx_fifo) + +/* + * Pressure sensor settings + */ +#define HAS_MS5607		1 +#define HAS_MS5611		0 +#define AO_MS5607_PRIVATE_PINS	1 +#define AO_MS5607_CS_PORT	(&stm_gpiob) +#define AO_MS5607_CS_PIN	12 +#define AO_MS5607_CS_MASK	(1 << AO_MS5607_CS) +#define AO_MS5607_MISO_PORT	(&stm_gpioa) +#define AO_MS5607_MISO_PIN	6 +#define AO_MS5607_MISO_MASK	(1 << AO_MS5607_MISO) +#define AO_MS5607_SPI_INDEX	AO_SPI_1_PA5_PA6_PA7 + +/* + * SPI Flash memory + */ + +#define M25_MAX_CHIPS		1 +#define AO_M25_SPI_CS_PORT	(&stm_gpiob) +#define AO_M25_SPI_CS_MASK	(1 << 8) +#define AO_M25_SPI_BUS		AO_SPI_2_PB13_PB14_PB15 + +/* + * Radio (cc1120) + */ + +/* gets pretty close to 434.550 */ + +#define AO_RADIO_CAL_DEFAULT 	0x6ca333 + +#define AO_FEC_DEBUG		0 +#define AO_CC1120_SPI_CS_PORT	(&stm_gpioa) +#define AO_CC1120_SPI_CS_PIN	2 +#define AO_CC1120_SPI_BUS	AO_SPI_2_PB13_PB14_PB15 +#define AO_CC1120_SPI		stm_spi2 + +#define AO_CC1120_INT_PORT		(&stm_gpioa) +#define AO_CC1120_INT_PIN		(3) +#define AO_CC1120_MCU_WAKEUP_PORT	(&stm_gpioa) +#define AO_CC1120_MCU_WAKEUP_PIN	(4) + +#define AO_CC1120_INT_GPIO	2 +#define AO_CC1120_INT_GPIO_IOCFG	CC1120_IOCFG2 + +#define AO_CC1120_MARC_GPIO	3 +#define AO_CC1120_MARC_GPIO_IOCFG	CC1120_IOCFG3 + +#define HAS_BOOT_RADIO		0 + +#define HAS_HIGHG_ACCEL		1 + +/* + * mma655x + */ + +#define HAS_MMA655X		1 +#define AO_MMA655X_SPI_INDEX	AO_SPI_1_PB3_PB4_PB5 +#define AO_MMA655X_CS_PORT	(&stm_gpiob) +#define AO_MMA655X_CS_PIN	9 +#define AO_MMA655X_INVERT	1 + +#define NUM_CMDS		16 + +/* + * Companion + */ + +#define AO_COMPANION_CS_PORT	(&stm_gpiob) +#define AO_COMPANION_CS_PIN	(6) +#define AO_COMPANION_SPI_BUS	AO_SPI_2_PB13_PB14_PB15 + +/* + * Monitor + */ + +#define HAS_MONITOR		0 +#define LEGACY_MONITOR		0 +#define HAS_MONITOR_PUT		1 +#define AO_MONITOR_LED		0 +#define HAS_RSSI		0 + +/* + * Profiling Viterbi decoding + */ + +#ifndef AO_PROFILE +#define AO_PROFILE	       	0 +#endif + +#endif /* _AO_PINS_H_ */ diff --git a/src/telemetrum-v2.0/ao_telemetrum.c b/src/telemetrum-v2.0/ao_telemetrum.c new file mode 100644 index 00000000..e365417d --- /dev/null +++ b/src/telemetrum-v2.0/ao_telemetrum.c @@ -0,0 +1,90 @@ +/* + * Copyright © 2011 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> +#include <ao_ms5607.h> +#include <ao_mma655x.h> +#include <ao_log.h> +#include <ao_exti.h> +#include <ao_packet.h> +#include <ao_companion.h> +#include <ao_profile.h> +#if HAS_SAMPLE_PROFILE +#include <ao_sample_profile.h> +#endif +#if HAS_STACK_GUARD +#include <ao_mpu.h> +#endif + +int +main(void) +{ +	ao_clock_init(); +	 +#if HAS_STACK_GUARD +	ao_mpu_init(); +#endif + +	ao_task_init(); +	ao_serial_init(); +	ao_led_init(LEDS_AVAILABLE); +	ao_led_on(AO_LED_GREEN); +	ao_timer_init(); + +	ao_spi_init(); +	ao_dma_init(); +	ao_exti_init(); + +	ao_adc_init(); +#if HAS_BEEP +	ao_beep_init(); +#endif +	ao_cmd_init(); + +#if HAS_MS5607 +	ao_ms5607_init(); +#endif +#if HAS_MMA655X +	ao_mma655x_init(); +#endif + +	ao_storage_init(); +	 +	ao_flight_init(); +	ao_log_init(); +	ao_report_init(); + +	ao_usb_init(); +	ao_gps_init(); +	ao_gps_report_metrum_init(); +	ao_telemetry_init(); +	ao_radio_init(); +	ao_packet_slave_init(FALSE); +	ao_igniter_init(); +	ao_companion_init(); + +	ao_config_init(); +#if AO_PROFILE +	ao_profile_init(); +#endif +#if HAS_SAMPLE_PROFILE +	ao_sample_profile_init(); +#endif +	 +	ao_start_scheduler(); +	return 0; +} diff --git a/src/telemetrum-v2.0/flash-loader/Makefile b/src/telemetrum-v2.0/flash-loader/Makefile new file mode 100644 index 00000000..cb99c51e --- /dev/null +++ b/src/telemetrum-v2.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telemetrum-v2.0 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telemetrum-v2.0/flash-loader/ao_pins.h b/src/telemetrum-v2.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..304bb7c3 --- /dev/null +++ b/src/telemetrum-v2.0/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 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_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE		8000000 + +#include <ao_flash_stm_pins.h> + +/* Companion port cs_companion0 PB6 */ + +#define AO_BOOT_PIN			1 +#define AO_BOOT_APPLICATION_GPIO	stm_gpiob +#define AO_BOOT_APPLICATION_PIN		6 +#define AO_BOOT_APPLICATION_VALUE	1 +#define AO_BOOT_APPLICATION_MODE	AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ | 
