From 27a467d802a80a33ea20eb5cda2558d03caa2c00 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Oct 2014 00:03:28 -0700 Subject: altos: Copy cc1120 driver to cc1200 driver and hack a bit The cc1200 is similar to the cc1120, although many registers have changed. This driver can send a bare carrier and an RDF tone, but does not yet receive or transmit telemetry data. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 1249 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1249 insertions(+) create mode 100644 src/drivers/ao_cc1200.c (limited to 'src/drivers/ao_cc1200.c') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c new file mode 100644 index 00000000..a69cdc11 --- /dev/null +++ b/src/drivers/ao_cc1200.c @@ -0,0 +1,1249 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include +#include +#include +#include + +#define AO_RADIO_MAX_RECV sizeof(struct ao_packet) +#define AO_RADIO_MAX_SEND sizeof(struct ao_packet) + +static uint8_t ao_radio_mutex; + +static uint8_t ao_radio_wake; /* radio ready. Also used as sleep address */ +static uint8_t ao_radio_abort; /* radio operation should abort */ +static uint8_t ao_radio_mcu_wake; /* MARC status change */ +static uint8_t ao_radio_marc_status; /* Last read MARC status value */ +static uint8_t ao_radio_tx_finished; /* MARC status indicates TX finished */ + +int8_t ao_radio_rssi; /* Last received RSSI value */ + +#define CC1200_DEBUG 1 +#define CC1200_TRACE 1 + +extern const uint32_t ao_radio_cal; + +#define FOSC 32000000 + +#define ao_radio_try_select(task_id) ao_spi_try_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_125kHz, task_id) +#define ao_radio_select() ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_125kHz) +#define ao_radio_deselect() ao_spi_put_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS) +#define ao_radio_spi_send_sync(d,l) ao_spi_send_sync((d), (l), AO_CC1200_SPI_BUS) +#define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1200_SPI_BUS) +#define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1200_SPI_BUS) +#define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1200_SPI_BUS) +#define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1200_SPI_BUS) + +static uint8_t +ao_radio_reg_read(uint16_t addr) +{ + uint8_t data[2]; + uint8_t d; + +#if CC1200_TRACE + printf("\t\tao_radio_reg_read (%04x): ", addr); flush(); +#endif + if (CC1200_IS_EXTENDED(addr)) { + data[0] = ((1 << CC1200_READ) | + (0 << CC1200_BURST) | + CC1200_EXTENDED); + data[1] = addr; + d = 2; + } else { + data[0] = ((1 << CC1200_READ) | + (0 << CC1200_BURST) | + addr); + d = 1; + } + ao_radio_select(); + ao_radio_spi_send(data, d); + ao_radio_spi_recv(data, 1); + ao_radio_deselect(); +#if CC1200_TRACE + printf (" %02x\n", data[0]); +#endif + return data[0]; +} + +static void +ao_radio_reg_write(uint16_t addr, uint8_t value) +{ + uint8_t data[3]; + uint8_t d; + +#if CC1200_TRACE + printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value); +#endif + if (CC1200_IS_EXTENDED(addr)) { + data[0] = ((0 << CC1200_READ) | + (0 << CC1200_BURST) | + CC1200_EXTENDED); + data[1] = addr; + d = 2; + } else { + data[0] = ((0 << CC1200_READ) | + (0 << CC1200_BURST) | + addr); + d = 1; + } + data[d] = value; + ao_radio_select(); + ao_radio_spi_send(data, d+1); + ao_radio_deselect(); +#if CC1200_TRACE + (void) ao_radio_reg_read(addr); +#endif +} + +static uint8_t +ao_radio_strobe(uint8_t addr) +{ + uint8_t in; + +#if CC1200_TRACE + printf("\t\tao_radio_strobe (%02x): ", addr); flush(); +#endif + ao_radio_select(); + ao_radio_duplex(&addr, &in, 1); + ao_radio_deselect(); +#if CC1200_TRACE + printf("%02x\n", in); flush(); +#endif + return in; +} + +#if 0 +static uint8_t +ao_radio_fifo_read(uint8_t *data, uint8_t len) +{ + uint8_t addr = ((1 << CC1200_READ) | + (1 << CC1200_BURST) | + CC1200_FIFO); + uint8_t status; + + ao_radio_select(); + ao_radio_duplex(&addr, &status, 1); + ao_radio_spi_recv(data, len); + ao_radio_deselect(); + return status; +} +#endif + +static uint8_t +ao_radio_fifo_write_start(void) +{ + uint8_t addr = ((0 << CC1200_READ) | + (1 << CC1200_BURST) | + CC1200_FIFO); + uint8_t status; + + ao_radio_select(); + ao_radio_duplex(&addr, &status, 1); + return status; +} + +static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) { + ao_radio_deselect(); + return status; +} + +static uint8_t +ao_radio_fifo_write(uint8_t *data, uint8_t len) +{ + uint8_t status = ao_radio_fifo_write_start(); + ao_radio_spi_send(data, len); + return ao_radio_fifo_write_stop(status); +} + +static uint8_t +ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) +{ + uint8_t status = ao_radio_fifo_write_start(); + ao_radio_spi_send_fixed(data, len); + return ao_radio_fifo_write_stop(status); +} + +static uint8_t +ao_radio_tx_fifo_space(void) +{ + return CC1200_FIFO_SIZE - ao_radio_reg_read(CC1200_NUM_TXBYTES); +} + +#if CC1200_DEBUG || CC1200_TRACE +static uint8_t +ao_radio_status(void) +{ + return ao_radio_strobe (CC1200_SNOP); +} +#endif + +void +ao_radio_recv_abort(void) +{ + ao_radio_abort = 1; + ao_wakeup(&ao_radio_wake); +} + +#define ao_radio_rdf_value 0x55 + +static uint8_t +ao_radio_get_marc_status(void) +{ + return ao_radio_reg_read(CC1200_MARC_STATUS1); +} + +static void +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 & ~(CC1200_MARC_STATUS1_TX_FINISHED|CC1200_MARC_STATUS1_RX_FINISHED)) + ao_radio_abort = 1; + if (ao_radio_marc_status & (CC1200_MARC_STATUS1_TX_FINISHED)) + ao_radio_tx_finished = 1; +} + +static void +ao_radio_isr(void) +{ + ao_exti_disable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN); + ao_radio_wake = 1; + ao_wakeup(&ao_radio_wake); +} + +static void +ao_radio_start_tx(void) +{ + ao_exti_set_callback(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, ao_radio_isr); + ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN); + ao_radio_tx_finished = 0; + ao_radio_strobe(CC1200_STX); +} + +static void +ao_radio_idle(void) +{ + for (;;) { + uint8_t state = (ao_radio_strobe(CC1200_SIDLE) >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK; + if (state == CC1200_STATUS_STATE_IDLE) + break; + if (state == CC1200_STATUS_STATE_TX_FIFO_ERROR) + ao_radio_strobe(CC1200_SFTX); + if (state == CC1200_STATUS_STATE_RX_FIFO_ERROR) + ao_radio_strobe(CC1200_SFRX); + } + /* Flush any pending TX bytes */ + ao_radio_strobe(CC1200_SFTX); +} + +/* + * 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_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 + * + * (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 (79.4) + * + * Symbol rate 9600 Baud: + * + * DATARATE_M = 239914 + * DATARATE_E = 7 + * CHANBW = 19.9 (round to 19.8) + * + * Symbol rate 2400 Baud: + * + * DATARATE_M = 239914 + * DATARATE_E = 5 + * CHANBW = 5.0 (round to 9.5) + */ + +#define PACKET_SYMBOL_RATE_M 239914 + +#define PACKET_SYMBOL_RATE_E_384 9 + +/* 200 / 2 = 100 */ +#define PACKET_CHAN_BW_384 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_12 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \ + (21 << CC1200_CHAN_BW_BB_CIC_DECFACT)) + +#define PACKET_SYMBOL_RATE_E_96 7 +/* 200 / 10 = 20 */ +#define PACKET_CHAN_BW_96 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \ + (21 << CC1200_CHAN_BW_BB_CIC_DECFACT)) + +#define PACKET_SYMBOL_RATE_E_24 5 +/* 200 / 25 = 8 */ +#define PACKET_CHAN_BW_24 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \ + (44 << CC1200_CHAN_BW_BB_CIC_DECFACT)) + +static const uint16_t packet_setup[] = { + CC1200_SYMBOL_RATE1, ((PACKET_SYMBOL_RATE_M >> 8) & 0xff), + CC1200_SYMBOL_RATE0, ((PACKET_SYMBOL_RATE_M >> 0) & 0xff), + CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) | + (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | + (0 << CC1200_PKT_CFG1_APPEND_STATUS)), + CC1200_PKT_CFG0, ((0 << CC1200_PKT_CFG0_RESERVED7) | + (CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1200_PKT_CFG0_UART_MODE_EN) | + (0 << CC1200_PKT_CFG0_UART_SWAP_EN)), + CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), +}; + +static const uint16_t packet_setup_384[] = { + CC1200_DEVIATION_M, PACKET_DEV_M_384, + CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | + (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | + (PACKET_DEV_E_384 << CC1200_MODCFG_DEV_E_DEV_E)), + CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_384 << CC1200_SYMBOL_RATE2_DATARATE_E) | + (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), + CC1200_CHAN_BW, PACKET_CHAN_BW_384, + CC1200_PA_CFG0, 0x7b, +}; + +static const uint16_t packet_setup_96[] = { + CC1200_DEVIATION_M, PACKET_DEV_M_96, + CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | + (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | + (PACKET_DEV_E_96 << CC1200_MODCFG_DEV_E_DEV_E)), + CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_96 << CC1200_SYMBOL_RATE2_DATARATE_E) | + (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), + CC1200_CHAN_BW, PACKET_CHAN_BW_96, + CC1200_PA_CFG0, 0x7d, +}; + +static const uint16_t packet_setup_24[] = { + CC1200_DEVIATION_M, PACKET_DEV_M_24, + CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | + (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | + (PACKET_DEV_E_24 << CC1200_MODCFG_DEV_E_DEV_E)), + CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_24 << CC1200_SYMBOL_RATE2_DATARATE_E) | + (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), + CC1200_CHAN_BW, PACKET_CHAN_BW_24, + CC1200_PA_CFG0, 0x7e, +}; + +static const uint16_t packet_tx_setup[] = { + CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_RX0TX1_CFG, +}; + +static const uint16_t packet_rx_setup[] = { + CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1200_PKT_CFG2_PKT_FORMAT)), + AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_CLKEN_SOFT, +}; + +/* + * RDF deviation is 5kHz + * + * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * + * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989 + */ + +#define RDF_DEV_E 3 +#define RDF_DEV_M 71 + +/* + * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone) + * + * (2**20 + DATARATE_M) * 2 ** DATARATE_E + * Rdata = -------------------------------------- * fosc + * 2 ** 39 + * + * DATARATE_M = 25166 + * DATARATE_E = 5 + * + * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes + */ +#define RDF_SYMBOL_RATE_E 5 +#define RDF_SYMBOL_RATE_M 25166 +#define RDF_PACKET_LEN 50 + +static const uint16_t rdf_setup[] = { + CC1200_DEVIATION_M, RDF_DEV_M, + CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | + (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | + (RDF_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)), + CC1200_SYMBOL_RATE2, ((RDF_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) | + (((RDF_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), + CC1200_SYMBOL_RATE1, ((RDF_SYMBOL_RATE_M >> 8) & 0xff), + CC1200_SYMBOL_RATE0, ((RDF_SYMBOL_RATE_M >> 0) & 0xff), + CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) | + (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | + (0 << CC1200_PKT_CFG1_APPEND_STATUS)), + CC1200_PKT_CFG0, ((0 << CC1200_PKT_CFG0_RESERVED7) | + (CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1200_PKT_CFG0_UART_MODE_EN) | + (0 << CC1200_PKT_CFG0_UART_SWAP_EN)), + CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), + CC1200_PA_CFG0, 0x7e, +}; + +/* + * APRS deviation is 3kHz + * + * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * + * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz + */ + +#define APRS_DEV_E 2 +#define APRS_DEV_M 137 + +/* + * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate) + * + * (2**20 + DATARATE_M) * 2 ** DATARATE_E + * Rdata = -------------------------------------- * fosc + * 2 ** 39 + * + * DATARATE_M = 239914 + * DATARATE_E = 7 + * + * Rdata = 9599.998593330383301 + * + */ +#define APRS_SYMBOL_RATE_E 7 +#define APRS_SYMBOL_RATE_M 239914 + +static const uint16_t aprs_setup[] = { + CC1200_DEVIATION_M, APRS_DEV_M, + CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | + (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | + (APRS_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)), + CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) | + (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), + CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff), + CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff), + CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) | + (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | + (0 << CC1200_PKT_CFG1_APPEND_STATUS)), + CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), + CC1200_PA_CFG0, 0x7d, +}; + +/* + * For Test mode, we want an unmodulated carrier. To do that, we + * set the deviation to zero and enable a preamble so that the radio + * turns on before we send any data + */ + +static const uint16_t test_setup[] = { + CC1200_DEVIATION_M, 0, + CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | + (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | + (0 << CC1200_MODCFG_DEV_E_DEV_E)), + CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) | + (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), + CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff), + CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff), + CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) | + (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | + (0 << CC1200_PKT_CFG1_APPEND_STATUS)), + CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), +}; + +#define AO_PKT_CFG0_INFINITE ((0 << CC1200_PKT_CFG0_RESERVED7) | \ + (CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1200_PKT_CFG0_LENGTH_CONFIG) | \ + (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \ + (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \ + (0 << CC1200_PKT_CFG0_UART_SWAP_EN)) + +#define AO_PKT_CFG0_FIXED ((0 << CC1200_PKT_CFG0_RESERVED7) | \ + (CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | \ + (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \ + (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \ + (0 << CC1200_PKT_CFG0_UART_SWAP_EN)) + +static uint16_t ao_radio_mode; + +#define AO_RADIO_MODE_BITS_PACKET 1 +#define AO_RADIO_MODE_BITS_PACKET_TX 2 +#define AO_RADIO_MODE_BITS_TX_BUF 4 +#define AO_RADIO_MODE_BITS_TX_FINISH 8 +#define AO_RADIO_MODE_BITS_PACKET_RX 16 +#define AO_RADIO_MODE_BITS_RDF 32 +#define AO_RADIO_MODE_BITS_APRS 64 +#define AO_RADIO_MODE_BITS_TEST 128 +#define AO_RADIO_MODE_BITS_INFINITE 256 +#define AO_RADIO_MODE_BITS_FIXED 512 + +#define AO_RADIO_MODE_NONE 0 +#define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF) +#define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH) +#define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX) +#define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH) +#define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF) +#define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF) +#define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH) +#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; + + if (new_mode == ao_radio_mode) + return; + + changes = new_mode & (~ao_radio_mode); + + 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) + ao_radio_set_regs(packet_tx_setup); + + if (changes & AO_RADIO_MODE_BITS_TX_BUF) + ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_TXFIFO_THR); + + if (changes & AO_RADIO_MODE_BITS_TX_FINISH) + ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_RX0TX1_CFG); + + if (changes & AO_RADIO_MODE_BITS_PACKET_RX) + ao_radio_set_regs(packet_rx_setup); + + if (changes & AO_RADIO_MODE_BITS_RDF) + ao_radio_set_regs(rdf_setup); + + if (changes & AO_RADIO_MODE_BITS_APRS) + ao_radio_set_regs(aprs_setup); + + if (changes & AO_RADIO_MODE_BITS_TEST) + ao_radio_set_regs(test_setup); + + if (changes & AO_RADIO_MODE_BITS_INFINITE) + ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_INFINITE); + + if (changes & AO_RADIO_MODE_BITS_FIXED) + ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_FIXED); + + ao_radio_mode = new_mode; +} + +static const uint16_t radio_setup[] = { +#include "ao_cc1200_CC1200.h" +}; + +static uint8_t ao_radio_configured = 0; + +static void +ao_radio_setup(void) +{ +// ao_radio_strobe(CC1200_SRES); + + ao_radio_set_regs(radio_setup); + + ao_radio_mode = 0; + + ao_config_get(); + + ao_radio_configured = 1; +} + +static void +ao_radio_set_len(uint8_t len) +{ + static uint8_t last_len; + + if (len != last_len) { + ao_radio_reg_write(CC1200_PKT_LEN, len); + last_len = len; + } +} + +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); + + if (!ao_radio_configured) + ao_radio_setup(); + if (ao_config.radio_setting != last_radio_setting) { + ao_radio_reg_write(CC1200_FREQ2, ao_config.radio_setting >> 16); + ao_radio_reg_write(CC1200_FREQ1, ao_config.radio_setting >> 8); + ao_radio_reg_write(CC1200_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); +} + +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) + +static void +ao_rdf_start(uint8_t len) +{ + ao_radio_abort = 0; + ao_radio_get(len); + + ao_radio_set_mode(AO_RADIO_MODE_RDF); + ao_radio_wake = 0; + +} + +static void +ao_rdf_run(void) +{ + ao_radio_start_tx(); + + ao_arch_block_interrupts(); + while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake) + ao_sleep(&ao_radio_wake); + ao_arch_release_interrupts(); + if (ao_radio_mcu_wake) + ao_radio_check_marc_status(); + if (!ao_radio_wake) + ao_radio_idle(); + ao_radio_put(); +} + +void +ao_radio_rdf(void) +{ + ao_rdf_start(AO_RADIO_RDF_LEN); + + ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN); + + ao_rdf_run(); +} + +void +ao_radio_continuity(uint8_t c) +{ + uint8_t i; + uint8_t status; + + ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN); + + status = ao_radio_fifo_write_start(); + for (i = 0; i < 3; i++) { + ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN); + if (i < c) + ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN); + else + ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN); + } + ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN); + status = ao_radio_fifo_write_stop(status); + (void) status; + ao_rdf_run(); +} + +void +ao_radio_rdf_abort(void) +{ + ao_radio_abort = 1; + ao_wakeup(&ao_radio_wake); +} + +static void +ao_radio_test_cmd(void) +{ + uint8_t mode = 2; + static uint8_t radio_on; + ao_cmd_white(); + if (ao_cmd_lex_c != '\n') { + ao_cmd_decimal(); + mode = (uint8_t) ao_cmd_lex_u32; + } + mode++; + if ((mode & 2) && !radio_on) { +#if HAS_MONITOR + ao_monitor_disable(); +#endif +#if PACKET_HAS_SLAVE + ao_packet_slave_stop(); +#endif + ao_radio_get(0xff); + ao_radio_set_mode(AO_RADIO_MODE_TEST); + ao_radio_strobe(CC1200_STX); +#if CC1200_TRACE + { int t; + for (t = 0; t < 10; t++) { + printf ("status: %02x\n", ao_radio_status()); + ao_delay(AO_MS_TO_TICKS(100)); + } + } +#endif + radio_on = 1; + } + if (mode == 3) { + printf ("Hit a character to stop..."); flush(); + getchar(); + putchar('\n'); + } + if ((mode & 1) && radio_on) { + ao_radio_idle(); + ao_radio_put(); + radio_on = 0; +#if HAS_MONITOR + ao_monitor_enable(); +#endif + } +} + +static void +ao_radio_wait_isr(uint16_t timeout) +{ + if (timeout) + ao_alarm(timeout); + ao_arch_block_interrupts(); + while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort) + if (ao_sleep(&ao_radio_wake)) + ao_radio_abort = 1; + ao_arch_release_interrupts(); + if (timeout) + ao_clear_alarm(); + if (ao_radio_mcu_wake) + ao_radio_check_marc_status(); +} + +void +ao_radio_send(const void *d, uint8_t size) +{ + (void) d; + (void) size; +} + +#define AO_RADIO_LOTS 64 + +void +ao_radio_send_aprs(ao_radio_fill_func fill) +{ + uint8_t buf[AO_RADIO_LOTS], *b; + int cnt; + int total = 0; + uint8_t done = 0; + uint8_t started = 0; + uint8_t fifo_space; + + ao_radio_get(0xff); + fifo_space = CC1200_FIFO_SIZE; + while (!done) { + cnt = (*fill)(buf, sizeof(buf)); + if (cnt < 0) { + done = 1; + cnt = -cnt; + } + total += cnt; + + /* At the last buffer, set the total length */ + if (done) + ao_radio_set_len(total & 0xff); + + b = buf; + while (cnt) { + uint8_t this_len = cnt; + + /* Wait for some space in the fifo */ + while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) { + ao_radio_wake = 0; + ao_radio_wait_isr(0); + } + if (ao_radio_abort) + break; + if (this_len > fifo_space) + this_len = fifo_space; + + cnt -= this_len; + + if (done) { + if (cnt) + ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF); + else + ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH); + } else + ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF); + + ao_radio_fifo_write(b, this_len); + b += this_len; + + if (!started) { + ao_radio_start_tx(); + started = 1; + } else + ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN); + } + if (ao_radio_abort) { + ao_radio_idle(); + break; + } + /* Wait for the transmitter to go idle */ + ao_radio_wake = 0; + ao_radio_wait_isr(0); + } + ao_radio_put(); +} + +uint8_t +ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) +{ + (void) d; + (void) size; + (void) timeout; + return 0; +} + + +#if CC1200_DEBUG +static char *cc1200_state_name[] = { + [CC1200_STATUS_STATE_IDLE] = "IDLE", + [CC1200_STATUS_STATE_RX] = "RX", + [CC1200_STATUS_STATE_TX] = "TX", + [CC1200_STATUS_STATE_FSTXON] = "FSTXON", + [CC1200_STATUS_STATE_CALIBRATE] = "CALIBRATE", + [CC1200_STATUS_STATE_SETTLING] = "SETTLING", + [CC1200_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR", + [CC1200_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR", +}; + +struct ao_cc1200_reg { + uint16_t addr; + char *name; +}; + +static const struct ao_cc1200_reg ao_cc1200_reg[] = { + { .addr = CC1200_IOCFG3, .name = "IOCFG3" }, + { .addr = CC1200_IOCFG2, .name = "IOCFG2" }, + { .addr = CC1200_IOCFG1, .name = "IOCFG1" }, + { .addr = CC1200_IOCFG0, .name = "IOCFG0" }, + { .addr = CC1200_SYNC3, .name = "SYNC3" }, + { .addr = CC1200_SYNC2, .name = "SYNC2" }, + { .addr = CC1200_SYNC1, .name = "SYNC1" }, + { .addr = CC1200_SYNC0, .name = "SYNC0" }, + { .addr = CC1200_SYNC_CFG1, .name = "SYNC_CFG1" }, + { .addr = CC1200_SYNC_CFG0, .name = "SYNC_CFG0" }, + { .addr = CC1200_DEVIATION_M, .name = "DEVIATION_M" }, + { .addr = CC1200_MODCFG_DEV_E, .name = "MODCFG_DEV_E" }, + { .addr = CC1200_DCFILT_CFG, .name = "DCFILT_CFG" }, + { .addr = CC1200_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" }, + { .addr = CC1200_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" }, + { .addr = CC1200_IQIC, .name = "IQIC" }, + { .addr = CC1200_CHAN_BW, .name = "CHAN_BW" }, + { .addr = CC1200_MDMCFG1, .name = "MDMCFG1" }, + { .addr = CC1200_MDMCFG0, .name = "MDMCFG0" }, + { .addr = CC1200_SYMBOL_RATE2, .name = "SYMBOL_RATE2" }, + { .addr = CC1200_SYMBOL_RATE1, .name = "SYMBOL_RATE1" }, + { .addr = CC1200_SYMBOL_RATE0, .name = "SYMBOL_RATE0" }, + { .addr = CC1200_AGC_REF, .name = "AGC_REF" }, + { .addr = CC1200_AGC_CS_THR, .name = "AGC_CS_THR" }, + { .addr = CC1200_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" }, + { .addr = CC1200_AGC_CFG3, .name = "AGC_CFG3" }, + { .addr = CC1200_AGC_CFG2, .name = "AGC_CFG2" }, + { .addr = CC1200_AGC_CFG1, .name = "AGC_CFG1" }, + { .addr = CC1200_AGC_CFG0, .name = "AGC_CFG0" }, + { .addr = CC1200_FIFO_CFG, .name = "FIFO_CFG" }, + { .addr = CC1200_DEV_ADDR, .name = "DEV_ADDR" }, + { .addr = CC1200_SETTLING_CFG, .name = "SETTLING_CFG" }, + { .addr = CC1200_FS_CFG, .name = "FS_CFG" }, + { .addr = CC1200_WOR_CFG1, .name = "WOR_CFG1" }, + { .addr = CC1200_WOR_CFG0, .name = "WOR_CFG0" }, + { .addr = CC1200_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" }, + { .addr = CC1200_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" }, + { .addr = CC1200_RXDCM_TIME, .name = "RXDCM_TIME" }, + { .addr = CC1200_PKT_CFG2, .name = "PKT_CFG2" }, + { .addr = CC1200_PKT_CFG1, .name = "PKT_CFG1" }, + { .addr = CC1200_PKT_CFG0, .name = "PKT_CFG0" }, + { .addr = CC1200_RFEND_CFG1, .name = "RFEND_CFG1" }, + { .addr = CC1200_RFEND_CFG0, .name = "RFEND_CFG0" }, + { .addr = CC1200_PA_CFG1, .name = "PA_CFG1" }, + { .addr = CC1200_PA_CFG0, .name = "PA_CFG0" }, + { .addr = CC1200_PKT_LEN, .name = "PKT_LEN" }, + { .addr = CC1200_IF_MIX_CFG, .name = "IF_MIX_CFG" }, + { .addr = CC1200_FREQOFF_CFG, .name = "FREQOFF_CFG" }, + { .addr = CC1200_TOC_CFG, .name = "TOC_CFG" }, + { .addr = CC1200_MARC_SPARE, .name = "MARC_SPARE" }, + { .addr = CC1200_ECG_CFG, .name = "ECG_CFG" }, + { .addr = CC1200_EXT_CTRL, .name = "EXT_CTRL" }, + { .addr = CC1200_RCCAL_FINE, .name = "RCCAL_FINE" }, + { .addr = CC1200_RCCAL_COARSE, .name = "RCCAL_COARSE" }, + { .addr = CC1200_RCCAL_OFFSET, .name = "RCCAL_OFFSET" }, + { .addr = CC1200_FREQOFF1, .name = "FREQOFF1" }, + { .addr = CC1200_FREQOFF0, .name = "FREQOFF0" }, + { .addr = CC1200_FREQ2, .name = "FREQ2" }, + { .addr = CC1200_FREQ1, .name = "FREQ1" }, + { .addr = CC1200_FREQ0, .name = "FREQ0" }, + { .addr = CC1200_IF_ADC2, .name = "IF_ADC2" }, + { .addr = CC1200_IF_ADC1, .name = "IF_ADC1" }, + { .addr = CC1200_IF_ADC0, .name = "IF_ADC0" }, + { .addr = CC1200_FS_DIG1, .name = "FS_DIG1" }, + { .addr = CC1200_FS_DIG0, .name = "FS_DIG0" }, + { .addr = CC1200_FS_CAL3, .name = "FS_CAL3" }, + { .addr = CC1200_FS_CAL2, .name = "FS_CAL2" }, + { .addr = CC1200_FS_CAL1, .name = "FS_CAL1" }, + { .addr = CC1200_FS_CAL0, .name = "FS_CAL0" }, + { .addr = CC1200_FS_CHP, .name = "FS_CHP" }, + { .addr = CC1200_FS_DIVTWO, .name = "FS_DIVTWO" }, + { .addr = CC1200_FS_DSM1, .name = "FS_DSM1" }, + { .addr = CC1200_FS_DSM0, .name = "FS_DSM0" }, + { .addr = CC1200_FS_DVC1, .name = "FS_DVC1" }, + { .addr = CC1200_FS_DVC0, .name = "FS_DVC0" }, + { .addr = CC1200_FS_LBI, .name = "FS_LBI" }, + { .addr = CC1200_FS_PFD, .name = "FS_PFD" }, + { .addr = CC1200_FS_PRE, .name = "FS_PRE" }, + { .addr = CC1200_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" }, + { .addr = CC1200_FS_SPARE, .name = "FS_SPARE" }, + { .addr = CC1200_FS_VCO4, .name = "FS_VCO4" }, + { .addr = CC1200_FS_VCO3, .name = "FS_VCO3" }, + { .addr = CC1200_FS_VCO2, .name = "FS_VCO2" }, + { .addr = CC1200_FS_VCO1, .name = "FS_VCO1" }, + { .addr = CC1200_FS_VCO0, .name = "FS_VCO0" }, + { .addr = CC1200_GBIAS6, .name = "GBIAS6" }, + { .addr = CC1200_GBIAS5, .name = "GBIAS5" }, + { .addr = CC1200_GBIAS4, .name = "GBIAS4" }, + { .addr = CC1200_GBIAS3, .name = "GBIAS3" }, + { .addr = CC1200_GBIAS2, .name = "GBIAS2" }, + { .addr = CC1200_GBIAS1, .name = "GBIAS1" }, + { .addr = CC1200_GBIAS0, .name = "GBIAS0" }, + { .addr = CC1200_IFAMP, .name = "IFAMP" }, + { .addr = CC1200_LNA, .name = "LNA" }, + { .addr = CC1200_RXMIX, .name = "RXMIX" }, + { .addr = CC1200_XOSC5, .name = "XOSC5" }, + { .addr = CC1200_XOSC4, .name = "XOSC4" }, + { .addr = CC1200_XOSC3, .name = "XOSC3" }, + { .addr = CC1200_XOSC2, .name = "XOSC2" }, + { .addr = CC1200_XOSC1, .name = "XOSC1" }, + { .addr = CC1200_XOSC0, .name = "XOSC0" }, + { .addr = CC1200_ANALOG_SPARE, .name = "ANALOG_SPARE" }, + { .addr = CC1200_PA_CFG3, .name = "PA_CFG3" }, + { .addr = CC1200_WOR_TIME1, .name = "WOR_TIME1" }, + { .addr = CC1200_WOR_TIME0, .name = "WOR_TIME0" }, + { .addr = CC1200_WOR_CAPTURE1, .name = "WOR_CAPTURE1" }, + { .addr = CC1200_WOR_CAPTURE0, .name = "WOR_CAPTURE0" }, + { .addr = CC1200_BIST, .name = "BIST" }, + { .addr = CC1200_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" }, + { .addr = CC1200_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" }, + { .addr = CC1200_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" }, + { .addr = CC1200_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" }, + { .addr = CC1200_IQIE_I1, .name = "IQIE_I1" }, + { .addr = CC1200_IQIE_I0, .name = "IQIE_I0" }, + { .addr = CC1200_IQIE_Q1, .name = "IQIE_Q1" }, + { .addr = CC1200_IQIE_Q0, .name = "IQIE_Q0" }, + { .addr = CC1200_RSSI1, .name = "RSSI1" }, + { .addr = CC1200_RSSI0, .name = "RSSI0" }, + { .addr = CC1200_MARCSTATE, .name = "MARCSTATE" }, + { .addr = CC1200_LQI_VAL, .name = "LQI_VAL" }, + { .addr = CC1200_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" }, + { .addr = CC1200_DEM_STATUS, .name = "DEM_STATUS" }, + { .addr = CC1200_FREQOFF_EST1, .name = "FREQOFF_EST1" }, + { .addr = CC1200_FREQOFF_EST0, .name = "FREQOFF_EST0" }, + { .addr = CC1200_AGC_GAIN3, .name = "AGC_GAIN3" }, + { .addr = CC1200_AGC_GAIN2, .name = "AGC_GAIN2" }, + { .addr = CC1200_AGC_GAIN1, .name = "AGC_GAIN1" }, + { .addr = CC1200_AGC_GAIN0, .name = "AGC_GAIN0" }, + { .addr = CC1200_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" }, + { .addr = CC1200_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" }, + { .addr = CC1200_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" }, + { .addr = CC1200_RNDGEN, .name = "RNDGEN" }, + { .addr = CC1200_MAGN2, .name = "MAGN2" }, + { .addr = CC1200_MAGN1, .name = "MAGN1" }, + { .addr = CC1200_MAGN0, .name = "MAGN0" }, + { .addr = CC1200_ANG1, .name = "ANG1" }, + { .addr = CC1200_ANG0, .name = "ANG0" }, + { .addr = CC1200_CHFILT_I2, .name = "CHFILT_I2" }, + { .addr = CC1200_CHFILT_I1, .name = "CHFILT_I1" }, + { .addr = CC1200_CHFILT_I0, .name = "CHFILT_I0" }, + { .addr = CC1200_CHFILT_Q2, .name = "CHFILT_Q2" }, + { .addr = CC1200_CHFILT_Q1, .name = "CHFILT_Q1" }, + { .addr = CC1200_CHFILT_Q0, .name = "CHFILT_Q0" }, + { .addr = CC1200_GPIO_STATUS, .name = "GPIO_STATUS" }, + { .addr = CC1200_FSCAL_CTRL, .name = "FSCAL_CTRL" }, + { .addr = CC1200_PHASE_ADJUST, .name = "PHASE_ADJUST" }, + { .addr = CC1200_PARTNUMBER, .name = "PARTNUMBER" }, + { .addr = CC1200_PARTVERSION, .name = "PARTVERSION" }, + { .addr = CC1200_SERIAL_STATUS, .name = "SERIAL_STATUS" }, + { .addr = CC1200_RX_STATUS, .name = "RX_STATUS" }, + { .addr = CC1200_TX_STATUS, .name = "TX_STATUS" }, + { .addr = CC1200_MARC_STATUS1, .name = "MARC_STATUS1" }, + { .addr = CC1200_MARC_STATUS0, .name = "MARC_STATUS0" }, + { .addr = CC1200_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" }, + { .addr = CC1200_FSRF_TEST, .name = "FSRF_TEST" }, + { .addr = CC1200_PRE_TEST, .name = "PRE_TEST" }, + { .addr = CC1200_PRE_OVR, .name = "PRE_OVR" }, + { .addr = CC1200_ADC_TEST, .name = "ADC_TEST" }, + { .addr = CC1200_DVC_TEST, .name = "DVC_TEST" }, + { .addr = CC1200_ATEST, .name = "ATEST" }, + { .addr = CC1200_ATEST_LVDS, .name = "ATEST_LVDS" }, + { .addr = CC1200_ATEST_MODE, .name = "ATEST_MODE" }, + { .addr = CC1200_XOSC_TEST1, .name = "XOSC_TEST1" }, + { .addr = CC1200_XOSC_TEST0, .name = "XOSC_TEST0" }, + { .addr = CC1200_RXFIRST, .name = "RXFIRST" }, + { .addr = CC1200_TXFIRST, .name = "TXFIRST" }, + { .addr = CC1200_RXLAST, .name = "RXLAST" }, + { .addr = CC1200_TXLAST, .name = "TXLAST" }, + { .addr = CC1200_NUM_TXBYTES, .name = "NUM_TXBYTES" }, + { .addr = CC1200_NUM_RXBYTES, .name = "NUM_RXBYTES" }, + { .addr = CC1200_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" }, + { .addr = CC1200_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" }, +}; + +#define AO_NUM_CC1200_REG (sizeof ao_cc1200_reg / sizeof ao_cc1200_reg[0]) + +static void ao_radio_show(void) { + uint8_t status = ao_radio_status(); + unsigned int i; + + ao_radio_get(0xff); + status = ao_radio_status(); + printf ("Status: %02x\n", status); + printf ("CHIP_RDY: %d\n", (status >> CC1200_STATUS_CHIP_RDY) & 1); + printf ("STATE: %s\n", cc1200_state_name[(status >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK]); + printf ("MARC: %02x\n", ao_radio_get_marc_status()); + + for (i = 0; i < AO_NUM_CC1200_REG; i++) + printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1200_reg[i].addr), ao_cc1200_reg[i].name); + + ao_radio_put(); +} + +static void ao_radio_beep(void) { + ao_radio_rdf(); +} + +static void ao_radio_packet(void) { + static const 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)); +} + +void +ao_radio_test_recv(void) +{ + uint8_t bytes[34]; + uint8_t b; + + if (ao_radio_recv(bytes, 34, 0)) { + if (bytes[33] & 0x80) + printf ("CRC OK"); + else + printf ("CRC BAD"); + printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32])); + for (b = 0; b < 32; b++) + printf (" %02x", bytes[b]); + printf ("\n"); + } +} + +#if HAS_APRS +#include + +static void +ao_radio_aprs(void) +{ + ao_packet_slave_stop(); + ao_aprs_send(); +} +#endif +#endif + +static void +ao_radio_strobe_test(void) +{ + uint8_t r; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + r = ao_radio_strobe(ao_cmd_lex_i); + printf ("Strobe %02x -> %02x (rdy %d state %d)\n", + ao_cmd_lex_i, + r, + r >> 7, + (r >> 4) & 0x7); +} + +static void +ao_radio_write_test(void) +{ + uint16_t addr; + uint8_t data; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + addr = ao_cmd_lex_i; + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + data = ao_cmd_lex_i; + printf ("Write %04x = %02x\n", addr, data); + ao_radio_reg_write(addr, data); +} + +static void +ao_radio_read_test(void) +{ + uint16_t addr; + uint8_t data; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + addr = ao_cmd_lex_i; + data = ao_radio_reg_read(addr); + printf ("Read %04x = %02x\n", addr, data); +} + +static const struct ao_cmds ao_radio_cmds[] = { + { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" }, +#if CC1200_DEBUG +#if HAS_APRS + { ao_radio_aprs, "G\0Send APRS packet" }, +#endif + { ao_radio_show, "R\0Show CC1200 status" }, + { ao_radio_beep, "b\0Emit an RDF beacon" }, + { ao_radio_packet, "p\0Send a test packet" }, + { ao_radio_test_recv, "q\0Recv a test packet" }, +#endif + { ao_radio_strobe_test, "S \0Strobe radio" }, + { ao_radio_write_test, "W \0Write radio reg" }, + { ao_radio_read_test, "R \0Read radio reg" }, + { 0, NULL } +}; + +void +ao_radio_init(void) +{ + ao_radio_configured = 0; + ao_spi_init_cs (AO_CC1200_SPI_CS_PORT, (1 << AO_CC1200_SPI_CS_PIN)); + +#if 0 + AO_CC1200_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1200_SPI_CS_PIN)); + for (i = 0; i < 10000; i++) { + if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0) + break; + } + AO_CC1200_SPI_CS_PORT->bsrr = (1 << AO_CC1200_SPI_CS_PIN); + if (i == 10000) + ao_panic(AO_PANIC_SELF_TEST_CC1200); +#endif + + /* Enable the EXTI interrupt for the appropriate pin */ + ao_enable_port(AO_CC1200_INT_PORT); + ao_exti_setup(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, + AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH, + ao_radio_isr); + + ao_cmd_register(&ao_radio_cmds[0]); +} -- cgit v1.2.3 From 4a3fe79266a77f8fc001117f49db1d2f14f9e6b6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 7 Oct 2014 05:34:06 +0200 Subject: altos: Complete cc1200 driver Deal with differences between cc1120 and cc1200, including built-in packet support and various register changes. This now works to send and receive telemetry, as well as send APRS and RDF. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 554 ++++++++++++++++++++++++++--------------- src/drivers/ao_cc1200.h | 129 +++++++--- src/drivers/ao_cc1200_CC1200.h | 72 +++++- 3 files changed, 499 insertions(+), 256 deletions(-) (limited to 'src/drivers/ao_cc1200.c') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index a69cdc11..39d3d522 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -21,30 +21,24 @@ #include #include -#define AO_RADIO_MAX_RECV sizeof(struct ao_packet) -#define AO_RADIO_MAX_SEND sizeof(struct ao_packet) - static uint8_t ao_radio_mutex; static uint8_t ao_radio_wake; /* radio ready. Also used as sleep address */ static uint8_t ao_radio_abort; /* radio operation should abort */ -static uint8_t ao_radio_mcu_wake; /* MARC status change */ -static uint8_t ao_radio_marc_status; /* Last read MARC status value */ -static uint8_t ao_radio_tx_finished; /* MARC status indicates TX finished */ int8_t ao_radio_rssi; /* Last received RSSI value */ -#define CC1200_DEBUG 1 -#define CC1200_TRACE 1 +#define CC1200_DEBUG 0 +#define CC1200_LOW_LEVEL_DEBUG 0 +#define CC1200_TRACE 0 +#define CC1200_APRS_TRACE 0 extern const uint32_t ao_radio_cal; -#define FOSC 32000000 +#define FOSC 40000000 -#define ao_radio_try_select(task_id) ao_spi_try_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_125kHz, task_id) #define ao_radio_select() ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_125kHz) #define ao_radio_deselect() ao_spi_put_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS) -#define ao_radio_spi_send_sync(d,l) ao_spi_send_sync((d), (l), AO_CC1200_SPI_BUS) #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1200_SPI_BUS) #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1200_SPI_BUS) #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1200_SPI_BUS) @@ -128,7 +122,6 @@ ao_radio_strobe(uint8_t addr) return in; } -#if 0 static uint8_t ao_radio_fifo_read(uint8_t *data, uint8_t len) { @@ -143,7 +136,6 @@ ao_radio_fifo_read(uint8_t *data, uint8_t len) ao_radio_deselect(); return status; } -#endif static uint8_t ao_radio_fifo_write_start(void) @@ -164,7 +156,7 @@ static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) { } static uint8_t -ao_radio_fifo_write(uint8_t *data, uint8_t len) +ao_radio_fifo_write(const uint8_t *data, uint8_t len) { uint8_t status = ao_radio_fifo_write_start(); ao_radio_spi_send(data, len); @@ -185,13 +177,11 @@ ao_radio_tx_fifo_space(void) return CC1200_FIFO_SIZE - ao_radio_reg_read(CC1200_NUM_TXBYTES); } -#if CC1200_DEBUG || CC1200_TRACE static uint8_t ao_radio_status(void) { return ao_radio_strobe (CC1200_SNOP); } -#endif void ao_radio_recv_abort(void) @@ -202,25 +192,6 @@ ao_radio_recv_abort(void) #define ao_radio_rdf_value 0x55 -static uint8_t -ao_radio_get_marc_status(void) -{ - return ao_radio_reg_read(CC1200_MARC_STATUS1); -} - -static void -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 & ~(CC1200_MARC_STATUS1_TX_FINISHED|CC1200_MARC_STATUS1_RX_FINISHED)) - ao_radio_abort = 1; - if (ao_radio_marc_status & (CC1200_MARC_STATUS1_TX_FINISHED)) - ao_radio_tx_finished = 1; -} - static void ao_radio_isr(void) { @@ -232,19 +203,27 @@ ao_radio_isr(void) static void ao_radio_start_tx(void) { - ao_exti_set_callback(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, ao_radio_isr); ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN); - ao_radio_tx_finished = 0; ao_radio_strobe(CC1200_STX); } +static void +ao_radio_start_rx(void) +{ + ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN); + ao_radio_strobe(CC1200_SRX); +} + static void ao_radio_idle(void) { for (;;) { uint8_t state = (ao_radio_strobe(CC1200_SIDLE) >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK; - if (state == CC1200_STATUS_STATE_IDLE) + if (state == CC1200_STATUS_STATE_IDLE) { + ao_radio_strobe(CC1200_SFTX); + ao_radio_strobe(CC1200_SFRX); break; + } if (state == CC1200_STATUS_STATE_TX_FIFO_ERROR) ao_radio_strobe(CC1200_SFTX); if (state == CC1200_STATUS_STATE_RX_FIFO_ERROR) @@ -257,30 +236,30 @@ ao_radio_idle(void) /* * Packet deviation * - * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * fdev = fosc >> 22 * (256 + dev_m) << dev_e * * Deviation for 38400 baud should be 20.5kHz: * - * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz + * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 3) = 20523Hz * * Deviation for 9600 baud should be 5.125kHz: * - * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 3) = 5127Hz + * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 1) = 5131Hz * * 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 + * 40e6 / (2 ** 21) * (79) = 1506Hz */ -#define PACKET_DEV_M_384 80 -#define PACKET_DEV_E_384 5 +#define PACKET_DEV_M_384 13 +#define PACKET_DEV_E_384 3 -#define PACKET_DEV_M_96 80 -#define PACKET_DEV_E_96 3 +#define PACKET_DEV_M_96 13 +#define PACKET_DEV_E_96 1 -#define PACKET_DEV_M_24 137 -#define PACKET_DEV_E_24 1 +#define PACKET_DEV_M_24 79 +#define PACKET_DEV_E_24 0 /* * For our packet data @@ -299,37 +278,37 @@ ao_radio_idle(void) * * Symbol rate 38400 Baud: * - * DATARATE_M = 239914 - * DATARATE_E = 9 - * CHANBW = 79.4 (79.4) + * DATARATE_M = 1013008 + * DATARATE_E = 8 + * CHANBW = 104.16667 * * Symbol rate 9600 Baud: * - * DATARATE_M = 239914 - * DATARATE_E = 7 - * CHANBW = 19.9 (round to 19.8) + * DATARATE_M = 1013008 + * DATARATE_E = 6 + * CHANBW = 26.042 (round to 19.8) * * Symbol rate 2400 Baud: * - * DATARATE_M = 239914 - * DATARATE_E = 5 + * DATARATE_M = 1013008 + * DATARATE_E = 4 * CHANBW = 5.0 (round to 9.5) */ -#define PACKET_SYMBOL_RATE_M 239914 +#define PACKET_SYMBOL_RATE_M 1013008 -#define PACKET_SYMBOL_RATE_E_384 9 +#define PACKET_SYMBOL_RATE_E_384 8 /* 200 / 2 = 100 */ #define PACKET_CHAN_BW_384 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_12 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \ - (21 << CC1200_CHAN_BW_BB_CIC_DECFACT)) + (16 << CC1200_CHAN_BW_BB_CIC_DECFACT)) -#define PACKET_SYMBOL_RATE_E_96 7 +#define PACKET_SYMBOL_RATE_E_96 6 /* 200 / 10 = 20 */ #define PACKET_CHAN_BW_96 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \ - (21 << CC1200_CHAN_BW_BB_CIC_DECFACT)) + (16 << CC1200_CHAN_BW_BB_CIC_DECFACT)) -#define PACKET_SYMBOL_RATE_E_24 5 +#define PACKET_SYMBOL_RATE_E_24 4 /* 200 / 25 = 8 */ #define PACKET_CHAN_BW_24 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \ (44 << CC1200_CHAN_BW_BB_CIC_DECFACT)) @@ -337,17 +316,17 @@ ao_radio_idle(void) static const uint16_t packet_setup[] = { CC1200_SYMBOL_RATE1, ((PACKET_SYMBOL_RATE_M >> 8) & 0xff), CC1200_SYMBOL_RATE0, ((PACKET_SYMBOL_RATE_M >> 0) & 0xff), - CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | - (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), - CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) | - (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | - (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | - (0 << CC1200_PKT_CFG1_APPEND_STATUS)), - CC1200_PKT_CFG0, ((0 << CC1200_PKT_CFG0_RESERVED7) | - (CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | - (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | - (0 << CC1200_PKT_CFG0_UART_MODE_EN) | - (0 << CC1200_PKT_CFG0_UART_SWAP_EN)), + CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */ + ((0 << CC1200_PKT_CFG2_FG_MODE_EN) | + (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */ + ((1 << CC1200_PKT_CFG1_FEC_EN) | + (1 << CC1200_PKT_CFG1_WHITE_DATA) | + (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) | + (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES << CC1200_PKT_CFG1_CRC_CFG) | + (1 << CC1200_PKT_CFG1_APPEND_STATUS)), CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), }; @@ -357,10 +336,14 @@ static const uint16_t packet_setup_384[] = { CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | (PACKET_DEV_E_384 << CC1200_MODCFG_DEV_E_DEV_E)), - CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_384 << CC1200_SYMBOL_RATE2_DATARATE_E) | + CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_384 << CC1200_SYMBOL_RATE2_DATARATE_E) | (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), CC1200_CHAN_BW, PACKET_CHAN_BW_384, - CC1200_PA_CFG0, 0x7b, + CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */ + ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) | + (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) | + (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) | + (0 << CC1200_MDMCFG2_CFM_DATA_EN)), }; static const uint16_t packet_setup_96[] = { @@ -368,10 +351,14 @@ static const uint16_t packet_setup_96[] = { CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | (PACKET_DEV_E_96 << CC1200_MODCFG_DEV_E_DEV_E)), - CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_96 << CC1200_SYMBOL_RATE2_DATARATE_E) | + CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_96 << CC1200_SYMBOL_RATE2_DATARATE_E) | (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), CC1200_CHAN_BW, PACKET_CHAN_BW_96, - CC1200_PA_CFG0, 0x7d, + CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */ + ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) | + (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) | + (CC1200_MDMCFG2_UPSAMPLER_P_32 << CC1200_MDMCFG2_UPSAMPLER_P) | + (0 << CC1200_MDMCFG2_CFM_DATA_EN)), }; static const uint16_t packet_setup_24[] = { @@ -379,34 +366,27 @@ static const uint16_t packet_setup_24[] = { CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | (PACKET_DEV_E_24 << CC1200_MODCFG_DEV_E_DEV_E)), - CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_24 << CC1200_SYMBOL_RATE2_DATARATE_E) | + CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_24 << CC1200_SYMBOL_RATE2_DATARATE_E) | (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), CC1200_CHAN_BW, PACKET_CHAN_BW_24, - CC1200_PA_CFG0, 0x7e, -}; - -static const uint16_t packet_tx_setup[] = { - CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | - (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), - AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_RX0TX1_CFG, -}; - -static const uint16_t packet_rx_setup[] = { - CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | - (CC1200_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1200_PKT_CFG2_PKT_FORMAT)), - AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_CLKEN_SOFT, + CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */ + ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) | + (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) | + (CC1200_MDMCFG2_UPSAMPLER_P_64 << CC1200_MDMCFG2_UPSAMPLER_P) | + (0 << CC1200_MDMCFG2_CFM_DATA_EN)), }; /* - * RDF deviation is 5kHz + * RDF deviation is 3kHz * - * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0 + * fdev = fosc >> 21 * dev_m dev_e == 0 * - * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989 + * 40e6 / (2 ** 21) * 157 = 2995Hz */ -#define RDF_DEV_E 3 -#define RDF_DEV_M 71 +#define RDF_DEV_E 0 +#define RDF_DEV_M 157 /* * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone) @@ -415,13 +395,13 @@ static const uint16_t packet_rx_setup[] = { * Rdata = -------------------------------------- * fosc * 2 ** 39 * - * DATARATE_M = 25166 - * DATARATE_E = 5 + * DATARATE_M = 669411 + * DATARATE_E = 4 * * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes */ -#define RDF_SYMBOL_RATE_E 5 -#define RDF_SYMBOL_RATE_M 25166 +#define RDF_SYMBOL_RATE_E 4 +#define RDF_SYMBOL_RATE_M 669411 #define RDF_PACKET_LEN 50 static const uint16_t rdf_setup[] = { @@ -429,36 +409,42 @@ static const uint16_t rdf_setup[] = { CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | (RDF_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)), - CC1200_SYMBOL_RATE2, ((RDF_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) | + CC1200_SYMBOL_RATE2, ((RDF_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) | (((RDF_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), - CC1200_SYMBOL_RATE1, ((RDF_SYMBOL_RATE_M >> 8) & 0xff), - CC1200_SYMBOL_RATE0, ((RDF_SYMBOL_RATE_M >> 0) & 0xff), - CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | - (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), - CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) | - (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | - (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | - (0 << CC1200_PKT_CFG1_APPEND_STATUS)), - CC1200_PKT_CFG0, ((0 << CC1200_PKT_CFG0_RESERVED7) | - (CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | - (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | - (0 << CC1200_PKT_CFG0_UART_MODE_EN) | - (0 << CC1200_PKT_CFG0_UART_SWAP_EN)), - CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | - (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), - CC1200_PA_CFG0, 0x7e, + CC1200_SYMBOL_RATE1, ((RDF_SYMBOL_RATE_M >> 8) & 0xff), + CC1200_SYMBOL_RATE0, ((RDF_SYMBOL_RATE_M >> 0) & 0xff), + CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */ + ((0 << CC1200_PKT_CFG2_FG_MODE_EN) | + (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */ + ((0 << CC1200_PKT_CFG1_FEC_EN) | + (0 << CC1200_PKT_CFG1_WHITE_DATA) | + (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) | + (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | + (0 << CC1200_PKT_CFG1_APPEND_STATUS)), + CC1200_PREAMBLE_CFG1, + ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), + CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */ + ((0 << CC1200_MDMCFG2_ASK_SHAPE) | + (0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) | + (12 << CC1200_MDMCFG2_UPSAMPLER_P) | + (0 << CC1200_MDMCFG2_CFM_DATA_EN)), }; /* * APRS deviation is 3kHz * - * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0 + * fdev = fosc >> 21 * dev_m dev_e == 0 * - * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz + * 40e6 / (2 ** 21) * 157 = 2995Hz */ -#define APRS_DEV_E 2 -#define APRS_DEV_M 137 +#define APRS_DEV_E 0 +#define APRS_DEV_M 157 /* * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate) @@ -467,33 +453,48 @@ static const uint16_t rdf_setup[] = { * Rdata = -------------------------------------- * fosc * 2 ** 39 * - * DATARATE_M = 239914 - * DATARATE_E = 7 + * DATARATE_M = 1013008 + * DATARATE_E = 6 * * Rdata = 9599.998593330383301 * */ -#define APRS_SYMBOL_RATE_E 7 -#define APRS_SYMBOL_RATE_M 239914 +#define APRS_SYMBOL_RATE_E 6 +#define APRS_SYMBOL_RATE_M 1013008 static const uint16_t aprs_setup[] = { CC1200_DEVIATION_M, APRS_DEV_M, CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | (APRS_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)), - CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) | + CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) | (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), - CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff), - CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff), - CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | - (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), - CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) | - (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | - (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | - (0 << CC1200_PKT_CFG1_APPEND_STATUS)), - CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | - (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), - CC1200_PA_CFG0, 0x7d, + CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff), + CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff), + CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */ + ((0 << CC1200_PKT_CFG2_FG_MODE_EN) | + (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */ + ((0 << CC1200_PKT_CFG1_FEC_EN) | + (0 << CC1200_PKT_CFG1_WHITE_DATA) | + (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) | + (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | + (0 << CC1200_PKT_CFG1_APPEND_STATUS)), + CC1200_PKT_CFG0, /* Packet Configuration Reg. 0 */ + ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1200_PKT_CFG0_UART_MODE_EN) | + (0 << CC1200_PKT_CFG0_UART_SWAP_EN)), + CC1200_PREAMBLE_CFG1, + ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), + CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */ + ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) | + (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) | + (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) | + (0 << CC1200_MDMCFG2_CFM_DATA_EN)), }; /* @@ -521,14 +522,12 @@ static const uint16_t test_setup[] = { (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), }; -#define AO_PKT_CFG0_INFINITE ((0 << CC1200_PKT_CFG0_RESERVED7) | \ - (CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1200_PKT_CFG0_LENGTH_CONFIG) | \ +#define AO_PKT_CFG0_INFINITE ((CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1200_PKT_CFG0_LENGTH_CONFIG) | \ (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \ (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \ (0 << CC1200_PKT_CFG0_UART_SWAP_EN)) -#define AO_PKT_CFG0_FIXED ((0 << CC1200_PKT_CFG0_RESERVED7) | \ - (CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | \ +#define AO_PKT_CFG0_FIXED ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | \ (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \ (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \ (0 << CC1200_PKT_CFG0_UART_SWAP_EN)) @@ -536,10 +535,9 @@ static const uint16_t test_setup[] = { static uint16_t ao_radio_mode; #define AO_RADIO_MODE_BITS_PACKET 1 -#define AO_RADIO_MODE_BITS_PACKET_TX 2 #define AO_RADIO_MODE_BITS_TX_BUF 4 #define AO_RADIO_MODE_BITS_TX_FINISH 8 -#define AO_RADIO_MODE_BITS_PACKET_RX 16 +#define AO_RADIO_MODE_BITS_RX 16 #define AO_RADIO_MODE_BITS_RDF 32 #define AO_RADIO_MODE_BITS_APRS 64 #define AO_RADIO_MODE_BITS_TEST 128 @@ -547,14 +545,13 @@ static uint16_t ao_radio_mode; #define AO_RADIO_MODE_BITS_FIXED 512 #define AO_RADIO_MODE_NONE 0 -#define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF) -#define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH) -#define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX) -#define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH) -#define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF) -#define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF) -#define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH) -#define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF) +#define AO_RADIO_MODE_PACKET_TX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH) +#define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_RX) +#define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH) +#define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF) +#define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF) +#define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH) +#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) @@ -596,17 +593,14 @@ ao_radio_set_mode(uint16_t new_mode) } } - if (changes & AO_RADIO_MODE_BITS_PACKET_TX) - ao_radio_set_regs(packet_tx_setup); - if (changes & AO_RADIO_MODE_BITS_TX_BUF) ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_TXFIFO_THR); if (changes & AO_RADIO_MODE_BITS_TX_FINISH) - ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_RX0TX1_CFG); + ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX); - if (changes & AO_RADIO_MODE_BITS_PACKET_RX) - ao_radio_set_regs(packet_rx_setup); + if (changes & AO_RADIO_MODE_BITS_RX) + ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX); if (changes & AO_RADIO_MODE_BITS_RDF) ao_radio_set_regs(rdf_setup); @@ -635,7 +629,7 @@ static uint8_t ao_radio_configured = 0; static void ao_radio_setup(void) { -// ao_radio_strobe(CC1200_SRES); + ao_radio_strobe(CC1200_SRES); ao_radio_set_regs(radio_setup); @@ -682,6 +676,56 @@ ao_radio_get(uint8_t len) #define ao_radio_put() ao_mutex_put(&ao_radio_mutex) +static inline uint8_t +ao_radio_state(void) +{ + return (ao_radio_status() >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK; +} + +#if CC1200_DEBUG +void +ao_radio_show_state(char *where) +{ + printf("%s: state %d len %d rxbytes %d\n", + where, ao_radio_state(), + ao_radio_reg_read(CC1200_PKT_LEN), + ao_radio_reg_read(CC1200_NUM_RXBYTES)); +} +#else +#define ao_radio_show_state(where) +#endif + +/* Wait for the radio to signal an interrupt + */ +static void +ao_radio_wait_isr(uint16_t timeout) +{ + uint8_t state; + + state = ao_radio_state(); + switch (state) { + case CC1200_STATUS_STATE_IDLE: + case CC1200_STATUS_STATE_RX_FIFO_ERROR: + case CC1200_STATUS_STATE_TX_FIFO_ERROR: +#if CC1200_LOW_LEVEL_DEBUG + printf("before wait, state %d\n", state); flush(); +#endif + ao_radio_abort = 1; + return; + } + + if (timeout) + ao_alarm(timeout); + + ao_arch_block_interrupts(); + while (!ao_radio_wake && !ao_radio_abort) + if (ao_sleep(&ao_radio_wake)) + ao_radio_abort = 1; + ao_arch_release_interrupts(); + if (timeout) + ao_clear_alarm(); +} + static void ao_rdf_start(uint8_t len) { @@ -690,20 +734,13 @@ ao_rdf_start(uint8_t len) ao_radio_set_mode(AO_RADIO_MODE_RDF); ao_radio_wake = 0; - } static void -ao_rdf_run(void) +ao_radio_run(void) { ao_radio_start_tx(); - - ao_arch_block_interrupts(); - while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake) - ao_sleep(&ao_radio_wake); - ao_arch_release_interrupts(); - if (ao_radio_mcu_wake) - ao_radio_check_marc_status(); + ao_radio_wait_isr(0); if (!ao_radio_wake) ao_radio_idle(); ao_radio_put(); @@ -716,7 +753,7 @@ ao_radio_rdf(void) ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN); - ao_rdf_run(); + ao_radio_run(); } void @@ -738,7 +775,7 @@ ao_radio_continuity(uint8_t c) ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN); status = ao_radio_fifo_write_stop(status); (void) status; - ao_rdf_run(); + ao_radio_run(); } void @@ -794,29 +831,18 @@ ao_radio_test_cmd(void) } } -static void -ao_radio_wait_isr(uint16_t timeout) -{ - if (timeout) - ao_alarm(timeout); - ao_arch_block_interrupts(); - while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort) - if (ao_sleep(&ao_radio_wake)) - ao_radio_abort = 1; - ao_arch_release_interrupts(); - if (timeout) - ao_clear_alarm(); - if (ao_radio_mcu_wake) - ao_radio_check_marc_status(); -} - void ao_radio_send(const void *d, uint8_t size) { - (void) d; - (void) size; + ao_radio_get(size); + ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX); + + ao_radio_fifo_write(d, size); + + ao_radio_run(); } + #define AO_RADIO_LOTS 64 void @@ -837,6 +863,9 @@ ao_radio_send_aprs(ao_radio_fill_func fill) done = 1; cnt = -cnt; } +#if CC1200_APRS_TRACE + printf("APRS fill %d bytes done %d\n", cnt, done); +#endif total += cnt; /* At the last buffer, set the total length */ @@ -849,8 +878,11 @@ ao_radio_send_aprs(ao_radio_fill_func fill) /* Wait for some space in the fifo */ while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) { +#if CC1200_APRS_TRACE + printf("APRS space %d cnt %d\n", fifo_space, cnt); flush(); +#endif ao_radio_wake = 0; - ao_radio_wait_isr(0); + ao_radio_wait_isr(AO_MS_TO_TICKS(1000)); } if (ao_radio_abort) break; @@ -867,33 +899,130 @@ ao_radio_send_aprs(ao_radio_fill_func fill) } else ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF); + ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN); + ao_radio_fifo_write(b, this_len); b += this_len; - +#if CC1200_APRS_TRACE + printf("APRS write fifo %d space now %d\n", this_len, ao_radio_tx_fifo_space()); +#endif if (!started) { - ao_radio_start_tx(); +#if CC1200_APRS_TRACE + printf("APRS start\n"); +#endif + ao_radio_strobe(CC1200_STX); +#if CC1200_APRS_TRACE + { int t; + for (t = 0; t < 20; t++) { + uint8_t status = ao_radio_status(); + uint8_t space = ao_radio_tx_fifo_space(); + printf ("status: %02x fifo %d\n", status, space); + if ((status >> 4) == 2) + break; + ao_delay(AO_MS_TO_TICKS(0)); + } + } +#endif started = 1; - } else - ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN); + } } if (ao_radio_abort) { ao_radio_idle(); break; } - /* Wait for the transmitter to go idle */ - ao_radio_wake = 0; - ao_radio_wait_isr(0); } + /* Wait for the transmitter to go idle */ + ao_radio_wake = 0; +#if CC1200_APRS_TRACE + printf("APRS wait idle\n"); flush(); +#endif + ao_radio_wait_isr(AO_MS_TO_TICKS(1000)); +#if CC1200_APRS_TRACE + printf("APRS abort %d\n", ao_radio_abort); +#endif ao_radio_put(); } +#if 0 +static uint8_t +ao_radio_marc_state(void) +{ + return ao_radio_reg_read(CC1200_MARCSTATE); +} + +static uint8_t +ao_radio_modem_status1(void) +{ + return ao_radio_reg_read(CC1200_MODEM_STATUS1); +} + +static uint8_t +ao_radio_modem_status0(void) +{ + return ao_radio_reg_read(CC1200_MODEM_STATUS0); +} + +struct ao_radio_state { + char where[4]; + uint8_t marc_state; + uint8_t marc_status1; + uint8_t marc_status0; + uint8_t modem_status1; + uint8_t modem_status0; +}; + +static void +ao_radio_fill_state(char *where, struct ao_radio_state *s) +{ + strcpy(s->where, where); + s->marc_state = ao_radio_marc_state(); + s->marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1); + s->marc_status0 = ao_radio_reg_read(CC1200_MARC_STATUS0); + s->modem_status1 = ao_radio_modem_status1(); + s->modem_status0 = ao_radio_modem_status0(); +} + +static void +ao_radio_dump_state(struct ao_radio_state *s) +{ + printf ("%s: marc %2x marc1 %2x marc0 %2x modem1 %2x modem0 %2x\n", + s->where, s->marc_state, s->marc_status1, s->marc_status0, s->modem_status1, s->modem_status0); +} +#endif + uint8_t ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) { - (void) d; - (void) size; - (void) timeout; - return 0; + ao_radio_abort = 0; + ao_radio_wake = 0; + ao_radio_get(size - 2); + ao_radio_idle(); + ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX); + ao_radio_wake = 0; + ao_radio_start_rx(); + ao_radio_wait_isr(timeout); + if (ao_radio_wake) { + int8_t rssi; + uint8_t status; + + status = ao_radio_fifo_read(d, size); + (void) status; + rssi = ((int8_t *) d)[size - 2]; + ao_radio_rssi = rssi; + + /* Bound it to the representable range */ + if (rssi > -11) + rssi = -11; + + /* Write it back to the packet */ + ((int8_t *) d)[size-2] = AO_RADIO_FROM_RSSI(rssi); + } else { + ao_radio_idle(); + ao_radio_rssi = 0; + } + + ao_radio_put(); + return ao_radio_wake; } @@ -932,6 +1061,7 @@ static const struct ao_cc1200_reg ao_cc1200_reg[] = { { .addr = CC1200_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" }, { .addr = CC1200_IQIC, .name = "IQIC" }, { .addr = CC1200_CHAN_BW, .name = "CHAN_BW" }, + { .addr = CC1200_MDMCFG2, .name = "MDMCFG2" }, { .addr = CC1200_MDMCFG1, .name = "MDMCFG1" }, { .addr = CC1200_MDMCFG0, .name = "MDMCFG0" }, { .addr = CC1200_SYMBOL_RATE2, .name = "SYMBOL_RATE2" }, @@ -1064,8 +1194,8 @@ static const struct ao_cc1200_reg ao_cc1200_reg[] = { { .addr = CC1200_PARTNUMBER, .name = "PARTNUMBER" }, { .addr = CC1200_PARTVERSION, .name = "PARTVERSION" }, { .addr = CC1200_SERIAL_STATUS, .name = "SERIAL_STATUS" }, - { .addr = CC1200_RX_STATUS, .name = "RX_STATUS" }, - { .addr = CC1200_TX_STATUS, .name = "TX_STATUS" }, + { .addr = CC1200_MODEM_STATUS1, .name = "MODEM_STATUS1" }, + { .addr = CC1200_MODEM_STATUS0, .name = "MODEM_STATUS0" }, { .addr = CC1200_MARC_STATUS1, .name = "MARC_STATUS1" }, { .addr = CC1200_MARC_STATUS0, .name = "MARC_STATUS0" }, { .addr = CC1200_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" }, @@ -1091,11 +1221,17 @@ static const struct ao_cc1200_reg ao_cc1200_reg[] = { #define AO_NUM_CC1200_REG (sizeof ao_cc1200_reg / sizeof ao_cc1200_reg[0]) +static uint8_t +ao_radio_get_marc_status(void) +{ + return ao_radio_reg_read(CC1200_MARC_STATUS1); +} + static void ao_radio_show(void) { - uint8_t status = ao_radio_status(); + uint8_t status; unsigned int i; - ao_radio_get(0xff); + ao_mutex_get(&ao_radio_mutex); status = ao_radio_status(); printf ("Status: %02x\n", status); printf ("CHIP_RDY: %d\n", (status >> CC1200_STATUS_CHIP_RDY) & 1); @@ -1141,6 +1277,8 @@ ao_radio_test_recv(void) printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32])); for (b = 0; b < 32; b++) printf (" %02x", bytes[b]); + + printf (" RSSI %02x LQI %02x", bytes[32], bytes[33]); printf ("\n"); } } @@ -1151,12 +1289,15 @@ ao_radio_test_recv(void) static void ao_radio_aprs(void) { +#if PACKET_HAS_SLAVE ao_packet_slave_stop(); +#endif ao_aprs_send(); } #endif #endif +#if CC1200_LOW_LEVEL_DEBUG static void ao_radio_strobe_test(void) { @@ -1204,6 +1345,7 @@ ao_radio_read_test(void) data = ao_radio_reg_read(addr); printf ("Read %04x = %02x\n", addr, data); } +#endif static const struct ao_cmds ao_radio_cmds[] = { { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" }, @@ -1216,9 +1358,11 @@ static const struct ao_cmds ao_radio_cmds[] = { { ao_radio_packet, "p\0Send a test packet" }, { ao_radio_test_recv, "q\0Recv a test packet" }, #endif - { ao_radio_strobe_test, "S \0Strobe radio" }, +#if CC1200_LOW_LEVEL_DEBUG + { ao_radio_strobe_test, "A \0Strobe radio" }, { ao_radio_write_test, "W \0Write radio reg" }, - { ao_radio_read_test, "R \0Read radio reg" }, + { ao_radio_read_test, "B \0Read radio reg" }, +#endif { 0, NULL } }; diff --git a/src/drivers/ao_cc1200.h b/src/drivers/ao_cc1200.h index 987f9bda..b04775fd 100644 --- a/src/drivers/ao_cc1200.h +++ b/src/drivers/ao_cc1200.h @@ -27,7 +27,7 @@ #define CC1200_IOCFG_GPIO_INV 6 #define CC1200_IOCFG_GPIO_CFG 0 #define CC1200_IOCFG_GPIO_CFG_RXFIFO_THR 0 -#define CC1200_IOCFG_GPIO_CFG_RXFIFO_THR_PKT 1 +#define CC1200_IOCFG_GPIO_CFG_RXFIFO_THR_PKT 1 #define CC1200_IOCFG_GPIO_CFG_TXFIFO_THR 2 #define CC1200_IOCFG_GPIO_CFG_TXFIFO_THR_PKT 3 #define CC1200_IOCFG_GPIO_CFG_RXFIFO_OVERFLOW 4 @@ -101,7 +101,6 @@ #define CC1200_IOCFG_GPIO_CFG_EXT_OSC_EN 60 #define CC1200_IOCFG_GPIO_CFG_MASK 0x3f -#define CC1200_IOCFG3 0x00 #define CC1200_IOCFG2 0x01 #define CC1200_IOCFG1 0x02 #define CC1200_IOCFG0 0x03 @@ -141,21 +140,21 @@ #define CC1200_DEVIATION_M 0x0a #define CC1200_MODCFG_DEV_E 0x0b -#define CC1200_MODCFG_DEV_E_MODEM_MODE 6 +#define CC1200_MODCFG_DEV_E_MODEM_MODE 6 #define CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL 0 #define CC1200_MODCFG_DEV_E_MODEM_MODE_DSSS_REPEAT 1 #define CC1200_MODCFG_DEV_E_MODEM_MODE_DSSS_PN 2 #define CC1200_MODCFG_DEV_E_MODEM_MODE_CARRIER_SENSE 3 #define CC1200_MODCFG_DEV_E_MODEM_MODE_MASK 3 -#define CC1200_MODCFG_DEV_E_MOD_FORMAT 3 -#define CC1200_MODCFG_DEV_E_MOD_FORMAT_2_FSK 0 -#define CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK 1 -#define CC1200_MODCFG_DEV_E_MOD_FORMAT_ASK_OOK 3 -#define CC1200_MODCFG_DEV_E_MOD_FORMAT_4_FSK 4 -#define CC1200_MODCFG_DEV_E_MOD_FORMAT_4_GFSK 5 -#define CC1200_MODCFG_DEV_E_MOD_FORMAT_MASK 7 -#define CC1200_MODCFG_DEV_E_DEV_E 0 -#define CC1200_MODCFG_DEV_E_DEV_E_MASK 7 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT 3 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_2_FSK 0 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK 1 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_ASK_OOK 3 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_4_FSK 4 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_4_GFSK 5 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_MASK 7 +#define CC1200_MODCFG_DEV_E_DEV_E 0 +#define CC1200_MODCFG_DEV_E_DEV_E_MASK 7 #define CC1200_DCFILT_CFG 0x0c #define CC1200_PREAMBLE_CFG1 0x0d @@ -226,10 +225,10 @@ #define CC1200_MDMCFG0_VITERBI_EN 2 #define CC1200_SYMBOL_RATE2 0x13 -#define CC1200_SYMBOL_RATE2_DATARATE_E 4 -#define CC1200_SYMBOL_RATE2_DATARATE_E_MASK 0xf -#define CC1200_SYMBOL_RATE2_DATARATE_M_19_16 0 -#define CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK 0xf +#define CC1200_SYMBOL_RATE2_DATARATE_E 4 +#define CC1200_SYMBOL_RATE2_DATARATE_E_MASK 0xf +#define CC1200_SYMBOL_RATE2_DATARATE_M_19_16 0 +#define CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK 0xf #define CC1200_SYMBOL_RATE1 0x14 #define CC1200_SYMBOL_RATE0 0x15 @@ -338,6 +337,8 @@ #define CC1200_WOR_EVENT0_LSB 0x24 #define CC1200_RXDCM_TIME 0x25 #define CC1200_PKT_CFG2 0x26 +#define CC1200_PKT_CFG2_BYTE_SWAP_EN 6 +#define CC1200_PKT_CFG2_FG_MODE_EN 5 #define CC1200_PKT_CFG2_CCA_MODE 2 #define CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR 0 #define CC1200_PKT_CFG2_CCA_MODE_RSSI_THRESHOLD 1 @@ -353,19 +354,20 @@ #define CC1200_PKT_CFG2_PKT_FORMAT_MASK 3 #define CC1200_PKT_CFG1 0x27 +#define CC1200_PKT_CFG1_FEC_EN 7 #define CC1200_PKT_CFG1_WHITE_DATA 6 -#define CC1200_PKT_CFG1_ADDR_CHECK_CFG 4 +#define CC1200_PKT_CFG1_PN9_SWAP_EN 5 +#define CC1200_PKT_CFG1_ADDR_CHECK_CFG 3 #define CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE 0 #define CC1200_PKT_CFG1_ADDR_CHECK_CFG_CHECK 1 #define CC1200_PKT_CFG1_ADDR_CHECK_CFG_00_BROADCAST 2 #define CC1200_PKT_CFG1_ADDR_CHECK_CFG_00_FF_BROADCAST 3 #define CC1200_PKT_CFG1_ADDR_CHECK_CFG_MASK 3 -#define CC1200_PKT_CFG1_CRC_CFG 2 +#define CC1200_PKT_CFG1_CRC_CFG 1 #define CC1200_PKT_CFG1_CRC_CFG_DISABLED 0 #define CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES 1 #define CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ZEROS 2 #define CC1200_PKT_CFG1_CRC_CFG_MASK 3 -#define CC1200_PKT_CFG1_BYTE_SWAP_EN 1 #define CC1200_PKT_CFG1_APPEND_STATUS 0 #define CC1200_PKT_CFG0 0x28 @@ -382,13 +384,29 @@ #define CC1200_PKT_CFG0_UART_SWAP_EN 0 #define CC1200_RFEND_CFG1 0x29 +#define CC1200_RFEND_CFG1_RXOFF_MODE 4 +#define CC1200_RFEND_CFG1_RXOFF_MODE_IDLE 0 +#define CC1200_RFEND_CFG1_RXOFF_MODE_FSTXON 1 +#define CC1200_RFEND_CFG1_RXOFF_MODE_TX 2 +#define CC1200_RFEND_CFG1_RXOFF_MODE_RX 3 +#define CC1200_RFEND_CFG1_RX_TIME 1 +#define CC1200_RFEND_CFG1_RX_TIME_INFINITE 7 +#define CC1200_RFEND_CFG1_RX_TIME_QUAL 0 #define CC1200_RFEND_CFG0 0x2a +#define CC1200_RFEND_CFG0_CAL_END_WAKE_UP_EN 6 +#define CC1200_RFEND_CFG0_TXOFF_MODE 4 +#define CC1200_RFEND_CFG0_TXOFF_MODE_IDLE 0 +#define CC1200_RFEND_CFG0_TXOFF_MODE_FSTXON 1 +#define CC1200_RFEND_CFG0_TXOFF_MODE_TX 2 +#define CC1200_RFEND_CFG0_TXOFF_MODE_RX 3 +#define CC1200_RFEND_CFG0_TERM_ON_BAD_PACKET_EN 3 +#define CC1200_RFEND_CFG0_ANT_DIV_RX_TERM_CFG 0 #define CC1200_PA_CFG1 0x2b #define CC1200_PA_CFG0 0x2c #define CC1200_ASK_CFG 0x2d #define CC1200_PKT_LEN 0x2e -#define CC1200_EXTENDED 0x2f +#define CC1200_EXTENDED 0x2f /* Command strobes */ #define CC1200_SRES 0x30 @@ -424,10 +442,25 @@ #define CC1200_ECG_CFG (CC1200_EXTENDED_BIT | 0x04) #define CC1200_MDMCFG2 (CC1200_EXTENDED_BIT | 0x05) -# define CC1200_MDMCFG2_ASK_SHAPE 6 -# define CC1200_MDMCFG2_SYMBOL_MAP_CFG 4 -# define CC1200_MDMCFG2_UPSAMPLER_P 1 -# define CC1200_MDMCFG2_CFM_DATA_EN 0 +#define CC1200_MDMCFG2_ASK_SHAPE 6 +#define CC1200_MDMCFG2_ASK_SHAPE_8 0 +#define CC1200_MDMCFG2_ASK_SHAPE_16 1 +#define CC1200_MDMCFG2_ASK_SHAPE_32 2 +#define CC1200_MDMCFG2_ASK_SHAPE_128 3 +#define CC1200_MDMCFG2_SYMBOL_MAP_CFG 4 +#define CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 0 +#define CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_1 1 +#define CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_2 2 +#define CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_3 3 +#define CC1200_MDMCFG2_UPSAMPLER_P 1 +#define CC1200_MDMCFG2_UPSAMPLER_P_1 0 +#define CC1200_MDMCFG2_UPSAMPLER_P_2 1 +#define CC1200_MDMCFG2_UPSAMPLER_P_4 2 +#define CC1200_MDMCFG2_UPSAMPLER_P_8 3 +#define CC1200_MDMCFG2_UPSAMPLER_P_16 4 +#define CC1200_MDMCFG2_UPSAMPLER_P_32 5 +#define CC1200_MDMCFG2_UPSAMPLER_P_64 6 +#define CC1200_MDMCFG2_CFM_DATA_EN 0 #define CC1200_EXT_CTRL (CC1200_EXTENDED_BIT | 0x06) #define CC1200_RCCAL_FINE (CC1200_EXTENDED_BIT | 0x07) @@ -527,23 +560,39 @@ #define CC1200_PARTNUMBER (CC1200_EXTENDED_BIT | 0x8f) #define CC1200_PARTVERSION (CC1200_EXTENDED_BIT | 0x90) #define CC1200_SERIAL_STATUS (CC1200_EXTENDED_BIT | 0x91) -#define CC1200_RX_STATUS (CC1200_EXTENDED_BIT | 0x92) -#define CC1200_TX_STATUS (CC1200_EXTENDED_BIT | 0x93) +#define CC1200_MODEM_STATUS1 (CC1200_EXTENDED_BIT | 0x92) +#define CC1200_MODEM_STATUS1_SYNC_FOUND 7 +#define CC1200_MODEM_STATUS1_RXFIFO_FULL 6 +#define CC1200_MODEM_STATUS1_RXFIFO_THR 5 +#define CC1200_MODEM_STATUS1_RXFIFO_EMPTY 4 +#define CC1200_MODEM_STATUS1_RXFIFO_OVERFLOW 3 +#define CC1200_MODEM_STATUS1_RXFIFO_UNDERFLOW 2 +#define CC1200_MODEM_STATUS1_PQT_REACHED 1 +#define CC1200_MODEM_STATUS1_PQT_VALID 0 + +#define CC1200_MODEM_STATUS0 (CC1200_EXTENDED_BIT | 0x93) +#define CC1200_MODEM_STATUS0_FEC_RX_OVERFLOW 6 +#define CC1200_MODEM_STATUS0_SYNC_SENT 4 +#define CC1200_MODEM_STATUS0_TXFIFO_FULL 3 +#define CC1200_MODEM_STATUS0_TXFIFO_THR 2 +#define CC1200_MODEM_STATUS0_TXFIFO_OVERFLOW 1 +#define CC1200_MODEM_STATUS0_TXFIFO_UNDERFLOW 0 + #define CC1200_MARC_STATUS1 (CC1200_EXTENDED_BIT | 0x94) -# define CC1200_MARC_STATUS1_NO_FAILURE 0 -# define CC1200_MARC_STATUS1_RX_TIMEOUT 1 -# define CC1200_MARC_STATUS1_RX_TERMINATION 2 -# define CC1200_MARC_STATUS1_EWOR_SYNC_LOST 3 -# define CC1200_MARC_STATUS1_MAXIMUM_LENGTH 4 -# define CC1200_MARC_STATUS1_ADDRESS 5 -# define CC1200_MARC_STATUS1_CRC 6 -# define CC1200_MARC_STATUS1_TX_FIFO_OVERFLOW 7 -# define CC1200_MARC_STATUS1_TX_FIFO_UNDERFLOW 8 -# define CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW 9 -# define CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW 10 -# define CC1200_MARC_STATUS1_TX_ON_CCA_FAILED 11 -# define CC1200_MARC_STATUS1_TX_FINISHED 0x40 -# define CC1200_MARC_STATUS1_RX_FINISHED 0x80 +#define CC1200_MARC_STATUS1_NO_FAILURE 0 +#define CC1200_MARC_STATUS1_RX_TIMEOUT 1 +#define CC1200_MARC_STATUS1_RX_TERMINATION 2 +#define CC1200_MARC_STATUS1_EWOR_SYNC_LOST 3 +#define CC1200_MARC_STATUS1_MAXIMUM_LENGTH 4 +#define CC1200_MARC_STATUS1_ADDRESS 5 +#define CC1200_MARC_STATUS1_CRC 6 +#define CC1200_MARC_STATUS1_TX_FIFO_OVERFLOW 7 +#define CC1200_MARC_STATUS1_TX_FIFO_UNDERFLOW 8 +#define CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW 9 +#define CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW 10 +#define CC1200_MARC_STATUS1_TX_ON_CCA_FAILED 11 +#define CC1200_MARC_STATUS1_TX_FINISHED 0x40 +#define CC1200_MARC_STATUS1_RX_FINISHED 0x80 #define CC1200_MARC_STATUS0 (CC1200_EXTENDED_BIT | 0x95) #define CC1200_PA_IFAMP_TEST (CC1200_EXTENDED_BIT | 0x96) #define CC1200_FSRF_TEST (CC1200_EXTENDED_BIT | 0x97) diff --git a/src/drivers/ao_cc1200_CC1200.h b/src/drivers/ao_cc1200_CC1200.h index 670e89ef..8d5c3b2a 100644 --- a/src/drivers/ao_cc1200_CC1200.h +++ b/src/drivers/ao_cc1200_CC1200.h @@ -7,34 +7,84 @@ * ***************************************************************/ +#ifndef AO_CC1200_AGC_GAIN_ADJUST +#define AO_CC1200_AGC_GAIN_ADJUST -81 +#endif CC1200_IOCFG2, 0x06, /* GPIO2 IO Pin Configuration */ - CC1200_SYNC1, 0x6e, /* Sync Word Configuration [15:8] */ - CC1200_SYNC0, 0x4e, /* Sync Word Configuration [7:0] */ - CC1200_SYNC_CFG1, 0xea, /* Sync Word Detection Configuration Reg. 1 */ + CC1200_SYNC3, 0xD3, /* Sync Word Configuration [23:16] */ + CC1200_SYNC2, 0x91, /* Sync Word Configuration [23:16] */ + CC1200_SYNC1, 0xD3, /* Sync Word Configuration [15:8] */ + CC1200_SYNC0, 0x91, /* Sync Word Configuration [7:0] */ + CC1200_SYNC_CFG1, /* Sync Word Detection Configuration Reg. 1 */ + ((CC1200_SYNC_CFG1_SYNC_MODE_16_BITS << CC1200_SYNC_CFG1_SYNC_MODE) | + (0xc << CC1200_SYNC_CFG1_SYNC_THR)), + CC1200_SYNC_CFG0, /* Sync Word Detection Configuration Reg. 0 */ + ((1 << CC1200_SYNC_CFG0_AUTO_CLEAR) | + (0 << CC1200_SYNC_CFG0_RX_CONFIG_LIMITATION) | + (1 << CC1200_SYNC_CFG0_PQT_GATING_EN) | + (0 << CC1200_SYNC_CFG0_EXT_SYNC_DETECT) | + (CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_DISABLED << CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK)), CC1200_DEVIATION_M, 0x50, /* Frequency Deviation Configuration */ CC1200_DCFILT_CFG, 0x5d, /* Digital DC Removal Configuration */ - CC1200_PREAMBLE_CFG0, 0x8a, /* Preamble Detection Configuration Reg. 0 */ + CC1200_PREAMBLE_CFG0, /* Preamble Detection Configuration Reg. 0 */ + ((1 << CC1200_PREAMBLE_CFG0_PQT_EN) | + (CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_24 << CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT) | + (2 << CC1200_PREAMBLE_CFG0_PQT)), CC1200_IQIC, 0xcb, /* Digital Image Channel Compensation Configuration */ CC1200_CHAN_BW, 0x11, /* Channel Filter Configuration */ CC1200_MDMCFG1, 0x40, /* General Modem Parameter Configuration Reg. 1 */ CC1200_MDMCFG0, 0x05, /* General Modem Parameter Configuration Reg. 0 */ CC1200_SYMBOL_RATE2, 0x93, /* Symbol Rate Configuration Exponent and Mantissa [1.. */ - CC1200_AGC_REF, 0x37, /* AGC Reference Level Configuration */ + CC1200_AGC_REF, 0x27, /* AGC Reference Level Configuration */ CC1200_AGC_CS_THR, 0xec, /* Carrier Sense Threshold Configuration */ + CC1200_AGC_GAIN_ADJUST, /* RSSI adjustment */ + AO_CC1200_AGC_GAIN_ADJUST, CC1200_AGC_CFG1, 0x51, /* Automatic Gain Control Configuration Reg. 1 */ CC1200_AGC_CFG0, 0x87, /* Automatic Gain Control Configuration Reg. 0 */ - CC1200_FIFO_CFG, 0x00, /* FIFO Configuration */ - CC1200_FS_CFG, 0x14, /* Frequency Synthesizer Configuration */ - CC1200_PKT_CFG2, 0x20, /* Packet Configuration Reg. 2 */ - CC1200_PKT_CFG1, 0xc3, /* Packet Configuration Reg. 1 */ - CC1200_PKT_CFG0, 0x20, /* Packet Configuration Reg. 0 */ + CC1200_FIFO_CFG, 0x40, /* FIFO Configuration */ + CC1200_SETTLING_CFG, /* Frequency Synthesizer Calibration and Settling Configuration */ + ((CC1200_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON << CC1200_SETTLING_CFG_FS_AUTOCAL) | + (CC1200_SETTLING_CFG_LOCK_TIME_75_30 << CC1200_SETTLING_CFG_LOCK_TIME) | + (CC1200_SETTLING_CFG_FSREG_TIME_60 << CC1200_SETTLING_CFG_FSREG_TIME)), + CC1200_FS_CFG, /* Frequency Synthesizer Configuration */ + ((1 << CC1200_FS_CFG_LOCK_EN) | + (CC1200_FS_CFG_FSD_BANDSELECT_410_480 << CC1200_FS_CFG_FSD_BANDSELECT)), + CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */ + ((0 << CC1200_PKT_CFG2_FG_MODE_EN) | + (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */ + ((1 << CC1200_PKT_CFG1_FEC_EN) | + (1 << CC1200_PKT_CFG1_WHITE_DATA) | + (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) | + (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES << CC1200_PKT_CFG1_CRC_CFG) | + (1 << CC1200_PKT_CFG1_APPEND_STATUS)), + CC1200_PKT_CFG0, /* Packet Configuration Reg. 0 */ + ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1200_PKT_CFG0_UART_MODE_EN) | + (0 << CC1200_PKT_CFG0_UART_SWAP_EN)), + CC1200_RFEND_CFG1, /* RFEND Configuration Reg. 1 */ + ((CC1200_RFEND_CFG1_RXOFF_MODE_IDLE << CC1200_RFEND_CFG1_RXOFF_MODE) | + (CC1200_RFEND_CFG1_RX_TIME_INFINITE << CC1200_RFEND_CFG1_RX_TIME) | + (0 << CC1200_RFEND_CFG1_RX_TIME_QUAL)), + CC1200_RFEND_CFG0, /* RFEND Configuration Reg. 0 */ + ((0 << CC1200_RFEND_CFG0_CAL_END_WAKE_UP_EN) | + (CC1200_RFEND_CFG0_TXOFF_MODE_IDLE << CC1200_RFEND_CFG0_TXOFF_MODE) | + (1 << CC1200_RFEND_CFG0_TERM_ON_BAD_PACKET_EN) | + (0 << CC1200_RFEND_CFG0_ANT_DIV_RX_TERM_CFG)), CC1200_PA_CFG1, 0x3f, /* Power Amplifier Configuration Reg. 1 */ CC1200_PA_CFG0, 0x53, /* Power Amplifier Configuration Reg. 0 */ CC1200_PKT_LEN, 0xff, /* Packet Length Configuration */ CC1200_IF_MIX_CFG, 0x1c, /* IF Mix Configuration */ CC1200_FREQOFF_CFG, 0x22, /* Frequency Offset Correction Configuration */ - CC1200_MDMCFG2, 0x0c, /* General Modem Parameter Configuration Reg. 2 */ + CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */ + ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) | + (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) | + (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) | + (0 << CC1200_MDMCFG2_CFM_DATA_EN)), CC1200_FREQ2, 0x6c, /* Frequency Configuration [23:16] */ CC1200_FREQ1, 0xa3, /* Frequency Configuration [15:8] */ CC1200_FREQ0, 0x33, /* Frequency Configuration [7:0] */ -- cgit v1.2.3 From c831f1ffb378c20b7513d209d60cdd5dee9db85b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 25 Oct 2014 17:44:48 -0700 Subject: altos: Perform cc1200 calibration less often. Tweak radio params This performs calibration after every 4 operations, or when the frequency changes. This reduces the time it takes to get to receive mode. This also makes the sync and preamble qualifiers more strict to reject bad packets. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 16 +++++++++------- src/drivers/ao_cc1200_CC1200.h | 6 +++--- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'src/drivers/ao_cc1200.c') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index 39d3d522..a3c1cbd4 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -219,18 +219,18 @@ ao_radio_idle(void) { for (;;) { uint8_t state = (ao_radio_strobe(CC1200_SIDLE) >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK; - if (state == CC1200_STATUS_STATE_IDLE) { - ao_radio_strobe(CC1200_SFTX); - ao_radio_strobe(CC1200_SFRX); + if (state == CC1200_STATUS_STATE_IDLE) break; - } if (state == CC1200_STATUS_STATE_TX_FIFO_ERROR) ao_radio_strobe(CC1200_SFTX); if (state == CC1200_STATUS_STATE_RX_FIFO_ERROR) ao_radio_strobe(CC1200_SFRX); } - /* Flush any pending TX bytes */ + /* Flush any pending data in the fifos */ ao_radio_strobe(CC1200_SFTX); + ao_radio_strobe(CC1200_SFRX); + /* Make sure the RF calibration is current */ + ao_radio_strobe(CC1200_SCAL); } /* @@ -635,6 +635,8 @@ ao_radio_setup(void) ao_radio_mode = 0; + ao_radio_idle(); + ao_config_get(); ao_radio_configured = 1; @@ -666,6 +668,7 @@ ao_radio_get(uint8_t len) ao_radio_reg_write(CC1200_FREQ1, ao_config.radio_setting >> 8); ao_radio_reg_write(CC1200_FREQ0, ao_config.radio_setting); last_radio_setting = ao_config.radio_setting; + ao_radio_strobe(CC1200_SCAL); } if (ao_config.radio_rate != last_radio_rate) { ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET; @@ -994,9 +997,8 @@ uint8_t ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) { ao_radio_abort = 0; - ao_radio_wake = 0; + ao_radio_get(size - 2); - ao_radio_idle(); ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX); ao_radio_wake = 0; ao_radio_start_rx(); diff --git a/src/drivers/ao_cc1200_CC1200.h b/src/drivers/ao_cc1200_CC1200.h index ab642f70..c078c09d 100644 --- a/src/drivers/ao_cc1200_CC1200.h +++ b/src/drivers/ao_cc1200_CC1200.h @@ -34,7 +34,7 @@ CC1200_SYNC0, 0x91, /* Sync Word Configuration [7:0] */ CC1200_SYNC_CFG1, /* Sync Word Detection Configuration Reg. 1 */ ((CC1200_SYNC_CFG1_SYNC_MODE_16_BITS << CC1200_SYNC_CFG1_SYNC_MODE) | - (12 << CC1200_SYNC_CFG1_SYNC_THR)), + (11 << CC1200_SYNC_CFG1_SYNC_THR)), CC1200_SYNC_CFG0, /* Sync Word Detection Configuration Reg. 0 */ ((1 << CC1200_SYNC_CFG0_AUTO_CLEAR) | (0 << CC1200_SYNC_CFG0_RX_CONFIG_LIMITATION) | @@ -46,7 +46,7 @@ CC1200_PREAMBLE_CFG0, /* Preamble Detection Configuration Reg. 0 */ ((1 << CC1200_PREAMBLE_CFG0_PQT_EN) | (CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_11 << CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT) | - (12 << CC1200_PREAMBLE_CFG0_PQT)), + (6 << CC1200_PREAMBLE_CFG0_PQT)), CC1200_IQIC, 0xcb, /* Digital Image Channel Compensation Configuration */ CC1200_CHAN_BW, 0x11, /* Channel Filter Configuration */ CC1200_MDMCFG1, 0x40, /* General Modem Parameter Configuration Reg. 1 */ @@ -60,7 +60,7 @@ CC1200_AGC_CFG0, 0x87, /* Automatic Gain Control Configuration Reg. 0 */ CC1200_FIFO_CFG, 0x40, /* FIFO Configuration */ CC1200_SETTLING_CFG, /* Frequency Synthesizer Calibration and Settling Configuration */ - ((CC1200_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON << CC1200_SETTLING_CFG_FS_AUTOCAL) | + ((CC1200_SETTLING_CFG_FS_AUTOCAL_EVERY_4TH_TIME << CC1200_SETTLING_CFG_FS_AUTOCAL) | (CC1200_SETTLING_CFG_LOCK_TIME_75_30 << CC1200_SETTLING_CFG_LOCK_TIME) | (CC1200_SETTLING_CFG_FSREG_TIME_60 << CC1200_SETTLING_CFG_FSREG_TIME)), CC1200_FS_CFG, /* Frequency Synthesizer Configuration */ -- cgit v1.2.3 From ef00182c79bd7a56fbc5d782cb8f4aa0079bb86f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 25 Oct 2014 21:14:25 -0700 Subject: altos: Increase CC1200 SPI data rate to 8MHz This got set to 125kHz to make debugging with a logic analyzer easier and never changed back to a reasonable speed. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/drivers/ao_cc1200.c') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index a3c1cbd4..fdaa6754 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -37,7 +37,7 @@ extern const uint32_t ao_radio_cal; #define FOSC 40000000 -#define ao_radio_select() ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_125kHz) +#define ao_radio_select() ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_8MHz) #define ao_radio_deselect() ao_spi_put_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS) #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1200_SPI_BUS) #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1200_SPI_BUS) -- cgit v1.2.3 From 2f0ff9675017655846a8abc617b4dc9a3666d0b9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Nov 2014 16:01:24 -0800 Subject: altos: Use AO_SPO_SPEED_FAST for CC1200 This asks for the fastest available SPI speed, instead of fixing it to 8MHz, which may not be supported on every architecture. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/drivers/ao_cc1200.c') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index fdaa6754..8f31d2b4 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -37,7 +37,7 @@ extern const uint32_t ao_radio_cal; #define FOSC 40000000 -#define ao_radio_select() ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_8MHz) +#define ao_radio_select() ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_FAST) #define ao_radio_deselect() ao_spi_put_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS) #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1200_SPI_BUS) #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1200_SPI_BUS) -- cgit v1.2.3 From 437eba2ff27b2b7dfd0f363819b9a43ab8b28ead Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Nov 2014 20:04:47 -0800 Subject: altos: Reset interrupt flags before TX in CC1200 driver Failing to reset the flags set during interrupt leads to short-circuiting transmission and not a lot of packets going out. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/drivers/ao_cc1200.c') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index 8f31d2b4..930680b2 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -28,8 +28,14 @@ static uint8_t ao_radio_abort; /* radio operation should abort */ int8_t ao_radio_rssi; /* Last received RSSI value */ +#ifndef CC1200_DEBUG #define CC1200_DEBUG 0 +#endif + +#ifndef CC1200_LOW_LEVEL_DEBUG #define CC1200_LOW_LEVEL_DEBUG 0 +#endif + #define CC1200_TRACE 0 #define CC1200_APRS_TRACE 0 @@ -742,6 +748,8 @@ ao_rdf_start(uint8_t len) static void ao_radio_run(void) { + ao_radio_wake = 0; + ao_radio_abort = 0; ao_radio_start_tx(); ao_radio_wait_isr(0); if (!ao_radio_wake) @@ -858,6 +866,7 @@ ao_radio_send_aprs(ao_radio_fill_func fill) uint8_t started = 0; uint8_t fifo_space; + ao_radio_abort = 0; ao_radio_get(0xff); fifo_space = CC1200_FIFO_SIZE; while (!done) { -- cgit v1.2.3 From eabeb76a2a9acb624ae364c4f0f315bfc3549d98 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Nov 2014 18:31:15 -0800 Subject: altos/cc1200: Wait for packet to be placed in FIFO during receive This changes the receive code to use MCU_STATUS, waiting for MARC_STATUS1 to indicate that the packet is in the fifo before reading it out. It also fixes the receive timeout code to keep receiving if the preamble or sync have been seen when the timeout fires. This makes TeleLCO able to use short timeouts during scanning while still successfully receiving packets. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 103 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 22 deletions(-) (limited to 'src/drivers/ao_cc1200.c') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index 930680b2..93bb2c6c 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -599,14 +599,20 @@ ao_radio_set_mode(uint16_t new_mode) } } - if (changes & AO_RADIO_MODE_BITS_TX_BUF) + if (changes & AO_RADIO_MODE_BITS_TX_BUF) { ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_TXFIFO_THR); + ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH); + } - if (changes & AO_RADIO_MODE_BITS_TX_FINISH) + if (changes & AO_RADIO_MODE_BITS_TX_FINISH) { ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX); + ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH); + } - if (changes & AO_RADIO_MODE_BITS_RX) - ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX); + if (changes & AO_RADIO_MODE_BITS_RX) { + ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP); + ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH); + } if (changes & AO_RADIO_MODE_BITS_RDF) ao_radio_set_regs(rdf_setup); @@ -709,20 +715,6 @@ ao_radio_show_state(char *where) static void ao_radio_wait_isr(uint16_t timeout) { - uint8_t state; - - state = ao_radio_state(); - switch (state) { - case CC1200_STATUS_STATE_IDLE: - case CC1200_STATUS_STATE_RX_FIFO_ERROR: - case CC1200_STATUS_STATE_TX_FIFO_ERROR: -#if CC1200_LOW_LEVEL_DEBUG - printf("before wait, state %d\n", state); flush(); -#endif - ao_radio_abort = 1; - return; - } - if (timeout) ao_alarm(timeout); @@ -731,6 +723,7 @@ ao_radio_wait_isr(uint16_t timeout) if (ao_sleep(&ao_radio_wake)) ao_radio_abort = 1; ao_arch_release_interrupts(); + if (timeout) ao_clear_alarm(); } @@ -1005,14 +998,80 @@ ao_radio_dump_state(struct ao_radio_state *s) uint8_t ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) { - ao_radio_abort = 0; + uint8_t success = 0; + ao_radio_abort = 0; ao_radio_get(size - 2); ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX); ao_radio_wake = 0; ao_radio_start_rx(); - ao_radio_wait_isr(timeout); - if (ao_radio_wake) { + + while (!ao_radio_abort) { + ao_radio_wait_isr(timeout); + if (ao_radio_wake) { + uint8_t marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1); + + /* Check the receiver status to see what happened + */ + switch (marc_status1) { + case CC1200_MARC_STATUS1_RX_FINISHED: + case CC1200_MARC_STATUS1_ADDRESS: + case CC1200_MARC_STATUS1_CRC: + /* Normal return, go fetch the bytes from the FIFO + * and give them back to the caller + */ + success = 1; + break; + case CC1200_MARC_STATUS1_RX_TIMEOUT: + case CC1200_MARC_STATUS1_RX_TERMINATION: + case CC1200_MARC_STATUS1_EWOR_SYNC_LOST: + case CC1200_MARC_STATUS1_MAXIMUM_LENGTH: + case CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW: + case CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW: + /* Something weird happened; reset the radio and + * return failure + */ + success = 0; + break; + default: + /* some other status; go wait for the radio to do something useful + */ + continue; + } + break; + } else { + uint8_t modem_status1 = ao_radio_reg_read(CC1200_MODEM_STATUS1); + + /* Check to see if the packet header has been seen, in which case we'll + * want to keep waiting for the rest of the packet to appear + */ + if (modem_status1 & ((1 << CC1200_MODEM_STATUS1_SYNC_FOUND) | + (1 << CC1200_MODEM_STATUS1_PQT_REACHED))) + { + ao_radio_abort = 0; + + /* Set a timeout based on the packet length so that we make sure to + * wait long enough to receive the whole thing. + * + * timeout = bits * FEC expansion / rate + */ + switch (ao_config.radio_rate) { + default: + case AO_RADIO_RATE_38400: + timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 384) + 1; + break; + case AO_RADIO_RATE_9600: + timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 96) + 1; + break; + case AO_RADIO_RATE_2400: + timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 24) + 1; + break; + } + } + } + } + + if (success) { int8_t rssi; uint8_t status; @@ -1033,7 +1092,7 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) } ao_radio_put(); - return ao_radio_wake; + return success; } -- cgit v1.2.3 From b6462ca3a7e99fe390ec97f94c23d36fab8c294d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Nov 2014 18:56:40 -0800 Subject: altos/cc1200: With PQT wide open, we can't use PQT_REACHED for start Because we're allowing even signals only weakly correlated with the preamble through to sync detection, we can't use the PQT_REACHED symbol to tell when a packet header has been seen. Instead, just look for SYNC_FOUND. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/drivers/ao_cc1200.c') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index 93bb2c6c..8546900e 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -1045,8 +1045,7 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) /* Check to see if the packet header has been seen, in which case we'll * want to keep waiting for the rest of the packet to appear */ - if (modem_status1 & ((1 << CC1200_MODEM_STATUS1_SYNC_FOUND) | - (1 << CC1200_MODEM_STATUS1_PQT_REACHED))) + if (modem_status1 & (1 << CC1200_MODEM_STATUS1_SYNC_FOUND)) { ao_radio_abort = 0; -- cgit v1.2.3