diff options
Diffstat (limited to 'src/drivers')
| -rw-r--r-- | src/drivers/ao_aprs.c | 104 | ||||
| -rw-r--r-- | src/drivers/ao_cc1120.c | 338 | ||||
| -rw-r--r-- | src/drivers/ao_cc1120.h | 8 | ||||
| -rw-r--r-- | src/drivers/ao_cc1120_CC1120.h | 56 | ||||
| -rw-r--r-- | src/drivers/ao_cc115l.c | 78 | ||||
| -rw-r--r-- | src/drivers/ao_gps_skytraq.c | 9 | ||||
| -rw-r--r-- | src/drivers/ao_gps_ublox.c | 12 | ||||
| -rw-r--r-- | src/drivers/ao_lco_func.c | 16 | ||||
| -rw-r--r-- | src/drivers/ao_packet_master.c | 8 | ||||
| -rw-r--r-- | src/drivers/ao_pad.c | 16 | 
10 files changed, 444 insertions, 201 deletions
| 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; | 
