summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/ao_aprs.c104
-rw-r--r--src/drivers/ao_cc1120.c338
-rw-r--r--src/drivers/ao_cc1120.h8
-rw-r--r--src/drivers/ao_cc1120_CC1120.h56
-rw-r--r--src/drivers/ao_cc115l.c78
-rw-r--r--src/drivers/ao_gps_skytraq.c9
-rw-r--r--src/drivers/ao_gps_ublox.c12
-rw-r--r--src/drivers/ao_lco_func.c16
-rw-r--r--src/drivers/ao_packet_master.c8
-rw-r--r--src/drivers/ao_pad.c16
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;