From 30eb5d2fa77e036690170e7057fa9df669375ae5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Jun 2016 18:40:46 -0700 Subject: altos/drivers: Use more reliable byte interface for CC1120 reception This replaces direct register access with function calls to allow that code to respect the hardware requirements. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 5b814667..eb7d872b 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -44,7 +44,10 @@ extern const uint32_t ao_radio_cal; #define ao_radio_try_select(task_id) ao_spi_try_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz, task_id) #define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz) #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS) -#define ao_radio_spi_send_sync(d,l) ao_spi_send_sync((d), (l), AO_CC1120_SPI_BUS) +#define ao_radio_spi_start_bytes() ao_spi_start_bytes(AO_CC1120_SPI_BUS) +#define ao_radio_spi_stop_bytes() ao_spi_stop_bytes(AO_CC1120_SPI_BUS) +#define ao_radio_spi_send_byte(b) ao_spi_send_byte(b, AO_CC1120_SPI_BUS) +#define ao_radio_spi_recv_byte() ao_spi_recv_byte(AO_CC1120_SPI_BUS) #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS) #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS) #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS) @@ -111,28 +114,23 @@ ao_radio_reg_write(uint16_t addr, uint8_t value) static void _ao_radio_burst_read_start (uint16_t addr) { - uint8_t data[2]; - uint8_t d; + ao_radio_spi_start_bytes(); if (CC1120_IS_EXTENDED(addr)) { - data[0] = ((1 << CC1120_READ) | - (1 << CC1120_BURST) | - CC1120_EXTENDED); - data[1] = addr; - d = 2; + ao_radio_spi_send_byte((1 << CC1120_READ) | + (1 << CC1120_BURST) | + CC1120_EXTENDED); } else { - data[0] = ((1 << CC1120_READ) | - (1 << CC1120_BURST) | - addr); - d = 1; + addr |= ((1 << CC1120_READ) | + (1 << CC1120_BURST)); } - - ao_radio_spi_send_sync(data, d); + ao_radio_spi_send_byte(addr); } static void ao_radio_burst_read_stop (void) { + ao_radio_spi_stop_bytes(); ao_radio_deselect(); } @@ -1029,8 +1027,7 @@ ao_radio_rx_isr(void) rx_starting = 0; ao_wakeup(&ao_radio_wake); } - d = AO_CC1120_SPI.dr; - AO_CC1120_SPI.dr = 0; + d = ao_radio_spi_recv_byte(); if (rx_ignore == 0) { if (rx_data_cur < rx_data_count) rx_data[rx_data_cur++] = d; @@ -1099,7 +1096,7 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) rx_data_count = len * 8; /* bytes to bits */ rx_data_cur = 0; rx_data_consumed = 0; - rx_ignore = 2; + rx_ignore = 1; /* Must be set before changing the frequency; any abort * after the frequency is set needs to terminate the read @@ -1149,9 +1146,7 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) ao_radio_select(); _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); if (rx_ignore) { - uint8_t ignore = AO_CC1120_SPI.dr; - (void) ignore; - AO_CC1120_SPI.dr = 0; + (void) ao_radio_spi_recv_byte(); --rx_ignore; } } -- cgit v1.2.3 From 3b3a24f5f39a1b72cc8947c33b609f454b46aff8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 29 Jun 2016 12:49:16 -0700 Subject: altos: cc1200: use FIFO threshold pin output for APRS buffering Instead of polling the device for fifo space, just use the available pin configuration to figure out if there is enough space for a single APRS buffer. Then set the APRS buffer size to match the fifo threshold setting in the chip so that we know we can write the whole APRS buffer once the pin says there's space. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 105 ++++++++++++++---------------------------------- 1 file changed, 31 insertions(+), 74 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index 6bccb188..cd85f208 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -185,9 +185,9 @@ ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) } static uint8_t -ao_radio_tx_fifo_space(void) +ao_radio_int_pin(void) { - return CC1200_FIFO_SIZE - ao_radio_reg_read(CC1200_NUM_TXBYTES); + return ao_gpio_get(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_CC1200_INT); } static uint8_t @@ -482,6 +482,7 @@ static const uint16_t rdf_setup[] = { */ #define APRS_SYMBOL_RATE_E 6 #define APRS_SYMBOL_RATE_M 1013008 +#define APRS_BUFFER_SIZE 64 static const uint16_t aprs_setup[] = { CC1200_DEVIATION_M, APRS_DEV_M, @@ -516,6 +517,9 @@ static const uint16_t aprs_setup[] = { (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_FIFO_CFG, + ((0 << CC1200_FIFO_CFG_CRC_AUTOFLUSH) | + (APRS_BUFFER_SIZE << CC1200_FIFO_CFG_FIFO_THR)), }; /* @@ -861,105 +865,58 @@ ao_radio_send(const void *d, uint8_t size) ao_radio_run(); } - -#define AO_RADIO_LOTS 64 - void ao_radio_send_aprs(ao_radio_fill_func fill) { - uint8_t buf[AO_RADIO_LOTS], *b; + uint8_t buf[APRS_BUFFER_SIZE]; int cnt; int total = 0; uint8_t done = 0; uint8_t started = 0; - uint8_t fifo_space; ao_radio_abort = 0; ao_radio_get(0xff); - fifo_space = CC1200_FIFO_SIZE; - while (!done) { + ao_radio_wake = 0; + while (!done && !ao_radio_abort) { cnt = (*fill)(buf, sizeof(buf)); if (cnt < 0) { 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 */ 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) { -#if CC1200_APRS_TRACE - printf("APRS space %d cnt %d\n", fifo_space, cnt); flush(); -#endif - ao_radio_wake = 0; - ao_radio_wait_isr(AO_MS_TO_TICKS(1000)); - } - 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); - + /* Wait for some space in the fifo */ + while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) { + ao_radio_wake = 0; 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) { -#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; - } + ao_radio_wait_isr(AO_MS_TO_TICKS(1000)); } - if (ao_radio_abort) { - ao_radio_idle(); + if (ao_radio_abort) break; + + if (done) + ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH); + else + ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF); + + ao_radio_fifo_write(buf, cnt); + if (!started) { + ao_radio_strobe(CC1200_STX); + started = 1; } } /* 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 + while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) { + ao_radio_wake = 0; + ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN); + ao_radio_wait_isr(AO_MS_TO_TICKS(1000)); + } + if (ao_radio_abort) + ao_radio_idle(); ao_radio_put(); } -- cgit v1.2.3 From a04830a636a71808ea8ef5ac5dfa59d6978d9f3b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 29 Jun 2016 18:41:24 -0700 Subject: altos: Use FIFO_THR pin for cc1120 transmit buffering Instead of reading NUM_TXBYTES, set the FIFO_THR pin to indicate when 64 bytes are available in the buffer. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 138 ++++++++++++++++++++++-------------------------- 1 file changed, 64 insertions(+), 74 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index eb7d872b..6b800585 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -204,9 +204,9 @@ ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) } static uint8_t -ao_radio_tx_fifo_space(void) +ao_radio_int_pin(void) { - return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES); + return ao_gpio_get(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_CC1120_INT); } #if CC1120_DEBUG @@ -262,11 +262,16 @@ ao_radio_isr(void) } static void -ao_radio_start_tx(void) +ao_radio_enable_isr(void) { - ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr); ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN); +} + +static void +ao_radio_start_tx(void) +{ + ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr); ao_radio_tx_finished = 0; ao_radio_strobe(CC1120_STX); } @@ -422,10 +427,13 @@ static const uint16_t packet_setup_24[] = { CC1120_PA_CFG0, 0x7e, }; +#define AO_CC1120_TX_BUFFER 64 + static const uint16_t packet_tx_setup[] = { CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), - AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG, + CC1120_FIFO_CFG, ((0 << CC1120_FIFO_CFG_CRC_AUTOFLUSH) | + (AO_CC1120_TX_BUFFER << CC1120_FIFO_CFG_FIFO_THR)), }; static const uint16_t packet_rx_setup[] = { @@ -532,6 +540,8 @@ static const uint16_t aprs_setup[] = { CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) | (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)), CC1120_PA_CFG0, 0x7d, + CC1120_FIFO_CFG, ((0 << CC1120_FIFO_CFG_CRC_AUTOFLUSH) | + (AO_CC1120_TX_BUFFER << CC1120_FIFO_CFG_FIFO_THR)), }; /* @@ -737,8 +747,10 @@ ao_rdf_run(void) ao_radio_start_tx(); ao_arch_block_interrupts(); - while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake) + while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake) { + ao_radio_enable_isr(); ao_sleep(&ao_radio_wake); + } ao_arch_release_interrupts(); if (ao_radio_mcu_wake) ao_radio_check_marc_status(); @@ -844,18 +856,14 @@ ao_radio_wait_isr(uint16_t timeout) ao_radio_check_marc_status(); } -static uint8_t -ao_radio_wait_tx(uint8_t wait_fifo) +static void +ao_radio_wait_fifo(void) { - uint8_t fifo_space = 0; - - do { + while (ao_radio_int_pin() != 0 && !ao_radio_abort) { + ao_radio_wake = 0; + ao_radio_enable_isr(); ao_radio_wait_isr(0); - if (!wait_fifo) - return 0; - fifo_space = ao_radio_tx_fifo_space(); - } while (!fifo_space && !ao_radio_abort); - return fifo_space; + } } static uint8_t tx_data[(AO_RADIO_MAX_SEND + 4) * 2]; @@ -867,7 +875,6 @@ ao_radio_send(const void *d, uint8_t size) uint8_t encode_len; uint8_t this_len; uint8_t started = 0; - uint8_t fifo_space; encode_len = ao_fec_encode(d, size, tx_data); @@ -878,14 +885,17 @@ ao_radio_send(const void *d, uint8_t size) /* Flush any pending TX bytes */ ao_radio_strobe(CC1120_SFTX); - started = 0; - fifo_space = CC1120_FIFO_SIZE; while (encode_len) { this_len = encode_len; - ao_radio_wake = 0; - if (this_len > fifo_space) { - this_len = fifo_space; + if (started) { + ao_radio_wait_fifo(); + if (ao_radio_abort) + break; + } + + if (this_len > AO_CC1120_TX_BUFFER) { + this_len = AO_CC1120_TX_BUFFER; ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF); } else { ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH); @@ -898,35 +908,32 @@ ao_radio_send(const void *d, uint8_t size) if (!started) { ao_radio_start_tx(); started = 1; - } else { - ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - } - - fifo_space = ao_radio_wait_tx(encode_len != 0); - if (ao_radio_abort) { - ao_radio_idle(); - break; } } - while (started && !ao_radio_abort && !ao_radio_tx_finished) + while (started && !ao_radio_abort && !ao_radio_tx_finished) { + ao_radio_wake = 0; + ao_radio_enable_isr(); ao_radio_wait_isr(0); + } + if (ao_radio_abort) + ao_radio_idle(); ao_radio_put(); } -#define AO_RADIO_LOTS 64 - void ao_radio_send_aprs(ao_radio_fill_func fill) { - uint8_t buf[AO_RADIO_LOTS], *b; + uint8_t buf[AO_CC1120_TX_BUFFER]; int cnt; int total = 0; uint8_t done = 0; uint8_t started = 0; - uint8_t fifo_space; ao_radio_get(0xff); - fifo_space = CC1120_FIFO_SIZE; + + ao_radio_abort = 0; + + ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr); while (!done) { cnt = (*fill)(buf, sizeof(buf)); if (cnt < 0) { @@ -935,51 +942,34 @@ ao_radio_send_aprs(ao_radio_fill_func fill) } 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); - } + /* Wait for some space in the fifo */ + if (started) { + ao_radio_wait_fifo(); 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_CC1120_INT_PORT, AO_CC1120_INT_PIN); } - if (ao_radio_abort) { - ao_radio_idle(); - break; + + if (done) { + ao_radio_set_len(total & 0xff); + ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH); + } else + ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF); + + ao_radio_fifo_write(buf, cnt); + + if (!started) { + ao_radio_start_tx(); + started = 1; } - /* Wait for the transmitter to go idle */ + } + /* Wait for the transmitter to go idle */ + while (started && ao_radio_int_pin() != 0 && !ao_radio_abort) { ao_radio_wake = 0; + ao_radio_enable_isr(); ao_radio_wait_isr(0); } + if (ao_radio_abort) + ao_radio_idle(); ao_radio_put(); } -- cgit v1.2.3