diff options
| -rw-r--r-- | src/.gitignore | 1 | ||||
| -rw-r--r-- | src/Makefile | 6 | ||||
| -rw-r--r-- | src/drivers/ao_cc1120.c | 87 | ||||
| -rw-r--r-- | src/drivers/ao_cc1120_CC1120.h | 28 | ||||
| -rw-r--r-- | src/drivers/ao_fec.h | 60 | ||||
| -rw-r--r-- | src/drivers/ao_fec_tx.c | 139 | ||||
| -rw-r--r-- | src/megametrum-v0.1/Makefile | 3 | ||||
| -rw-r--r-- | src/test/Makefile | 7 | ||||
| -rw-r--r-- | src/test/ao_fec_tx_test.c | 47 | ||||
| -rw-r--r-- | src/util/make-whiten | 37 | 
10 files changed, 372 insertions, 43 deletions
| diff --git a/src/.gitignore b/src/.gitignore index c6e1e353..cae36ae6 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,2 +1,3 @@  altitude.h  altitude-pa.h +ao_whiten.h diff --git a/src/Makefile b/src/Makefile index c2e324c4..3fca2ab2 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,6 +6,7 @@  vpath make-altitude util  vpath make-altitude-pa util  vpath make-kalman util +vpath make-whiten util  vpath kalman.5c kalman  vpath kalman_filter.5c kalman  vpath load_csv.5c kalman @@ -46,7 +47,7 @@ uninstall:  all-recursive: all-local -all-local: altitude.h altitude-pa.h ao_kalman.h +all-local: altitude.h altitude-pa.h ao_kalman.h ao_whiten.h  altitude.h: make-altitude  	nickle $< > $@ @@ -57,5 +58,8 @@ altitude-pa.h: make-altitude-pa  ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c  	bash $< kalman > $@ +ao_whiten.h: make-whiten +	nickle $< > $@ +  clean-local:  	rm -f altitude.h ao_kalman.h diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index f06d52ca..231d14d4 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -18,6 +18,7 @@  #include <ao.h>  #include <ao_cc1120.h>  #include <ao_exti.h> +#include <ao_fec.h>  uint8_t ao_radio_wake;  uint8_t ao_radio_mutex; @@ -240,26 +241,27 @@ ao_radio_rx_done(void)  	return ao_radio_marc_status() == CC1120_MARC_STATUS1_RX_FINISHED;  } +static void +ao_radio_start_tx(void) +{ +	ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); +	ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); +	ao_radio_strobe(CC1120_STX); +} +  void  ao_radio_rdf(uint8_t len)  {  	int i;  	ao_radio_get(len); -	ao_radio_abort = 0;  	ao_radio_wake = 0;  	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_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); -  	ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); -	ao_radio_reg_write(CC1120_PKT_LEN, len); - -	ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - -	ao_radio_strobe(CC1120_STX); +	ao_radio_start_tx();  	cli();  	while (!ao_radio_wake && !ao_radio_abort) @@ -327,24 +329,45 @@ ao_radio_test(void)  void  ao_radio_send(void *d, uint8_t size)  { -	uint8_t	marc_status; - +	uint8_t		marc_status; +	static uint8_t	prepare[128]; +	uint8_t		prepare_len; +	static uint8_t	encode[256]; +	uint8_t		encode_len; +	static uint8_t	interleave[256]; +	uint8_t		interleave_len; + +	ao_fec_dump_bytes(d, size, "Input"); + +#if 1 +	prepare_len = ao_fec_prepare(d, size, prepare); +	ao_fec_dump_bytes(prepare, prepare_len, "Prepare"); + +	ao_fec_whiten(prepare, prepare_len, prepare); +	ao_fec_dump_bytes(prepare, prepare_len, "Whiten"); + +	encode_len = ao_fec_encode(prepare, prepare_len, encode); +	ao_fec_dump_bytes(encode, encode_len, "Encode"); + +	interleave_len = ao_fec_interleave(encode, encode_len, interleave); +	ao_fec_dump_bytes(interleave, interleave_len, "Interleave"); +	ao_radio_get(interleave_len); +	ao_radio_fifo_write(interleave, interleave_len); +#else  	ao_radio_get(size); -	ao_radio_wake = 0;  	ao_radio_fifo_write(d, size); -	ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); -	ao_radio_strobe(CC1120_STX); +#endif + +	ao_radio_wake = 0; + +	ao_radio_start_tx(); +  	cli(); -	for (;;) { -		if (ao_radio_wake) { -			marc_status = ao_radio_marc_status(); -			if (marc_status != CC1120_MARC_STATUS1_NO_FAILURE) -				break; -			ao_radio_wake = 0; -		} +	while (!ao_radio_wake && !ao_radio_abort)  		ao_sleep(&ao_radio_wake); -	}  	sei(); +	if (!ao_radio_tx_done()) +		ao_radio_idle();  	ao_radio_put();  } @@ -361,6 +384,7 @@ ao_radio_recv(__xdata void *d, uint8_t size)  	cli();  	for (;;) {  		if (ao_radio_abort) +  			break;  		if (ao_radio_wake) {  			marc_status = ao_radio_marc_status(); @@ -413,7 +437,7 @@ static const uint16_t packet_setup[] = {  	CC1120_DRATE0,		((PACKET_DRATE_M >> 0) & 0xff),  	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)), -	CC1120_PKT_CFG1,	((1 << CC1120_PKT_CFG1_WHITE_DATA) | +	CC1120_PKT_CFG1,	((0 << CC1120_PKT_CFG1_WHITE_DATA) |  				 (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) |  				 (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) |  				 (1 << CC1120_PKT_CFG1_APPEND_STATUS)), @@ -469,9 +493,6 @@ ao_radio_setup(void)  	for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2)  		ao_radio_reg_write(radio_setup[i], radio_setup[i+1]); -	/* Enable marc status interrupt on gpio 2 pin */ -	ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP); -  	ao_radio_set_packet();  	ao_config_get(); @@ -707,6 +728,21 @@ static void ao_radio_beep(void) {  	ao_radio_rdf(RDF_PACKET_LEN);  } +static void ao_radio_packet(void) { +	static uint8_t packet[] = { +#if 1 +		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +#else +		3, 1, 2, 3 +#endif +	}; + +	ao_radio_send(packet, sizeof (packet)); +} +  #endif  static const struct ao_cmds ao_radio_cmds[] = { @@ -714,6 +750,7 @@ static const struct ao_cmds ao_radio_cmds[] = {  #if CC1120_DEBUG  	{ ao_radio_show,	"R\0Show CC1120 status" },  	{ ao_radio_beep,	"b\0Emit an RDF beacon" }, +	{ ao_radio_packet,	"p\0Send a test packet" },  #endif  	{ 0, NULL }  }; diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h index c900b7f9..c0f35a23 100644 --- a/src/drivers/ao_cc1120_CC1120.h +++ b/src/drivers/ao_cc1120_CC1120.h @@ -21,29 +21,27 @@   *
   ***************************************************************/
 -        CC1120_SYNC3,                          0x93,       /* Sync Word Configuration [31:24] */
 -        CC1120_SYNC2,                          0x0b,       /* Sync Word Configuration [23:16] */
 -        CC1120_SYNC1,                          0x51,       /* Sync Word Configuration [15:8] */
 -        CC1120_SYNC0,                          0xde,       /* Sync Word Configuration [7:0] */
 +        CC1120_SYNC3,                          0xD3,       /* Sync Word Configuration [31:24] */
 +        CC1120_SYNC2,                          0x91,       /* Sync Word Configuration [23:16] */
 +        CC1120_SYNC1,                          0xD3,       /* Sync Word Configuration [15:8] */
 +        CC1120_SYNC0,                          0x91,       /* Sync Word Configuration [7:0] */
 +
          CC1120_SYNC_CFG1,                      0x08,       /* Sync Word Detection Configuration */
 -        CC1120_SYNC_CFG0,                      0x17,       /* Sync Word Length Configuration */
 -#if 0
 -        CC1120_DEVIATION_M,                    0x50,       /* Frequency Deviation Configuration */
 -        CC1120_MODCFG_DEV_E,                   0x0d,       /* Modulation Format and Frequency Deviation Configuration */
 -#endif
 +        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_PREAMBLE_CFG1,                  0x18,       /* Preamble Length 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,                  0x2a,       /*  */
          CC1120_FREQ_IF_CFG,                    0x40,       /* RX Mixer Frequency Configuration */
          CC1120_IQIC,                           0x46,       /* Digital Image Channel Compensation Configuration */
          CC1120_CHAN_BW,                        0x02,       /* Channel Filter Configuration */
 +
          CC1120_MDMCFG1,                        0x46,       /* General Modem Parameter Configuration */
          CC1120_MDMCFG0,                        0x05,       /* General Modem Parameter Configuration */
 -#if 0
 -        CC1120_DRATE2,                         0x93,       /* Data Rate Configuration Exponent and Mantissa [19:16] */
 -        CC1120_DRATE1,                         0xa4,       /* Data Rate Configuration Mantissa [15:8] */
 -        CC1120_DRATE0,                         0x00,       /* Data Rate Configuration Mantissa [7:0] */
 -#endif
 +
          CC1120_AGC_REF,                        0x20,       /* AGC Reference Level Configuration */
          CC1120_AGC_CS_THR,                     0x19,       /* Carrier Sense Threshold Configuration */
          CC1120_AGC_GAIN_ADJUST,                0x00,       /* RSSI Offset Configuration */
 diff --git a/src/drivers/ao_fec.h b/src/drivers/ao_fec.h new file mode 100644 index 00000000..db5523a3 --- /dev/null +++ b/src/drivers/ao_fec.h @@ -0,0 +1,60 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_FEC_H_ +#define _AO_FEC_H_ + +#include <stdint.h> + +#define AO_FEC_CRC_INIT			0xffff +#define AO_FEC_TRELLIS_TERMINATOR	0x0b +#define AO_FEC_PREPARE_EXTRA		4 + +void +ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name); + +uint16_t +ao_fec_crc(uint8_t *bytes, uint8_t len); + +/* + * Append CRC and terminator bytes, returns resulting length. + * 'out' must be at least len + AO_FEC_PREPARE_EXTRA bytes long + */ +uint8_t +ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Whiten data using the cc1111 PN9 sequence. 'out' + * must be 'len' bytes long. 'out' and 'in' can be + * the same array + */ +uint8_t +ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Encode data. 'out' must be len*2 bytes long + */ +uint8_t +ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Interleave data. 'out' must be 'len' bytes long + */ +uint8_t +ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); + +#endif /* _AO_FEC_H_ */ diff --git a/src/drivers/ao_fec_tx.c b/src/drivers/ao_fec_tx.c new file mode 100644 index 00000000..b8933956 --- /dev/null +++ b/src/drivers/ao_fec_tx.c @@ -0,0 +1,139 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao_fec.h> +#include <stdio.h> + +void +ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name) +{ +	uint8_t	i; + +	printf ("%s (%d):", name, len); +	for (i = 0; i < len; i++) { +		if ((i & 7) == 0) +			printf ("\n\t%02x:", i); +		printf(" %02x", bytes[i]); +	} +	printf ("\n"); +} + +static uint16_t inline +crc_byte(uint8_t byte, uint16_t crc) +{ +	uint8_t	bit; + +	for (bit = 0; bit < 8; bit++) { +		if (((crc & 0x8000) >> 8) ^ (byte & 0x80)) +			crc = (crc << 1) ^ 0x8005; +		else +			crc = (crc << 1); +		byte <<= 1; +	} +	return crc; +} + +uint16_t +ao_fec_crc(uint8_t *bytes, uint8_t len) +{ +	uint16_t	crc = AO_FEC_CRC_INIT; + +	while (len--) +		crc = crc_byte(*bytes++, crc); +	return crc; +} + +uint8_t +ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out) +{ +	uint16_t	crc = ao_fec_crc (in, len); +	uint8_t		i; +	uint8_t		num_fec; + +	/* Copy data */ +	for (i = 0; i < len; i++) +		out[i] = in[i]; + +	/* Append CRC */ +	out[i++] = crc >> 8; +	out[i++] = crc; + +	/* Append FEC -- 1 byte if odd, two bytes if even */ +	num_fec = 2 - (i & 1); +	while (num_fec--) +		out[i++] = AO_FEC_TRELLIS_TERMINATOR; +	return i; +} + +static const uint8_t whiten[] = { +#include "ao_whiten.h" +}; + +uint8_t +ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) +{ +	const uint8_t	*w = whiten; + +	while (len--) +		*out++ = *in++ ^ *w++; +} + +static const uint8_t ao_fec_encode_table[16] = { +	0, 3, 1, 2, +	3, 0, 2, 1, +	3, 0, 2, 1, +	0, 3, 1, 2 +}; + +uint8_t +ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out) +{ +	uint16_t	fec = 0, output; +	uint8_t		byte, bit; + +	for (byte = 0; byte < len; byte++) { +		fec = (fec & 0x700) | in[byte]; +		output = 0; +		for (bit = 0; bit < 8; bit++) { +			output = output << 2 | ao_fec_encode_table[fec >> 7]; +			fec = (fec << 1) & 0x7ff; +		} +		out[byte * 2] = output >> 8; +		out[byte * 2 + 1] = output; +	} +	return len * 2; +} + +uint8_t +ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out) +{ +	uint8_t	i, j; + +	for (i = 0; i < len; i += 4) { +		uint32_t	interleaved = 0; + +		for (j = 0; j < 4 * 4; j++) { +			interleaved <<= 2; +			interleaved |= (in[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; +		} +		out[i+0] = interleaved >> 24; +		out[i+1] = interleaved >> 16; +		out[i+2] = interleaved >> 8; +		out[i+3] = interleaved; +	} +	return len; +} diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 5761fed7..054855ba 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -18,6 +18,8 @@ INC = \  	ao_ms5607.h \  	ao_hmc5883.h \  	ao_mpu6000.h \ +	ao_cc1120_CC1120.h \ +	ao_whiten.h \  	stm32l.h  # @@ -45,6 +47,7 @@ ALTOS_SRC = \  	ao_dma_stm.c \  	ao_spi_stm.c \  	ao_cc1120.c \ +	ao_fec_tx.c \  	ao_ms5607.c \  	ao_adc_stm.c \  	ao_beep_stm.c \ diff --git a/src/test/Makefile b/src/test/Makefile index 1e54f5e0..3e308dd7 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,6 @@  vpath % ..:../core:../drivers:../util -PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test +PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test ao_fec_tx_test  KALMAN=make-kalman  @@ -38,4 +38,7 @@ ao_convert_pa_test: ao_convert_pa_test.c ao_convert_pa.c altitude-pa.h  	cc $(CFLAGS) -o $@ $<  ao_kalman.h: $(KALMAN) -	(cd .. && make ao_kalman.h)
\ No newline at end of file +	(cd .. && make ao_kalman.h) + +ao_fec_tx_test: ao_fec_tx_test.c ao_fec_tx.c +	cc $(CFLAGS) -o $@ ao_fec_tx_test.c ../drivers/ao_fec_tx.c diff --git a/src/test/ao_fec_tx_test.c b/src/test/ao_fec_tx_test.c new file mode 100644 index 00000000..b8dc9308 --- /dev/null +++ b/src/test/ao_fec_tx_test.c @@ -0,0 +1,47 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao_fec.h> +#include <stdlib.h> +#include <stdio.h> + +int +main(int argc, char **argv) +{ +	uint8_t		input[4] = { 3, 1, 2, 3 }; +	uint8_t		prepare[sizeof(input) + AO_FEC_PREPARE_EXTRA]; +	uint8_t		encode[sizeof(prepare) * 2]; +	uint8_t		interleave[sizeof(encode)]; +	uint8_t		prepare_len; +	uint8_t		encode_len; +	uint8_t		interleave_len; + +	ao_fec_dump_bytes(input, sizeof(input), "Input"); + +	prepare_len = ao_fec_prepare(input, sizeof (input), prepare); + +	ao_fec_dump_bytes(prepare, prepare_len, "Prepare"); +	 +	encode_len = ao_fec_encode(prepare, prepare_len, encode); + +	ao_fec_dump_bytes(encode, encode_len, "Encode"); +	 +	interleave_len = ao_fec_interleave(encode, encode_len, interleave); + +	ao_fec_dump_bytes(interleave, interleave_len, "Interleave"); +} + diff --git a/src/util/make-whiten b/src/util/make-whiten new file mode 100644 index 00000000..d68a02af --- /dev/null +++ b/src/util/make-whiten @@ -0,0 +1,37 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +/* Generate the data whitening array used by the CC11* radios */ + +int pn9 = 0x1ff; + +void +pn9_step() { +	pn9 = (pn9 >> 1) | (((pn9 ^ (pn9 >> 5)) & 1) << 8); +} + +int val() +{ +	int	ret = pn9 & 0xff; + +	for (int i = 0; i < 8; i++) +		pn9_step(); +	return ret; +} + +for (int i = 0; i < 128; i++) +	printf (" /* %3d */ 0x%02x,\n", i + 1, val()); | 
