diff options
| author | Bdale Garbee <bdale@gag.com> | 2014-09-09 23:28:39 -0600 | 
|---|---|---|
| committer | Bdale Garbee <bdale@gag.com> | 2014-09-09 23:28:39 -0600 | 
| commit | 16405fd3eb6f82ef3a709e3ed30fc48faef7b547 (patch) | |
| tree | c111819b3ba0c9357af41c81b798326b9df7adad /src | |
| parent | 5a2f6ed6210844f7284fbf9f7ecba68c8a14fa52 (diff) | |
| parent | 28bd5057252e61bc5b1a35a00bc1f9fdfde097f7 (diff) | |
Merge branch 'branch-1.5' into debian
Conflicts:
	ChangeLog
	Releasing
	altosui/Instdrv/NSIS/Includes/java.nsh
	altosui/altos-windows.nsi.in
	configure.ac
	doc/Makefile
	doc/altusmetrum.xsl
	micropeak/micropeak-windows.nsi.in
	telegps/telegps-windows.nsi.in
Diffstat (limited to 'src')
101 files changed, 2395 insertions, 678 deletions
| diff --git a/src/Makefile b/src/Makefile index 4e8b3c20..20126de6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -22,9 +22,11 @@ SDCCDIRS=\  	telemini-v1.0 telemini-v2.0 \  	telebt-v1.0 \  	teleterra-v0.2 teleshield-v0.1 \ -	telefire-v0.1 telefire-v0.2 +	telefire-v0.1 telefire-v0.2 \ +	telerepeat-v1.0  ARMM3DIRS=\ +	easymega-v1.0 easymega-v1.0/flash-loader \  	telemega-v0.1 telemega-v0.1/flash-loader \  	telemega-v1.0 telemega-v1.0/flash-loader \  	telemetrum-v2.0 telemetrum-v2.0/flash-loader \ @@ -39,7 +41,7 @@ ARMM0DIRS=\  	easymini-v1.0 easymini-v1.0/flash-loader  AVRDIRS=\ -	telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 +	telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 microkite  SUBDIRS= @@ -98,7 +100,7 @@ uninstall:  all-recursive: all-local -all-local: altitude.h altitude-pa.h ao_kalman.h ao_whiten.h $(PDCLIB) +all-local: altitude.h altitude-pa.h altitude-pa-small.h ao_kalman.h ao_whiten.h $(PDCLIB)  altitude.h: make-altitude  	nickle $< > $@ @@ -106,7 +108,10 @@ altitude.h: make-altitude  altitude-pa.h: make-altitude-pa  	nickle $< > $@ -ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c +altitude-pa-small.h: make-altitude-pa +	nickle $< --sample 3 > $@ + +ao_kalman.h: make-kalman kalman.5c kalman_micro.5c kalman_filter.5c load_csv.5c matrix.5c  	bash $< kalman > $@  ao_whiten.h: make-whiten diff --git a/src/cc1111/ao_intflash.c b/src/cc1111/ao_intflash.c index 632e2a85..eb3535c6 100644 --- a/src/cc1111/ao_intflash.c +++ b/src/cc1111/ao_intflash.c @@ -129,6 +129,8 @@ ao_intflash_write_aligned(uint16_t pos, __xdata void *d, uint16_t len) __reentra  		nop  		_endasm;  	} +	__critical while (!ao_intflash_dma_done) +			   ao_sleep(&ao_intflash_dma_done);  }  static void diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 2b19f1f6..e12f813f 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -20,6 +20,8 @@  #define HAS_RADIO		1  #define DISABLE_LOG_SPACE	1 +#define AO_VALUE_32		0 +#define HAS_WIDE_GPS		0  #if defined(TELEMETRUM_V_1_0)  	/* Discontinued and was never built with CC1111 chips needing this */ @@ -56,6 +58,9 @@  	#define HAS_ACCEL		1  	#define HAS_IGNITE		1  	#define HAS_MONITOR		0 +	#define HAS_TELEMETRY		1 +	#define HAS_RADIO_RATE		0	/* not enough space for this */ +	#define HAS_MUTEX_TRY		0  #endif  #if defined(TELEMETRUM_V_1_1) @@ -96,6 +101,9 @@  	#define HAS_ACCEL		1  	#define HAS_IGNITE		1  	#define HAS_MONITOR		0 +	#define HAS_TELEMETRY		1 +	#define HAS_RADIO_RATE		0	/* not enough space for this */ +	#define HAS_MUTEX_TRY		0  #endif  #if defined(TELEMETRUM_V_1_2) @@ -136,6 +144,9 @@  	#define HAS_ACCEL		1  	#define HAS_IGNITE		1  	#define HAS_MONITOR		0 +	#define HAS_TELEMETRY		1 +	#define HAS_RADIO_RATE		0	/* not enough space for this */ +	#define HAS_MUTEX_TRY		0  #endif  #if defined(TELEDONGLE_V_0_2) @@ -164,6 +175,8 @@  	#define LEGACY_MONITOR		1  	#define HAS_RSSI		1  	#define HAS_AES			0 +	#define HAS_TELEMETRY		0 +	#define AO_RADIO_REG_TEST	1  #endif  #if defined(TELEMINI_V_1_0) @@ -193,6 +206,8 @@  	#define HAS_ACCEL		0  	#define HAS_IGNITE		1  	#define HAS_MONITOR		0 +	#define HAS_TELEMETRY		1 +	#define HAS_RADIO_RATE		0	/* not enough space for this */  #endif  #if defined(TELENANO_V_0_1) @@ -220,6 +235,8 @@  	#define HAS_ACCEL		0  	#define HAS_IGNITE		0  	#define HAS_MONITOR		0 +	#define HAS_TELEMETRY		1 +	#define HAS_RADIO_RATE		0	/* not enough space for this */  #endif  #if defined(TELEMETRUM_V_0_1) @@ -252,6 +269,8 @@  	#define HAS_ACCEL		1  	#define HAS_IGNITE		1  	#define HAS_MONITOR		0 +	#define HAS_TELEMETRY		1 +	#define HAS_RADIO_RATE		0	/* not enough space for this */  	#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX	((uint32_t) 127 * (uint32_t) 1024)  #endif @@ -283,6 +302,7 @@  	#define LEGACY_MONITOR		1  	#define HAS_RSSI		1  	#define HAS_AES			0 +	#define HAS_TELEMETRY		0  #endif  #if defined(TIDONGLE) @@ -312,6 +332,7 @@  	#define LEGACY_MONITOR		1  	#define HAS_RSSI		1  	#define HAS_AES			0 +	#define HAS_TELEMETRY		0  #endif  #if defined(TELEBT_V_0_0) @@ -350,6 +371,8 @@  	#define LEGACY_MONITOR		1  	#define HAS_RSSI		0  	#define HAS_AES			0 +	#define HAS_TELEMETRY		0 +	#define AO_RADIO_REG_TEST	1  #endif  #if defined(TELEBT_V_0_1) @@ -396,6 +419,8 @@  	#define LEGACY_MONITOR		1  	#define HAS_RSSI		0  	#define HAS_AES			0 +	#define HAS_TELEMETRY		0 +	#define AO_RADIO_REG_TEST	1  #endif  #if defined(TELELAUNCH_V_0_1) @@ -428,6 +453,7 @@  	#define HAS_IGNITE		1  	#define HAS_MONITOR		0  	#define HAS_AES			1 +	#define HAS_TELEMETRY		0  #endif  #if DBG_ON_P1 diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 190647ce..b9821a42 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -40,6 +40,42 @@  #define IF_FREQ_CONTROL	6  /* + *  http://www.ntia.doc.gov/files/ntia/publications/84-168.pdf + * + * Necessary bandwidth for a FSK modulated signal: + * + *	bw = 2.6d + 0.55b	1.5 < m < 5.5 + *	bw = 2.1d + 1.9b	5.5 < m < 20 + * + *	b is the modulation rate in bps + *	d is the peak deviation (from the center) + * + *	m = 2d / b + * + * 20.5 kHz deviation 38.4kbps signal: + * + *	m = 41 / 38.4, which is < 5.5: + * + *	bw = 2.6 * 20.5 + 0.55 * 38.4 = 74.42kHz + * + *	M = 1, E = 3, bw = 75kHz + * + * 5.125 kHz deviation, 9.6kbps signal + * + *	m = 10.25 / 9.6, which is < 5.5: + * + *	bw = 2.6 * 5.125 + 0.55 * 9.6 = 18.6kHz + * + *	M = 2, E = 3, bw = 53.6kHz + * + * 1.28125kHz deviation, 2.4kbps signal + * + *	m = 2.565 / 2.4, which is < 5.5: + * + *	bw = 2.6 * 20.5 + 1.9 * 2.4 = 47.61kHz + * + *	M = 3, E = 3, bw = 53.6kHz + *   * For channel bandwidth of 93.75 kHz, the CHANBW_E and CHANBW_M values are   *   * BW = 24e6 / (8 * (4 + M) * 2 ** E) @@ -47,7 +83,9 @@   * So, M = 0 and E = 3   */ -#define CHANBW_M	0 +#define CHANBW_M_384	1 +#define CHANBW_M_96	3 +#define CHANBW_M_24	3  #define CHANBW_E	3  /* @@ -55,22 +93,41 @@   *   * R = (256 + M) * 2** E * 24e6 / 2**28   * - * So M is 163 and E is 10 + * So for 38360kBaud, M is 163 and E is 10   */ -#define DRATE_E		10  #define DRATE_M		163 +#define DRATE_E_384	10 + +/* For 9600 baud, M is 163 and E is 8 + */ + +#define DRATE_E_96	8 + +/* For 2400 baud, M is 163 and E is 6 + */ + +#define DRATE_E_24	6 +  /*   * For a channel deviation of 20.5kHz, the DEVIATION_E and DEVIATION_M values are:   *   * F = 24e6/2**17 * (8 + DEVIATION_M) * 2**DEVIATION_E   * - * So M is 6 and E is 3 + * For 20.5kHz deviation, M is 6 and E is 3 + * For 5.125kHz deviation, M is 6 and E is 1 + * For 1.28125kHz deviation, M is 0 and E is 0   */ -#define DEVIATION_M	6 -#define DEVIATION_E	3 +#define DEVIATION_M_384	6 +#define DEVIATION_E_384	3 + +#define DEVIATION_M_96	6 +#define DEVIATION_E_96	1 + +#define DEVIATION_M_24	0 +#define DEVIATION_E_24	0  /*   * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone), @@ -122,13 +179,10 @@ static __code uint8_t radio_setup[] = {  	RF_FSCTRL1_OFF,		(IF_FREQ_CONTROL << RF_FSCTRL1_FREQ_IF_SHIFT),  	RF_FSCTRL0_OFF,		(0 << RF_FSCTRL0_FREQOFF_SHIFT), -	RF_MDMCFG4_OFF,		((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | -				 (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | -				 (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)),  	RF_MDMCFG3_OFF,		(DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), -	RF_MDMCFG2_OFF,		(RF_MDMCFG2_DEM_DCFILT_OFF | +	RF_MDMCFG2_OFF,		(RF_MDMCFG2_DEM_DCFILT_ON |  				 RF_MDMCFG2_MOD_FORMAT_GFSK | -				 RF_MDMCFG2_SYNC_MODE_15_16_THRES), +				 RF_MDMCFG2_SYNC_MODE_15_16),  	RF_MDMCFG1_OFF,		(RF_MDMCFG1_FEC_EN |  				 RF_MDMCFG1_NUM_PREAMBLE_4 |  				 (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), @@ -136,9 +190,6 @@ static __code uint8_t radio_setup[] = {  	RF_CHANNR_OFF,		0, -	RF_DEVIATN_OFF,		((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | -				 (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), -  	/* SmartRF says set LODIV_BUF_CURRENT_TX to 0  	 * And, we're not using power ramping, so use PA_POWER 0  	 */ @@ -155,8 +206,8 @@ static __code uint8_t radio_setup[] = {  	RF_FSCAL1_OFF,		0x00,  	RF_FSCAL0_OFF,		0x1F, -	RF_TEST2_OFF,		0x88, -	RF_TEST1_OFF,		0x31, +	RF_TEST2_OFF,		RF_TEST2_RX_LOW_DATA_RATE_MAGIC, +	RF_TEST1_OFF,		RF_TEST1_RX_LOW_DATA_RATE_MAGIC,  	RF_TEST0_OFF,		0x09,  	/* default sync values */ @@ -187,10 +238,16 @@ static __code uint8_t radio_setup[] = {  				 RF_BSCFG_BS_POST_KI_PRE_KI|  				 RF_BSCFG_BS_POST_KP_PRE_KP|  				 RF_BSCFG_BS_LIMIT_0), -	RF_AGCCTRL2_OFF,	0x03, -	RF_AGCCTRL1_OFF,	0x40, -	RF_AGCCTRL0_OFF,	0x91, - +	RF_AGCCTRL2_OFF,	(RF_AGCCTRL2_MAX_DVGA_GAIN_ALL| +				 RF_AGCCTRL2_MAX_LNA_GAIN_0| +				 RF_AGCCTRL2_MAGN_TARGET_33dB), +	RF_AGCCTRL1_OFF,	(RF_AGCCTRL1_AGC_LNA_PRIORITY_0 | +				 RF_AGCCTRL1_CARRIER_SENSE_REL_THR_DISABLE | +				 RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_0DB), +	RF_AGCCTRL0_OFF,	(RF_AGCCTRL0_HYST_LEVEL_NONE | +				 RF_AGCCTRL0_WAIT_TIME_8 | +				 RF_AGCCTRL0_AGC_FREEZE_NORMAL | +				 RF_AGCCTRL0_FILTER_LENGTH_8),  	RF_IOCFG2_OFF,		0x00,  	RF_IOCFG1_OFF,		0x00,  	RF_IOCFG0_OFF,		0x00, @@ -198,7 +255,7 @@ static __code uint8_t radio_setup[] = {  static __code uint8_t rdf_setup[] = {  	RF_MDMCFG4_OFF,		((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | -				 (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | +				 (CHANBW_M_384 << RF_MDMCFG4_CHANBW_M_SHIFT) |  				 (RDF_DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)),  	RF_MDMCFG3_OFF,		(RDF_DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT),  	RF_MDMCFG2_OFF,		(RF_MDMCFG2_DEM_DCFILT_OFF | @@ -212,26 +269,30 @@ static __code uint8_t rdf_setup[] = {  				 (RDF_DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)),  	/* packet length is set in-line */ -	RF_PKTCTRL1_OFF,	((1 << PKTCTRL1_PQT_SHIFT)| +	RF_PKTCTRL1_OFF,	((0 << PKTCTRL1_PQT_SHIFT)|  				 PKTCTRL1_ADR_CHK_NONE),  	RF_PKTCTRL0_OFF,	(RF_PKTCTRL0_PKT_FORMAT_NORMAL|  				 RF_PKTCTRL0_LENGTH_CONFIG_FIXED),  };  static __code uint8_t fixed_pkt_setup[] = { +#if !HAS_RADIO_RATE  	RF_MDMCFG4_OFF,		((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | -				 (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | -				 (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), +				 (CHANBW_M_384 << RF_MDMCFG4_CHANBW_M_SHIFT) | +				 (DRATE_E_384 << RF_MDMCFG4_DRATE_E_SHIFT)), +#endif  	RF_MDMCFG3_OFF,		(DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), -	RF_MDMCFG2_OFF,		(RF_MDMCFG2_DEM_DCFILT_OFF | +	RF_MDMCFG2_OFF,		(RF_MDMCFG2_DEM_DCFILT_ON |  				 RF_MDMCFG2_MOD_FORMAT_GFSK | -				 RF_MDMCFG2_SYNC_MODE_15_16_THRES), +				 RF_MDMCFG2_SYNC_MODE_15_16),  	RF_MDMCFG1_OFF,		(RF_MDMCFG1_FEC_EN |  				 RF_MDMCFG1_NUM_PREAMBLE_4 |  				 (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), -	RF_DEVIATN_OFF,		((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | -				 (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), +#if !HAS_RADIO_RATE +	RF_DEVIATN_OFF,		((DEVIATION_E_384 << RF_DEVIATN_DEVIATION_E_SHIFT) | +				 (DEVIATION_M_384 << RF_DEVIATN_DEVIATION_M_SHIFT)), +#endif  	/* max packet length -- now set inline */  	RF_PKTCTRL1_OFF,	((1 << PKTCTRL1_PQT_SHIFT)| @@ -243,6 +304,38 @@ static __code uint8_t fixed_pkt_setup[] = {  				 RF_PKTCTRL0_LENGTH_CONFIG_FIXED),  }; +#if HAS_RADIO_RATE +static __code struct { +	uint8_t		mdmcfg4; +	uint8_t		deviatn; +} packet_rate_setup[] = { +	/* 38400 */ +	{ +		((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | +		 (CHANBW_M_384 << RF_MDMCFG4_CHANBW_M_SHIFT) | +		 (DRATE_E_384 << RF_MDMCFG4_DRATE_E_SHIFT)), +		((DEVIATION_E_384 << RF_DEVIATN_DEVIATION_E_SHIFT) | +		 (DEVIATION_M_384 << RF_DEVIATN_DEVIATION_M_SHIFT)), +	}, +	/* 9600 */ +	{ +		((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | +		 (CHANBW_M_96 << RF_MDMCFG4_CHANBW_M_SHIFT) | +		 (DRATE_E_96 << RF_MDMCFG4_DRATE_E_SHIFT)), +		((DEVIATION_E_96 << RF_DEVIATN_DEVIATION_E_SHIFT) | +		 (DEVIATION_M_96 << RF_DEVIATN_DEVIATION_M_SHIFT)), +	}, +	/* 2400 */ +	{ +		((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | +		 (CHANBW_M_24 << RF_MDMCFG4_CHANBW_M_SHIFT) | +		 (DRATE_E_24 << RF_MDMCFG4_DRATE_E_SHIFT)), +		((DEVIATION_E_24 << RF_DEVIATN_DEVIATION_E_SHIFT) | +		 (DEVIATION_M_24 << RF_DEVIATN_DEVIATION_M_SHIFT)), +	}, +}; +#endif +  __xdata uint8_t	ao_radio_dma;  __xdata uint8_t ao_radio_dma_done;  __xdata uint8_t ao_radio_done; @@ -308,6 +401,10 @@ ao_radio_get(uint8_t len)  	RF_FREQ1 = (uint8_t) (ao_config.radio_setting >> 8);  	RF_FREQ0 = (uint8_t) (ao_config.radio_setting);  	RF_PKTLEN = len; +#if HAS_RADIO_RATE +	RF_MDMCFG4 = packet_rate_setup[ao_config.radio_rate].mdmcfg4; +	RF_DEVIATN = packet_rate_setup[ao_config.radio_rate].deviatn; +#endif  } @@ -551,8 +648,31 @@ ao_radio_test_cmd(void)  		ao_radio_test(0);  } +#if AO_RADIO_REG_TEST +static void +ao_radio_set_reg(void) +{ +	uint8_t	offset; +	ao_cmd_hex(); +	offset = ao_cmd_lex_i; +	if (ao_cmd_status != ao_cmd_success) +		return; +	ao_cmd_hex(); +	printf("RF[%x] %x", offset, RF[offset]); +	if (ao_cmd_status == ao_cmd_success) { +		RF[offset] = ao_cmd_lex_i; +		printf (" -> %x", RF[offset]); +	} +	ao_cmd_status = ao_cmd_success; +	printf("\n"); +} +#endif +  __code struct ao_cmds ao_radio_cmds[] = {  	{ ao_radio_test_cmd,	"C <1 start, 0 stop, none both>\0Radio carrier test" }, +#if AO_RADIO_REG_TEST +	{ ao_radio_set_reg,	"V <offset> <value>\0Set radio register" }, +#endif  	{ 0,	NULL },  }; diff --git a/src/cc1111/cc1111.h b/src/cc1111/cc1111.h index 80d3fb70..ac1e71c9 100644 --- a/src/cc1111/cc1111.h +++ b/src/cc1111/cc1111.h @@ -1165,12 +1165,73 @@ __xdata __at (0xdf16) uint8_t RF_BSCFG;  __xdata __at (0xdf17) uint8_t RF_AGCCTRL2;  #define RF_AGCCTRL2_OFF	0x17 +#define RF_AGCCTRL2_MAX_DVGA_GAIN_ALL		(0 << 6) +#define RF_AGCCTRL2_MAX_DVGA_GAIN_BUT_1		(1 << 6) +#define RF_AGCCTRL2_MAX_DVGA_GAIN_BUT_2		(2 << 6) +#define RF_AGCCTRL2_MAX_DVGA_GAIN_BUT_3		(3 << 6) +#define RF_AGCCTRL2_MAX_LNA_GAIN_0		(0 << 3) +#define RF_AGCCTRL2_MAX_LNA_GAIN_2_6		(1 << 3) +#define RF_AGCCTRL2_MAX_LNA_GAIN_6_1		(2 << 3) +#define RF_AGCCTRL2_MAX_LNA_GAIN_7_4		(3 << 3) +#define RF_AGCCTRL2_MAX_LNA_GAIN_9_2		(4 << 3) +#define RF_AGCCTRL2_MAX_LNA_GAIN_11_5		(5 << 3) +#define RF_AGCCTRL2_MAX_LNA_GAIN_14_6		(6 << 3) +#define RF_AGCCTRL2_MAX_LNA_GAIN_17_1		(7 << 3) +#define RF_AGCCTRL2_MAGN_TARGET_24dB		(0 << 0) +#define RF_AGCCTRL2_MAGN_TARGET_27dB		(1 << 0) +#define RF_AGCCTRL2_MAGN_TARGET_30dB		(2 << 0) +#define RF_AGCCTRL2_MAGN_TARGET_33dB		(3 << 0) +#define RF_AGCCTRL2_MAGN_TARGET_36dB		(4 << 0) +#define RF_AGCCTRL2_MAGN_TARGET_38dB		(5 << 0) +#define RF_AGCCTRL2_MAGN_TARGET_40dB		(6 << 0) +#define RF_AGCCTRL2_MAGN_TARGET_42dB		(7 << 0) +  __xdata __at (0xdf18) uint8_t RF_AGCCTRL1;  #define RF_AGCCTRL1_OFF	0x18 +#define RF_AGCCTRL1_AGC_LNA_PRIORITY_0		(0 << 6) +#define RF_AGCCTRL1_AGC_LNA_PRIORITY_1		(1 << 6) +#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_DISABLE	(0 << 4) +#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_6DB		(1 << 4) +#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_10DB		(2 << 4) +#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_14DB		(3 << 4) +#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_DISABLE	(0x8 << 0) +#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_7DB_BELOW	(0x9 << 0) +#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_6DB_BELOW	(0xa << 0) +#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_5DB_BELOW	(0xb << 0) +#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_4DB_BELOW	(0xc << 0) +#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_3DB_BELOW	(0xd << 0) +#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_2DB_BELOW	(0xe << 0) +#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_1DB_BELOW	(0xf << 0) +#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_0DB		(0x0 << 0) +#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_1DB_ABOVE	(0x1 << 0) +#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_2DB_ABOVE	(0x2 << 0) +#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_3DB_ABOVE	(0x3 << 0) +#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_4DB_ABOVE	(0x4 << 0) +#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_5DB_ABOVE	(0x5 << 0) +#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_6DB_ABOVE	(0x6 << 0) +#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_7DB_ABOVE	(0x7 << 0) +  __xdata __at (0xdf19) uint8_t RF_AGCCTRL0;  #define RF_AGCCTRL0_OFF	0x19 +#define RF_AGCCTRL0_HYST_LEVEL_NONE		(0 << 6) +#define RF_AGCCTRL0_HYST_LEVEL_LOW		(1 << 6) +#define RF_AGCCTRL0_HYST_LEVEL_MEDIUM		(2 << 6) +#define RF_AGCCTRL0_HYST_LEVEL_HIGH		(3 << 6) +#define RF_AGCCTRL0_WAIT_TIME_8			(0 << 4) +#define RF_AGCCTRL0_WAIT_TIME_16		(1 << 4) +#define RF_AGCCTRL0_WAIT_TIME_24		(2 << 4) +#define RF_AGCCTRL0_WAIT_TIME_32		(3 << 4) +#define RF_AGCCTRL0_AGC_FREEZE_NORMAL		(0 << 2) +#define RF_AGCCTRL0_AGC_FREEZE_SYNC		(1 << 2) +#define RF_AGCCTRL0_AGC_FREEZE_MANUAL_ANALOG	(2 << 2) +#define RF_AGCCTRL0_AGC_FREEZE_MANUAL_BOTH	(3 << 2) +#define RF_AGCCTRL0_FILTER_LENGTH_8		(0 << 0) +#define RF_AGCCTRL0_FILTER_LENGTH_16		(1 << 0) +#define RF_AGCCTRL0_FILTER_LENGTH_32		(2 << 0) +#define RF_AGCCTRL0_FILTER_LENGTH_64		(3 << 0) +  __xdata __at (0xdf1a) uint8_t RF_FREND1;  #define RF_FREND1_OFF	0x1a diff --git a/src/drivers/ao_aprs.c b/src/drivers/ao_aprs.c index 8a1b6a4d..19beb78f 100644 --- a/src/drivers/ao_aprs.c +++ b/src/drivers/ao_aprs.c @@ -1,11 +1,11 @@ -/**  +/**   * http://ad7zj.net/kd7lmo/aprsbeacon_code.html   *   * @mainpage Pico Beacon   *   * @section overview_sec Overview   * - * The Pico Beacon is an APRS based tracking beacon that operates in the UHF 420-450MHz band.  The device utilizes a  + * The Pico Beacon is an APRS based tracking beacon that operates in the UHF 420-450MHz band.  The device utilizes a   * Microchip PIC 18F2525 embedded controller, Motorola M12+ GPS engine, and Analog Devices AD9954 DDS.  The device is capable   * of generating a 1200bps A-FSK and 9600 bps FSK AX.25 compliant APRS (Automatic Position Reporting System) message. @@ -24,7 +24,7 @@   *                                     (4) corrected size of LOG_COORD block when searching for end of log.   *   * @subsection v303 V3.03 - * 15 Sep 2005, Change include; (1) removed AD9954 setting SDIO as input pin,  + * 15 Sep 2005, Change include; (1) removed AD9954 setting SDIO as input pin,   *                                     (2) additional comments and Doxygen tags,   *                                     (3) integration and test code calculates DDS FTW,   *                                     (4) swapped bus and reference analog input ports (hardware change), @@ -38,7 +38,7 @@   *                                    (2) Doxygen documentation clean up and additions, and   *                                    (3) added integration and test code to baseline.   * - *  + *   * @subsection v301 V3.01   * 13 Jan 2005, Renamed project and files to Pico Beacon.   * @@ -54,28 +54,28 @@   *                                     (8) added flight data recorder, and   *                                     (9) added diagnostics terminal mode.   * - *  + *   * @subsection v201 V2.01 - * 30 Jan 2004, Change include; (1) General clean up of in-line documentation, and  + * 30 Jan 2004, Change include; (1) General clean up of in-line documentation, and   *                                     (2) changed temperature resolution to 0.1 degrees F.   * - *  + *   * @subsection v200 V2.00   * 26 Oct 2002, Change include; (1) Micro Beacon II hardware changes including PIC18F252 processor, - *                                     (2) serial EEPROM,  - *                                     (3) GPS power control,  - *                                     (4) additional ADC input, and  - *                                     (5) LM60 temperature sensor.                             + *                                     (2) serial EEPROM, + *                                     (3) GPS power control, + *                                     (4) additional ADC input, and + *                                     (5) LM60 temperature sensor.   *   *   * @subsection v101 V1.01 - * 5 Dec 2001, Change include; (1) Changed startup message, and  + * 5 Dec 2001, Change include; (1) Changed startup message, and   *                                    (2) applied SEPARATE pragma to several methods for memory usage.   *   *   * @subsection v100 V1.00   * 25 Sep 2001, Initial release.  Flew ANSR-3 and ANSR-4. - *  + *   * @@ -102,11 +102,11 @@   *  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 - *   + * - *  - *  + * + *   * @section design Design Details   *   * Provides design details on a variety of the components that make up the Pico Beacon. @@ -118,29 +118,33 @@   *  @page power Power Consumption   *   *  Measured DC power consumption. - *  - *  3VDC prime power current  + * + *  3VDC prime power current   * - *    7mA Held in reset  + *    7mA Held in reset - *   18mA Processor running, all I/O off  + *   18mA Processor running, all I/O off - *  110mA GPS running  + *  110mA GPS running - *  120mA GPS running w/antenna  + *  120mA GPS running w/antenna - *  250mA DDS running and GPS w/antenna  + *  250mA DDS running and GPS w/antenna - *  420mA DDS running, GPS w/antenna, and PA chain on with no RF  + *  420mA DDS running, GPS w/antenna, and PA chain on with no RF - *  900mA Transmit  + *  900mA Transmit   *   */  #ifndef AO_APRS_TEST  #include <ao.h> + +#if !HAS_APRS +#error HAS_APRS not set +#endif  #endif  #include <ao_aprs.h> @@ -176,11 +180,11 @@ static uint16_t sysCRC16(const uint8_t *buffer, uint8_t length, uint16_t crc)  {      uint8_t i, bit, value; -    for (i = 0; i < length; ++i)  +    for (i = 0; i < length; ++i)      {          value = buffer[i]; -        for (bit = 0; bit < 8; ++bit)  +        for (bit = 0; bit < 8; ++bit)          {              crc ^= (value & 0x01);              crc = ( crc & 0x01 ) ? ( crc >> 1 ) ^ 0x8408 : ( crc >> 1 ); @@ -253,7 +257,7 @@ typedef enum  /// AX.25 compliant packet header that contains destination, station call sign, and path.  /// 0x76 for SSID-11, 0x78 for SSID-12 -static uint8_t TNC_AX25_HEADER[] = {  +static uint8_t TNC_AX25_HEADER[] = {      'A' << 1, 'P' << 1, 'A' << 1, 'M' << 1, ' ' << 1, ' ' << 1, 0x60,      'N' << 1, '0' << 1, 'C' << 1, 'A' << 1, 'L' << 1, 'L' << 1, 0x78,      'W' << 1, 'I' << 1, 'D' << 1, 'E' << 1, '2' << 1, ' ' << 1, 0x65, @@ -261,6 +265,7 @@ static uint8_t TNC_AX25_HEADER[] = {  #define TNC_CALLSIGN_OFF	7  #define TNC_CALLSIGN_LEN	6 +#define TNC_SSID_OFF		13  static void  tncSetCallsign(void) @@ -275,6 +280,9 @@ tncSetCallsign(void)  	}  	for (; i < TNC_CALLSIGN_LEN; i++)  		TNC_AX25_HEADER[TNC_CALLSIGN_OFF + i] = ' ' << 1; + +	/* Fill in the SSID with the low digit of the serial number */ +	TNC_AX25_HEADER[TNC_SSID_OFF] = 0x60 | ((ao_config.aprs_ssid & 0xf) << 1);  #endif  } @@ -302,7 +310,7 @@ static uint8_t tncBitStuff;  /// Buffer to hold the message portion of the AX.25 packet as we prepare it.  static uint8_t tncBuffer[TNC_BUFFER_SIZE]; -/**  +/**   *   Initialize the TNC internal variables.   */  static void tncInit() @@ -323,7 +331,7 @@ static void tnc1200TimerTick()      else          timeNCOFreq = 0x3aab; -    switch (tncMode)  +    switch (tncMode)      {          case TNC_TX_READY:              // Generate a test signal alteranting between high and low tones. @@ -339,16 +347,16 @@ static void tnc1200TimerTick()                  else                      tncTxBit = 0;  	    } -                     +              // When the flag is done, determine if we need to send more or data. -            if (++tncBitCount == 8)  +            if (++tncBitCount == 8)              {                  tncBitCount = 0;                  tncShift = 0x7e;                  // Once we transmit x mS of flags, send the data.                  // txDelay bytes * 8 bits/byte * 833uS/bit = x mS -                if (++tncIndex == TNC_TX_DELAY)  +                if (++tncIndex == TNC_TX_DELAY)                  {                      tncIndex = 0;                      tncShift = TNC_AX25_HEADER[0]; @@ -361,7 +369,7 @@ static void tnc1200TimerTick()          case TNC_TX_HEADER:              // Determine if we have sent 5 ones in a row, if we have send a zero. -            if (tncBitStuff == 0x1f)  +            if (tncBitStuff == 0x1f)              {                  if (tncTxBit == 0)                      tncTxBit = 1; @@ -381,17 +389,17 @@ static void tnc1200TimerTick()                      tncTxBit = 0;  	    } -            // Save the data stream so we can determine if bit stuffing is  +            // Save the data stream so we can determine if bit stuffing is              // required on the next bit time.              tncBitStuff = ((tncBitStuff << 1) | (tncShift & 0x01)) & 0x1f;              // If all the bits were shifted, get the next byte. -            if (++tncBitCount == 8)  +            if (++tncBitCount == 8)              {                  tncBitCount = 0;                  // After the header is sent, then send the data. -                if (++tncIndex == sizeof(TNC_AX25_HEADER))  +                if (++tncIndex == sizeof(TNC_AX25_HEADER))                  {                      tncIndex = 0;                      tncShift = tncBuffer[0]; @@ -406,7 +414,7 @@ static void tnc1200TimerTick()          case TNC_TX_DATA:              // Determine if we have sent 5 ones in a row, if we have send a zero. -            if (tncBitStuff == 0x1f)  +            if (tncBitStuff == 0x1f)              {                  if (tncTxBit == 0)                      tncTxBit = 1; @@ -426,17 +434,17 @@ static void tnc1200TimerTick()                      tncTxBit = 0;  	    } -            // Save the data stream so we can determine if bit stuffing is  +            // Save the data stream so we can determine if bit stuffing is              // required on the next bit time.              tncBitStuff = ((tncBitStuff << 1) | (tncShift & 0x01)) & 0x1f;              // If all the bits were shifted, get the next byte. -            if (++tncBitCount == 8)  +            if (++tncBitCount == 8)              {                  tncBitCount = 0;                  // If everything was sent, transmit closing flags. -                if (++tncIndex == tncLength)  +                if (++tncIndex == tncLength)                  {                      tncIndex = 0;                      tncShift = 0x7e; @@ -451,7 +459,7 @@ static void tnc1200TimerTick()          case TNC_TX_END:              // The variable tncShift contains the lastest data byte. -            // NRZI enocde the data stream.  +            // NRZI enocde the data stream.              if ((tncShift & 0x01) == 0x00) {                  if (tncTxBit == 0)                      tncTxBit = 1; @@ -460,13 +468,13 @@ static void tnc1200TimerTick()  	    }              // If all the bits were shifted, get the next one. -            if (++tncBitCount == 8)  +            if (++tncBitCount == 8)              {                  tncBitCount = 0;                  tncShift = 0x7e; -     +                  // Transmit two closing flags. -                if (++tncIndex == 2)  +                if (++tncIndex == 2)                  {                      tncMode = TNC_TX_READY; @@ -530,6 +538,7 @@ static int tncComment(uint8_t *buf)  #ifdef AO_SENSE_MAIN  		       " M%d.%d"  #endif +		       " %d"  		       , ao_gps_locked(),  		       ao_num_sats(),  		       battery/10, @@ -542,6 +551,7 @@ static int tncComment(uint8_t *buf)  		       , main/10,  		       main%10  #endif +		       , ao_serial_number  		);  #else  	return sprintf((char *) buf, @@ -703,7 +713,7 @@ static int tncPositionPacket(void)      if (ao_gps_data.flags & AO_GPS_VALID) {  	latitude = ao_gps_data.latitude;  	longitude = ao_gps_data.longitude; -	altitude = ao_gps_data.altitude; +	altitude = AO_TELEMETRY_LOCATION_ALTITUDE(&ao_gps_data);  	if (altitude < 0)  	    altitude = 0;      } @@ -759,7 +769,7 @@ tncFill(uint8_t *buf, int16_t len)      return l;  } -/**  +/**   *    Prepare an AX.25 data packet.  Each time this method is called, it automatically   *    rotates through 1 of 3 messages.   * diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 31225939..3ea8b704 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -41,8 +41,10 @@ extern const uint32_t	ao_radio_cal;  #define FOSC	32000000 +#define ao_radio_try_select(task_id)	ao_spi_try_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz, task_id)  #define ao_radio_select()	ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz)  #define ao_radio_deselect()	ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS) +#define ao_radio_spi_send_sync(d,l)	ao_spi_send_sync((d), (l), AO_CC1120_SPI_BUS)  #define ao_radio_spi_send(d,l)	ao_spi_send((d), (l), AO_CC1120_SPI_BUS)  #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)  #define ao_radio_spi_recv(d,l)	ao_spi_recv((d), (l), AO_CC1120_SPI_BUS) @@ -107,7 +109,7 @@ ao_radio_reg_write(uint16_t addr, uint8_t value)  }  static void -ao_radio_burst_read_start (uint16_t addr) +_ao_radio_burst_read_start (uint16_t addr)  {  	uint8_t data[2];  	uint8_t d; @@ -124,8 +126,8 @@ ao_radio_burst_read_start (uint16_t addr)  			   addr);  		d = 1;  	} -	ao_radio_select(); -	ao_radio_spi_send(data, d); + +	ao_radio_spi_send_sync(data, d);  }  static void @@ -209,7 +211,7 @@ ao_radio_tx_fifo_space(void)  	return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES);  } -#if 0 +#if CC1120_DEBUG  static uint8_t  ao_radio_status(void)  { @@ -245,7 +247,7 @@ ao_radio_check_marc_status(void)  {  	ao_radio_mcu_wake = 0;  	ao_radio_marc_status = ao_radio_get_marc_status(); -	 +  	/* Anyt other than 'tx/rx finished' means an error occurred */  	if (ao_radio_marc_status & ~(CC1120_MARC_STATUS1_TX_FINISHED|CC1120_MARC_STATUS1_RX_FINISHED))  		ao_radio_abort = 1; @@ -275,48 +277,102 @@ static void  ao_radio_idle(void)  {  	for (;;) { -		uint8_t	state = ao_radio_strobe(CC1120_SIDLE); -		if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE) +		uint8_t	state = (ao_radio_strobe(CC1120_SIDLE) >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK; +		if (state == CC1120_STATUS_STATE_IDLE)  			break; -		if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_TX_FIFO_ERROR) +		if (state == CC1120_STATUS_STATE_TX_FIFO_ERROR)  			ao_radio_strobe(CC1120_SFTX); +		if (state == CC1120_STATUS_STATE_RX_FIFO_ERROR) +			ao_radio_strobe(CC1120_SFRX);  	}  	/* Flush any pending TX bytes */  	ao_radio_strobe(CC1120_SFTX);  }  /* - * Packet deviation is 20.5kHz + * Packet deviation   *   *	fdev = fosc >> 24 * (256 + dev_m) << dev_e   * + * Deviation for 38400 baud should be 20.5kHz: + *   *     	32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz + * + * Deviation for 9600 baud should be 5.125kHz: + * + *     	32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 3) = 5127Hz + * + * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and + * cc115l can't do that, so we'll use 1.5kHz instead: + * + *     	32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 1) = 1499Hz   */ -#define PACKET_DEV_E	5 -#define PACKET_DEV_M	80 +#define PACKET_DEV_M_384	80 +#define PACKET_DEV_E_384	5 + +#define PACKET_DEV_M_96		80 +#define PACKET_DEV_E_96		3 + +#define PACKET_DEV_M_24		137 +#define PACKET_DEV_E_24		1  /* - * For our packet data, set the symbol rate to 38400 Baud + * For our packet data   *   *              (2**20 + DATARATE_M) * 2 ** DATARATE_E   *	Rdata = -------------------------------------- * fosc   *		             2 ** 39   * + * Given the bit period of the baseband, T, the bandwidth of the + * baseband signal is B = 1/(2T).  The overall bandwidth of the + * modulated signal is then Channel bandwidth = 2Δf + 2B. + * + * 38400 -- 2 * 20500 + 38400 = 79.4 kHz + *  9600 -- 2 * 5.125 +  9600 = 19.9 kHz + *  2400 -- 2 * 1.5   +  2400 =  5.4 khz + * + * Symbol rate 38400 Baud:   *   *	DATARATE_M = 239914   *	DATARATE_E = 9 + *	CHANBW = 79.4 (round to 100) + * + * Symbol rate 9600 Baud: + * + *	DATARATE_M = 239914 + *	DATARATE_E = 7 + *	CHANBW = 19.9 (round to 20) + * + * Symbol rate 2400 Baud: + * + *	DATARATE_M = 239914 + *	DATARATE_E = 5 + *	CHANBW = 5.0 (round to 8.0)   */ -#define PACKET_DRATE_E	9 +  #define PACKET_DRATE_M	239914 +#define PACKET_DRATE_E_384	9 + +/* 200 / 2 = 100 */ +#define PACKET_CHAN_BW_384	((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \ +				 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \ +				 (2 << CC1120_CHAN_BW_BB_CIC_DECFACT)) + +#define PACKET_DRATE_E_96	7 +/* 200 / 10 = 20 */ +#define PACKET_CHAN_BW_96	((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \ +				 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \ +				 (10 << CC1120_CHAN_BW_BB_CIC_DECFACT)) + +#define PACKET_DRATE_E_24	5 +/* 200 / 25 = 8 */ +#define PACKET_CHAN_BW_24	((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \ +				 (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \ +				 (25 << CC1120_CHAN_BW_BB_CIC_DECFACT)) +  static const uint16_t packet_setup[] = { -	CC1120_DEVIATION_M,	PACKET_DEV_M, -	CC1120_MODCFG_DEV_E,	((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | -				 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | -				 (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)), -	CC1120_DRATE2,		((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) | -				 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)),  	CC1120_DRATE1,		((PACKET_DRATE_M >> 8) & 0xff),  	CC1120_DRATE0,		((PACKET_DRATE_M >> 0) & 0xff),  	CC1120_PKT_CFG2,	((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | @@ -335,6 +391,39 @@ static const uint16_t packet_setup[] = {  	AO_CC1120_MARC_GPIO_IOCFG,		CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP,  }; +static const uint16_t packet_setup_384[] = { +	CC1120_DEVIATION_M,	PACKET_DEV_M_384, +	CC1120_MODCFG_DEV_E,	((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | +				 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | +				 (PACKET_DEV_E_384 << CC1120_MODCFG_DEV_E_DEV_E)), +	CC1120_DRATE2,		((PACKET_DRATE_E_384 << CC1120_DRATE2_DATARATE_E) | +				 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), +	CC1120_CHAN_BW,		PACKET_CHAN_BW_384, +	CC1120_PA_CFG0,		0x7b, +}; + +static const uint16_t packet_setup_96[] = { +	CC1120_DEVIATION_M,	PACKET_DEV_M_96, +	CC1120_MODCFG_DEV_E,	((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | +				 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | +				 (PACKET_DEV_E_96 << CC1120_MODCFG_DEV_E_DEV_E)), +	CC1120_DRATE2,		((PACKET_DRATE_E_96 << CC1120_DRATE2_DATARATE_E) | +				 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), +	CC1120_CHAN_BW,		PACKET_CHAN_BW_96, +	CC1120_PA_CFG0,		0x7d, +}; + +static const uint16_t packet_setup_24[] = { +	CC1120_DEVIATION_M,	PACKET_DEV_M_24, +	CC1120_MODCFG_DEV_E,	((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | +				 (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | +				 (PACKET_DEV_E_24 << CC1120_MODCFG_DEV_E_DEV_E)), +	CC1120_DRATE2,		((PACKET_DRATE_E_24 << CC1120_DRATE2_DATARATE_E) | +				 (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), +	CC1120_CHAN_BW,		PACKET_CHAN_BW_24, +	CC1120_PA_CFG0,		0x7e, +}; +  static const uint16_t packet_tx_setup[] = {  	CC1120_PKT_CFG2,	((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) |  				 (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), @@ -397,6 +486,7 @@ static const uint16_t rdf_setup[] = {  				 (0 << CC1120_PKT_CFG0_UART_SWAP_EN)),          CC1120_PREAMBLE_CFG1,	((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |  				 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)), +	CC1120_PA_CFG0,		0x7e,  };  /* @@ -443,6 +533,7 @@ static const uint16_t aprs_setup[] = {  				 (0 << CC1120_PKT_CFG1_APPEND_STATUS)),          CC1120_PREAMBLE_CFG1,	((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |  				 (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)), +	CC1120_PA_CFG0,		0x7d,  };  /* @@ -506,23 +597,48 @@ static uint16_t ao_radio_mode;  #define AO_RADIO_MODE_TEST		(AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)  static void +_ao_radio_set_regs(const uint16_t *regs, int nreg) +{ +	int i; + +	for (i = 0; i < nreg; i++) { +		ao_radio_reg_write(regs[0], regs[1]); +		regs += 2; +	} +} + +#define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1) + +static void  ao_radio_set_mode(uint16_t new_mode)  {  	uint16_t changes; -	unsigned int i;  	if (new_mode == ao_radio_mode)  		return;  	changes = new_mode & (~ao_radio_mode); -	if (changes & AO_RADIO_MODE_BITS_PACKET) -		for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2) -			ao_radio_reg_write(packet_setup[i], packet_setup[i+1]); + +	if (changes & AO_RADIO_MODE_BITS_PACKET) { +		ao_radio_set_regs(packet_setup); + +		switch (ao_config.radio_rate) { +		default: +		case AO_RADIO_RATE_38400: +			ao_radio_set_regs(packet_setup_384); +			break; +		case AO_RADIO_RATE_9600: +			ao_radio_set_regs(packet_setup_96); +			break; +		case AO_RADIO_RATE_2400: +			ao_radio_set_regs(packet_setup_24); +			break; +		} +	}  	if (changes & AO_RADIO_MODE_BITS_PACKET_TX) -		for (i = 0; i < sizeof (packet_tx_setup) / sizeof (packet_tx_setup[0]); i += 2) -			ao_radio_reg_write(packet_tx_setup[i], packet_tx_setup[i+1]); -		 +		ao_radio_set_regs(packet_tx_setup); +  	if (changes & AO_RADIO_MODE_BITS_TX_BUF)  		ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR); @@ -530,20 +646,16 @@ ao_radio_set_mode(uint16_t new_mode)  		ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG);  	if (changes & AO_RADIO_MODE_BITS_PACKET_RX) -		for (i = 0; i < sizeof (packet_rx_setup) / sizeof (packet_rx_setup[0]); i += 2) -			ao_radio_reg_write(packet_rx_setup[i], packet_rx_setup[i+1]); -		 +		ao_radio_set_regs(packet_rx_setup); +  	if (changes & AO_RADIO_MODE_BITS_RDF) -		for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) -			ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); +		ao_radio_set_regs(rdf_setup);  	if (changes & AO_RADIO_MODE_BITS_APRS) -		for (i = 0; i < sizeof (aprs_setup) / sizeof (aprs_setup[0]); i += 2) -			ao_radio_reg_write(aprs_setup[i], aprs_setup[i+1]); +		ao_radio_set_regs(aprs_setup);  	if (changes & AO_RADIO_MODE_BITS_TEST) -		for (i = 0; i < sizeof (test_setup) / sizeof (test_setup[0]); i += 2) -			ao_radio_reg_write(test_setup[i], test_setup[i+1]); +		ao_radio_set_regs(test_setup);  	if (changes & AO_RADIO_MODE_BITS_INFINITE)  		ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE); @@ -563,12 +675,9 @@ static uint8_t	ao_radio_configured = 0;  static void  ao_radio_setup(void)  { -	unsigned int	i; -  	ao_radio_strobe(CC1120_SRES); -	for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) -		ao_radio_reg_write(radio_setup[i], radio_setup[i+1]); +	ao_radio_set_regs(radio_setup);  	ao_radio_mode = 0; @@ -592,6 +701,7 @@ static void  ao_radio_get(uint8_t len)  {  	static uint32_t	last_radio_setting; +	static uint8_t	last_radio_rate;  	ao_mutex_get(&ao_radio_mutex); @@ -603,6 +713,10 @@ ao_radio_get(uint8_t len)  		ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting);  		last_radio_setting = ao_config.radio_setting;  	} +	if (ao_config.radio_rate != last_radio_rate) { +		ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET; +		last_radio_rate = ao_config.radio_rate; +	}  	ao_radio_set_len(len);  } @@ -696,7 +810,7 @@ ao_radio_test_cmd(void)  		ao_radio_set_mode(AO_RADIO_MODE_TEST);  		ao_radio_strobe(CC1120_STX);  #if CC1120_TRACE -		{ int t;  +		{ int t;  			for (t = 0; t < 10; t++) {  				printf ("status: %02x\n", ao_radio_status());  				ao_delay(AO_MS_TO_TICKS(100)); @@ -793,7 +907,7 @@ ao_radio_send(const void *d, uint8_t size)  		} else {  			ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);  		} -			 +  		fifo_space = ao_radio_wait_tx(encode_len != 0);  		if (ao_radio_abort) {  			ao_radio_idle(); @@ -881,6 +995,11 @@ static uint16_t	rx_data_consumed;  static uint16_t rx_data_cur;  static uint8_t	rx_ignore;  static uint8_t	rx_waiting; +static uint8_t	rx_starting; +static uint8_t	rx_task_id; +static uint32_t	rx_fast_start; +static uint32_t rx_slow_start; +static uint32_t	rx_missed;  #if AO_PROFILE  static uint32_t	rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick; @@ -895,13 +1014,34 @@ ao_radio_rx_isr(void)  {  	uint8_t	d; +	if (rx_task_id) { +		if (ao_radio_try_select(rx_task_id)) { +			++rx_fast_start; +			rx_task_id = 0; +			_ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); +		} else { +			if (rx_ignore) +				--rx_ignore; +			else { +				ao_radio_abort = 1; +				rx_missed++; +			} +			return; +		} +	} +	if (rx_starting) { +		rx_starting = 0; +		ao_wakeup(&ao_radio_wake); +	}  	d = AO_CC1120_SPI.dr;  	AO_CC1120_SPI.dr = 0;  	if (rx_ignore == 0) { -		if (rx_data_cur >= rx_data_count) -			ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); -		else +		if (rx_data_cur < rx_data_count)  			rx_data[rx_data_cur++] = d; +		if (rx_data_cur >= rx_data_count) { +			ao_spi_clr_cs(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN)); +			ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); +		}  		if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {  #if AO_PROFILE  			if (!rx_packet_tick) @@ -920,24 +1060,20 @@ ao_radio_rx_isr(void)  static uint16_t  ao_radio_rx_wait(void)  { -	do { -		if (ao_radio_mcu_wake) -			ao_radio_check_marc_status(); -		ao_alarm(AO_MS_TO_TICKS(100)); -		ao_arch_block_interrupts(); -		rx_waiting = 1; -		while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK && -		       !ao_radio_abort && -		       !ao_radio_mcu_wake) -		{ -			if (ao_sleep(&ao_radio_wake)) -				ao_radio_abort = 1; -		} -		rx_waiting = 0; -		ao_arch_release_interrupts(); -		ao_clear_alarm(); -	} while (ao_radio_mcu_wake); -	if (ao_radio_abort) +	ao_alarm(AO_MS_TO_TICKS(100)); +	ao_arch_block_interrupts(); +	rx_waiting = 1; +	while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK && +	       !ao_radio_abort && +	       !ao_radio_mcu_wake) +	{ +		if (ao_sleep(&ao_radio_wake)) +			ao_radio_abort = 1; +	} +	rx_waiting = 0; +	ao_arch_release_interrupts(); +	ao_clear_alarm(); +	if (ao_radio_abort || ao_radio_mcu_wake)  		return 0;  	rx_data_consumed += AO_FEC_DECODE_BLOCK;  #if AO_PROFILE @@ -977,48 +1113,67 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)  	 */  	ao_radio_abort = 0; -	/* configure interrupt pin */  	ao_radio_get(len); -	ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);  	ao_radio_wake = 0;  	ao_radio_mcu_wake = 0; -	AO_CC1120_SPI.cr2 = 0; - -	/* clear any RXNE */ -	(void) AO_CC1120_SPI.dr; +	ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX); -	/* Have the radio signal when the preamble quality goes high */ -	ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_PQT_REACHED); +	/* configure interrupt pin */ +	ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT);  	ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, -			 AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH); -	ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr); +			 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH); + +	ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);  	ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); -	ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN); + +	rx_starting = 1; +	rx_task_id = ao_cur_task->task_id;  	ao_radio_strobe(CC1120_SRX); -	/* Wait for the preamble to appear */ -	ao_radio_wait_isr(timeout); +	if (timeout) +		ao_alarm(timeout); +	ao_arch_block_interrupts(); +	while (rx_starting && !ao_radio_abort) { +		if (ao_sleep(&ao_radio_wake)) +			ao_radio_abort = 1; +	} +	uint8_t	rx_task_id_save = rx_task_id; +	rx_task_id = 0; +	rx_starting = 0; +	ao_arch_release_interrupts(); +	if (timeout) +		ao_clear_alarm(); +  	if (ao_radio_abort) {  		ret = 0; +		rx_task_id = 0;  		goto abort;  	} -	ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT); -	ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, -			 AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH); - -	ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr); -	ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - -	ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); +	if (rx_task_id_save) { +		++rx_slow_start; +		ao_radio_select(); +		_ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); +		if (rx_ignore) { +			uint8_t ignore = AO_CC1120_SPI.dr; +			(void) ignore; +			AO_CC1120_SPI.dr = 0; +			--rx_ignore; +		} +	}  	ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);  	ao_radio_burst_read_stop(); +	if (ao_radio_mcu_wake) +		ao_radio_check_marc_status(); +	if (ao_radio_abort) +		ret = 0; +  abort:  	/* Convert from 'real' rssi to cc1111-style values */ @@ -1033,7 +1188,7 @@ abort:  		radio_rssi = AO_RADIO_FROM_RSSI (rssi);  	} -	ao_radio_strobe(CC1120_SIDLE); +	ao_radio_idle();  	ao_radio_put(); @@ -1072,7 +1227,7 @@ struct ao_cc1120_reg {  	char		*name;  }; -const static struct ao_cc1120_reg ao_cc1120_reg[] = { +static const struct ao_cc1120_reg ao_cc1120_reg[] = {  	{ .addr = CC1120_IOCFG3,	.name = "IOCFG3" },  	{ .addr = CC1120_IOCFG2,	.name = "IOCFG2" },  	{ .addr = CC1120_IOCFG1,	.name = "IOCFG1" }, @@ -1253,7 +1408,7 @@ const static struct ao_cc1120_reg ao_cc1120_reg[] = {  static void ao_radio_show(void) {  	uint8_t	status = ao_radio_status(); -	int	i; +	unsigned int	i;  	ao_radio_get(0xff);  	status = ao_radio_status(); @@ -1264,6 +1419,10 @@ static void ao_radio_show(void) {  	for (i = 0; i < AO_NUM_CC1120_REG; i++)  		printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name); + +	printf("RX fast start: %u\n", rx_fast_start); +	printf("RX slow start: %u\n", rx_slow_start); +	printf("RX missed:     %u\n", rx_missed);  	ao_radio_put();  } @@ -1287,12 +1446,12 @@ static void ao_radio_packet(void) {  }  void -ao_radio_test_recv() +ao_radio_test_recv(void)  {  	uint8_t	bytes[34];  	uint8_t	b; -	if (ao_radio_recv(bytes, 34)) { +	if (ao_radio_recv(bytes, 34, 0)) {  		if (bytes[33] & 0x80)  			printf ("CRC OK");  		else @@ -1308,13 +1467,12 @@ ao_radio_test_recv()  #include <ao_aprs.h>  static void -ao_radio_aprs() +ao_radio_aprs(void)  {  	ao_packet_slave_stop();  	ao_aprs_send();  }  #endif -  #endif  static const struct ao_cmds ao_radio_cmds[] = { diff --git a/src/drivers/ao_cc1120.h b/src/drivers/ao_cc1120.h index a1d78c01..943f3449 100644 --- a/src/drivers/ao_cc1120.h +++ b/src/drivers/ao_cc1120.h @@ -189,6 +189,12 @@  #define CC1120_FREQ_IF_CFG	0x0f  #define CC1120_IQIC		0x10  #define CC1120_CHAN_BW		0x11 +#define  CC1120_CHAN_BW_CHFILT_BYPASS		7 +#define  CC1120_CHAN_BW_ADC_CIC_DECFACT		6 +#define  CC1120_CHAN_BW_ADC_CIC_DECFACT_20		0 +#define  CC1120_CHAN_BW_ADC_CIC_DECFACT_32		1 +#define  CC1120_CHAN_BW_BB_CIC_DECFACT		0 +  #define CC1120_MDMCFG1		0x12  #define  CC1120_MDMCFG1_CARRIER_SENSE_GATE	7  #define  CC1120_MDMCFG1_FIFO_EN			6 @@ -294,7 +300,7 @@  #define  CC1120_SETTLING_CFG_FS_AUTOCAL_MASK		3  #define  CC1120_SETTLING_CFG_LOCK_TIME		1  #define  CC1120_SETTLING_CFG_LOCK_TIME_50_20		0 -#define  CC1120_SETTLING_CFG_LOCK_TIME_70_30		1 +#define  CC1120_SETTLING_CFG_LOCK_TIME_75_30		1  #define  CC1120_SETTLING_CFG_LOCK_TIME_100_40		2  #define  CC1120_SETTLING_CFG_LOCK_TIME_150_60		3  #define  CC1120_SETTLING_CFG_LOCK_TIME_MASK		3 diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h index 399abc4d..21a31a89 100644 --- a/src/drivers/ao_cc1120_CC1120.h +++ b/src/drivers/ao_cc1120_CC1120.h @@ -31,20 +31,23 @@          CC1120_SYNC0,                          0x91,       /* Sync Word Configuration [7:0] */
          CC1120_SYNC_CFG1,				   /* Sync Word Detection Configuration */
 -		(CC1120_SYNC_CFG1_DEM_CFG_PQT_GATING_ENABLED << CC1120_SYNC_CFG1_DEM_CFG) |
 -		(0x07 << CC1120_SYNC_CFG1_SYNC_THR),
 +		(CC1120_SYNC_CFG1_DEM_CFG_PQT_GATING_DISABLED << CC1120_SYNC_CFG1_DEM_CFG) |
 +		(0xc << CC1120_SYNC_CFG1_SYNC_THR),
          CC1120_SYNC_CFG0,
  		(CC1120_SYNC_CFG0_SYNC_MODE_16_BITS << CC1120_SYNC_CFG0_SYNC_MODE) |
 -		(CC1120_SYNC_CFG0_SYNC_NUM_ERROR_2 << CC1120_SYNC_CFG0_SYNC_NUM_ERROR),
 -        CC1120_DCFILT_CFG,                     0x1c,       /* Digital DC Removal Configuration */
 +		(CC1120_SYNC_CFG0_SYNC_NUM_ERROR_DISABLED << CC1120_SYNC_CFG0_SYNC_NUM_ERROR),
 +        CC1120_DCFILT_CFG,                     0x15,       /* Digital DC Removal Configuration */
          CC1120_PREAMBLE_CFG1,                         	   /* Preamble Length Configuration */
  		(CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) |
  		(CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD),
          CC1120_PREAMBLE_CFG0,
 -		(1 << CC1120_PREAMBLE_CFG0_PQT_EN) |
 -		(0x6 << CC1120_PREAMBLE_CFG0_PQT),
 -        CC1120_FREQ_IF_CFG,                    0x40,       /* RX Mixer Frequency Configuration */
 -        CC1120_IQIC,                           0x46,       /* Digital Image Channel Compensation Configuration */
 +		(0 << CC1120_PREAMBLE_CFG0_PQT_EN) |
 +		(0xe << CC1120_PREAMBLE_CFG0_PQT),
 +
 +	/* Adjust PQT lower to accept fewer packets */
 +
 +        CC1120_FREQ_IF_CFG,                    0x3a,       /* RX Mixer Frequency Configuration */
 +        CC1120_IQIC,                           0x00,       /* Digital Image Channel Compensation Configuration */
          CC1120_CHAN_BW,                        0x02,       /* Channel Filter Configuration */
          CC1120_MDMCFG1,                     		   /* General Modem Parameter Configuration */
 @@ -53,12 +56,12 @@  		(0 << CC1120_MDMCFG1_MANCHESTER_EN) |
  		(0 << CC1120_MDMCFG1_INVERT_DATA_EN) |
  		(0 << CC1120_MDMCFG1_COLLISION_DETECT_EN) |
 -		(CC1120_MDMCFG1_DVGA_GAIN_9 << CC1120_MDMCFG1_DVGA_GAIN) |
 +		(CC1120_MDMCFG1_DVGA_GAIN_0 << CC1120_MDMCFG1_DVGA_GAIN) |
  		(0 << CC1120_MDMCFG1_SINGLE_ADC_EN),
 -        CC1120_MDMCFG0,                        0x05,       /* General Modem Parameter Configuration */
 +        CC1120_MDMCFG0,                        0x0d,       /* General Modem Parameter Configuration */
  	/* AGC reference = 10 * log10(receive BW) - 4 = 10 * log10(100e3) - 4 = 46 */
 -        CC1120_AGC_REF,                        46,         /* AGC Reference Level Configuration */
 +        CC1120_AGC_REF,                        0x36,         /* AGC Reference Level Configuration */
  	/* Carrier sense threshold - 25dB above the noise */
          CC1120_AGC_CS_THR,                     25,         /* Carrier Sense Threshold Configuration */
 @@ -93,7 +96,7 @@          CC1120_SETTLING_CFG,                          	   /* Frequency Synthesizer Calibration and Settling Configuration */
  		(CC1120_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON << CC1120_SETTLING_CFG_FS_AUTOCAL) |
 -		(CC1120_SETTLING_CFG_LOCK_TIME_50_20 << CC1120_SETTLING_CFG_LOCK_TIME) |
 +		(CC1120_SETTLING_CFG_LOCK_TIME_75_30 << CC1120_SETTLING_CFG_LOCK_TIME) |
  		(CC1120_SETTLING_CFG_FSREG_TIME_60 << CC1120_SETTLING_CFG_FSREG_TIME),
          CC1120_FS_CFG,                                	   /* Frequency Synthesizer Configuration */
 @@ -109,7 +112,7 @@          CC1120_PKT_CFG1,                       0x45,       /* Packet Configuration, Reg 1 */
          CC1120_PKT_CFG0,                       0x00,       /* Packet Configuration, Reg 0 */
  #endif
 -        CC1120_RFEND_CFG1,                     0x0f,       /* RFEND Configuration, Reg 1 */
 +        CC1120_RFEND_CFG1,                     0x0e,       /* RFEND Configuration, Reg 1 */
          CC1120_RFEND_CFG0,                     0x00,       /* RFEND Configuration, Reg 0 */
  	//        CC1120_PA_CFG2,                        0x3f,       /* Power Amplifier Configuration, Reg 2 */
  	CC1120_PA_CFG2,                        0x3f,       /* Power Amplifier Configuration, Reg 2 */
 @@ -117,8 +120,8 @@          CC1120_PA_CFG0,                        0x7b,       /* Power Amplifier Configuration, Reg 0 */
          CC1120_PKT_LEN,                        0xff,       /* Packet Length Configuration */
          CC1120_IF_MIX_CFG,                     0x00,       /* IF Mix Configuration */
 -        CC1120_FREQOFF_CFG,                    0x22,       /* Frequency Offset Correction Configuration */
 -        CC1120_TOC_CFG,                        0x0b,       /* Timing Offset Correction Configuration */
 +        CC1120_FREQOFF_CFG,                    0x20,       /* Frequency Offset Correction Configuration */
 +        CC1120_TOC_CFG,                        0x0a,       /* Timing Offset Correction Configuration */
          CC1120_MARC_SPARE,                     0x00,       /* MARC Spare */
          CC1120_ECG_CFG,                        0x00,       /* External Clock Frequency Configuration */
          CC1120_SOFT_TX_DATA_CFG,               0x00,       /* Soft TX Data Configuration */
 @@ -167,7 +170,7 @@          CC1120_XOSC4,                          0xa0,       /* Crystal Oscillator Configuration, Reg 4 */
          CC1120_XOSC3,                          0x03,       /* Crystal Oscillator Configuration, Reg 3 */
          CC1120_XOSC2,                          0x04,       /* Crystal Oscillator Configuration, Reg 2 */
 -        CC1120_XOSC1,                          0x01,       /* Crystal Oscillator Configuration, Reg 1 */
 +        CC1120_XOSC1,                          0x03,       /* Crystal Oscillator Configuration, Reg 1 */
          CC1120_XOSC0,                          0x00,       /* Crystal Oscillator Configuration, Reg 0 */
          CC1120_ANALOG_SPARE,                   0x00,       /*  */
          CC1120_PA_CFG3,                        0x00,       /* Power Amplifier Configuration, Reg 3 */
 @@ -196,31 +199,10 @@          CC1120_AGC_GAIN2,                      0xd1,       /* AGC Gain, Reg 2 */
          CC1120_AGC_GAIN1,                      0x00,       /* AGC Gain, Reg 1 */
          CC1120_AGC_GAIN0,                      0x3f,       /* AGC Gain, Reg 0 */
 -        CC1120_SOFT_RX_DATA_OUT,               0x00,       /* Soft Decision Symbol Data */
 -        CC1120_SOFT_TX_DATA_IN,                0x00,       /* Soft TX Data Input Register */
 -        CC1120_ASK_SOFT_RX_DATA,               0x30,       /* AGC ASK Soft Decision Output */
          CC1120_RNDGEN,                         0x7f,       /* Random Number Value */
 -        CC1120_MAGN2,                          0x00,       /* Signal Magnitude after CORDIC [16] */
 -        CC1120_MAGN1,                          0x00,       /* Signal Magnitude after CORDIC [15:8] */
 -        CC1120_MAGN0,                          0x00,       /* Signal Magnitude after CORDIC [7:0] */
 -        CC1120_ANG1,                           0x00,       /* Signal Angular after CORDIC [9:8] */
 -        CC1120_ANG0,                           0x00,       /* Signal Angular after CORDIC [7:0] */
 -        CC1120_CHFILT_I2,                      0x08,       /* Channel Filter Data Real Part [18:16] */
 -        CC1120_CHFILT_I1,                      0x00,       /* Channel Filter Data Real Part [15:8] */
 -        CC1120_CHFILT_I0,                      0x00,       /* Channel Filter Data Real Part [7:0] */
 -        CC1120_CHFILT_Q2,                      0x00,       /* Channel Filter Data Imaginary Part [18:16] */
 -        CC1120_CHFILT_Q1,                      0x00,       /* Channel Filter Data Imaginary Part [15:8] */
 -        CC1120_CHFILT_Q0,                      0x00,       /* Channel Filter Data Imaginary Part [7:0] */
 -        CC1120_GPIO_STATUS,                    0x00,       /* GPIO Status */
          CC1120_FSCAL_CTRL,                     0x01,       /*  */
          CC1120_PHASE_ADJUST,                   0x00,       /*  */
 -        CC1120_PARTNUMBER,                     0x00,       /* Part Number */
 -        CC1120_PARTVERSION,                    0x00,       /* Part Revision */
          CC1120_SERIAL_STATUS,                  0x00,       /* Serial Status */
 -        CC1120_RX_STATUS,                      0x01,       /* RX Status */
 -        CC1120_TX_STATUS,                      0x00,       /* TX Status */
 -        CC1120_MARC_STATUS1,                   0x00,       /* MARC Status, Reg 1 */
 -        CC1120_MARC_STATUS0,                   0x00,       /* MARC Status, Reg 0 */
          CC1120_PA_IFAMP_TEST,                  0x00,       /*  */
          CC1120_FSRF_TEST,                      0x00,       /*  */
          CC1120_PRE_TEST,                       0x00,       /*  */
 diff --git a/src/drivers/ao_cc115l.c b/src/drivers/ao_cc115l.c index f250e714..cf61acfe 100644 --- a/src/drivers/ao_cc115l.c +++ b/src/drivers/ao_cc115l.c @@ -249,36 +249,81 @@ ao_radio_idle(void)  }  /* - * Packet deviation is 20.5kHz + * Packet deviation   *   *	fdev = fosc >> 17 * (8 + dev_m) << dev_e   * + * For 38400 baud, use 20.5kHz: + *   *     	26e6 / (2 ** 17) * (8 + 5) * (2 ** 3) = 20630Hz + * + * For 9600 baud, use 5.125kHz: + * + *     	26e6 / (2 ** 17) * (8 + 5) * (2 ** 1) = 5157Hz + * + * For 2400 baud, use 1.5kHz: + * + *     	26e6 / (2 ** 17) * (8 + 0) * (2 ** 0) = 1587Hz   */ -#define PACKET_DEV_E	3 -#define PACKET_DEV_M	5 +#define PACKET_DEV_E_384	3 +#define PACKET_DEV_M_384	5 + +#define PACKET_DEV_E_96		1 +#define PACKET_DEV_M_96		5 + +#define PACKET_DEV_E_24		0 +#define PACKET_DEV_M_24		0  /* - * For our packet data, set the symbol rate to 38400 Baud + * For our packet data:   *   *              (256 + DATARATE_M) * 2 ** DATARATE_E   *	Rdata = -------------------------------------- * fosc   *		             2 ** 28   * + * For 38400 baud: + *   *		(256 + 131) * (2 ** 10) / (2**28) * 26e6 = 38383   *   *	DATARATE_M = 131 - *	DATARATE_E = 10 + *	DATARATE_E_384 = 10 + *	DATARATE_E_96 = 8 + *	DATARATE_E_24 = 6   */ -#define PACKET_DRATE_E	10 -#define PACKET_DRATE_M	131 +#define PACKET_DRATE_M		131 + +#define PACKET_DRATE_E_384	10 +#define PACKET_DRATE_E_96	8 +#define PACKET_DRATE_E_24	6 + +static const struct { +	uint8_t		mdmcfg4; +	uint8_t		deviatn; +} packet_rate_setup[] = { +	[AO_RADIO_RATE_38400] = { +		.mdmcfg4 = ((0xf << 4) | +			    (PACKET_DRATE_E_384 << CC115L_MDMCFG4_DRATE_E)), +		.deviatn = ((PACKET_DEV_E_384 << CC115L_DEVIATN_DEVIATION_E) | +			    (PACKET_DEV_M_384 << CC115L_DEVIATN_DEVIATION_M)), +	}, + +	[AO_RADIO_RATE_9600] = { +		.mdmcfg4 = ((0xf << 4) | +			    (PACKET_DRATE_E_96 << CC115L_MDMCFG4_DRATE_E)), +		.deviatn = ((PACKET_DEV_E_96 << CC115L_DEVIATN_DEVIATION_E) | +			    (PACKET_DEV_M_96 << CC115L_DEVIATN_DEVIATION_M)), +	}, + +	[AO_RADIO_RATE_2400] = { +		.mdmcfg4 = ((0xf << 4) | +			    (PACKET_DRATE_E_24 << CC115L_MDMCFG4_DRATE_E)), +		.deviatn = ((PACKET_DEV_E_24 << CC115L_DEVIATN_DEVIATION_E) | +			    (PACKET_DEV_M_24 << CC115L_DEVIATN_DEVIATION_M)), +	}, +};  static const uint16_t packet_setup[] = { -	CC115L_DEVIATN,		((PACKET_DEV_E << CC115L_DEVIATN_DEVIATION_E) | -				 (PACKET_DEV_M << CC115L_DEVIATN_DEVIATION_M)), -	CC115L_MDMCFG4,		((0xf << 4) | -				 (PACKET_DRATE_E << CC115L_MDMCFG4_DRATE_E)),  	CC115L_MDMCFG3,		(PACKET_DRATE_M),  	CC115L_MDMCFG2,		(0x00 |  				 (CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) | @@ -403,9 +448,13 @@ ao_radio_set_mode(uint16_t new_mode)  		return;  	changes = new_mode & (~ao_radio_mode); -	if (changes & AO_RADIO_MODE_BITS_PACKET_TX) +	if (changes & AO_RADIO_MODE_BITS_PACKET_TX) { +		ao_radio_reg_write(CC115L_MDMCFG4, packet_rate_setup[ao_config.radio_rate].mdmcfg4); +		ao_radio_reg_write(CC115L_DEVIATN, packet_rate_setup[ao_config.radio_rate].deviatn); +  		for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2)  			ao_radio_reg_write(packet_setup[i], packet_setup[i+1]); +	}  	if (changes & AO_RADIO_MODE_BITS_RDF)  		for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) @@ -494,6 +543,7 @@ static void  ao_radio_get(void)  {  	static uint32_t	last_radio_setting; +	static uint8_t	last_radio_rate;  	ao_mutex_get(&ao_radio_mutex);  	if (!ao_radio_configured) @@ -504,6 +554,10 @@ ao_radio_get(void)  		ao_radio_reg_write(CC115L_FREQ0, ao_config.radio_setting);  		last_radio_setting = ao_config.radio_setting;  	} +	if (ao_config.radio_rate != last_radio_rate) { +		ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET_TX; +		last_radio_rate = ao_config.radio_rate; +	}  }  static void diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 944a37f9..066df6ff 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -278,16 +278,17 @@ ao_nmea_gga(void)  	ao_gps_lexchar();  	i = ao_gps_decimal(0xff); -	if (i <= 50) { -		i = (uint8_t) 5 * i; +	if (i <= 25) { +		i = (uint8_t) 10 * i;  		if (ao_gps_char == '.') -			i = (i + ((uint8_t) ao_gps_decimal(1) >> 1)); +			i = (i + ((uint8_t) ao_gps_decimal(1)));  	} else  		i = 255;  	ao_gps_next.hdop = i;  	ao_gps_skip_field(); -	ao_gps_next.altitude = ao_gps_decimal(0xff); +	AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_next, ao_gps_decimal(0xff)); +  	ao_gps_skip_field();	/* skip any fractional portion */  	ao_nmea_finish(); diff --git a/src/drivers/ao_gps_ublox.c b/src/drivers/ao_gps_ublox.c index 077698a9..74c29e0a 100644 --- a/src/drivers/ao_gps_ublox.c +++ b/src/drivers/ao_gps_ublox.c @@ -728,7 +728,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_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_data, nav_posllh.alt_msl / 1000);  				ao_gps_data.latitude = nav_posllh.lat;  				ao_gps_data.longitude = nav_posllh.lon; @@ -740,11 +740,11 @@ ao_gps(void) __reentrant  				ao_gps_data.minute = nav_timeutc.min;  				ao_gps_data.second = nav_timeutc.sec; -				ao_gps_data.pdop = nav_dop.pdop; -				ao_gps_data.hdop = nav_dop.hdop; -				ao_gps_data.vdop = nav_dop.vdop; - -				/* mode is not set */ +				/* we report dop scaled by 10, but ublox provides dop scaled by 100 +				 */ +				ao_gps_data.pdop = nav_dop.pdop / 10; +				ao_gps_data.hdop = nav_dop.hdop / 10; +				ao_gps_data.vdop = nav_dop.vdop / 10;  				ao_gps_data.ground_speed = nav_velned.g_speed;  				ao_gps_data.climb_rate = -nav_velned.vel_d; diff --git a/src/drivers/ao_lco_func.c b/src/drivers/ao_lco_func.c index 9e642836..32c00068 100644 --- a/src/drivers/ao_lco_func.c +++ b/src/drivers/ao_lco_func.c @@ -28,7 +28,21 @@ ao_lco_query(uint16_t box, struct ao_pad_query *query, uint16_t *tick_offset)  {  	int8_t		r;  	uint16_t	sent_time; +	uint16_t	timeout = AO_MS_TO_TICKS(10); +#if HAS_RADIO_RATE +	switch (ao_config.radio_rate) { +	case AO_RADIO_RATE_38400: +	default: +		break; +	case AO_RADIO_RATE_9600: +		timeout = AO_MS_TO_TICKS(20); +		break; +	case AO_RADIO_RATE_2400: +		timeout = AO_MS_TO_TICKS(80); +		break; +	} +#endif  	ao_mutex_get(&ao_lco_mutex);  	command.tick = ao_time() - *tick_offset;  	command.box = box; @@ -36,7 +50,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), timeout);  	if (r == AO_RADIO_CMAC_OK)  		*tick_offset = sent_time - query->tick;  	ao_mutex_put(&ao_lco_mutex); diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c index d6c99cbd..23545049 100644 --- a/src/drivers/ao_packet_master.c +++ b/src/drivers/ao_packet_master.c @@ -57,6 +57,12 @@ static __xdata uint16_t		ao_packet_master_time;  #define AO_PACKET_MASTER_DELAY_LONG	AO_MS_TO_TICKS(1000)  #define AO_PACKET_MASTER_DELAY_TIMEOUT	AO_MS_TO_TICKS(2000) +#if HAS_RADIO_RATE +#define AO_PACKET_MASTER_RECV_DELAY	AO_MS_TO_TICKS(100) << (ao_config.radio_rate << 1) +#else +#define AO_PACKET_MASTER_RECV_DELAY	AO_MS_TO_TICKS(100) +#endif +  static void  ao_packet_master_busy(void)  { @@ -91,7 +97,7 @@ ao_packet_master(void)  		if (ao_tx_packet.len)  			ao_packet_master_busy();  		ao_packet_master_check_busy(); -		ao_alarm(ao_packet_master_delay); +		ao_alarm(AO_PACKET_MASTER_RECV_DELAY);  		r = ao_packet_recv();  		ao_clear_alarm();  		if (r) { diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 144cbd70..dc2c83fe 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -362,14 +362,26 @@ ao_pad_test(void)  void  ao_pad_manual(void)  { +	uint8_t	ignite; +	int	repeat;  	ao_cmd_white();  	if (!ao_match_word("DoIt"))  		return;  	ao_cmd_decimal();  	if (ao_cmd_status != ao_cmd_success)  		return; -	ao_pad_ignite = 1 << ao_cmd_lex_i; -	ao_wakeup(&ao_pad_ignite); +	ignite = 1 << ao_cmd_lex_i; +	ao_cmd_decimal(); +	if (ao_cmd_status != ao_cmd_success) { +		repeat = 1; +		ao_cmd_status = ao_cmd_success; +	} else +		repeat = ao_cmd_lex_i; +	while (repeat-- > 0) { +		ao_pad_ignite = ignite; +		ao_wakeup(&ao_pad_ignite); +		ao_delay(AO_PAD_FIRE_TIME>>1); +	}  }  static __xdata struct ao_task ao_pad_task; diff --git a/src/easymega-v0.1/.gitignore b/src/easymega-v1.0/.gitignore index 410943d5..410943d5 100644 --- a/src/easymega-v0.1/.gitignore +++ b/src/easymega-v1.0/.gitignore diff --git a/src/easymega-v0.1/Makefile b/src/easymega-v1.0/Makefile index 66619852..c3b360b4 100644 --- a/src/easymega-v0.1/Makefile +++ b/src/easymega-v1.0/Makefile @@ -107,13 +107,13 @@ ALTOS_SRC = \  	$(SAMPLE_PROFILE) \  	$(STACK_GUARD) -PRODUCT=EasyMega-v0.1 +PRODUCT=EasyMega-v1.0  PRODUCT_DEF=-DEASYMEGA -IDPRODUCT=0x0023 +IDPRODUCT=0x0028  CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g -PROGNAME=easymega-v0.1 +PROGNAME=easymega-v1.0  PROG=$(PROGNAME)-$(VERSION).elf  HEX=$(PROGNAME)-$(VERSION).ihx diff --git a/src/easymega-v0.1/ao_easymega.c b/src/easymega-v1.0/ao_easymega.c index e217c33c..e217c33c 100644 --- a/src/easymega-v0.1/ao_easymega.c +++ b/src/easymega-v1.0/ao_easymega.c diff --git a/src/easymega-v0.1/ao_pins.h b/src/easymega-v1.0/ao_pins.h index cb6e3980..d6490ba5 100644 --- a/src/easymega-v0.1/ao_pins.h +++ b/src/easymega-v1.0/ao_pins.h @@ -65,6 +65,9 @@  #define ao_gps_fifo		(ao_stm_usart1.rx_fifo)  #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX	(1024 * 1024) +#define AO_CONFIG_MAX_SIZE                     1024 +#define LOG_ERASE_MARK                         0x55 +#define LOG_MAX_ERASE                          128  #define HAS_EEPROM		1  #define USE_INTERNAL_FLASH	0  #define USE_EEPROM_CONFIG	1 diff --git a/src/easymega-v0.1/flash-loader/Makefile b/src/easymega-v1.0/flash-loader/Makefile index 35312fd6..d83cb70a 100644 --- a/src/easymega-v0.1/flash-loader/Makefile +++ b/src/easymega-v1.0/flash-loader/Makefile @@ -4,5 +4,5 @@  #  TOPDIR=../.. -HARDWARE=easymega-v0.1 +HARDWARE=easymega-v1.0  include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/easymega-v0.1/flash-loader/ao_pins.h b/src/easymega-v1.0/flash-loader/ao_pins.h index 445289bf..445289bf 100644 --- a/src/easymega-v0.1/flash-loader/ao_pins.h +++ b/src/easymega-v1.0/flash-loader/ao_pins.h diff --git a/src/kalman/kalman.5c b/src/kalman/kalman.5c index 46fa8e1f..55fde04c 100755 --- a/src/kalman/kalman.5c +++ b/src/kalman/kalman.5c @@ -457,7 +457,7 @@ void main() {  					name = sprintf("%s_K%d_%d", prefix, i, time_inc);  				else  					name = sprintf("%s_K%d%d_%d", prefix, i, j, time_inc); -				printf ("#define %s to_fix32(%12.10f)\n", name, k[i,j]); +				printf ("#define %s to_fix_k(%12.10f)\n", name, k[i,j]);  			}  		printf ("\n");  		exit(0); diff --git a/src/kalman/kalman_micro.5c b/src/kalman/kalman_micro.5c index 266a1182..1b080384 100644 --- a/src/kalman/kalman_micro.5c +++ b/src/kalman/kalman_micro.5c @@ -307,7 +307,7 @@ void main() {  					name = sprintf("%s_K%d_%d", prefix, i, time_inc);  				else  					name = sprintf("%s_K%d%d_%d", prefix, i, j, time_inc); -				printf ("#define %s to_fix32(%12.10f)\n", name, k[i,j]); +				printf ("#define %s to_fix_k(%12.10f)\n", name, k[i,j]);  			}  		printf ("\n");  		exit(0); diff --git a/src/kernel/ao.h b/src/kernel/ao.h index 5ff9b518..ad5bbf8e 100644 --- a/src/kernel/ao.h +++ b/src/kernel/ao.h @@ -132,6 +132,9 @@ ao_clock_init(void);   */  #ifndef ao_mutex_get +uint8_t +ao_mutex_try(__xdata uint8_t *ao_mutex, uint8_t task_id) __reentrant; +  void  ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant; @@ -275,15 +278,17 @@ ao_report_init(void);   * Given raw data, convert to SI units   */ +#if HAS_BARO  /* pressure from the sensor to altitude in meters */ -int16_t -ao_pres_to_altitude(int16_t pres) __reentrant; +alt_t +ao_pres_to_altitude(pres_t pres) __reentrant; -int16_t -ao_altitude_to_pres(int16_t alt) __reentrant; +pres_t +ao_altitude_to_pres(alt_t alt) __reentrant;  int16_t  ao_temp_to_dC(int16_t temp) __reentrant; +#endif  /*   * ao_convert_pa.c @@ -293,11 +298,13 @@ ao_temp_to_dC(int16_t temp) __reentrant;  #include <ao_data.h> +#if HAS_BARO  alt_t -ao_pa_to_altitude(int32_t pa); +ao_pa_to_altitude(pres_t pa);  int32_t  ao_altitude_to_pa(alt_t alt); +#endif  #if HAS_DBG  #include <ao_dbg.h> @@ -522,6 +529,9 @@ struct ao_telemetry_raw_recv {  #endif  void +ao_telemetry_reset_interval(void); + +void  ao_telemetry_set_interval(uint16_t interval);  void @@ -558,6 +568,15 @@ extern __xdata int8_t	ao_radio_rssi;  #define HAS_RADIO_XMIT HAS_RADIO  #endif +#define AO_RADIO_RATE_38400	0 +#define AO_RADIO_RATE_9600	1 +#define AO_RADIO_RATE_2400	2 +#define AO_RADIO_RATE_MAX	AO_RADIO_RATE_2400 + +#if defined(HAS_RADIO) && !defined(HAS_RADIO_RATE) +#define HAS_RADIO_RATE	HAS_RADIO +#endif +  void  ao_radio_general_isr(void) ao_arch_interrupt(16); @@ -757,11 +776,13 @@ extern __xdata uint8_t ao_force_freq;   * ao_rssi.c   */ +#ifdef AO_LED_TYPE  void -ao_rssi_set(int rssi_value); +ao_rssi_set(int16_t rssi_value);  void -ao_rssi_init(uint8_t rssi_led); +ao_rssi_init(AO_LED_TYPE rssi_led); +#endif  /*   * ao_product.c diff --git a/src/kernel/ao_cmd.c b/src/kernel/ao_cmd.c index 0052bdce..d2f583ef 100644 --- a/src/kernel/ao_cmd.c +++ b/src/kernel/ao_cmd.c @@ -290,6 +290,9 @@ version(void)  #if defined(AO_BOOT_APPLICATION_BASE) && defined(AO_BOOT_APPLICATION_BOUND)  	       "program-space    %u\n"  #endif +#if AO_VALUE_32 +	       "altitude-32      1\n" +#endif  	       , ao_manufacturer  	       , ao_product  	       , ao_serial_number diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c index 71445335..6b8a1813 100644 --- a/src/kernel/ao_config.c +++ b/src/kernel/ao_config.c @@ -50,17 +50,25 @@ __xdata uint8_t ao_config_mutex;  #error Please define USE_INTERNAL_FLASH  #endif  #endif +  #ifndef AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX -#if USE_INTERNAL_FLASH -#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX	ao_storage_config -#else -#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX	((uint32_t) 192 * (uint32_t) 1024) -#endif +# if FLIGHT_LOG_APPEND +#  define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX	ao_storage_log_max +# else +#  if USE_INTERNAL_FLASH +#   define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX	ao_storage_config +#  else +#   define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX	((uint32_t) 192 * (uint32_t) 1024) +#  endif +# endif  #endif +  #ifndef AO_CONFIG_DEFAULT_RADIO_POWER  #define AO_CONFIG_DEFAULT_RADIO_POWER		0x60  #endif  #define AO_CONFIG_DEFAULT_RADIO_AMP		0 +#define AO_CONFIG_DEFAULT_APRS_SSID		(ao_serial_number % 10) +#define AO_CONFIG_DEFAULT_RADIO_RATE		AO_RADIO_RATE_38400  #if HAS_EEPROM  static void @@ -85,10 +93,18 @@ ao_config_put(void)  #endif  #if HAS_RADIO + +#if HAS_RADIO_FORWARD +__xdata uint32_t	ao_send_radio_setting; +#endif +  void  ao_config_set_radio(void)  {  	ao_config.radio_setting = ao_freq_to_set(ao_config.frequency, ao_config.radio_cal); +#if HAS_RADIO_FORWARD +	ao_send_radio_setting = ao_freq_to_set(ao_config.send_frequency, ao_config.radio_cal); +#endif  }  #endif /* HAS_RADIO */ @@ -192,6 +208,18 @@ _ao_config_get(void)  		if (minor < 18)  			ao_config.pyro_time = AO_CONFIG_DEFAULT_PYRO_TIME;  #endif +#if HAS_APRS +		if (minor < 19) +			ao_config.aprs_ssid = AO_CONFIG_DEFAULT_APRS_SSID; +#endif +#if HAS_RADIO_RATE +		if (minor < 20) +			ao_config.radio_rate = AO_CONFIG_DEFAULT_RADIO_RATE; +#endif +#if HAS_RADIO_FORWARD +		if (minor < 21) +			ao_config.send_frequency = 434550; +#endif  		ao_config.minor = AO_CONFIG_MINOR;  		ao_config_dirty = 1;  	} @@ -283,6 +311,32 @@ ao_config_frequency_set(void) __reentrant  	ao_radio_recv_abort();  #endif  } + +#endif + +#if HAS_RADIO_FORWARD +void +ao_config_send_frequency_show(void) __reentrant +{ +	printf("Send frequency: %ld\n", +	       ao_config.send_frequency); +} + +void +ao_config_send_frequency_set(void) __reentrant +{ +	ao_cmd_decimal(); +	if (ao_cmd_status != ao_cmd_success) +		return; +	_ao_config_edit_start(); +	ao_config.send_frequency = ao_cmd_lex_u32; +	ao_config_set_radio(); +	_ao_config_edit_finish(); +#if HAS_RADIO_RECV +	ao_radio_recv_abort(); +#endif +} +  #endif  #if HAS_FLIGHT @@ -477,18 +531,73 @@ ao_config_radio_cal_set(void) __reentrant  	ao_config_set_radio();  	_ao_config_edit_finish();  } + +#endif + +#if HAS_RADIO_RATE +#ifndef HAS_TELEMETRY +#error Please define HAS_TELEMETRY +#endif + +void +ao_config_radio_rate_show(void) __reentrant +{ +	printf("Telemetry rate: %d\n", ao_config.radio_rate); +} + +void +ao_config_radio_rate_set(void) __reentrant +{ +	ao_cmd_decimal(); +	if (ao_cmd_status != ao_cmd_success) +		return; +	if (AO_RADIO_RATE_MAX < ao_cmd_lex_i) { +		ao_cmd_status = ao_cmd_lex_error; +		return; +	} +	_ao_config_edit_start(); +	ao_config.radio_rate = ao_cmd_lex_i; +#if HAS_TELEMETRY +	ao_telemetry_reset_interval(); +#endif +	_ao_config_edit_finish(); +#if HAS_RADIO_RECV +	ao_radio_recv_abort(); +#endif +}  #endif  #if HAS_LOG +  void  ao_config_log_show(void) __reentrant  {  	printf("Max flight log: %d kB\n", (int16_t) (ao_config.flight_log_max >> 10)); +#if FLIGHT_LOG_APPEND +	printf("Log fixed: 1\n"); +#endif  } +#if FLIGHT_LOG_APPEND +void +ao_config_log_fix_append(void) +{ +	_ao_config_edit_start(); +	ao_config.flight_log_max = ao_storage_log_max; +	_ao_config_edit_finish(); +	ao_mutex_get(&ao_config_mutex); +	_ao_config_put(); +	ao_config_dirty = 0; +	ao_mutex_put(&ao_config_mutex); +} +#endif +  void  ao_config_log_set(void) __reentrant  { +#if FLIGHT_LOG_APPEND +	printf("Flight log fixed size %d kB\n", ao_storage_log_max >> 10); +#else  	uint16_t	block = (uint16_t) (ao_storage_block >> 10);  	uint16_t	log_max = (uint16_t) (ao_storage_log_max >> 10); @@ -506,6 +615,7 @@ ao_config_log_set(void) __reentrant  		ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10;  		_ao_config_edit_finish();  	} +#endif  }  #endif /* HAS_LOG */ @@ -737,6 +847,30 @@ ao_config_pyro_time_set(void)  }  #endif +#if HAS_APRS +void +ao_config_aprs_ssid_show(void) +{ +	printf ("APRS SSID: %d\n", +		ao_config.aprs_ssid); +} + +void +ao_config_aprs_ssid_set(void) +{ +	ao_cmd_decimal(); +	if (ao_cmd_status != ao_cmd_success) +		return; +	if (15 < ao_cmd_lex_i) { +		ao_cmd_status = ao_cmd_lex_error; +		return; +	} +	_ao_config_edit_start(); +	ao_config.aprs_ssid = ao_cmd_lex_i; +	_ao_config_edit_finish(); +} +#endif /* HAS_APRS */ +  struct ao_config_var {  	__code char	*str;  	void		(*set)(void) __reentrant; @@ -766,12 +900,20 @@ __code struct ao_config_var ao_config_vars[] = {  #if HAS_RADIO  	{ "F <freq>\0Frequency (kHz)",  	  ao_config_frequency_set, ao_config_frequency_show }, +#if HAS_RADIO_FORWARD +	{ "R <freq>\0Repeater output frequency (kHz)", +	  ao_config_send_frequency_set, ao_config_send_frequency_show }, +#endif  	{ "c <call>\0Callsign (8 char max)",  	  ao_config_callsign_set,	ao_config_callsign_show },  	{ "e <0 disable, 1 enable>\0Enable telemetry and RDF",  	  ao_config_radio_enable_set, ao_config_radio_enable_show },  	{ "f <cal>\0Radio calib (cal = rf/(xtal/2^16))",  	  ao_config_radio_cal_set,  	ao_config_radio_cal_show }, +#if HAS_RADIO_RATE +	{ "T <rate>\0Telemetry rate (0=38.4, 1=9.6, 2=2.4)", +	  ao_config_radio_rate_set,	ao_config_radio_rate_show }, +#endif  #if HAS_RADIO_POWER  	{ "p <setting>\0Radio power setting (0-255)",  	  ao_config_radio_power_set,	ao_config_radio_power_show }, @@ -817,6 +959,10 @@ __code struct ao_config_var ao_config_vars[] = {  	{ "t <motion> <interval>\0Tracker configuration",  	  ao_config_tracker_set, ao_config_tracker_show },  #endif +#if HAS_APRS +	{ "S <ssid>\0Set APRS SSID (0-15)", +	  ao_config_aprs_ssid_set, ao_config_aprs_ssid_show }, +#endif  	{ "s\0Show",  	  ao_config_show,		0 },  #if HAS_EEPROM diff --git a/src/kernel/ao_config.h b/src/kernel/ao_config.h index 2b5cd352..164584a5 100644 --- a/src/kernel/ao_config.h +++ b/src/kernel/ao_config.h @@ -28,6 +28,10 @@  #define USE_EEPROM_CONFIG 0  #endif +#ifndef FLIGHT_LOG_APPEND +#define FLIGHT_LOG_APPEND 0 +#endif +  #if USE_STORAGE_CONFIG  #include <ao_storage.h> @@ -53,7 +57,7 @@  #endif  #define AO_CONFIG_MAJOR	1 -#define AO_CONFIG_MINOR	18 +#define AO_CONFIG_MINOR	21  #define AO_AES_LEN 16 @@ -102,8 +106,21 @@ struct ao_config {  #if AO_PYRO_NUM  	uint16_t	pyro_time;		/* minor version 18 */  #endif +#if HAS_APRS +	uint8_t		aprs_ssid;		/* minor version 19 */ +#endif +#if HAS_RADIO_RATE +	uint8_t		radio_rate;		/* minor version 20 */ +#endif +#if HAS_RADIO_FORWARD +	uint32_t	send_frequency;		/* minor version 21 */ +#endif  }; +#if HAS_RADIO_FORWARD +extern __xdata uint32_t	ao_send_radio_setting; +#endif +  #define AO_IGNITE_MODE_DUAL		0  #define AO_IGNITE_MODE_APOGEE		1  #define AO_IGNITE_MODE_MAIN		2 @@ -141,6 +158,9 @@ void  ao_config_set_radio(void);  void +ao_config_log_fix_append(void); + +void  ao_config_init(void);  #endif /* _AO_CONFIG_H_ */ diff --git a/src/kernel/ao_convert.c b/src/kernel/ao_convert.c index aa9b5f48..db1f2301 100644 --- a/src/kernel/ao_convert.c +++ b/src/kernel/ao_convert.c @@ -19,14 +19,16 @@  #include "ao.h"  #endif -static const int16_t altitude_table[] = { +#include <ao_sample.h> + +static const ao_v_t altitude_table[] = {  #include "altitude.h"  };  #define ALT_FRAC_SCALE	(1 << ALT_FRAC_BITS)  #define ALT_FRAC_MASK	(ALT_FRAC_SCALE - 1) -int16_t +ao_v_t  ao_pres_to_altitude(int16_t pres) __reentrant  {  	uint8_t	o; @@ -43,9 +45,9 @@ ao_pres_to_altitude(int16_t pres) __reentrant  #if AO_NEED_ALTITUDE_TO_PRES  int16_t -ao_altitude_to_pres(int16_t alt) __reentrant +ao_altitude_to_pres(ao_v_t alt) __reentrant  { -	int16_t span, sub_span; +	ao_v_t span, sub_span;  	uint8_t	l, h, m;  	int32_t pres; diff --git a/src/kernel/ao_convert_pa.c b/src/kernel/ao_convert_pa.c index fe6e0ef6..410815b6 100644 --- a/src/kernel/ao_convert_pa.c +++ b/src/kernel/ao_convert_pa.c @@ -24,7 +24,11 @@  #endif  static const alt_t altitude_table[] AO_CONST_ATTRIB = { +#if AO_SMALL_ALTITUDE_TABLE +#include "altitude-pa-small.h" +#else  #include "altitude-pa.h" +#endif  };  #ifndef FETCH_ALT @@ -35,11 +39,11 @@ static const alt_t altitude_table[] AO_CONST_ATTRIB = {  #define ALT_MASK	(ALT_SCALE - 1)  alt_t -ao_pa_to_altitude(int32_t pa) +ao_pa_to_altitude(pres_t pa)  {  	int16_t	o;  	int16_t	part; -	int32_t low, high; +	alt_t low, high;  	if (pa < 0)  		pa = 0; @@ -48,16 +52,16 @@ ao_pa_to_altitude(int32_t pa)  	o = pa >> ALT_SHIFT;  	part = pa & ALT_MASK; -	low = (int32_t) FETCH_ALT(o) * (ALT_SCALE - part); -	high = (int32_t) FETCH_ALT(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;  }  #ifdef AO_CONVERT_TEST -int32_t -ao_altitude_to_pa(int32_t alt) +pres_t +ao_altitude_to_pa(alt_t alt)  { -	int32_t 	span, sub_span; +	alt_t 	span, sub_span;  	uint16_t	l, h, m;  	int32_t 	pa; @@ -72,7 +76,7 @@ ao_altitude_to_pa(int32_t alt)  	}  	span = altitude_table[l] - altitude_table[h];  	sub_span = altitude_table[l] - alt; -	pa = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_SHIFT) + (span >> 1)) / span; +	pa = ((((alt_t) l * (span - sub_span) + (alt_t) h * sub_span) << ALT_SHIFT) + (span >> 1)) / span;  	if (pa > 120000)  		pa = 120000;  	if (pa < 0) diff --git a/src/kernel/ao_convert_pa_test.c b/src/kernel/ao_convert_pa_test.c index 7d5b1922..95422862 100644 --- a/src/kernel/ao_convert_pa_test.c +++ b/src/kernel/ao_convert_pa_test.c @@ -18,6 +18,7 @@  #include <stdint.h>  #define AO_CONVERT_TEST  typedef int32_t alt_t; +typedef int32_t pres_t;  #include "ao_host.h"  #include "ao_convert_pa.c" diff --git a/src/kernel/ao_data.h b/src/kernel/ao_data.h index c4b062fd..8f75ad87 100644 --- a/src/kernel/ao_data.h +++ b/src/kernel/ao_data.h @@ -117,9 +117,7 @@ extern volatile __data uint8_t		ao_data_count;  typedef int32_t	pres_t; -#ifndef AO_ALT_TYPE  #define AO_ALT_TYPE	int32_t -#endif  typedef AO_ALT_TYPE	alt_t; @@ -146,10 +144,6 @@ 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:   * diff --git a/src/kernel/ao_flight.c b/src/kernel/ao_flight.c index 2b433ee9..251dbc02 100644 --- a/src/kernel/ao_flight.c +++ b/src/kernel/ao_flight.c @@ -60,10 +60,10 @@ __xdata uint8_t			ao_sensor_errors;   * resting   */  static __data uint16_t		ao_interval_end; -static __data int16_t		ao_interval_min_height; -static __data int16_t		ao_interval_max_height; +static __data ao_v_t		ao_interval_min_height; +static __data ao_v_t		ao_interval_max_height;  #if HAS_ACCEL -static __data int16_t		ao_coast_avg_accel; +static __data ao_v_t		ao_coast_avg_accel;  #endif  __pdata uint8_t			ao_flight_force_idle; @@ -398,14 +398,14 @@ ao_flight(void)  }  #if HAS_FLIGHT_DEBUG -static inline int int_part(int16_t i)	{ return i >> 4; } -static inline int frac_part(int16_t i)	{ return ((i & 0xf) * 100 + 8) / 16; } +static inline int int_part(ao_v_t i)	{ return i >> 4; } +static inline int frac_part(ao_v_t i)	{ return ((i & 0xf) * 100 + 8) / 16; }  static void  ao_flight_dump(void)  {  #if HAS_ACCEL -	int16_t	accel; +	ao_v_t	accel;  	accel = ((ao_config.accel_plus_g - ao_sample_accel) * ao_accel_scale) >> 16;  #endif diff --git a/src/kernel/ao_forward.c b/src/kernel/ao_forward.c new file mode 100644 index 00000000..2a937183 --- /dev/null +++ b/src/kernel/ao_forward.c @@ -0,0 +1,48 @@ +/* + * Copyright © 2014 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_telem.h" + +static void +ao_monitor_forward(void) +{ +	uint32_t					recv_radio_setting; +	static __xdata struct ao_telemetry_all_recv	packet; + +	for (;;) { +		while (ao_monitoring) +			ao_sleep(DATA_TO_XDATA(&ao_monitoring)); + +		if (!ao_radio_recv(&packet, sizeof(packet), 0)) +			continue; +		if (!(packet.status & PKT_APPEND_STATUS_1_CRC_OK)) +			continue; +		recv_radio_setting = ao_config.radio_setting; +		ao_config.radio_setting = ao_send_radio_setting; +		ao_radio_send(&packet.telemetry, sizeof (packet.telemetry)); +		ao_config.radio_setting = recv_radio_setting; +	} +} + +static __xdata struct ao_task ao_monitor_forward_task; + +void +ao_monitor_forward_init(void) __reentrant +{ +	ao_add_task(&ao_monitor_forward_task, ao_monitor_forward, "monitor_forward"); +} diff --git a/src/kernel/ao_forward.h b/src/kernel/ao_forward.h new file mode 100644 index 00000000..1897dc08 --- /dev/null +++ b/src/kernel/ao_forward.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2014 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_FORWARD_H_ +#define _AO_FORWARD_H_ + +void +ao_monitor_forward_init(void) __reentrant; + +#endif /* _AO_FORWARD_H_ */ diff --git a/src/kernel/ao_gps_print.c b/src/kernel/ao_gps_print.c index 47c945d7..d26021da 100644 --- a/src/kernel/ao_gps_print.c +++ b/src/kernel/ao_gps_print.c @@ -20,6 +20,10 @@  #endif  #include "ao_telem.h" +#ifndef AO_TELEMETRY_LOCATION_ALTITUDE +#define AO_TELEMETRY_LOCATION_ALTITUDE(l)	((l)->altitude) +#endif +  void  ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant  { @@ -42,7 +46,7 @@ ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant  	       AO_TELEM_GPS_ALTITUDE " %d ",  	       (long) gps_data->latitude,  	       (long) gps_data->longitude, -	       gps_data->altitude); +	       AO_TELEMETRY_LOCATION_ALTITUDE(gps_data));  	if (gps_data->flags & AO_GPS_DATE_VALID)  		printf(AO_TELEM_GPS_YEAR " %d " diff --git a/src/kernel/ao_gps_report.c b/src/kernel/ao_gps_report.c index 07201ac2..7ef98a97 100644 --- a/src/kernel/ao_gps_report.c +++ b/src/kernel/ao_gps_report.c @@ -52,8 +52,12 @@ ao_gps_report(void)  			gps_log.u.gps_longitude = gps_data.longitude;  			ao_log_data(&gps_log);  			gps_log.type = AO_LOG_GPS_ALT; -			gps_log.u.gps_altitude.altitude = gps_data.altitude; -			gps_log.u.gps_altitude.unused = 0xffff; +			gps_log.u.gps_altitude.altitude_low = gps_data.altitude_low; +#if HAS_WIDE_GPS +			gps_log.u.gps_altitude.altitude_high = gps_data.altitude_high; +#else +			gps_log.u.gps_altitude.altitude_high = 0xffff; +#endif  			ao_log_data(&gps_log);  			if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) {  				gps_log.type = AO_LOG_GPS_DATE; diff --git a/src/kernel/ao_gps_report_mega.c b/src/kernel/ao_gps_report_mega.c index cb0c0fd9..f3711fb1 100644 --- a/src/kernel/ao_gps_report_mega.c +++ b/src/kernel/ao_gps_report_mega.c @@ -78,7 +78,8 @@ ao_gps_report_mega(void)  #if GPS_SPARSE_LOG  		/* Don't log data if GPS has a fix and hasn't moved for a while */  		if ((gps_data.flags & AO_GPS_VALID) && -		    !ao_gps_sparse_should_log(gps_data.latitude, gps_data.longitude, gps_data.altitude)) +		    !ao_gps_sparse_should_log(gps_data.latitude, gps_data.longitude, +					      AO_TELEMETRY_LOCATION_ALTITUDE(&gps_data))  			continue;  #endif  		if ((new & AO_GPS_NEW_DATA) && (gps_data.flags & AO_GPS_VALID)) { @@ -87,8 +88,8 @@ ao_gps_report_mega(void)  			gps_log.type = AO_LOG_GPS_TIME;  			gps_log.u.gps.latitude = gps_data.latitude;  			gps_log.u.gps.longitude = gps_data.longitude; -			gps_log.u.gps.altitude = gps_data.altitude; - +			gps_log.u.gps.altitude_low = gps_data.altitude_low; +			gps_log.u.gps.altitude_high = gps_data.altitude_high;  			gps_log.u.gps.hour = gps_data.hour;  			gps_log.u.gps.minute = gps_data.minute;  			gps_log.u.gps.second = gps_data.second; diff --git a/src/kernel/ao_gps_report_metrum.c b/src/kernel/ao_gps_report_metrum.c index 696a833b..8ce074fe 100644 --- a/src/kernel/ao_gps_report_metrum.c +++ b/src/kernel/ao_gps_report_metrum.c @@ -44,7 +44,8 @@ ao_gps_report_metrum(void)  			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; +			gps_log.u.gps.altitude_low = gps_data.altitude_low; +			gps_log.u.gps.altitude_high = gps_data.altitude_high;  			ao_log_metrum(&gps_log);  			gps_log.type = AO_LOG_GPS_TIME; @@ -55,6 +56,7 @@ ao_gps_report_metrum(void)  			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; +			gps_log.u.gps_time.pdop = gps_data.pdop;  			ao_log_metrum(&gps_log);  		} diff --git a/src/kernel/ao_gps_show.c b/src/kernel/ao_gps_show.c index 3a05e35a..e45cd795 100644 --- a/src/kernel/ao_gps_show.c +++ b/src/kernel/ao_gps_show.c @@ -19,6 +19,8 @@  #include <ao.h>  #endif +#include <ao_data.h> +  void  ao_gps_show(void) __reentrant  { @@ -27,7 +29,11 @@ ao_gps_show(void) __reentrant  	printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day);  	printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second);  	printf ("Lat/Lon: %ld %ld\n", (long) ao_gps_data.latitude, (long) ao_gps_data.longitude); -	printf ("Alt: %d\n", ao_gps_data.altitude); +#if HAS_WIDE_GPS +	printf ("Alt: %ld\n", (long) AO_TELEMETRY_LOCATION_ALTITUDE(&ao_gps_data)); +#else +	printf ("Alt: %d\n", AO_TELEMETRY_LOCATION_ALTITUDE(&ao_gps_data)); +#endif  	printf ("Flags: 0x%x\n", ao_gps_data.flags);  	printf ("Sats: %d", ao_gps_tracking_data.channels);  	for (i = 0; i < ao_gps_tracking_data.channels; i++) diff --git a/src/kernel/ao_kalman.c b/src/kernel/ao_kalman.c index 9aea1f14..7b0f8145 100644 --- a/src/kernel/ao_kalman.c +++ b/src/kernel/ao_kalman.c @@ -23,32 +23,31 @@  #include "ao_sample.h"  #include "ao_kalman.h" +static __pdata ao_k_t		ao_k_height; +static __pdata ao_k_t		ao_k_speed; +static __pdata ao_k_t		ao_k_accel; -static __pdata int32_t		ao_k_height; -static __pdata int32_t		ao_k_speed; -static __pdata int32_t		ao_k_accel; +#define AO_K_STEP_100		to_fix_v(0.01) +#define AO_K_STEP_2_2_100	to_fix_v(0.00005) -#define AO_K_STEP_100		to_fix16(0.01) -#define AO_K_STEP_2_2_100	to_fix16(0.00005) +#define AO_K_STEP_10		to_fix_v(0.1) +#define AO_K_STEP_2_2_10	to_fix_v(0.005) -#define AO_K_STEP_10		to_fix16(0.1) -#define AO_K_STEP_2_2_10	to_fix16(0.005) +#define AO_K_STEP_1		to_fix_v(1) +#define AO_K_STEP_2_2_1		to_fix_v(0.5) -#define AO_K_STEP_1		to_fix16(1) -#define AO_K_STEP_2_2_1		to_fix16(0.5) +__pdata ao_v_t			ao_height; +__pdata ao_v_t			ao_speed; +__pdata ao_v_t			ao_accel; +__xdata ao_v_t			ao_max_height; +static __pdata ao_k_t		ao_avg_height_scaled; +__xdata ao_v_t			ao_avg_height; -__pdata int16_t			ao_height; -__pdata int16_t			ao_speed; -__pdata int16_t			ao_accel; -__xdata int16_t			ao_max_height; -static __pdata int32_t		ao_avg_height_scaled; -__xdata int16_t			ao_avg_height; - -__pdata int16_t			ao_error_h; -__pdata int16_t			ao_error_h_sq_avg; +__pdata ao_v_t			ao_error_h; +__pdata ao_v_t			ao_error_h_sq_avg;  #if HAS_ACCEL -__pdata int16_t			ao_error_a; +__pdata ao_v_t			ao_error_a;  #endif  static void @@ -56,40 +55,40 @@ ao_kalman_predict(void)  {  #ifdef AO_FLIGHT_TEST  	if (ao_sample_tick - ao_sample_prev_tick > 50) { -		ao_k_height += ((int32_t) ao_speed * AO_K_STEP_1 + -				(int32_t) ao_accel * AO_K_STEP_2_2_1) >> 4; -		ao_k_speed += (int32_t) ao_accel * AO_K_STEP_1; +		ao_k_height += ((ao_k_t) ao_speed * AO_K_STEP_1 + +				(ao_k_t) ao_accel * AO_K_STEP_2_2_1) >> 4; +		ao_k_speed += (ao_k_t) ao_accel * AO_K_STEP_1;  		return;  	}  	if (ao_sample_tick - ao_sample_prev_tick > 5) { -		ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 + -				(int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4; -		ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10; +		ao_k_height += ((ao_k_t) ao_speed * AO_K_STEP_10 + +				(ao_k_t) ao_accel * AO_K_STEP_2_2_10) >> 4; +		ao_k_speed += (ao_k_t) ao_accel * AO_K_STEP_10;  		return;  	}  	if (ao_flight_debug) {  		printf ("predict speed %g + (%g * %g) = %g\n",  			ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0, -			(ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0)); +			(ao_k_speed + (ao_k_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0));  	}  #endif -	ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 + -			(int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4; -	ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100; +	ao_k_height += ((ao_k_t) ao_speed * AO_K_STEP_100 + +			(ao_k_t) ao_accel * AO_K_STEP_2_2_100) >> 4; +	ao_k_speed += (ao_k_t) ao_accel * AO_K_STEP_100;  }  static void  ao_kalman_err_height(void)  { -	int16_t	e; -	int16_t height_distrust; +	ao_v_t	e; +	ao_v_t height_distrust;  #if HAS_ACCEL -	int16_t	speed_distrust; +	ao_v_t	speed_distrust;  #endif -	ao_error_h = ao_sample_height - (int16_t) (ao_k_height >> 16); +	ao_error_h = ao_sample_height - (ao_v_t) (ao_k_height >> 16);  	e = ao_error_h;  	if (e < 0) @@ -123,7 +122,7 @@ ao_kalman_err_height(void)  #endif  		if (height_distrust > 0x100)  			height_distrust = 0x100; -		ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8); +		ao_error_h = (ao_v_t) (((ao_k_t) ao_error_h * (0x100 - height_distrust)) >> 8);  #ifdef AO_FLIGHT_TEST  		if (ao_flight_debug) {  			printf("over height %g over speed %g distrust: %g height: error %d -> %d\n", @@ -142,21 +141,21 @@ ao_kalman_correct_baro(void)  	ao_kalman_err_height();  #ifdef AO_FLIGHT_TEST  	if (ao_sample_tick - ao_sample_prev_tick > 50) { -		ao_k_height += (int32_t) AO_BARO_K0_1 * ao_error_h; -		ao_k_speed  += (int32_t) AO_BARO_K1_1 * ao_error_h; -		ao_k_accel  += (int32_t) AO_BARO_K2_1 * ao_error_h; +		ao_k_height += (ao_k_t) AO_BARO_K0_1 * ao_error_h; +		ao_k_speed  += (ao_k_t) AO_BARO_K1_1 * ao_error_h; +		ao_k_accel  += (ao_k_t) AO_BARO_K2_1 * ao_error_h;  		return;  	}  	if (ao_sample_tick - ao_sample_prev_tick > 5) { -		ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h; -		ao_k_speed  += (int32_t) AO_BARO_K1_10 * ao_error_h; -		ao_k_accel  += (int32_t) AO_BARO_K2_10 * ao_error_h; +		ao_k_height += (ao_k_t) AO_BARO_K0_10 * ao_error_h; +		ao_k_speed  += (ao_k_t) AO_BARO_K1_10 * ao_error_h; +		ao_k_accel  += (ao_k_t) AO_BARO_K2_10 * ao_error_h;  		return;  	}  #endif -	ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h; -	ao_k_speed  += (int32_t) AO_BARO_K1_100 * ao_error_h; -	ao_k_accel  += (int32_t) AO_BARO_K2_100 * ao_error_h; +	ao_k_height += (ao_k_t) AO_BARO_K0_100 * ao_error_h; +	ao_k_speed  += (ao_k_t) AO_BARO_K1_100 * ao_error_h; +	ao_k_accel  += (ao_k_t) AO_BARO_K2_100 * ao_error_h;  }  #if HAS_ACCEL @@ -164,7 +163,7 @@ ao_kalman_correct_baro(void)  static void  ao_kalman_err_accel(void)  { -	int32_t	accel; +	ao_k_t	accel;  	accel = (ao_config.accel_plus_g - ao_sample_accel) * ao_accel_scale; @@ -187,18 +186,18 @@ ao_kalman_correct_both(void)  				(double) ao_error_h, AO_BOTH_K10_1 / 65536.0,  				(double) ao_error_a, AO_BOTH_K11_1 / 65536.0,  				(ao_k_speed + -				 (int32_t) AO_BOTH_K10_1 * ao_error_h + -				 (int32_t) AO_BOTH_K11_1 * ao_error_a) / (65536.0 * 16.0)); +				 (ao_k_t) AO_BOTH_K10_1 * ao_error_h + +				 (ao_k_t) AO_BOTH_K11_1 * ao_error_a) / (65536.0 * 16.0));  		}  		ao_k_height += -			(int32_t) AO_BOTH_K00_1 * ao_error_h + -			(int32_t) AO_BOTH_K01_1 * ao_error_a; +			(ao_k_t) AO_BOTH_K00_1 * ao_error_h + +			(ao_k_t) AO_BOTH_K01_1 * ao_error_a;  		ao_k_speed += -			(int32_t) AO_BOTH_K10_1 * ao_error_h + -			(int32_t) AO_BOTH_K11_1 * ao_error_a; +			(ao_k_t) AO_BOTH_K10_1 * ao_error_h + +			(ao_k_t) AO_BOTH_K11_1 * ao_error_a;  		ao_k_accel += -			(int32_t) AO_BOTH_K20_1 * ao_error_h + -			(int32_t) AO_BOTH_K21_1 * ao_error_a; +			(ao_k_t) AO_BOTH_K20_1 * ao_error_h + +			(ao_k_t) AO_BOTH_K21_1 * ao_error_a;  		return;  	}  	if (ao_sample_tick - ao_sample_prev_tick > 5) { @@ -208,18 +207,18 @@ ao_kalman_correct_both(void)  				(double) ao_error_h, AO_BOTH_K10_10 / 65536.0,  				(double) ao_error_a, AO_BOTH_K11_10 / 65536.0,  				(ao_k_speed + -				 (int32_t) AO_BOTH_K10_10 * ao_error_h + -				 (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0)); +				 (ao_k_t) AO_BOTH_K10_10 * ao_error_h + +				 (ao_k_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0));  		}  		ao_k_height += -			(int32_t) AO_BOTH_K00_10 * ao_error_h + -			(int32_t) AO_BOTH_K01_10 * ao_error_a; +			(ao_k_t) AO_BOTH_K00_10 * ao_error_h + +			(ao_k_t) AO_BOTH_K01_10 * ao_error_a;  		ao_k_speed += -			(int32_t) AO_BOTH_K10_10 * ao_error_h + -			(int32_t) AO_BOTH_K11_10 * ao_error_a; +			(ao_k_t) AO_BOTH_K10_10 * ao_error_h + +			(ao_k_t) AO_BOTH_K11_10 * ao_error_a;  		ao_k_accel += -			(int32_t) AO_BOTH_K20_10 * ao_error_h + -			(int32_t) AO_BOTH_K21_10 * ao_error_a; +			(ao_k_t) AO_BOTH_K20_10 * ao_error_h + +			(ao_k_t) AO_BOTH_K21_10 * ao_error_a;  		return;  	}  	if (ao_flight_debug) { @@ -228,19 +227,19 @@ ao_kalman_correct_both(void)  			(double) ao_error_h, AO_BOTH_K10_100 / 65536.0,  			(double) ao_error_a, AO_BOTH_K11_100 / 65536.0,  			(ao_k_speed + -			 (int32_t) AO_BOTH_K10_100 * ao_error_h + -			 (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0)); +			 (ao_k_t) AO_BOTH_K10_100 * ao_error_h + +			 (ao_k_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0));  	}  #endif  	ao_k_height += -		(int32_t) AO_BOTH_K00_100 * ao_error_h + -		(int32_t) AO_BOTH_K01_100 * ao_error_a; +		(ao_k_t) AO_BOTH_K00_100 * ao_error_h + +		(ao_k_t) AO_BOTH_K01_100 * ao_error_a;  	ao_k_speed += -		(int32_t) AO_BOTH_K10_100 * ao_error_h + -		(int32_t) AO_BOTH_K11_100 * ao_error_a; +		(ao_k_t) AO_BOTH_K10_100 * ao_error_h + +		(ao_k_t) AO_BOTH_K11_100 * ao_error_a;  	ao_k_accel += -		(int32_t) AO_BOTH_K20_100 * ao_error_h + -		(int32_t) AO_BOTH_K21_100 * ao_error_a; +		(ao_k_t) AO_BOTH_K20_100 * ao_error_h + +		(ao_k_t) AO_BOTH_K21_100 * ao_error_a;  }  #else @@ -251,14 +250,14 @@ ao_kalman_correct_accel(void)  	ao_kalman_err_accel();  	if (ao_sample_tick - ao_sample_prev_tick > 5) { -		ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a; -		ao_k_speed  += (int32_t) AO_ACCEL_K1_10 * ao_error_a; -		ao_k_accel  += (int32_t) AO_ACCEL_K2_10 * ao_error_a; +		ao_k_height +=(ao_k_t) AO_ACCEL_K0_10 * ao_error_a; +		ao_k_speed  += (ao_k_t) AO_ACCEL_K1_10 * ao_error_a; +		ao_k_accel  += (ao_k_t) AO_ACCEL_K2_10 * ao_error_a;  		return;  	} -	ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a; -	ao_k_speed  += (int32_t) AO_ACCEL_K1_100 * ao_error_a; -	ao_k_accel  += (int32_t) AO_ACCEL_K2_100 * ao_error_a; +	ao_k_height += (ao_k_t) AO_ACCEL_K0_100 * ao_error_a; +	ao_k_speed  += (ao_k_t) AO_ACCEL_K1_100 * ao_error_a; +	ao_k_accel  += (ao_k_t) AO_ACCEL_K2_100 * ao_error_a;  }  #endif /* else FORCE_ACCEL */ diff --git a/src/kernel/ao_log.c b/src/kernel/ao_log.c index 91617d93..40a96ef7 100644 --- a/src/kernel/ao_log.c +++ b/src/kernel/ao_log.c @@ -142,19 +142,39 @@ ao_log_max_flight(void)  	return max_flight;  } -void -ao_log_scan(void) __reentrant +static void +ao_log_erase(uint8_t slot) __reentrant  { -	uint8_t		log_slot; -	uint8_t		log_slots; -	uint8_t		log_want; +	uint32_t log_current_pos, log_end_pos; -	ao_config_get(); +	ao_log_erase_mark(); +	log_current_pos = ao_log_pos(slot); +	log_end_pos = log_current_pos + ao_config.flight_log_max; +	while (log_current_pos < log_end_pos) { +		uint8_t	i; +		static __xdata uint8_t b; + +		/* +		 * Check to see if we've reached the end of +		 * the used memory to avoid re-erasing the same +		 * memory over and over again +		 */ +		for (i = 0; i < 16; i++) { +			if (ao_storage_read(log_current_pos + i, &b, 1)) +				if (b != 0xff) +					break; +		} +		if (i == 16) +			break; +		ao_storage_erase(log_current_pos); +		log_current_pos += ao_storage_block; +	} +} -	ao_flight_number = ao_log_max_flight(); -	if (ao_flight_number) -		if (++ao_flight_number == 0) -			ao_flight_number = 1; +static void +ao_log_find_max_erase_flight(void) __reentrant +{ +	uint8_t	log_slot;  	/* Now look through the log of flight numbers from erase operations and  	 * see if the last one is bigger than what we found above @@ -170,6 +190,80 @@ ao_log_scan(void) __reentrant  	}  	if (ao_flight_number == 0)  		ao_flight_number = 1; +} + +uint8_t +ao_log_scan(void) __reentrant +{ +	uint8_t		log_slot; +	uint8_t		log_slots; +#if FLIGHT_LOG_APPEND +	uint8_t		ret; +#else +	uint8_t		log_want; +#endif + +	ao_config_get(); + +	/* Get any existing flight number */ +	ao_flight_number = ao_log_max_flight(); + +#if FLIGHT_LOG_APPEND + +	/* Deal with older OS versions which stored multiple +	 * flights in rom by erasing everything after the first +	 * slot +	 */ +	if (ao_config.flight_log_max != ao_storage_log_max) { +		log_slots = ao_log_slots(); +		for (log_slot = 1; log_slot < log_slots; log_slot++) { +			if (ao_log_flight(log_slot) != 0) +				ao_log_erase(log_slot); +		} +		ao_config_log_fix_append(); +	} +	ao_log_current_pos = ao_log_pos(0); +	ao_log_end_pos = ao_log_current_pos + ao_storage_log_max; + +	if (ao_flight_number) { +		uint32_t	full = ao_log_current_pos; +		uint32_t	empty = ao_log_end_pos - ao_log_size; + +		/* If there's already a flight started, then find the +		 * end of it +		 */ +		for (;;) { +			ao_log_current_pos = (full + empty) >> 1; +			ao_log_current_pos -= ao_log_current_pos % ao_log_size; + +			if (ao_log_current_pos == full) { +				if (ao_log_check(ao_log_current_pos)) +					ao_log_current_pos += ao_log_size; +				break; +			} +			if (ao_log_current_pos == empty) +				break; + +			if (ao_log_check(ao_log_current_pos)) { +				full = ao_log_current_pos; +			} else { +				empty = ao_log_current_pos; +			} +		} +		ret = 1; +	} else { +		ao_log_find_max_erase_flight(); +		ret = 0; +	} +	ao_wakeup(&ao_flight_number); +	return ret; +#else + +	if (ao_flight_number) +		if (++ao_flight_number == 0) +			ao_flight_number = 1; + +	ao_log_find_max_erase_flight();  	/* With a flight number in hand, find a place to write a new log,  	 * use the target flight number to index the available log slots so @@ -190,8 +284,9 @@ ao_log_scan(void) __reentrant  		if (++log_slot >= log_slots)  			log_slot = 0;  	} while (log_slot != log_want); -  	ao_wakeup(&ao_flight_number); +	return 0; +#endif  }  void @@ -254,7 +349,6 @@ ao_log_delete(void) __reentrant  {  	uint8_t slot;  	uint8_t slots; -	uint32_t log_current_pos, log_end_pos;  	ao_cmd_decimal();  	if (ao_cmd_status != ao_cmd_success) @@ -268,28 +362,7 @@ ao_log_delete(void) __reentrant  #if HAS_TRACKER  				ao_tracker_erase_start(ao_cmd_lex_i);  #endif -				ao_log_erase_mark(); -				log_current_pos = ao_log_pos(slot); -				log_end_pos = log_current_pos + ao_config.flight_log_max; -				while (log_current_pos < log_end_pos) { -					uint8_t	i; -					static __xdata uint8_t b; - -					/* -					 * Check to see if we've reached the end of -					 * the used memory to avoid re-erasing the same -					 * memory over and over again -					 */ -					for (i = 0; i < 16; i++) { -						if (ao_storage_read(log_current_pos + i, &b, 1)) -							if (b != 0xff) -								break; -					} -					if (i == 16) -						break; -					ao_storage_erase(log_current_pos); -					log_current_pos += ao_storage_block; -				} +				ao_log_erase(slot);  #if HAS_TRACKER  				ao_tracker_erase_end();  #endif diff --git a/src/kernel/ao_log.h b/src/kernel/ao_log.h index 33cda3eb..c13a2580 100644 --- a/src/kernel/ao_log.h +++ b/src/kernel/ao_log.h @@ -51,11 +51,16 @@ extern __pdata enum ao_flight_state ao_log_state;  #define AO_LOG_FORMAT_NONE		127	/* No log at all */  extern __code uint8_t ao_log_format; +extern __code uint8_t ao_log_size;  /* Return the flight number from the given log slot, 0 if none */  uint16_t  ao_log_flight(uint8_t slot); +/* Check if there is valid log data at the specified location */ +uint8_t +ao_log_check(uint32_t pos); +  /* Flush the log */  void  ao_log_flush(void); @@ -67,7 +72,7 @@ ao_log(void);  /* functions provided in ao_log.c */  /* Figure out the current flight number */ -void +uint8_t  ao_log_scan(void) __reentrant;  /* Return the position of the start of the given log slot */ @@ -176,8 +181,8 @@ struct ao_log_record {  		int32_t		gps_latitude;  		int32_t		gps_longitude;  		struct { -			int16_t		altitude; -			uint16_t	unused; +			uint16_t	altitude_low; +			int16_t		altitude_high;  		} gps_altitude;  		struct {  			uint16_t	svid; @@ -246,7 +251,7 @@ struct ao_log_mega {  		struct {  			int32_t		latitude;	/* 4 */  			int32_t		longitude;	/* 8 */ -			int16_t		altitude;	/* 12 */ +			uint16_t	altitude_low;	/* 12 */  			uint8_t		hour;		/* 14 */  			uint8_t		minute;		/* 15 */  			uint8_t		second;		/* 16 */ @@ -261,7 +266,8 @@ struct ao_log_mega {  			uint8_t		hdop;		/* 27 */  			uint8_t		vdop;		/* 28 */  			uint8_t		mode;		/* 29 */ -		} gps;	/* 30 */ +			int16_t		altitude_high;	/* 30 */ +		} gps;	/* 32 */  		/* AO_LOG_GPS_SAT */  		struct {  			uint16_t	channels;	/* 4 */ @@ -273,6 +279,11 @@ struct ao_log_mega {  	} u;  }; +#define AO_LOG_MEGA_GPS_ALTITUDE(l)	((int32_t) ((l)->u.gps.altitude_high << 16) | ((l)->u.gps.altitude_low)) +#define AO_LOG_MEGA_SET_GPS_ALTITUDE(l,a)	(((l)->u.gps.mode |= AO_GPS_MODE_ALTITUDE_24), \ +						 ((l)->u.gps.altitude_high = (a) >> 16), \ +						 (l)->u.gps.altitude_low = (a)) +  struct ao_log_metrum {  	char			type;			/* 0 */  	uint8_t			csum;			/* 1 */ @@ -306,8 +317,9 @@ struct ao_log_metrum {  		struct {  			int32_t		latitude;	/* 4 */  			int32_t		longitude;	/* 8 */ -			int16_t		altitude;	/* 12 */ -		} gps;		/* 14 */ +			uint16_t	altitude_low;	/* 12 */ +			int16_t		altitude_high;	/* 14 */ +		} gps;		/* 16 */  		/* AO_LOG_GPS_TIME */  		struct {  			uint8_t		hour;		/* 4 */ @@ -317,7 +329,7 @@ struct ao_log_metrum {  			uint8_t		year;		/* 8 */  			uint8_t		month;		/* 9 */  			uint8_t		day;		/* 10 */ -			uint8_t		pad;		/* 11 */ +			uint8_t		pdop;		/* 11 */  		} gps_time;	/* 12 */  		/* AO_LOG_GPS_SAT (up to three packets) */  		struct { @@ -381,7 +393,7 @@ struct ao_log_gps {  		struct {  			int32_t		latitude;	/* 4 */  			int32_t		longitude;	/* 8 */ -			int16_t		altitude;	/* 12 */ +			uint16_t	altitude_low;	/* 12 */  			uint8_t		hour;		/* 14 */  			uint8_t		minute;		/* 15 */  			uint8_t		second;		/* 16 */ @@ -396,7 +408,7 @@ struct ao_log_gps {  			uint8_t		hdop;		/* 27 */  			uint8_t		vdop;		/* 28 */  			uint8_t		mode;		/* 29 */ -			uint8_t		state;		/* 30 */ +			int16_t		altitude_high;	/* 30 */  		} gps;	/* 31 */  		/* AO_LOG_GPS_SAT */  		struct { diff --git a/src/kernel/ao_log_gps.c b/src/kernel/ao_log_gps.c index 3b728c25..7643091c 100644 --- a/src/kernel/ao_log_gps.c +++ b/src/kernel/ao_log_gps.c @@ -26,6 +26,7 @@  static __xdata struct ao_log_gps log;  __code uint8_t ao_log_format = AO_LOG_FORMAT_TELEGPS; +__code uint8_t ao_log_size = sizeof (struct ao_log_gps);  static uint8_t  ao_log_csum(__xdata uint8_t *b) __reentrant @@ -75,7 +76,8 @@ ao_log_gps_data(uint16_t tick, struct ao_telemetry_location *gps_data)  	log.type = AO_LOG_GPS_TIME;  	log.u.gps.latitude = gps_data->latitude;  	log.u.gps.longitude = gps_data->longitude; -	log.u.gps.altitude = gps_data->altitude; +	log.u.gps.altitude_low = gps_data->altitude_low; +	log.u.gps.altitude_high = gps_data->altitude_high;  	log.u.gps.hour = gps_data->hour;  	log.u.gps.minute = gps_data->minute; @@ -135,3 +137,16 @@ ao_log_flight(uint8_t slot)  		return log.u.flight.flight;  	return 0;  } + +uint8_t +ao_log_check(uint32_t pos) +{ +	if (!ao_storage_read(pos, +			     &log, +			     sizeof (struct ao_log_gps))) +		return 0; + +	if (ao_log_dump_check_data()) +		return 1; +	return 0; +} diff --git a/src/kernel/ao_log_gps.h b/src/kernel/ao_log_gps.h index 5851f4d1..a9e8c831 100644 --- a/src/kernel/ao_log_gps.h +++ b/src/kernel/ao_log_gps.h @@ -21,9 +21,6 @@  #ifndef _AO_LOG_GPS_H_  #define _AO_LOG_GPS_H_ -uint8_t -ao_log_gps_should_log(int32_t lat, int32_t lon, int16_t alt); -  void  ao_log_gps_flight(void); diff --git a/src/kernel/ao_log_micro.c b/src/kernel/ao_log_micro.c index d665efb5..aef78def 100644 --- a/src/kernel/ao_log_micro.c +++ b/src/kernel/ao_log_micro.c @@ -22,10 +22,17 @@  static uint16_t ao_log_offset = STARTING_LOG_OFFSET; +#define AO_LOG_ID_SHIFT	12 +#define AO_LOG_ID_MASK	((1 << AO_LOG_ID_SHIFT) - 1) +  void  ao_log_micro_save(void)  {  	uint16_t	n_samples = (ao_log_offset - STARTING_LOG_OFFSET) / sizeof (uint16_t); + +#if AO_LOG_ID +	n_samples |= AO_LOG_ID << AO_LOG_ID_SHIFT; +#endif  	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)); @@ -99,8 +106,12 @@ ao_log_micro_dump(void)  	uint16_t	crc = 0xffff;  	ao_eeprom_read(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples)); +  	if (n_samples == 0xffff)  		n_samples = 0; +#if AO_LOG_ID +	n_samples &= AO_LOG_ID_MASK; +#endif  	nbytes = STARTING_LOG_OFFSET + sizeof (uint16_t) * n_samples;  	ao_async_start();  	ao_async_byte('M'); diff --git a/src/kernel/ao_microflight.c b/src/kernel/ao_microflight.c index f680e400..f7521f21 100644 --- a/src/kernel/ao_microflight.c +++ b/src/kernel/ao_microflight.c @@ -43,10 +43,12 @@ void  ao_microflight(void)  {  	int16_t		sample_count; +	int16_t		log_count;  	uint16_t	time;  	uint32_t	pa_interval_min, pa_interval_max;  	int32_t		pa_diff; -	uint8_t		h, i; +	uint8_t		h; +	uint8_t		i;  	uint8_t		accel_lock = 0;  	uint32_t	pa_sum = 0; @@ -60,19 +62,25 @@ ao_microflight(void)  	h = 0;  	for (;;) {  		time += SAMPLE_SLEEP; +#if BOOST_DETECT  		if ((sample_count & 0x1f) == 0)  			ao_led_on(AO_LED_REPORT); +#endif  		ao_delay_until(time);  		ao_microsample(); +#if BOOST_DETECT  		if ((sample_count & 0x1f) == 0)  			ao_led_off(AO_LED_REPORT); +#endif  		pa_hist[h] = pa;  		h = SKIP_PA_HIST(h,1);  		pa_diff = pa_ground - ao_pa; +#if BOOST_DETECT  		/* Check for a significant pressure change */  		if (pa_diff > BOOST_DETECT)  			break; +#endif  		if (sample_count < GROUND_AVG * 2) {  			if (sample_count < GROUND_AVG) @@ -82,6 +90,9 @@ ao_microflight(void)  			pa_ground = pa_sum >> GROUND_AVG_SHIFT;  			pa_sum = 0;  			sample_count = 0; +#if !BOOST_DETECT +			break; +#endif  		}  	} @@ -93,7 +104,10 @@ ao_microflight(void)  	}  	/* Log the remaining samples so we get a complete history since leaving the ground */ -	for (; i != h; i = SKIP_PA_HIST(i,2)) { +#if LOG_INTERVAL < NUM_PA_HIST +	for (; i != h; i = SKIP_PA_HIST(i,2)) +#endif +	{  		pa = pa_hist[i];  		ao_log_micro_data();  	} @@ -101,6 +115,7 @@ ao_microflight(void)  	/* Now sit around until the pressure is stable again and record the max */  	sample_count = 0; +	log_count = 0;  	pa_min = ao_pa;  	pa_interval_min = ao_pa;  	pa_interval_max = ao_pa; @@ -112,8 +127,11 @@ ao_microflight(void)  		ao_microsample();  		if ((sample_count & 3) == 0)  			ao_led_off(AO_LED_REPORT); -		if (sample_count & 1) +		if (log_count == LOG_INTERVAL - 1) {  			ao_log_micro_data(); +			log_count = 0; +		} else +			log_count++;  		/* If accelerating upwards, don't look for min pressure */  		if (ao_pa_accel < ACCEL_LOCK_PA) diff --git a/src/kernel/ao_microkalman.c b/src/kernel/ao_microkalman.c index 0684ea2b..75a29cc4 100644 --- a/src/kernel/ao_microkalman.c +++ b/src/kernel/ao_microkalman.c @@ -22,19 +22,19 @@  #define FIX_BITS	16 -#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) -#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) +#define to_fix_v(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix_k(x) ((int32_t) ((x) * 65536.0 + 0.5))  #define from_fix8(x)	((x) >> 8)  #define from_fix(x)	((x) >> 16) -#define fix8_to_fix16(x)	((x) << 8) +#define fix8_to_fix_v(x)	((x) << 8)  #define fix16_to_fix8(x)	((x) >> 8)  #include <ao_kalman.h>  /* Basic time step (96ms) */ -#define AO_MK_STEP	to_fix16(0.096) +#define AO_MK_STEP	to_fix_v(0.096)  /* step ** 2 / 2 */ -#define AO_MK_STEP_2_2	to_fix16(0.004608) +#define AO_MK_STEP_2_2	to_fix_v(0.004608)  uint32_t	ao_k_pa;		/* 24.8 fixed point */  int32_t		ao_k_pa_speed;		/* 16.16 fixed point */ @@ -49,7 +49,7 @@ ao_microkalman_init(void)  {  	ao_pa = pa;  	ao_k_pa = pa << 8; -}	 +}  void  ao_microkalman_predict(void) diff --git a/src/kernel/ao_monitor.c b/src/kernel/ao_monitor.c index 18f170b4..2d75c41c 100644 --- a/src/kernel/ao_monitor.c +++ b/src/kernel/ao_monitor.c @@ -115,6 +115,8 @@ ao_monitor_put(void)  {  #if LEGACY_MONITOR  	__xdata char callsign[AO_MAX_CALLSIGN+1]; +#endif +#if LEGACY_MONITOR || HAS_RSSI  	int16_t rssi;  #endif  	uint8_t ao_monitor_tail; @@ -240,7 +242,7 @@ ao_monitor_put(void)  			hex(sum);  			putchar ('\n');  #if HAS_RSSI -			if (recv_raw.packet[ao_monitoring + 1] & PKT_APPEND_STATUS_1_CRC_OK) { +			if (recv_raw.packet[ao_monitoring + 1] & AO_RADIO_STATUS_CRC_OK) {  				rssi = AO_RSSI_FROM_RADIO(recv_raw.packet[ao_monitoring]);  				ao_rssi_set(rssi);  			} diff --git a/src/kernel/ao_mutex.c b/src/kernel/ao_mutex.c index 952ff462..a36fe939 100644 --- a/src/kernel/ao_mutex.c +++ b/src/kernel/ao_mutex.c @@ -17,6 +17,29 @@  #include "ao.h" +#ifndef HAS_MUTEX_TRY +#define HAS_MUTEX_TRY 1 +#endif + +#if HAS_MUTEX_TRY + +uint8_t +ao_mutex_try(__xdata uint8_t *mutex, uint8_t task_id) __reentrant +{ +	uint8_t	ret; +	if (*mutex == task_id) +		ao_panic(AO_PANIC_MUTEX); +	ao_arch_critical( +		if (*mutex) +			ret = 0; +		else { +			*mutex = task_id; +			ret = 1; +		}); +	return ret; +} +#endif +  void  ao_mutex_get(__xdata uint8_t *mutex) __reentrant  { diff --git a/src/kernel/ao_pyro.c b/src/kernel/ao_pyro.c index 85d88d98..3044d565 100644 --- a/src/kernel/ao_pyro.c +++ b/src/kernel/ao_pyro.c @@ -69,6 +69,16 @@ ao_pyro_print_status(void)  uint16_t	ao_pyro_fired; +#ifndef PYRO_DBG +#define PYRO_DBG	0 +#endif + +#if PYRO_DBG +#define DBG(...)	do { printf("\t%d: ", (int) (pyro - ao_config.pyro)); printf(__VA_ARGS__); } while (0) +#else +#define DBG(...) +#endif +  /*   * Given a pyro structure, figure out   * if the current flight state satisfies all @@ -88,63 +98,73 @@ ao_pyro_ready(struct ao_pyro *pyro)  		case ao_pyro_accel_less:  			if (ao_accel <= pyro->accel_less)  				continue; +			DBG("accel %d > %d\n", ao_accel, pyro->accel_less);  			break;  		case ao_pyro_accel_greater:  			if (ao_accel >= pyro->accel_greater)  				continue; +			DBG("accel %d < %d\n", ao_accel, pyro->accel_greater);  			break; - -  		case ao_pyro_speed_less:  			if (ao_speed <= pyro->speed_less)  				continue; +			DBG("speed %d > %d\n", ao_speed, pyro->speed_less);  			break;  		case ao_pyro_speed_greater:  			if (ao_speed >= pyro->speed_greater)  				continue; +			DBG("speed %d < %d\n", ao_speed, pyro->speed_greater);  			break; -  		case ao_pyro_height_less:  			if (ao_height <= pyro->height_less)  				continue; +			DBG("height %d > %d\n", ao_height, pyro->height_less);  			break;  		case ao_pyro_height_greater:  			if (ao_height >= pyro->height_greater)  				continue; +			DBG("height %d < %d\n", ao_height, pyro->height_greater);  			break;  #if HAS_GYRO  		case ao_pyro_orient_less:  			if (ao_sample_orient <= pyro->orient_less)  				continue; +			DBG("orient %d > %d\n", ao_sample_orient, pyro->orient_less);  			break;  		case ao_pyro_orient_greater:  			if (ao_sample_orient >= pyro->orient_greater)  				continue; +			DBG("orient %d < %d\n", ao_sample_orient, pyro->orient_greater);  			break;  #endif  		case ao_pyro_time_less:  			if ((int16_t) (ao_time() - ao_boost_tick) <= pyro->time_less)  				continue; +			DBG("time %d > %d\n", (int16_t)(ao_time() - ao_boost_tick), pyro->time_less);  			break;  		case ao_pyro_time_greater:  			if ((int16_t) (ao_time() - ao_boost_tick) >= pyro->time_greater)  				continue; +			DBG("time %d < %d\n", (int16_t)(ao_time() - ao_boost_tick), pyro->time_greater);  			break;  		case ao_pyro_ascending:  			if (ao_speed > 0)  				continue; +			DBG("not ascending speed %d\n", ao_speed);  			break;  		case ao_pyro_descending:  			if (ao_speed < 0)  				continue; +			DBG("not descending speed %d\n", ao_speed);  			break;  		case ao_pyro_after_motor:  			if (ao_motor_number == pyro->motor)  				continue; +			DBG("motor %d != %d\n", ao_motor_number, pyro->motor);  			break;  		case ao_pyro_delay: @@ -154,10 +174,12 @@ ao_pyro_ready(struct ao_pyro *pyro)  		case ao_pyro_state_less:  			if (ao_flight_state < pyro->state_less)  				continue; +			DBG("state %d >= %d\n", ao_flight_state, pyro->state_less);  			break;  		case ao_pyro_state_greater_or_equal:  			if (ao_flight_state >= pyro->state_greater_or_equal)  				continue; +			DBG("state %d >= %d\n", ao_flight_state, pyro->state_less);  			break;  		default: @@ -230,7 +252,7 @@ ao_pyro_check(void)  	struct ao_pyro	*pyro;  	uint8_t		p, any_waiting;  	uint16_t	fire = 0; -	 +  	any_waiting = 0;  	for (p = 0; p < AO_PYRO_NUM; p++) {  		pyro = &ao_config.pyro[p]; @@ -266,6 +288,16 @@ ao_pyro_check(void)  		 * the delay to expire  		 */  		if (pyro->delay_done) { + +			/* Check to make sure the required conditions +			 * remain valid. If not, inhibit the channel +			 * by setting the fired bit +			 */ +			if (!ao_pyro_ready(pyro)) { +				pyro->fired = 1; +				continue; +			} +  			if ((int16_t) (ao_time() - pyro->delay_done) < 0)  				continue;  		} @@ -443,7 +475,7 @@ ao_pyro_set(void)  		printf ("invalid pyro channel %d\n", p);  		return;  	} -	pyro_tmp.flags = 0; +	memset(&pyro_tmp, '\0', sizeof (pyro_tmp));  	for (;;) {  		ao_cmd_white();  		if (ao_cmd_lex_c == '\n') @@ -467,13 +499,26 @@ ao_pyro_set(void)  		}  		pyro_tmp.flags |= ao_pyro_values[v].flag;  		if (ao_pyro_values[v].offset != NO_VALUE) { +			uint8_t negative = 0; +			ao_cmd_white(); +			if (ao_cmd_lex_c == '-') { +				negative = 1; +				ao_cmd_lex(); +			}  			ao_cmd_decimal();  			if (ao_cmd_status != ao_cmd_success)  				return; -			if (ao_pyro_values[v].flag & AO_PYRO_8_BIT_VALUE) +			if (ao_pyro_values[v].flag & AO_PYRO_8_BIT_VALUE) { +				if (negative) { +					ao_cmd_status = ao_cmd_syntax_error; +					return; +				}  				*((uint8_t *) ((char *) &pyro_tmp + ao_pyro_values[v].offset)) = ao_cmd_lex_i; -			else +			} else { +				if (negative) +					ao_cmd_lex_i = -ao_cmd_lex_i;  				*((int16_t *) ((char *) &pyro_tmp + ao_pyro_values[v].offset)) = ao_cmd_lex_i; +			}  		}  	}  	_ao_config_edit_start(); diff --git a/src/kernel/ao_pyro.h b/src/kernel/ao_pyro.h index b37aaeb1..0fde725a 100644 --- a/src/kernel/ao_pyro.h +++ b/src/kernel/ao_pyro.h @@ -83,6 +83,9 @@ ao_pyro_init(void);  void  ao_pyro_manual(uint8_t p); +enum ao_igniter_status +ao_pyro_status(uint8_t p); +  void  ao_pyro_print_status(void); diff --git a/src/kernel/ao_report.c b/src/kernel/ao_report.c index f2263154..5314fc8f 100644 --- a/src/kernel/ao_report.c +++ b/src/kernel/ao_report.c @@ -211,12 +211,23 @@ ao_report_continuity(void) __reentrant  			pause(AO_MS_TO_TICKS(100));  		}  	} else { -		c = 10; +		c = 5;  		while (c--) {  			high(AO_MS_TO_TICKS(20));  			low(AO_MS_TO_TICKS(20));  		}  	} +#if AO_PYRO_NUM +	pause(AO_MS_TO_TICKS(250)); +	for(c = 0; c < AO_PYRO_NUM; c++) { +		enum ao_igniter_status	status = ao_pyro_status(c); +		if (status == ao_igniter_ready) +			mid(AO_MS_TO_TICKS(25)); +		else +			low(AO_MS_TO_TICKS(25)); +		pause(AO_MS_TO_TICKS(200)); +	} +#endif  #if HAS_LOG  	if (ao_log_full()) {  		pause(AO_MS_TO_TICKS(100)); diff --git a/src/kernel/ao_rssi.c b/src/kernel/ao_rssi.c index 244a84fe..793b190b 100644 --- a/src/kernel/ao_rssi.c +++ b/src/kernel/ao_rssi.c @@ -17,9 +17,9 @@  #include "ao.h" -static __xdata uint16_t	ao_rssi_time; -static __pdata uint16_t	ao_rssi_delay; -static __pdata uint8_t	ao_rssi_led; +static __xdata uint16_t		ao_rssi_time; +static __pdata uint16_t		ao_rssi_delay; +static __pdata AO_LED_TYPE	ao_rssi_led;  void  ao_rssi(void) @@ -33,7 +33,7 @@ ao_rssi(void)  }  void -ao_rssi_set(int rssi_value) +ao_rssi_set(int16_t rssi_value)  {  	if (rssi_value > 0)  		rssi_value = 0; @@ -45,7 +45,7 @@ ao_rssi_set(int rssi_value)  __xdata struct ao_task ao_rssi_task;  void -ao_rssi_init(uint8_t rssi_led) +ao_rssi_init(AO_LED_TYPE rssi_led)  {  	ao_rssi_led = rssi_led;  	ao_rssi_delay = 0; diff --git a/src/kernel/ao_sample.c b/src/kernel/ao_sample.c index 34658951..29bf2bf6 100644 --- a/src/kernel/ao_sample.c +++ b/src/kernel/ao_sample.c @@ -245,7 +245,7 @@ ao_sample_preflight(void)  	} else {  #if HAS_ACCEL  		ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; -		ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; +		ao_accel_scale = to_fix_32(GRAVITY * 2 * 16) / ao_accel_2g;  #endif  		ao_sample_preflight_set();  		ao_preflight = FALSE; diff --git a/src/kernel/ao_sample.h b/src/kernel/ao_sample.h index 16d4c507..2ec998bd 100644 --- a/src/kernel/ao_sample.h +++ b/src/kernel/ao_sample.h @@ -24,6 +24,24 @@   * ao_sample.c   */ +#ifndef AO_VALUE_32 +#define AO_VALUE_32	1 +#endif + +#if AO_VALUE_32 +/* + * For 32-bit computed values, use 64-bit intermediates. + */ +typedef int64_t			ao_k_t; +typedef int32_t			ao_v_t; +#else +/* + * For 16-bit computed values, use 32-bit intermediates. + */ +typedef int32_t			ao_k_t; +typedef int16_t			ao_v_t; +#endif +  /*   * Barometer calibration   * @@ -87,9 +105,9 @@   * 2047m/s² (over 200g)   */ -#define AO_M_TO_HEIGHT(m)	((int16_t) (m)) -#define AO_MS_TO_SPEED(ms)	((int16_t) ((ms) * 16)) -#define AO_MSS_TO_ACCEL(mss)	((int16_t) ((mss) * 16)) +#define AO_M_TO_HEIGHT(m)	((ao_v_t) (m)) +#define AO_MS_TO_SPEED(ms)	((ao_v_t) ((ms) * 16)) +#define AO_MSS_TO_ACCEL(mss)	((ao_v_t) ((mss) * 16))  extern __pdata uint16_t	ao_sample_tick;		/* time of last data */  extern __data uint8_t	ao_sample_adc;		/* Ring position of last processed sample */ @@ -134,21 +152,33 @@ uint8_t ao_sample(void);   * ao_kalman.c   */ -#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) -#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) +#define to_fix_16(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix_32(x) ((int32_t) ((x) * 65536.0 + 0.5)) +#define to_fix_64(x) ((int64_t) ((x) * 65536.0 + 0.5)) + +#ifdef AO_VALUE_32 +#if AO_VALUE_32 +#define to_fix_v(x)	to_fix_32(x) +#define to_fix_k(x)	to_fix_64(x) +#else +#define to_fix_v(x)	to_fix_16(x) +#define to_fix_k(x)	to_fix_32(x) +#endif +  #define from_fix(x)	((x) >> 16) -extern __pdata int16_t			ao_height;	/* meters */ -extern __pdata int16_t			ao_speed;	/* m/s * 16 */ -extern __pdata int16_t			ao_accel;	/* m/s² * 16 */ -extern __xdata int16_t			ao_max_height;	/* max of ao_height */ -extern __xdata int16_t			ao_avg_height;	/* running average of height */ +extern __pdata ao_v_t			ao_height;	/* meters */ +extern __pdata ao_v_t			ao_speed;	/* m/s * 16 */ +extern __pdata ao_v_t			ao_accel;	/* m/s² * 16 */ +extern __xdata ao_v_t			ao_max_height;	/* max of ao_height */ +extern __xdata ao_v_t			ao_avg_height;	/* running average of height */ -extern __pdata int16_t			ao_error_h; -extern __pdata int16_t			ao_error_h_sq_avg; +extern __pdata ao_v_t			ao_error_h; +extern __pdata ao_v_t			ao_error_h_sq_avg;  #if HAS_ACCEL -extern __pdata int16_t			ao_error_a; +extern __pdata ao_v_t			ao_error_a; +#endif  #endif  void ao_kalman(void); diff --git a/src/kernel/ao_telemetry.c b/src/kernel/ao_telemetry.c index 9f778b09..56bd715e 100644 --- a/src/kernel/ao_telemetry.c +++ b/src/kernel/ao_telemetry.c @@ -1,5 +1,5 @@  /* - * Copyright © 2011 Keith Packard <keithp@keithp.com> + * Copyright © 2011 Keth 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 @@ -25,6 +25,10 @@  static __pdata uint16_t ao_telemetry_interval; +#if HAS_RADIO_RATE +static __xdata uint16_t ao_telemetry_desired_interval; +#endif +  #if HAS_RDF  static __pdata uint8_t ao_rdf = 0;  static __pdata uint16_t ao_rdf_time; @@ -64,7 +68,7 @@ static void  ao_send_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_SENSOR; @@ -106,12 +110,13 @@ ao_send_sensor(void)  #ifdef AO_SEND_MEGA +  /* Send mega sensor packet */  static void  ao_send_mega_sensor(void)  {  	__xdata	struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; -			 +  	telemetry.generic.tick = packet->tick;  	telemetry.generic.type = AO_TELEMETRY_MEGA_SENSOR; @@ -240,7 +245,7 @@ static void  ao_send_mini(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_MINI; @@ -339,7 +344,7 @@ ao_send_location(void)  		ao_mutex_get(&ao_gps_mutex);  		ao_xmemcpy(&telemetry.location.flags,  		       &ao_gps_data.flags, -		       26); +		       27);  		telemetry.location.tick = ao_gps_tick;  		ao_mutex_put(&ao_gps_mutex);  		ao_radio_send(&telemetry, sizeof (telemetry)); @@ -490,12 +495,33 @@ ao_telemetry(void)  	}  } +#if HAS_RADIO_RATE +void +ao_telemetry_reset_interval(void) +{ +	ao_telemetry_set_interval(ao_telemetry_desired_interval); +} +#endif +  void  ao_telemetry_set_interval(uint16_t interval)  {  	int8_t	cur = 0; + +#if HAS_RADIO_RATE +	/* Limit max telemetry rate based on available radio bandwidth. +	 */ +	static __xdata const uint16_t min_interval[] = { +		/* [AO_RADIO_RATE_38400] = */ AO_MS_TO_TICKS(100), +		/* [AO_RADIO_RATE_9600] = */ AO_MS_TO_TICKS(500), +		/* [AO_RADIO_RATE_2400] = */ AO_MS_TO_TICKS(1000) +	}; + +	ao_telemetry_desired_interval = interval; +	if (interval < min_interval[ao_config.radio_rate]) +		interval = min_interval[ao_config.radio_rate]; +#endif  	ao_telemetry_interval = interval; -	  #if AO_SEND_MEGA  	if (interval > 1)  		ao_telemetry_mega_data_max = 1; @@ -521,7 +547,7 @@ ao_telemetry_set_interval(uint16_t interval)  	ao_telemetry_companion_cur = cur;  #endif -	ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval; +	ao_telemetry_config_max = AO_SEC_TO_TICKS(5) / interval;  #if HAS_COMPANION  	if (ao_telemetry_config_max > cur)  		cur++; diff --git a/src/kernel/ao_telemetry.h b/src/kernel/ao_telemetry.h index be7d0340..83d432cf 100644 --- a/src/kernel/ao_telemetry.h +++ b/src/kernel/ao_telemetry.h @@ -86,12 +86,9 @@ struct ao_telemetry_configuration {  #define AO_TELEMETRY_LOCATION		0x05 -#define AO_GPS_MODE_NOT_VALID		'N' -#define AO_GPS_MODE_AUTONOMOUS		'A' -#define AO_GPS_MODE_DIFFERENTIAL	'D' -#define AO_GPS_MODE_ESTIMATED		'E' -#define AO_GPS_MODE_MANUAL		'M' -#define AO_GPS_MODE_SIMULATED		'S' +/* Mode bits */ + +#define AO_GPS_MODE_ALTITUDE_24		(1 << 0)	/* reports 24-bits of altitude */  struct ao_telemetry_location {  	uint16_t	serial;		/*  0 */ @@ -99,7 +96,7 @@ struct ao_telemetry_location {  	uint8_t		type;		/*  4 */  	uint8_t         flags;		/*  5 Number of sats and other flags */ -	int16_t         altitude;	/*  6 GPS reported altitude (m) */ +	uint16_t        altitude_low;	/*  6 GPS reported altitude (m) */  	int32_t         latitude;	/*  8 latitude (degrees * 10⁷) */  	int32_t         longitude;	/* 12 longitude (degrees * 10⁷) */  	uint8_t         year;		/* 16 (- 2000) */ @@ -115,10 +112,31 @@ struct ao_telemetry_location {  	uint16_t	ground_speed;	/* 26 cm/s */  	int16_t		climb_rate;	/* 28 cm/s */  	uint8_t		course;		/* 30 degrees / 2 */ -	uint8_t		unused;		/* 31 unused */ +	int8_t		altitude_high;	/* 31 high byte of altitude */  	/* 32 */  }; +#if HAS_GPS + +#ifndef HAS_WIDE_GPS +#define HAS_WIDE_GPS	1 +#endif + +#if HAS_WIDE_GPS +typedef int32_t		gps_alt_t; +#define AO_TELEMETRY_LOCATION_ALTITUDE(l) 	(((gps_alt_t) (l)->altitude_high << 16) | ((l)->altitude_low)) +#define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a) (((l)->mode |= AO_GPS_MODE_ALTITUDE_24), \ +						 ((l)->altitude_high = (a) >> 16), \ +						 ((l)->altitude_low = (a))) +#else +typedef int16_t		gps_alt_t; +#define AO_TELEMETRY_LOCATION_ALTITUDE(l)	((gps_alt_t) (l)->altitude_low) +#define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a)	(((l)->mode = 0, \ +						  (l)->altitude_low = (a))) +#endif /* HAS_WIDE_GPS */ + +#endif /* HAS_GPS */ +  #define AO_TELEMETRY_SATELLITE		0x06  struct ao_telemetry_satellite_info { diff --git a/src/kernel/ao_tracker.c b/src/kernel/ao_tracker.c index 9febc7f0..9b007af8 100644 --- a/src/kernel/ao_tracker.c +++ b/src/kernel/ao_tracker.c @@ -36,9 +36,9 @@ ao_usb_connected(void)  #endif  struct gps_position { -	int32_t	latitude; -	int32_t	longitude; -	int16_t	altitude; +	int32_t		latitude; +	int32_t		longitude; +	gps_alt_t	altitude;  };  #define GPS_RING	16 @@ -72,7 +72,7 @@ ao_tracker(void)  #if !HAS_USB_CONNECT  	ao_tracker_force_telem = 1;  #endif -	ao_log_scan(); +	log_started = ao_log_scan();  	ao_rdf_set(1); @@ -122,12 +122,13 @@ ao_tracker(void)  			{  				uint8_t	ring;  				uint8_t	moving = 0; +				gps_alt_t altitude = AO_TELEMETRY_LOCATION_ALTITUDE(&gps_data);  				for (ring = ao_gps_ring_next(gps_head); ring != gps_head; ring = ao_gps_ring_next(ring)) {  					ground_distance = ao_distance(gps_data.latitude, gps_data.longitude,  								      gps_position[ring].latitude,  								      gps_position[ring].longitude); -					height = gps_position[ring].altitude - gps_data.altitude; +					height = gps_position[ring].altitude - altitude;  					if (height < 0)  						height = -height; @@ -153,7 +154,7 @@ ao_tracker(void)  					ao_log_gps_data(gps_tick, &gps_data);  					gps_position[gps_head].latitude = gps_data.latitude;  					gps_position[gps_head].longitude = gps_data.longitude; -					gps_position[gps_head].altitude = gps_data.altitude; +					gps_position[gps_head].altitude = altitude;  					gps_head = ao_gps_ring_next(gps_head);  					ao_mutex_put(&tracker_mutex);  				} @@ -180,8 +181,7 @@ void  ao_tracker_erase_end(void)  {  	if (erasing_current) { -		ao_log_scan(); -		log_started = 0; +		log_started = ao_log_scan();  		ao_mutex_put(&tracker_mutex);  	}  } @@ -203,7 +203,7 @@ ao_tracker_set_telem(void)  	printf ("log_started: %d\n", log_started);  	printf ("latitude: %ld\n", (long) gps_data.latitude);  	printf ("longitude: %ld\n", (long) gps_data.longitude); -	printf ("altitude: %d\n", gps_data.altitude); +	printf ("altitude: %ld\n", AO_TELEMETRY_LOCATION_ALTITUDE(&gps_data));  	printf ("log_running: %d\n", ao_log_running);  	printf ("log_start_pos: %ld\n", (long) ao_log_start_pos);  	printf ("log_cur_pos: %ld\n", (long) ao_log_current_pos); diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 0891903e..21a7a8e5 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -161,16 +161,17 @@ static inline void ao_arch_restore_stack(void) {  #endif /* HAS_TASK */ -#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\n\nao_idle_loc:");	\ +		ao_arch_block_interrupts();			\  	} while (0) -#define ao_arch_critical(b) do {				\ -		ao_arch_block_interrupts();			\ -		do { b } while (0);				\ -		ao_arch_release_interrupts();			\ +#define ao_arch_critical(b) do {			\ +		uint32_t __mask = ao_arch_irqsave();	\ +		do { b } while (0);			\ +		ao_arch_irqrestore(__mask);		\  	} while (0)  /* diff --git a/src/megadongle-v0.1/Makefile b/src/megadongle-v0.1/Makefile index ade8e496..bbe2ea58 100644 --- a/src/megadongle-v0.1/Makefile +++ b/src/megadongle-v0.1/Makefile @@ -53,6 +53,7 @@ ALTOS_SRC = \  	ao_rssi.c \  	ao_send_packet.c \  	ao_packet_master.c \ +	ao_eeprom_stm.c \  	ao_packet.c  PRODUCT=MegaDongle-v0.1 diff --git a/src/megadongle-v0.1/ao_megadongle.c b/src/megadongle-v0.1/ao_megadongle.c index 2792af22..68d6de60 100644 --- a/src/megadongle-v0.1/ao_megadongle.c +++ b/src/megadongle-v0.1/ao_megadongle.c @@ -24,7 +24,7 @@ int  main(void)  {  	ao_clock_init(); -	 +  #if HAS_STACK_GUARD  	ao_mpu_init();  #endif @@ -48,7 +48,7 @@ main(void)  	ao_send_packet_init();  	ao_config_init(); -	 +  	ao_start_scheduler();  	return 0;  } diff --git a/src/megadongle-v0.1/ao_pins.h b/src/megadongle-v0.1/ao_pins.h index d460a490..9edd91f4 100644 --- a/src/megadongle-v0.1/ao_pins.h +++ b/src/megadongle-v0.1/ao_pins.h @@ -15,6 +15,8 @@   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.   */ +/* Using TeleMetrum v1.9 board */ +  #ifndef _AO_PINS_H_  #define _AO_PINS_H_ @@ -46,7 +48,7 @@  #define HAS_SERIAL_1		0  #define USE_SERIAL_1_STDIN	0  #define SERIAL_1_PB6_PB7	0 -#define SERIAL_1_PA9_PA10	1 +#define SERIAL_1_PA9_PA10	0  #define HAS_SERIAL_2		0  #define USE_SERIAL_2_STDIN	0 @@ -56,19 +58,18 @@  #define HAS_SERIAL_3		0  #define USE_SERIAL_3_STDIN	0  #define SERIAL_3_PB10_PB11	0 -#define SERIAL_3_PC10_PC11	1 +#define SERIAL_3_PC10_PC11	0  #define SERIAL_3_PD8_PD9	0 -#define ao_gps_getchar		ao_serial3_getchar -#define ao_gps_putchar		ao_serial3_putchar -#define ao_gps_set_speed	ao_serial3_set_speed - -#define HAS_EEPROM		0 -#define USE_INTERNAL_FLASH	0 +#define HAS_EEPROM		1 +#define USE_INTERNAL_FLASH	1 +#define USE_STORAGE_CONFIG	0 +#define USE_EEPROM_CONFIG	1  #define HAS_USB			1  #define HAS_BEEP		0  #define HAS_RADIO		1  #define HAS_TELEMETRY		0 +#define HAS_RSSI		1  #define HAS_SPI_1		0  #define SPI_1_PA5_PA6_PA7	0	/* Barometer */ @@ -76,7 +77,7 @@  #define SPI_1_PE13_PE14_PE15	0	/* Accelerometer */  #define HAS_SPI_2		1 -#define SPI_2_PB13_PB14_PB15	1	/* Flash, Companion */ +#define SPI_2_PB13_PB14_PB15	1	/* Radio */  #define SPI_2_PD1_PD3_PD4	0  #define SPI_2_OSPEEDR		STM_OSPEEDR_10MHz @@ -85,27 +86,17 @@  #define SPI_2_MISO_PIN		14  #define SPI_2_MOSI_PIN		15 -#define HAS_I2C_1		0 -#define I2C_1_PB8_PB9		1 - -#define HAS_I2C_2		0 -#define I2C_2_PB10_PB11		1 -  #define PACKET_HAS_SLAVE	0  #define PACKET_HAS_MASTER	1  #define LOW_LEVEL_DEBUG		0 -#define LED_PORT_0_ENABLE	STM_RCC_AHBENR_GPIOAEN -#define LED_PORT_1_ENABLE	STM_RCC_AHBENR_GPIOBEN -#define LED_PORT_0		(&stm_gpioa) -#define LED_PORT_0_MASK		(0xff) +#define LED_PORT_0_ENABLE	STM_RCC_AHBENR_GPIOCEN +#define LED_PORT_0		(&stm_gpioc) +#define LED_PORT_0_MASK		(0xffff)  #define LED_PORT_0_SHIFT	0 -#define LED_PORT_1_MASK		(0xff00) -#define LED_PORT_1_SHIFT	0 -#define LED_PORT_1		(&stm_gpiob) -#define LED_PIN_RED		1 -#define LED_PIN_GREEN		12 +#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) @@ -134,15 +125,15 @@  #define AO_FEC_DEBUG		0  #define AO_CC1120_SPI_CS_PORT	(&stm_gpioa) -#define AO_CC1120_SPI_CS_PIN	0 +#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_gpioc) -#define AO_CC1120_INT_PIN	13 +#define AO_CC1120_INT_PORT	(&stm_gpioa) +#define AO_CC1120_INT_PIN	3 -#define AO_CC1120_MCU_WAKEUP_PORT	(&stm_gpioc) -#define AO_CC1120_MCU_WAKEUP_PIN	(0) +#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 diff --git a/src/microkite/.gitignore b/src/microkite/.gitignore new file mode 100644 index 00000000..7a5d0a1f --- /dev/null +++ b/src/microkite/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +microkite-* diff --git a/src/microkite/Makefile b/src/microkite/Makefile new file mode 100644 index 00000000..b7523758 --- /dev/null +++ b/src/microkite/Makefile @@ -0,0 +1,134 @@ +# +# Tiny AltOS build +# +# +vpath % ../attiny:../drivers:../kernel:../product:.. +vpath ao-make-product.5c ../util +vpath make-altitude-pa ../util + +include ../avr/Makefile.defs + +PROGNAME=microkite-v0.1 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SCRIPT=microkite-load + +PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries +PUBLISH_HEX=$(PUBLISH_DIR)/$(HEX) +PUBLISH_SCRIPT=$(PUBLISH_DIR)/$(SCRIPT) + +MCU=attiny85 +DUDECPUTYPE=t85 +#PROGRAMMER=stk500v2 -P usb +LOADSLOW=-i 32 -B 32 +LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: + +#LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x + +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_report_micro.c \ +	ao_notask.c \ +	ao_eeprom_tiny.c \ +	ao_panic.c \ +	ao_log_micro.c \ +	ao_async.c \ +	ao_microflight.c \ +	ao_microkalman.c + +INC=\ +	ao.h \ +	ao_pins.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	ao_exti.h \ +	ao_ms5607.h \ +	ao_log_micro.h \ +	ao_micropeak.h \ +	altitude-pa.h + +IDPRODUCT=0 +PRODUCT=MicroKite-v0.1 +PRODUCT_DEF=-DMICROPEAK +CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../kernel -I.. -I../drivers -I../product +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTINY + +NICKLE=nickle + +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) $(HEX) microkite-load + +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) + +$(HEX): $(PROG) +	avr-size $(PROG) +	$(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ + + +load: $(HEX) +	$(LOADCMD) $(LOADARG)$(HEX) + +load-slow: $(HEX) +	$(LOADCMD) $(LOADSLOW) $(LOADARG)$(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) $(HEX) $(SCRIPT) +	rm -f ao_product.h + +publish: $(PUBLISH_HEX) $(PUBLISH_SCRIPT) + +$(PUBLISH_HEX): $(HEX) +	cp -a $(HEX) $@ + +$(PUBLISH_SCRIPT): $(SCRIPT) +	cp -a $(SCRIPT) $@ + +load-product: +	./$(SCRIPT) fast + +load-product-slow: +	./$(SCRIPT) slow + +../altitude-pa.h: make-altitude-pa +	nickle $< > $@ + +$(SCRIPT): $(SCRIPT).tmpl Makefile ../Version +	sed -e 's/%HEX%/$(HEX)/' -e 's/%LOADCMD%/$(LOADCMD)/' -e 's/%LOADARG%/$(LOADARG)/' -e 's/%LOADSLOW%/$(LOADSLOW)/' $(SCRIPT).tmpl > $@ || (rm $@ && exit 1) +	chmod +x $@ + +install: + +uninstall: + +$(OBJ): ao_product.h $(INC) diff --git a/src/microkite/ao_pins.h b/src/microkite/ao_pins.h new file mode 100644 index 00000000..346b63a1 --- /dev/null +++ b/src/microkite/ao_pins.h @@ -0,0 +1,71 @@ +/* + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ +#include <avr/pgmspace.h> + +#define AO_LED_ORANGE		(1<<4) +#define AO_LED_SERIAL		4 +#define AO_LED_PANIC		AO_LED_ORANGE +#define AO_LED_REPORT		AO_LED_ORANGE +#define LEDS_AVAILABLE		(AO_LED_ORANGE) +#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		0 +#define HAS_EEPROM		0 +#define HAS_BEEP		0 +#define AVR_CLOCK		250000UL + +/* 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 + +/* MS5607 */ +#define AO_MS5607_SPI_INDEX	0 +#define AO_MS5607_MISO_PORT	PORTB +#define AO_MS5607_MISO_PIN	0 +#define AO_MS5607_BARO_OVERSAMPLE	4096 +#define AO_MS5607_TEMP_OVERSAMPLE	1024 + +/* 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 +typedef int32_t alt_t; +#define FETCH_ALT(o)		((alt_t) pgm_read_dword(&altitude_table[o])) + +#define AO_ALT_VALUE(x)		((x) * (alt_t) 10) + +#define BOOST_DETECT		   0	/* none */ +#define LOG_INTERVAL		 200	/* 19.2 seconds */ +#define BOOST_DELAY		0 + +#define AO_LOG_ID		AO_LOG_ID_MICROKITE + +#endif /* _AO_PINS_H_ */ diff --git a/src/microkite/microkite-load.tmpl b/src/microkite/microkite-load.tmpl new file mode 100644 index 00000000..08236a15 --- /dev/null +++ b/src/microkite/microkite-load.tmpl @@ -0,0 +1,20 @@ +#!/bin/sh +dir=`dirname $0` + +HEX="$dir"/"%HEX%" +LOADCMD="%LOADCMD%" +LOADARG="%LOADARG%" +LOADSLOW="%LOADSLOW%" +LOADFAST="" + +case "$1" in +fast) +	LOADSPEED="$LOADFAST" +	;; +*) +	LOADSPEED="$LOADSLOW" +	;; +esac + +echo ${LOADCMD} ${LOADSPEED} ${LOADARG}${HEX} +${LOADCMD} ${LOADSPEED} ${LOADARG}${HEX} diff --git a/src/micropeak/Makefile b/src/micropeak/Makefile index 6ae3d0be..ac00f635 100644 --- a/src/micropeak/Makefile +++ b/src/micropeak/Makefile @@ -8,8 +8,15 @@ vpath make-altitude-pa ../util  include ../avr/Makefile.defs +PROGNAME=micropeak-v0.1 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SCRIPT=micropeak-load +  PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries -PUBLISH_FILE=$(PUBLISH_DIR)/$(PROG)-$(VERSION).hex +PUBLISH_HEX=$(PUBLISH_DIR)/$(HEX) +PUBLISH_SCRIPT=$(PUBLISH_DIR)/$(SCRIPT)  MCU=attiny85  DUDECPUTYPE=t85 @@ -55,8 +62,6 @@ CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTIN  NICKLE=nickle -PROG=micropeak-v0.1 -  SRC=$(ALTOS_SRC)  OBJ=$(SRC:.c=.o) @@ -68,7 +73,7 @@ endif  # Otherwise, print the full command line.  quiet ?= $($1) -all: $(PROG) $(PROG).hex +all: $(PROG) $(HEX) micropeak-load  CHECK=sh ../util/check-avr-mem @@ -76,16 +81,16 @@ $(PROG): Makefile $(OBJ)  	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ)  	$(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1) -$(PROG).hex: $(PROG) +$(HEX): $(PROG)  	avr-size $(PROG)  	$(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ -load: $(PROG).hex -	$(LOADCMD) $(LOADARG)$(PROG).hex +load: $(HEX) +	$(LOADCMD) $(LOADARG)$(HEX) -load-slow: $(PROG).hex -	$(LOADCMD) $(LOADSLOW) $(LOADARG)$(PROG).hex +load-slow: $(HEX) +	$(LOADCMD) $(LOADSLOW) $(LOADARG)$(HEX)  ao_product.h: ao-make-product.5c ../Version  	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ @@ -98,22 +103,30 @@ ao_product.o: ao_product.c ao_product.h  distclean:	clean  clean: -	rm -f *.o $(PROG) $(PROG).hex +	rm -f *.o $(PROG) $(HEX) $(SCRIPT)  	rm -f ao_product.h +publish: $(PUBLISH_HEX) $(PUBLISH_SCRIPT) -publish: $(PROG).hex -	cp -a $(PROG).hex $(PUBLISH_FILE) +$(PUBLISH_HEX): $(HEX) +	cp -a $(HEX) $@ + +$(PUBLISH_SCRIPT): $(SCRIPT) +	cp -a $(SCRIPT) $@  load-product: -	$(LOADCMD) $(LOADARG)$(PUBLISH_FILE) +	./$(SCRIPT) fast  load-product-slow: -	$(LOADCMD) $(LOADSLOW) $(LOADARG)$(PUBLISH_FILE) +	./$(SCRIPT) slow  ../altitude-pa.h: make-altitude-pa  	nickle $< > $@ +$(SCRIPT): $(SCRIPT).tmpl Makefile ../Version +	sed -e 's/%HEX%/$(HEX)/' -e 's/%LOADCMD%/$(LOADCMD)/' -e 's/%LOADARG%/$(LOADARG)/' -e 's/%LOADSLOW%/$(LOADSLOW)/' $(SCRIPT).tmpl > $@ || (rm $@ && exit 1) +	chmod +x $@ +  install:  uninstall: diff --git a/src/micropeak/micropeak-load.tmpl b/src/micropeak/micropeak-load.tmpl new file mode 100644 index 00000000..08236a15 --- /dev/null +++ b/src/micropeak/micropeak-load.tmpl @@ -0,0 +1,20 @@ +#!/bin/sh +dir=`dirname $0` + +HEX="$dir"/"%HEX%" +LOADCMD="%LOADCMD%" +LOADARG="%LOADARG%" +LOADSLOW="%LOADSLOW%" +LOADFAST="" + +case "$1" in +fast) +	LOADSPEED="$LOADFAST" +	;; +*) +	LOADSPEED="$LOADSLOW" +	;; +esac + +echo ${LOADCMD} ${LOADSPEED} ${LOADARG}${HEX} +${LOADCMD} ${LOADSPEED} ${LOADARG}${HEX} diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index 81151364..b7c28987 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -83,7 +83,7 @@ quiet ?= $($1)  all: $(PROG)  $(PROG): $(REL) Makefile -	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL)  	$(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@  ao_product.h: ao-make-product.5c ../Version diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 90fe7833..7311c21e 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -85,7 +85,7 @@ quiet ?= $($1)  all: $(PROG)  $(PROG): $(REL) Makefile -	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL)  	$(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM)  || rm $@  ao_product.h: ao-make-product.5c ../Version diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index dbbf57d8..e9b144c0 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -24,6 +24,7 @@ INC = \  	altitude.h \  	ao_kalman.h \  	ao_product.h \ +	ao_telemetry.h \  	$(TM_INC)  CORE_SRC = \ diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index d2fcb6d8..e1e350a6 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -85,7 +85,7 @@ quiet ?= $($1)  all: $(PROG)  $(PROG): $(REL) Makefile -	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL)  	$(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@  ao_product.h: ao-make-product.5c ../Version diff --git a/src/product/ao_micropeak.c b/src/product/ao_micropeak.c index 10f0d192..54522d86 100644 --- a/src/product/ao_micropeak.c +++ b/src/product/ao_micropeak.c @@ -73,8 +73,9 @@ main(void)  	ao_report_altitude();  	ao_pips();  	ao_log_micro_dump(); -	 +#if BOOST_DELAY	  	ao_delay(BOOST_DELAY); +#endif  	ao_microflight(); diff --git a/src/product/ao_micropeak.h b/src/product/ao_micropeak.h index 0ec407d7..622f5a69 100644 --- a/src/product/ao_micropeak.h +++ b/src/product/ao_micropeak.h @@ -29,8 +29,21 @@  #define BOOST_DETECT		360	/* 30m at sea level, 36m at 2000m */  #endif +#ifndef LOG_INTERVAL +#define LOG_INTERVAL		 2	/* 192 ms */ +#endif + +#define AO_LOG_ID_MICROPEAK	0 +#define AO_LOG_ID_MICROKITE	1 + +#ifndef AO_LOG_ID +#define AO_LOG_ID		AO_LOG_ID_MICROPEAK +#endif +  /* Wait after power on before doing anything to give the user time to assemble the rocket */ +#ifndef BOOST_DELAY  #define BOOST_DELAY		AO_SEC_TO_TICKS(60) +#endif  /* Pressure change (in Pa) to detect landing */  #define LAND_DETECT		24	/* 2m at sea level, 2.4m at 2000m */ diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index b461cd3f..7ad3b4b8 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -64,6 +64,9 @@  #define AO_SPI_INDEX(id)	((id) & AO_SPI_INDEX_MASK)  #define AO_SPI_CONFIG(id)	((id) & AO_SPI_CONFIG_MASK) +uint8_t +ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id); +  void  ao_spi_get(uint8_t spi_index, uint32_t speed); @@ -77,6 +80,9 @@ void  ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index);  void +ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index); + +void  ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);  void @@ -95,6 +101,15 @@ ao_spi_init(void);  		ao_spi_set_cs(reg,mask);			\  	} while (0) +static inline uint8_t +ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t speed, uint8_t task_id) +{ +	if (!ao_spi_try_get(bus, speed, task_id)) +		return 0; +	ao_spi_set_cs(reg, mask); +	return 1; +} +  #define ao_spi_put_mask(reg,mask,bus) do {	\  		ao_spi_clr_cs(reg,mask);	\  		ao_spi_put(bus);		\ @@ -252,6 +267,8 @@ extern struct ao_stm_usart	ao_stm_usart3;  #define ARM_PUSH32(stack, val)	(*(--(stack)) = (val)) +typedef uint32_t	ao_arch_irq_t; +  static inline uint32_t  ao_arch_irqsave(void) {  	uint32_t	primask; @@ -369,10 +386,10 @@ static inline void ao_arch_start_scheduler(void) {  		ao_arch_block_interrupts();			\  	} while (0) -#define ao_arch_critical(b) do {				\ -		ao_arch_block_interrupts();			\ -		do { b } while (0);				\ -		ao_arch_release_interrupts();			\ +#define ao_arch_critical(b) do {			\ +		uint32_t __mask = ao_arch_irqsave();	\ +		do { b } while (0);			\ +		ao_arch_irqrestore(__mask);		\  	} while (0)  #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 56329c24..885af544 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -154,6 +154,28 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)  }  void +ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index) +{ +	uint8_t		*b = block; +	struct stm_spi	*stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; + +	stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | +			(0 << STM_SPI_CR2_RXNEIE) | +			(0 << STM_SPI_CR2_ERRIE) | +			(0 << STM_SPI_CR2_SSOE) | +			(0 << STM_SPI_CR2_TXDMAEN) | +			(0 << STM_SPI_CR2_RXDMAEN)); + +	/* Clear RXNE */ +	(void) stm_spi->dr; + +	while (len--) { +		while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE))); +		stm_spi->dr = *b++; +	} +} + +void  ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)  {  	struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; @@ -356,13 +378,11 @@ ao_spi_enable_index(uint8_t spi_index)  	}  } -void -ao_spi_get(uint8_t spi_index, uint32_t speed) +static void +ao_spi_config(uint8_t spi_index, uint32_t speed)  {  	uint8_t		id = AO_SPI_INDEX(spi_index);  	struct stm_spi	*stm_spi = ao_spi_stm_info[id].stm_spi; - -	ao_mutex_get(&ao_spi_mutex[id]);  	stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) |			/* Three wire mode */  			(0 << STM_SPI_CR1_BIDIOE) |  			(0 << STM_SPI_CR1_CRCEN) |			/* CRC disabled */ @@ -378,7 +398,7 @@ ao_spi_get(uint8_t spi_index, uint32_t speed)  			(0 << STM_SPI_CR1_CPOL) |			/* Format 0 */  			(0 << STM_SPI_CR1_CPHA));  	if (spi_index != ao_spi_index[id]) { -		 +  		/* Disable old config  		 */  		ao_spi_disable_index(ao_spi_index[id]); @@ -386,13 +406,32 @@ ao_spi_get(uint8_t spi_index, uint32_t speed)  		/* Enable new config  		 */  		ao_spi_enable_index(spi_index); -		 +  		/* Remember current config  		 */  		ao_spi_index[id] = spi_index;  	}  } +uint8_t +ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id) +{ +	uint8_t		id = AO_SPI_INDEX(spi_index); + +	if (!ao_mutex_try(&ao_spi_mutex[id], task_id)) +		return 0; +	ao_spi_config(spi_index, speed); +	return 1; +} + +void +ao_spi_get(uint8_t spi_index, uint32_t speed) +{ +	uint8_t		id = AO_SPI_INDEX(spi_index); +	ao_mutex_get(&ao_spi_mutex[id]); +	ao_spi_config(spi_index, speed); +} +  void  ao_spi_put(uint8_t spi_index)  { diff --git a/src/telebt-v1.0/ao_pins.h b/src/telebt-v1.0/ao_pins.h index 9e47f3b8..4181ef35 100644 --- a/src/telebt-v1.0/ao_pins.h +++ b/src/telebt-v1.0/ao_pins.h @@ -48,6 +48,8 @@  #define BT_LINK_PIN		P1_7  #define HAS_MONITOR		1  #define LEGACY_MONITOR		0 +#define HAS_TELEMETRY		0 +#define AO_RADIO_REG_TEST	1  #define HAS_ADC			1  #define AO_PAD_ADC_BATT		0 diff --git a/src/telefire-v0.1/Makefile b/src/telefire-v0.1/Makefile index 25267268..99d29826 100644 --- a/src/telefire-v0.1/Makefile +++ b/src/telefire-v0.1/Makefile @@ -25,7 +25,6 @@ INC = \  CORE_SRC = \  	ao_cmd.c \  	ao_config.c \ -	ao_convert.c \  	ao_mutex.c \  	ao_panic.c \  	ao_stdio.c \ diff --git a/src/telefire-v0.1/ao_pins.h b/src/telefire-v0.1/ao_pins.h index f7a3ff2c..47ae663f 100644 --- a/src/telefire-v0.1/ao_pins.h +++ b/src/telefire-v0.1/ao_pins.h @@ -18,7 +18,8 @@  #ifndef _AO_PINS_H_  #define _AO_PINS_H_ -#define HAS_RADIO	1 +#define HAS_RADIO		1 +#define HAS_TELEMETRY		0  #define HAS_FLIGHT		0  #define HAS_USB			1 diff --git a/src/telefire-v0.2/Makefile b/src/telefire-v0.2/Makefile index ad5065c1..944543c5 100644 --- a/src/telefire-v0.2/Makefile +++ b/src/telefire-v0.2/Makefile @@ -25,7 +25,6 @@ INC = \  CORE_SRC = \  	ao_cmd.c \  	ao_config.c \ -	ao_convert.c \  	ao_mutex.c \  	ao_panic.c \  	ao_stdio.c \ diff --git a/src/telefire-v0.2/ao_pins.h b/src/telefire-v0.2/ao_pins.h index 96e6b066..28cc65b9 100644 --- a/src/telefire-v0.2/ao_pins.h +++ b/src/telefire-v0.2/ao_pins.h @@ -18,7 +18,9 @@  #ifndef _AO_PINS_H_  #define _AO_PINS_H_ -#define HAS_RADIO	1 +#define HAS_RADIO		1 +#define HAS_RADIO_RATE		1 +#define HAS_TELEMETRY		0  #define HAS_FLIGHT		0  #define HAS_USB			1 @@ -95,11 +97,13 @@  #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_ALL_CHANNELS	((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)) +/* Alarm 2 */  #define AO_SIREN_PORT		P2  #define AO_SIREN_DIR		P2DIR  #define AO_SIREN_PIN		3  #define AO_SIREN		P2_3 +/* Alarm 1 */  #define AO_STROBE_PORT		P2  #define AO_STROBE_DIR		P2DIR  #define AO_STROBE_PIN		4 diff --git a/src/telegps-v1.0/ao_pins.h b/src/telegps-v1.0/ao_pins.h index 5f53dd9d..d2382a56 100644 --- a/src/telegps-v1.0/ao_pins.h +++ b/src/telegps-v1.0/ao_pins.h @@ -71,11 +71,11 @@  #define HAS_GPS			1  #define HAS_FLIGHT		0  #define HAS_LOG			1 +#define FLIGHT_LOG_APPEND	1  #define HAS_TRACKER		1  #define AO_CONFIG_DEFAULT_APRS_INTERVAL		0  #define AO_CONFIG_DEFAULT_RADIO_POWER		0xc0 -#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX	496 * 1024  /*   * GPS diff --git a/src/telelco-v0.2/ao_lco.c b/src/telelco-v0.2/ao_lco.c index b3f5bb16..4b5f7a9b 100644 --- a/src/telelco-v0.2/ao_lco.c +++ b/src/telelco-v0.2/ao_lco.c @@ -258,7 +258,7 @@ ao_lco_search(void)  	for (box = 0; box < AO_PAD_MAX_BOXES; box++) {  		if ((box % 10) == 0)  			ao_lco_set_box(box); -		for (try = 0; try < 5; try++) { +		for (try = 0; try < 3; try++) {  			tick_offset = 0;  			r = ao_lco_query(box, &ao_pad_query, &tick_offset);  			PRINTD("box %d result %d\n", box, r); diff --git a/src/telelco-v0.2/ao_pins.h b/src/telelco-v0.2/ao_pins.h index a6fd4ff8..da790b14 100644 --- a/src/telelco-v0.2/ao_pins.h +++ b/src/telelco-v0.2/ao_pins.h @@ -48,6 +48,7 @@  #define HAS_USB			1  #define HAS_BEEP		1  #define HAS_RADIO		1 +#define HAS_RADIO_RATE		1  #define HAS_TELEMETRY		0  #define HAS_AES			1 diff --git a/src/telemega-v1.0/Makefile b/src/telemega-v1.0/Makefile index 46c768e4..4a1b3908 100644 --- a/src/telemega-v1.0/Makefile +++ b/src/telemega-v1.0/Makefile @@ -31,6 +31,7 @@ INC = \  	ao_mpu.h \  	stm32l.h \  	math.h \ +	ao_ms5607_convert.c \  	Makefile  # diff --git a/src/telemini-v2.0/Makefile b/src/telemini-v2.0/Makefile index ca69dc41..8657e9a9 100644 --- a/src/telemini-v2.0/Makefile +++ b/src/telemini-v2.0/Makefile @@ -25,7 +25,8 @@ INC = \  	ao_int64.h \  	ao_sample.h \  	ao_exti.h \ -	ao_task.h +	ao_task.h \ +	altitude-pa-small.h  CORE_SRC = \  	ao_cmd.c \ diff --git a/src/telemini-v2.0/ao_pins.h b/src/telemini-v2.0/ao_pins.h index f202ccd1..ed911798 100644 --- a/src/telemini-v2.0/ao_pins.h +++ b/src/telemini-v2.0/ao_pins.h @@ -22,15 +22,18 @@  #define HAS_FLIGHT		1  #define HAS_USB			1 +#define AO_VALUE_32		0  #define HAS_USB_PULLUP	1  #define AO_USB_PULLUP_PORT	P1  #define AO_USB_PULLUP_PIN	0  #define AO_USB_PULLUP		P1_0 +#define AO_SMALL_ALTITUDE_TABLE	1 +  #define USB_FORCE_FLIGHT_IDLE	1  #define HAS_BEEP		1 -#define HAS_BEEP_CONFIG		0 +#define HAS_BEEP_CONFIG		1  #define HAS_BATTERY_REPORT	1  #define HAS_GPS			0  #define HAS_SERIAL_1		0 @@ -39,6 +42,8 @@  #define USE_INTERNAL_FLASH	0  #define HAS_DBG			0  #define PACKET_HAS_SLAVE	1 +#define HAS_RADIO_RATE		1 +#define HAS_TELEMETRY		1  #define AO_LED_RED		2  #define LEDS_AVAILABLE		AO_LED_RED diff --git a/src/telerepeat-v1.0/Makefile b/src/telerepeat-v1.0/Makefile new file mode 100644 index 00000000..17f68377 --- /dev/null +++ b/src/telerepeat-v1.0/Makefile @@ -0,0 +1,100 @@ +# +# TeleRepeat build file +# + +TELEREPEAT_VER=1.0 +TELEREPEAT_DEF=1_0 + +vpath %.c ..:../kernel:../cc1111:../drivers:../product +vpath %.h ..:../kernel:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ +	ao.h \ +	ao_pins.h \ +	ao_arch.h \ +	ao_arch_funcs.h \ +	cc1111.h \ +	ao_product.h + +CORE_SRC = \ +	ao_cmd.c \ +	ao_config.c \ +	ao_monitor.c \ +	ao_mutex.c \ +	ao_panic.c \ +	ao_state.c \ +	ao_stdio.c \ +	ao_task.c \ +	ao_forward.c \ +	ao_storage.c \ +	ao_freq.c + +CC1111_SRC = \ +	ao_dbg.c \ +	ao_adc.c \ +	ao_dma.c \ +	ao_led.c \ +	ao_packet.c \ +	ao_intflash.c \ +	ao_packet_master.c \ +	ao_radio.c \ +	ao_romconfig.c \ +	ao_serial.c \ +	ao_string.c \ +	ao_timer.c \ +	ao_usb.c \ +	_bp.c + +DRIVER_SRC = \ +	ao_btm.c + +PRODUCT_SRC = \ +	ao_telerepeat.c + +SRC = \ +	$(CORE_SRC) \ +	$(CC1111_SRC) \ +	$(DRIVER_SRC) \ +	$(PRODUCT_SRC) + +PROGNAME = telerepeat-v$(TELEREPEAT_VER) +PROG = $(PROGNAME)-$(VERSION).ihx +PRODUCT=TeleRepeat-v$(TELEREPEAT_VER) +PRODUCT_DEF=-DTELEREPEAT_V_$(TELEREPEAT_DEF) +IDPRODUCT=0x000e +CODESIZE=0x7800 + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf "  $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: $(PROG) + +$(PROG): $(REL) Makefile +	$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) +	$(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ + +ao_product.h: ao-make-product.5c ../Version +	$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean:	clean + +clean: clean-cc1111 + +install: + +uninstall: diff --git a/src/telerepeat-v1.0/ao_pins.h b/src/telerepeat-v1.0/ao_pins.h new file mode 100644 index 00000000..2a7dbd3b --- /dev/null +++ b/src/telerepeat-v1.0/ao_pins.h @@ -0,0 +1,111 @@ +/* + * Copyright © 2010 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_RADIO		1 +#define HAS_RADIO_FORWARD	1 +#define HAS_FLIGHT		0 +#define HAS_USB			1 +#define HAS_BEEP		0 +#define HAS_SERIAL_1		1 +#define HAS_SERIAL_1_ALT_1	1 +#define HAS_SERIAL_1_ALT_2	0 +#define HAS_SERIAL_1_HW_FLOW	1 +#define USE_SERIAL_1_STDIN	1 +#define DELAY_SERIAL_1_STDIN	1 +#define HAS_DBG			1 +#define HAS_EEPROM		1 +#define HAS_LOG			0 +#define USE_INTERNAL_FLASH	1 +#define HAS_BTM			1 +#define DBG_ON_P1 		1 +#define DBG_ON_P0 		0 +#define PACKET_HAS_MASTER	1 +#define PACKET_HAS_SLAVE	0 +#define AO_LED_RED		1 +#define AO_LED_BLUE		2 +#define LEDS_AVAILABLE		(AO_LED_RED|AO_LED_BLUE) +#define AO_MONITOR_LED		AO_LED_RED +#define AO_BT_LED		AO_LED_BLUE +#define BT_LINK_ON_P2		0 +#define BT_LINK_ON_P1		1 +#define BT_LINK_PIN_INDEX	7 +#define BT_LINK_PIN		P1_7 +#define HAS_MONITOR		1 +#define HAS_MONITOR_PUT		1 +#define LEGACY_MONITOR		0 +#define HAS_TELEMETRY		0 +#define AO_RADIO_REG_TEST	1 + +#define HAS_ADC			1 +#define AO_PAD_ADC_BATT		0 +#define AO_ADC_PINS		(1 << AO_PAD_ADC_BATT) + +struct ao_adc { +	int16_t		batt; +}; + +#define AO_ADC_DUMP(p)							\ +	printf ("tick: %5u batt %5d\n",					\ +		(p)->tick,						\ +		(p)->adc.batt) + +#define FETCH_ADC() do {						\ +		a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.batt); \ +		a[0] = ADCL;						\ +		a[1] = ADCH;						\ +	} while (0) + +#if DBG_ON_P1 + +	#define DBG_CLOCK	(1 << 4)	/* mi0 */ +	#define DBG_DATA	(1 << 5)	/* mo0 */ +	#define DBG_RESET_N	(1 << 3)	/* c0 */ + +	#define DBG_CLOCK_PIN	(P1_4) +	#define DBG_DATA_PIN	(P1_5) +	#define DBG_RESET_N_PIN	(P1_3) + +	#define DBG_PORT_NUM	1 +	#define DBG_PORT	P1 +	#define DBG_PORT_SEL	P1SEL +	#define DBG_PORT_INP	P1INP +	#define DBG_PORT_DIR	P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + +	#define DBG_CLOCK	(1 << 3) +	#define DBG_DATA	(1 << 4) +	#define DBG_RESET_N	(1 << 5) + +	#define DBG_CLOCK_PIN	(P0_3) +	#define DBG_DATA_PIN	(P0_4) +	#define DBG_RESET_N_PIN	(P0_5) + +	#define DBG_PORT_NUM	0 +	#define DBG_PORT	P0 +	#define DBG_PORT_SEL	P0SEL +	#define DBG_PORT_INP	P0INP +	#define DBG_PORT_DIR	P0DIR + +#endif /* DBG_ON_P0 */ + +#endif /* _AO_PINS_H_ */ diff --git a/src/telerepeat-v1.0/ao_telerepeat.c b/src/telerepeat-v1.0/ao_telerepeat.c new file mode 100644 index 00000000..21bf8a73 --- /dev/null +++ b/src/telerepeat-v1.0/ao_telerepeat.c @@ -0,0 +1,47 @@ +/* + * 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_forward.h" + +void +main(void) +{ +	ao_clock_init(); + +	/* Turn on the LED until the system is stable */ +	ao_led_init(LEDS_AVAILABLE); +	ao_led_on(AO_LED_RED); + +	ao_task_init(); + +	ao_timer_init(); +	ao_cmd_init(); +	ao_usb_init(); +	ao_monitor_init(); +	ao_radio_init(); +	ao_packet_master_init(); +	ao_adc_init(); +	ao_btm_init(); +	ao_monitor_forward_init(); +	ao_storage_init(); +#if HAS_DBG +	ao_dbg_init(); +#endif +	ao_config_init(); +	ao_start_scheduler(); +} diff --git a/src/teleshield-v0.1/ao_pins.h b/src/teleshield-v0.1/ao_pins.h index 30239afc..68bb44ee 100644 --- a/src/teleshield-v0.1/ao_pins.h +++ b/src/teleshield-v0.1/ao_pins.h @@ -62,6 +62,7 @@  	#define HAS_RSSI		0  	#define HAS_AES			0  	#define HAS_RADIO		1 +	#define HAS_TELEMETRY		0  #endif  #if DBG_ON_P1 diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 1c12c437..472af534 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -71,7 +71,9 @@  	#define HAS_P2_ISR		1  	#define BATTERY_PIN		5 -	 +	#define HAS_TELEMETRY		0 + +	#define AO_VALUE_32		0  #endif  #if DBG_ON_P1 diff --git a/src/test/Makefile b/src/test/Makefile index 017f7f71..02e1d22b 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,7 @@  vpath % ..:../kernel:../drivers:../util:../micropeak:../aes:../product  PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_flight_test_mm \ +	ao_flight_test_metrum \  	ao_gps_test ao_gps_test_skytraq ao_gps_test_ublox ao_convert_test ao_convert_pa_test ao_fec_test \  	ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test \  	ao_ms5607_convert_test ao_quaternion_test @@ -33,6 +34,9 @@ ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c  ao_sample.c ao_kal  ao_flight_test_mm: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS)  	cc -DTELEMEGA=1 $(CFLAGS) -o $@ $< -lm +ao_flight_test_metrum: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS) +	cc -DTELEMETRUM_V2=1 $(CFLAGS) -o $@ $< -lm +  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_aprs_test.c b/src/test/ao_aprs_test.c index 86cf527a..ae505dea 100644 --- a/src/test/ao_aprs_test.c +++ b/src/test/ao_aprs_test.c @@ -21,6 +21,8 @@  #include <stdint.h>  #include <stdarg.h> +#define HAS_GPS	1 +  #include <ao_telemetry.h>  #define AO_GPS_NUM_SAT_MASK	(0xf << 0) @@ -97,41 +99,14 @@ audio_gap(int secs)  #endif  } -#include <math.h> - -int -ao_aprs_encode_altitude_expensive(int meters) -{ -	double	feet = meters / 0.3048; - -	double	encode = log(feet) / log(1.002); -	return floor(encode + 0.5); -} -  // This is where we go after reset.  int main(int argc, char **argv)  { -	int	e, x; -	int	a; - -	for (a = 1; a < 100000; a++) { -		e = ao_aprs_encode_altitude(a); -		x = ao_aprs_encode_altitude_expensive(a); - -		if (e != x) { -			double	back_feet, back_meters; -			back_feet = pow(1.002, e); -			back_meters = back_feet * 0.3048; -			fprintf (stderr, "APRS altitude encoding failure: altitude %d actual %d expected %d actual meters %f\n", -				 a, e, x, back_meters); -		} -	} -      audio_gap(1);      ao_gps_data.latitude = (45.0 + 28.25 / 60.0) * 10000000;      ao_gps_data.longitude = (-(122 + 44.2649 / 60.0)) * 10000000; -    ao_gps_data.altitude = 84; +    AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_data, 84);      ao_gps_data.flags = (AO_GPS_VALID|AO_GPS_RUNNING);      /* Transmit one packet */ diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 0647fc6c..8b737ca1 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -34,15 +34,21 @@  #define ao_data_ring_next(n)	(((n) + 1) & (AO_DATA_RING - 1))  #define ao_data_ring_prev(n)	(((n) - 1) & (AO_DATA_RING - 1)) +#if 0  #define AO_M_TO_HEIGHT(m)	((int16_t) (m))  #define AO_MS_TO_SPEED(ms)	((int16_t) ((ms) * 16))  #define AO_MSS_TO_ACCEL(mss)	((int16_t) ((mss) * 16)) +#endif  #define AO_GPS_NEW_DATA		1  #define AO_GPS_NEW_TRACKING	2  int ao_gps_new; +#if !defined(TELEMEGA) && !defined(TELEMETRUM_V2) +#define TELEMETRUM_V1 1 +#endif +  #if TELEMEGA  #define AO_ADC_NUM_SENSE	6  #define HAS_MS5607		1 @@ -50,6 +56,7 @@ int ao_gps_new;  #define HAS_MMA655X		1  #define HAS_HMC5883 		1  #define HAS_BEEP		1 +#define AO_CONFIG_MAX_SIZE	1024  struct ao_adc {  	int16_t			sense[AO_ADC_NUM_SENSE]; @@ -57,7 +64,25 @@ struct ao_adc {  	int16_t			v_pbatt;  	int16_t			temp;  }; -#else +#endif + +#if TELEMETRUM_V2 +#define AO_ADC_NUM_SENSE	2 +#define HAS_MS5607		1 +#define HAS_MMA655X		1 +#define HAS_BEEP		1 +#define AO_CONFIG_MAX_SIZE	1024 + +struct ao_adc { +	int16_t			sense_a; +	int16_t			sense_m; +	int16_t			v_batt; +	int16_t			temp; +}; +#endif + + +#if TELEMETRUM_V1  /*   * One set of samples read from the A/D converter   */ @@ -92,6 +117,7 @@ struct ao_adc {  #include <ao_data.h>  #include <ao_log.h>  #include <ao_telemetry.h> +#include <ao_sample.h>  #if TELEMEGA  int ao_gps_count; @@ -174,7 +200,7 @@ ao_gps_angle(void)  			ao_gps_static.latitude / 1e7,  			ao_gps_static.longitude / 1e7,  			&dist, &bearing); -	height = ao_gps_static.altitude - ao_gps_prev.altitude; +	height = AO_TELEMETRY_LOCATION_ALTITUDE(&ao_gps_static) - AO_TELEMETRY_LOCATION_ALTITUDE(&ao_gps_prev);  	angle = atan2(dist, height);  	return angle * 180/M_PI; @@ -185,17 +211,6 @@ ao_gps_angle(void)  #define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5))  #define from_fix(x)	((x) >> 16) -/* - * Above this height, the baro sensor doesn't work - */ -#define AO_BARO_SATURATE	13000 -#define AO_MIN_BARO_VALUE	ao_altitude_to_pres(AO_BARO_SATURATE) - -/* - * Above this speed, baro measurements are unreliable - */ -#define AO_MAX_BARO_SPEED	200 -  #define ACCEL_NOSE_UP	(ao_accel_2g >> 2)  extern enum ao_flight_state ao_flight_state; @@ -233,7 +248,7 @@ double	main_time;  int	tick_offset; -static int32_t	ao_k_height; +static ao_k_t	ao_k_height;  int16_t  ao_time(void) @@ -305,7 +320,7 @@ struct ao_cmds {  #define ao_xmemcmp(d,s,c) memcmp(d,s,c)  #define AO_NEED_ALTITUDE_TO_PRES 1 -#if TELEMEGA +#if TELEMEGA || TELEMETRUM_V2  #include "ao_convert_pa.c"  #include <ao_ms5607.h>  struct ao_ms5607_prom	ao_ms5607_prom; @@ -455,7 +470,7 @@ ao_insert(void)  #else  		double	accel = 0.0;  #endif -#if TELEMEGA +#if TELEMEGA || TELEMETRUM_V2  		double	height;  		ao_ms5607_convert(&ao_data_static.ms5607_raw, &ao_data_static.ms5607_cooked); @@ -550,6 +565,7 @@ ao_insert(void)  				mag_azel.el,  				mag_azel.az);  #endif +#if 0  			printf ("%7.2f state %-8.8s height %8.4f tilt %4d rot %4d dist %12.2f gps_tilt %4d gps_sats %2d\n",  				time,  				ao_state_names[ao_flight_state], @@ -559,6 +575,7 @@ ao_insert(void)  				(int) floor (ao_gps_angle() + 0.5),  				(ao_gps_static.flags & 0xf) * 10); +#endif  #if 0  			printf ("\t\tstate %-8.8s ground az: %4d el %4d mag az %4d el %4d rot az %4d el %4d el_diff %4d az_diff %4d angle %4d tilt %4d ground %8.5f %8.5f %8.5f cur %8.5f %8.5f %8.5f rot %8.5f %8.5f %8.5f\n",  				ao_state_names[ao_flight_state], @@ -581,9 +598,9 @@ ao_insert(void)  #endif  #endif -#if 0 +#if 1  			printf("%7.2f height %8.2f accel %8.3f " -#if TELEMEGA +#if TELEMEGA && 0  			       "angle %5d "  			       "accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f mag_x %8d mag_y %8d, mag_z %8d mag_angle %4d "  #endif @@ -591,7 +608,7 @@ ao_insert(void)  			       time,  			       height,  			       accel, -#if TELEMEGA +#if TELEMEGA && 0  			       ao_sample_orient,  			       ao_mpu6000_accel(ao_data_static.mpu6000.accel_x), @@ -674,7 +691,8 @@ ao_sleep(void *wchan)  			{  #if TELEMEGA  				ao_data_static.mpu6000 = ao_ground_mpu6000; -#else +#endif +#if TELEMETRUM_V1  				ao_data_static.adc.accel = ao_flight_ground_accel;  #endif  				ao_insert(); @@ -755,7 +773,10 @@ ao_sleep(void *wchan)  					ao_gps_static.tick = tick;  					ao_gps_static.latitude = int32(bytes, 0);  					ao_gps_static.longitude = int32(bytes, 4); -					ao_gps_static.altitude = int32(bytes, 8); +					{ +						int32_t	altitude = int32(bytes, 8); +						AO_TELEMETRY_LOCATION_SET_ALTITUDE(&ao_gps_static, altitude); +					}  					ao_gps_static.flags = bytes[13];  					if (!ao_gps_count)  						ao_gps_first = ao_gps_static; @@ -795,11 +816,64 @@ ao_sleep(void *wchan)  					pyro->flags |= ao_pyro_values[j].flag;  					if (ao_pyro_values[j].offset != NO_VALUE && i + 1 < nword) {  						int16_t	val = strtoul(words[++i], NULL, 10); +						printf("pyro %d condition %s value %d\n", p, words[i-1], val);  						*((int16_t *) ((char *) pyro + ao_pyro_values[j].offset)) = val;  					}  				}  			} -#else +#endif +#if TELEMETRUM_V2 +			if (log_format == AO_LOG_FORMAT_TELEMETRUM && nword == 14 && 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_static.mma655x = int16(bytes, 8); +					ao_records_read++; +					ao_insert(); +					return; +				} +				continue; +			} else if (nword == 3 && strcmp(words[0], "ms5607") == 0) { +				if (strcmp(words[1], "reserved:") == 0) +					ao_ms5607_prom.reserved = strtoul(words[2], NULL, 10); +				else if (strcmp(words[1], "sens:") == 0) +					ao_ms5607_prom.sens = strtoul(words[2], NULL, 10); +				else if (strcmp(words[1], "off:") == 0) +					ao_ms5607_prom.off = strtoul(words[2], NULL, 10); +				else if (strcmp(words[1], "tcs:") == 0) +					ao_ms5607_prom.tcs = strtoul(words[2], NULL, 10); +				else if (strcmp(words[1], "tco:") == 0) +					ao_ms5607_prom.tco = strtoul(words[2], NULL, 10); +				else if (strcmp(words[1], "tref:") == 0) +					ao_ms5607_prom.tref = strtoul(words[2], NULL, 10); +				else if (strcmp(words[1], "tempsens:") == 0) +					ao_ms5607_prom.tempsens = strtoul(words[2], NULL, 10); +				else if (strcmp(words[1], "crc:") == 0) +					ao_ms5607_prom.crc = strtoul(words[2], NULL, 10); +				continue; +			} +#endif +#if TELEMETRUM_V1  			if (nword == 4 && log_format != AO_LOG_FORMAT_TELEMEGA) {  				type = words[0][0];  				tick = strtoul(words[1], NULL, 16); @@ -924,7 +998,7 @@ ao_sleep(void *wchan)  			if (type != 'F' && !ao_flight_started)  				continue; -#if TELEMEGA +#if TELEMEGA || TELEMETRUM_V2  			(void) a;  			(void) b;  #else @@ -945,8 +1019,6 @@ ao_sleep(void *wchan)  				ao_data_static.tick = tick;  				ao_data_static.adc.accel = a;  				ao_data_static.adc.pres_real = b; -				if (b < AO_MIN_BARO_VALUE) -					b = AO_MIN_BARO_VALUE;  				ao_data_static.adc.pres = b;  				ao_records_read++;  				ao_insert(); diff --git a/src/test/ao_gps_test.c b/src/test/ao_gps_test.c index e799ab0f..543bbcc3 100644 --- a/src/test/ao_gps_test.c +++ b/src/test/ao_gps_test.c @@ -53,6 +53,9 @@ struct ao_gps_orig {  	uint16_t		v_error;	/* m */  }; +#define AO_TELEMETRY_LOCATION_ALTITUDE(l) 	((l)->altitude) +#define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a) ((l)->altitude = (a)) +  #define SIRF_SAT_STATE_ACQUIRED			(1 << 0)  #define SIRF_SAT_STATE_CARRIER_PHASE_VALID	(1 << 1)  #define SIRF_SAT_BIT_SYNC_COMPLETE		(1 << 2) @@ -433,7 +436,7 @@ ao_dump_state(void *wchan)  	if (wchan != &ao_gps_new)  		return; -	 +  	if (ao_gps_new & AO_GPS_NEW_DATA) {  		ao_gps_print(&ao_gps_data);  		putchar('\n'); diff --git a/src/test/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c index 1b590d5e..5eb7118d 100644 --- a/src/test/ao_gps_test_skytraq.c +++ b/src/test/ao_gps_test_skytraq.c @@ -16,6 +16,7 @@   */  #define AO_GPS_TEST +#define HAS_GPS 1  #include "ao_host.h"  #include <termios.h>  #include <errno.h> @@ -53,6 +54,9 @@ struct ao_gps_orig {  	uint16_t		v_error;	/* m */  }; +#define AO_TELEMETRY_LOCATION_ALTITUDE(l) 	((l)->altitude) +#define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a) ((l)->altitude = (a)) +  #define SIRF_SAT_STATE_ACQUIRED			(1 << 0)  #define SIRF_SAT_STATE_CARRIER_PHASE_VALID	(1 << 1)  #define SIRF_SAT_BIT_SYNC_COMPLETE		(1 << 2) diff --git a/src/test/ao_gps_test_ublox.c b/src/test/ao_gps_test_ublox.c index 4eb4b837..5ea205d6 100644 --- a/src/test/ao_gps_test_ublox.c +++ b/src/test/ao_gps_test_ublox.c @@ -16,6 +16,7 @@   */  #define AO_GPS_TEST +#define HAS_GPS	1  #include "ao_host.h"  #include <termios.h>  #include <errno.h> @@ -44,7 +45,7 @@ struct ao_telemetry_location {  	uint8_t			flags;  	int32_t			latitude;	/* degrees * 10⁷ */  	int32_t			longitude;	/* degrees * 10⁷ */ -	int16_t			altitude;	/* m */ +	int16_t			altitude_low;	/* m */  	uint16_t		ground_speed;	/* cm/s */  	uint8_t			course;		/* degrees / 2 */  	uint8_t			pdop;		/* * 5 */ @@ -53,8 +54,14 @@ struct ao_telemetry_location {  	int16_t			climb_rate;	/* cm/s */  	uint16_t		h_error;	/* m */  	uint16_t		v_error;	/* m */ +	int16_t			altitude_high;	/* m */  }; +typedef int32_t		gps_alt_t; +#define AO_TELEMETRY_LOCATION_ALTITUDE(l) 	(((gps_alt_t) (l)->altitude_high << 16) | ((l)->altitude_low)) +#define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a) (((l)->altitude_high = (a) >> 16), \ +						 ((l)->altitude_low = (a))) +  #define UBLOX_SAT_STATE_ACQUIRED		(1 << 0)  #define UBLOX_SAT_STATE_CARRIER_PHASE_VALID	(1 << 1)  #define UBLOX_SAT_BIT_SYNC_COMPLETE		(1 << 2) diff --git a/src/test/ao_micropeak_test.c b/src/test/ao_micropeak_test.c index 5961bd93..f4af707e 100644 --- a/src/test/ao_micropeak_test.c +++ b/src/test/ao_micropeak_test.c @@ -33,6 +33,7 @@ uint8_t ao_flight_debug;  #define AO_FLIGHT_TEST  typedef int32_t alt_t; +typedef int32_t pres_t;  #define AO_MS_TO_TICKS(ms)	((ms) / 10) diff --git a/src/test/plottest b/src/test/plottest index 76af5ee7..7d253ff1 100755 --- a/src/test/plottest +++ b/src/test/plottest @@ -10,7 +10,7 @@ plot "$1" using 1:3 with lines axes x1y1 title "raw height",\  "$1" using 1:9 with lines axes x1y1 title "height",\  "$1" using 1:11 with lines axes x1y2 title "speed",\  "$1" using 1:13 with lines axes x1y2 title "accel",\ -"$1" using 1:15 with lines axes x1y1 title "drogue",\ -"$1" using 1:17 with lines axes x1y1 title "main",\ -"$1" using 1:19 with lines axes x1y1 title "error" +"$1" using 1:17 with lines axes x1y1 title "drogue",\ +"$1" using 1:19 with lines axes x1y1 title "main",\ +"$1" using 1:21 with lines axes x1y1 title "error"  EOF diff --git a/src/util/make-altitude-pa b/src/util/make-altitude-pa index 22831d50..d36f3f41 100644 --- a/src/util/make-altitude-pa +++ b/src/util/make-altitude-pa @@ -185,105 +185,135 @@ line_t best_fit(real[] values, int first, int last) {         return (line_t) { m = m, b = b };  } -real	min_Pa = 0; -real	max_Pa = 120000; +void print_table (int pa_sample_shift, int pa_part_shift) +{ +	real	min_Pa = 0; +	real	max_Pa = 120000; -/* Target is an array of < 1000 entries */ -int pa_sample_shift = 2; -int pa_part_shift = 6; -int pa_part_mask = (1 << pa_part_shift) - 1; +	int pa_part_mask = (1 << pa_part_shift) - 1; -int num_part = ceil(max_Pa / (2 ** (pa_part_shift + pa_sample_shift))); +	int num_part = ceil(max_Pa / (2 ** (pa_part_shift + pa_sample_shift))); -int num_samples = num_part << pa_part_shift; +	int num_samples = num_part << pa_part_shift; -real sample_to_Pa(int sample) = sample << pa_sample_shift; +	real sample_to_Pa(int sample) = sample << pa_sample_shift; -real sample_to_altitude(int sample) = pressure_to_altitude(sample_to_Pa(sample)); +	real sample_to_altitude(int sample) = pressure_to_altitude(sample_to_Pa(sample)); -int part_to_sample(int part) = part << pa_part_shift; +	int part_to_sample(int part) = part << pa_part_shift; -int sample_to_part(int sample) = sample >> pa_part_shift; +	int sample_to_part(int sample) = sample >> pa_part_shift; -bool is_part(int sample) = (sample & pa_part_mask) == 0; +	bool is_part(int sample) = (sample & pa_part_mask) == 0; -real[num_samples] alt = { [n] = sample_to_altitude(n) }; +	real[num_samples] alt = { [n] = sample_to_altitude(n) }; -int seg_len = 1 << pa_part_shift; +	int seg_len = 1 << pa_part_shift; -line_t [num_part] fit = { -	[n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1) -}; - -real[num_samples/seg_len + 1]	alt_part; -real[dim(alt_part)]		alt_error = {0...}; - -alt_part[0] = fit[0].b; -alt_part[dim(fit)] = fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b; +	line_t [num_part] fit = { +		[n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1) +	}; -for (int i = 0; i < dim(fit) - 1; i++) { -	real	here, there; -	here = fit[i].m * (i+1) * seg_len + fit[i].b; -	there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b; -#	printf ("at %d mis-fit %8.2f\n", i, there - here); -	alt_part[i+1] = (here + there) / 2; -} +	real[num_samples/seg_len + 1]	alt_part; +	real[dim(alt_part)]		alt_error = {0...}; -real round(real x) = floor(x + 0.5); +	alt_part[0] = fit[0].b; +	alt_part[dim(fit)] = fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b; -real sample_to_fit_altitude(int sample) { -	int	sub = sample // seg_len; -	int	off = sample % seg_len; -	line_t	l = fit[sub]; -	real r_v; -	real i_v; +	for (int i = 0; i < dim(fit) - 1; i++) { +		real	here, there; +		here = fit[i].m * (i+1) * seg_len + fit[i].b; +		there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b; +#		printf ("at %d mis-fit %8.2f\n", i, there - here); +		alt_part[i+1] = (here + there) / 2; +	} -	r_v = sample * l.m + l.b; -	i_v = (round(alt_part[sub]*10) * (seg_len - off) + round(alt_part[sub+1]*10) * off) / seg_len; -	return i_v/10; -} +	real round(real x) = floor(x + 0.5); -real max_error = 0; -int max_error_sample = 0; -real total_error = 0; +	real sample_to_fit_altitude(int sample) { +		int	sub = sample // seg_len; +			int	off = sample % seg_len; +		line_t	l = fit[sub]; +		real r_v; +		real i_v; -for (int sample = 0; sample < num_samples; sample++) { -	real	Pa = sample_to_Pa(sample); -	real	meters = alt[sample]; +		r_v = sample * l.m + l.b; +		i_v = (round(alt_part[sub]*10) * (seg_len - off) + round(alt_part[sub+1]*10) * off) / seg_len; +		return i_v/10; +	} -	real	meters_approx = sample_to_fit_altitude(sample); -	real	error = abs(meters - meters_approx); +	real max_error = 0; +	int max_error_sample = 0; +	real total_error = 0; + +	for (int sample = 0; sample < num_samples; sample++) { +		real	Pa = sample_to_Pa(sample); +		real	meters = alt[sample]; + +		real	meters_approx = sample_to_fit_altitude(sample); +		real	error = abs(meters - meters_approx); + +		int	part = sample_to_part(sample); + +		if (error > alt_error[part]) +			alt_error[part] = error; + +		total_error += error; +		if (error > max_error) { +			max_error = error; +			max_error_sample = sample; +		} +		if (false) { +			printf ("	%8.1f %8.2f %8.2f %8.2f %s\n", +				Pa, +				meters, +				meters_approx, +				meters - meters_approx, +				is_part(sample) ? "*" : ""); +		} +	} -	int	part = sample_to_part(sample); +	printf ("/*max error %f at %7.3f kPa. Average error %f*/\n", +		max_error, sample_to_Pa(max_error_sample) / 1000, total_error / num_samples); -	if (error > alt_error[part]) -		alt_error[part] = error; +	printf ("#define NALT %d\n", dim(alt_part)); +	printf ("#define ALT_SHIFT %d\n", pa_part_shift + pa_sample_shift); +	printf ("#ifndef AO_ALT_VALUE\n#define AO_ALT_VALUE(x) (alt_t) (x)\n#endif\n"); -	total_error += error; -	if (error > max_error) { -		max_error = error; -		max_error_sample = sample; -	} -	if (false) { -		printf ("	%8.1f %8.2f %8.2f %8.2f %s\n", -			Pa, -			meters, -			meters_approx, -			meters - meters_approx, -			is_part(sample) ? "*" : ""); +	for (int part = 0; part < dim(alt_part); part++) { +		real kPa = sample_to_Pa(part_to_sample(part)) / 1000; +		printf ("AO_ALT_VALUE(%10.1f), /* %6.2f kPa error %6.2fm */\n", +			round (alt_part[part]*10) / 10, kPa, +			alt_error[part]);  	}  } -printf ("/*max error %f at %7.3f kPa. Average error %f*/\n", -	max_error, sample_to_Pa(max_error_sample) / 1000, total_error / num_samples); - -printf ("#define NALT %d\n", dim(alt_part)); -printf ("#define ALT_SHIFT %d\n", pa_part_shift + pa_sample_shift); -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 ("AO_ALT_VALUE(%10.1f), /* %6.2f kPa error %6.2fm */\n", -		round (alt_part[part]*10) / 10, kPa, -		alt_error[part]); +autoload ParseArgs; + +void main() +{ +	/* Target is an array of < 1000 entries */ +	int pa_sample_shift = 2; +	int pa_part_shift = 6; + +	ParseArgs::argdesc argd = { +		.args = { +			{ .var = { .arg_int = &pa_sample_shift }, +			  .abbr = 's', +			  .name = "sample", +			  .expr_name = "sample_shift", +			  .desc = "sample shift value" }, +			{ .var = { .arg_int = &pa_part_shift }, +			  .abbr = 'p', +			  .name = "part", +			  .expr_name = "part_shift", +			  .desc = "part shift value" }, +		} +	}; + +	ParseArgs::parseargs(&argd, &argv); + +	print_table(pa_sample_shift, pa_part_shift);  } + +main(); | 
