diff options
Diffstat (limited to 'src/core')
| -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_telemetry.c | 66 | ||||
| -rw-r--r-- | src/core/ao_telemetry.h | 44 | 
5 files changed, 461 insertions, 0 deletions
| 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..9c17eeed --- /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[0]; +				log.u.volt.sense_m = ao_data_ring[ao_log_data_pos].adc.sense[1]; +				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_telemetry.c b/src/core/ao_telemetry.c index 03a8a273..fb40451c 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,57 @@ 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.tick = packet->tick; +	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[0]; +	telemetry.metrum_sensor.sense_m = packet->adc.sense[1]; + +	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_MEGA_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_MEGA */ +  #ifdef AO_SEND_ALL_BARO  static uint8_t		ao_baro_sample; @@ -327,9 +382,14 @@ ao_telemetry(void)  				ao_send_mega_sensor();  				ao_send_mega_data();  #else +#ifdef AO_SEND_METRUM +				ao_send_metrum_sensor(); +				ao_send_metrum_data(); +#else  				ao_send_sensor();  #endif  #endif +#endif  #if HAS_COMPANION  				if (ao_companion_running) @@ -399,6 +459,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 f2d201de..17dc3e93 100644 --- a/src/core/ao_telemetry.h +++ b/src/core/ao_telemetry.h @@ -207,6 +207,48 @@ 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_SEND_ALL_BARO */  #define AO_TELEMETRY_BARO		0x80 @@ -240,6 +282,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_baro		baro;  }; | 
