X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=src%2Fdrivers%2Fao_cc1120.c;h=3ea8b7044b4cecb25f1880f5be5a3b1bbfb066cd;hp=5d51fbcd518a51df934ae649849cdfe364eacb32;hb=f395bcaa620490954d4a42de9b4870bc12bedc91;hpb=e0ee2ac6bc68b73e13bf34fac3ffd4a3b79dce98 diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 5d51fbcd..3ea8b704 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -41,8 +41,10 @@ extern const uint32_t ao_radio_cal; #define FOSC 32000000 +#define ao_radio_try_select(task_id) ao_spi_try_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz, task_id) #define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz) #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS) +#define ao_radio_spi_send_sync(d,l) ao_spi_send_sync((d), (l), AO_CC1120_SPI_BUS) #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS) #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS) #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS) @@ -107,7 +109,7 @@ ao_radio_reg_write(uint16_t addr, uint8_t value) } static void -ao_radio_burst_read_start (uint16_t addr) +_ao_radio_burst_read_start (uint16_t addr) { uint8_t data[2]; uint8_t d; @@ -124,8 +126,8 @@ ao_radio_burst_read_start (uint16_t addr) addr); d = 1; } - ao_radio_select(); - ao_radio_spi_send(data, d); + + ao_radio_spi_send_sync(data, d); } static void @@ -209,7 +211,7 @@ ao_radio_tx_fifo_space(void) return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES); } -#if 0 +#if CC1120_DEBUG static uint8_t ao_radio_status(void) { @@ -275,26 +277,45 @@ static void ao_radio_idle(void) { for (;;) { - uint8_t state = ao_radio_strobe(CC1120_SIDLE); - if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE) + uint8_t state = (ao_radio_strobe(CC1120_SIDLE) >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK; + if (state == CC1120_STATUS_STATE_IDLE) break; - if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_TX_FIFO_ERROR) + if (state == CC1120_STATUS_STATE_TX_FIFO_ERROR) ao_radio_strobe(CC1120_SFTX); + if (state == CC1120_STATUS_STATE_RX_FIFO_ERROR) + ao_radio_strobe(CC1120_SFRX); } /* Flush any pending TX bytes */ ao_radio_strobe(CC1120_SFTX); } /* - * Packet deviation is 20.5kHz + * Packet deviation * * fdev = fosc >> 24 * (256 + dev_m) << dev_e * + * Deviation for 38400 baud should be 20.5kHz: + * * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz + * + * Deviation for 9600 baud should be 5.125kHz: + * + * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 3) = 5127Hz + * + * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and + * cc115l can't do that, so we'll use 1.5kHz instead: + * + * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 1) = 1499Hz */ -#define PACKET_DEV_E 5 -#define PACKET_DEV_M 80 +#define PACKET_DEV_M_384 80 +#define PACKET_DEV_E_384 5 + +#define PACKET_DEV_M_96 80 +#define PACKET_DEV_E_96 3 + +#define PACKET_DEV_M_24 137 +#define PACKET_DEV_E_24 1 /* * For our packet data @@ -303,41 +324,55 @@ ao_radio_idle(void) * 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 = 74.42 (round to 100) + * CHANBW = 79.4 (round to 100) * * Symbol rate 9600 Baud: * * DATARATE_M = 239914 * DATARATE_E = 7 - * CHANBW = 58.58 (round to 62.5) + * CHANBW = 19.9 (round to 20) * * Symbol rate 2400 Baud: * * DATARATE_M = 239914 * DATARATE_E = 5 - * CHANBW = 47.61 (round to 50) + * CHANBW = 5.0 (round to 8.0) */ #define PACKET_DRATE_M 239914 #define PACKET_DRATE_E_384 9 -#define PACKET_CHAN_BW_384 0x02 /* 200 / 2 = 100 */ + +/* 200 / 2 = 100 */ +#define PACKET_CHAN_BW_384 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \ + (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \ + (2 << CC1120_CHAN_BW_BB_CIC_DECFACT)) #define PACKET_DRATE_E_96 7 -#define PACKET_CHAN_BW_96 0x42 /* 125 / 2 = 62.5 */ +/* 200 / 10 = 20 */ +#define PACKET_CHAN_BW_96 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \ + (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \ + (10 << CC1120_CHAN_BW_BB_CIC_DECFACT)) #define PACKET_DRATE_E_24 5 -#define PACKET_CHAN_BW_24 0x04 /* 200 / 4 = 50 */ +/* 200 / 25 = 8 */ +#define PACKET_CHAN_BW_24 ((0 << CC1120_CHAN_BW_CHFILT_BYPASS) | \ + (CC1120_CHAN_BW_ADC_CIC_DECFACT_20 << CC1120_CHAN_BW_ADC_CIC_DECFACT) | \ + (25 << CC1120_CHAN_BW_BB_CIC_DECFACT)) static const uint16_t packet_setup[] = { - CC1120_DEVIATION_M, PACKET_DEV_M, - CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | - (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | - (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)), CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff), CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff), CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | @@ -357,6 +392,10 @@ static const uint16_t packet_setup[] = { }; static const uint16_t packet_setup_384[] = { + CC1120_DEVIATION_M, PACKET_DEV_M_384, + CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | + (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | + (PACKET_DEV_E_384 << CC1120_MODCFG_DEV_E_DEV_E)), CC1120_DRATE2, ((PACKET_DRATE_E_384 << CC1120_DRATE2_DATARATE_E) | (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), CC1120_CHAN_BW, PACKET_CHAN_BW_384, @@ -364,6 +403,10 @@ static const uint16_t packet_setup_384[] = { }; static const uint16_t packet_setup_96[] = { + CC1120_DEVIATION_M, PACKET_DEV_M_96, + CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | + (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | + (PACKET_DEV_E_96 << CC1120_MODCFG_DEV_E_DEV_E)), CC1120_DRATE2, ((PACKET_DRATE_E_96 << CC1120_DRATE2_DATARATE_E) | (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), CC1120_CHAN_BW, PACKET_CHAN_BW_96, @@ -371,6 +414,10 @@ static const uint16_t packet_setup_96[] = { }; static const uint16_t packet_setup_24[] = { + CC1120_DEVIATION_M, PACKET_DEV_M_24, + CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | + (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | + (PACKET_DEV_E_24 << CC1120_MODCFG_DEV_E_DEV_E)), CC1120_DRATE2, ((PACKET_DRATE_E_24 << CC1120_DRATE2_DATARATE_E) | (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), CC1120_CHAN_BW, PACKET_CHAN_BW_24, @@ -948,6 +995,11 @@ static uint16_t rx_data_consumed; static uint16_t rx_data_cur; static uint8_t rx_ignore; static uint8_t rx_waiting; +static uint8_t rx_starting; +static uint8_t rx_task_id; +static uint32_t rx_fast_start; +static uint32_t rx_slow_start; +static uint32_t rx_missed; #if AO_PROFILE static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick; @@ -962,13 +1014,34 @@ ao_radio_rx_isr(void) { uint8_t d; + if (rx_task_id) { + if (ao_radio_try_select(rx_task_id)) { + ++rx_fast_start; + rx_task_id = 0; + _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); + } else { + if (rx_ignore) + --rx_ignore; + else { + ao_radio_abort = 1; + rx_missed++; + } + return; + } + } + if (rx_starting) { + rx_starting = 0; + ao_wakeup(&ao_radio_wake); + } d = AO_CC1120_SPI.dr; AO_CC1120_SPI.dr = 0; if (rx_ignore == 0) { - if (rx_data_cur >= rx_data_count) - ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - else + if (rx_data_cur < rx_data_count) rx_data[rx_data_cur++] = d; + if (rx_data_cur >= rx_data_count) { + ao_spi_clr_cs(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN)); + ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + } if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) { #if AO_PROFILE if (!rx_packet_tick) @@ -987,24 +1060,20 @@ ao_radio_rx_isr(void) static uint16_t ao_radio_rx_wait(void) { - do { - if (ao_radio_mcu_wake) - ao_radio_check_marc_status(); - ao_alarm(AO_MS_TO_TICKS(100)); - ao_arch_block_interrupts(); - rx_waiting = 1; - while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK && - !ao_radio_abort && - !ao_radio_mcu_wake) - { - if (ao_sleep(&ao_radio_wake)) - ao_radio_abort = 1; - } - rx_waiting = 0; - ao_arch_release_interrupts(); - ao_clear_alarm(); - } while (ao_radio_mcu_wake); - if (ao_radio_abort) + ao_alarm(AO_MS_TO_TICKS(100)); + ao_arch_block_interrupts(); + rx_waiting = 1; + while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK && + !ao_radio_abort && + !ao_radio_mcu_wake) + { + if (ao_sleep(&ao_radio_wake)) + ao_radio_abort = 1; + } + rx_waiting = 0; + ao_arch_release_interrupts(); + ao_clear_alarm(); + if (ao_radio_abort || ao_radio_mcu_wake) return 0; rx_data_consumed += AO_FEC_DECODE_BLOCK; #if AO_PROFILE @@ -1044,48 +1113,67 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) */ ao_radio_abort = 0; - /* configure interrupt pin */ ao_radio_get(len); - ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX); ao_radio_wake = 0; ao_radio_mcu_wake = 0; - AO_CC1120_SPI.cr2 = 0; - - /* clear any RXNE */ - (void) AO_CC1120_SPI.dr; + ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX); - /* Have the radio signal when the preamble quality goes high */ - ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_PQT_REACHED); + /* configure interrupt pin */ + ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT); ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, - AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH); - ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_isr); + AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH); + + ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr); ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_exti_enable(AO_CC1120_MCU_WAKEUP_PORT, AO_CC1120_MCU_WAKEUP_PIN); + + rx_starting = 1; + rx_task_id = ao_cur_task->task_id; ao_radio_strobe(CC1120_SRX); - /* Wait for the preamble to appear */ - ao_radio_wait_isr(timeout); + if (timeout) + ao_alarm(timeout); + ao_arch_block_interrupts(); + while (rx_starting && !ao_radio_abort) { + if (ao_sleep(&ao_radio_wake)) + ao_radio_abort = 1; + } + uint8_t rx_task_id_save = rx_task_id; + rx_task_id = 0; + rx_starting = 0; + ao_arch_release_interrupts(); + if (timeout) + ao_clear_alarm(); + if (ao_radio_abort) { ret = 0; + rx_task_id = 0; goto abort; } - ao_radio_reg_write(AO_CC1120_INT_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT); - ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, - AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH); - - ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr); - ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - - ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); + if (rx_task_id_save) { + ++rx_slow_start; + ao_radio_select(); + _ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); + if (rx_ignore) { + uint8_t ignore = AO_CC1120_SPI.dr; + (void) ignore; + AO_CC1120_SPI.dr = 0; + --rx_ignore; + } + } ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait); ao_radio_burst_read_stop(); + if (ao_radio_mcu_wake) + ao_radio_check_marc_status(); + if (ao_radio_abort) + ret = 0; + abort: /* Convert from 'real' rssi to cc1111-style values */ @@ -1100,7 +1188,7 @@ abort: radio_rssi = AO_RADIO_FROM_RSSI (rssi); } - ao_radio_strobe(CC1120_SIDLE); + ao_radio_idle(); ao_radio_put(); @@ -1139,7 +1227,7 @@ struct ao_cc1120_reg { char *name; }; -const static struct ao_cc1120_reg ao_cc1120_reg[] = { +static const struct ao_cc1120_reg ao_cc1120_reg[] = { { .addr = CC1120_IOCFG3, .name = "IOCFG3" }, { .addr = CC1120_IOCFG2, .name = "IOCFG2" }, { .addr = CC1120_IOCFG1, .name = "IOCFG1" }, @@ -1320,7 +1408,7 @@ const static struct ao_cc1120_reg ao_cc1120_reg[] = { static void ao_radio_show(void) { uint8_t status = ao_radio_status(); - int i; + unsigned int i; ao_radio_get(0xff); status = ao_radio_status(); @@ -1331,6 +1419,10 @@ static void ao_radio_show(void) { for (i = 0; i < AO_NUM_CC1120_REG; i++) printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name); + + printf("RX fast start: %u\n", rx_fast_start); + printf("RX slow start: %u\n", rx_slow_start); + printf("RX missed: %u\n", rx_missed); ao_radio_put(); } @@ -1354,12 +1446,12 @@ static void ao_radio_packet(void) { } void -ao_radio_test_recv() +ao_radio_test_recv(void) { uint8_t bytes[34]; uint8_t b; - if (ao_radio_recv(bytes, 34)) { + if (ao_radio_recv(bytes, 34, 0)) { if (bytes[33] & 0x80) printf ("CRC OK"); else @@ -1375,13 +1467,12 @@ ao_radio_test_recv() #include static void -ao_radio_aprs() +ao_radio_aprs(void) { ao_packet_slave_stop(); ao_aprs_send(); } #endif - #endif static const struct ao_cmds ao_radio_cmds[] = {