X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fdrivers%2Fao_cc1120.c;h=b1a1377875c0d17be8c9c65185e89bbdd8b35fbc;hb=cdaa0d7b272505c49017f409b7c0b8e3240608f0;hp=3ea8b7044b4cecb25f1880f5be5a3b1bbfb066cd;hpb=f395bcaa620490954d4a42de9b4870bc12bedc91;p=fw%2Faltos diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 3ea8b704..b1a13778 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -3,7 +3,8 @@ * * 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. + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -44,7 +45,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 +115,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(); } @@ -184,9 +183,8 @@ ao_radio_fifo_write_start(void) return status; } -static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) { +static inline void ao_radio_fifo_write_stop(void) { ao_radio_deselect(); - return status; } static uint8_t @@ -194,7 +192,8 @@ 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); + ao_radio_fifo_write_stop(); + return status; } static uint8_t @@ -202,13 +201,14 @@ 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); + ao_radio_fifo_write_stop(); + return status; } 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); } #if CC1120_DEBUG @@ -264,11 +264,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); } @@ -424,10 +429,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[] = { @@ -534,6 +542,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)), }; /* @@ -739,8 +749,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(); @@ -763,11 +775,10 @@ 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(); + (void) 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) @@ -776,8 +787,7 @@ ao_radio_continuity(uint8_t c) 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_radio_fifo_write_stop(); ao_rdf_run(); } @@ -795,8 +805,7 @@ ao_radio_test_cmd(void) 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 = ao_cmd_decimal(); } mode++; if ((mode & 2) && !radio_on) { @@ -837,31 +846,23 @@ 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)) + if (ao_sleep_for(&ao_radio_wake, timeout)) ao_radio_abort = 1; ao_arch_release_interrupts(); - if (timeout) - ao_clear_alarm(); if (ao_radio_mcu_wake) 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]; @@ -873,7 +874,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); @@ -884,14 +884,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); @@ -904,35 +907,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) { @@ -941,51 +941,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(); } @@ -1014,6 +997,8 @@ ao_radio_rx_isr(void) { uint8_t d; + if (ao_radio_abort) + return; if (rx_task_id) { if (ao_radio_try_select(rx_task_id)) { ++rx_fast_start; @@ -1033,8 +1018,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; @@ -1060,19 +1044,17 @@ ao_radio_rx_isr(void) static uint16_t ao_radio_rx_wait(void) { - 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)) + if (ao_sleep_for(&ao_radio_wake, AO_MS_TO_TICKS(100))) 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; @@ -1083,7 +1065,7 @@ ao_radio_rx_wait(void) } uint8_t -ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) +ao_radio_recv(void *d, uint8_t size, uint8_t timeout) { uint8_t len; uint8_t radio_rssi = 0; @@ -1105,7 +1087,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 @@ -1125,31 +1107,28 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) 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); - rx_starting = 1; rx_task_id = ao_cur_task->task_id; + 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_strobe(CC1120_SRX); - if (timeout) - ao_alarm(timeout); ao_arch_block_interrupts(); while (rx_starting && !ao_radio_abort) { - if (ao_sleep(&ao_radio_wake)) + if (ao_sleep_for(&ao_radio_wake, timeout)) 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) { + if (rx_task_id_save == 0) + ao_radio_burst_read_stop(); ret = 0; - rx_task_id = 0; goto abort; } @@ -1158,9 +1137,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; } } @@ -1469,7 +1446,9 @@ ao_radio_test_recv(void) static void ao_radio_aprs(void) { +#if PACKET_HAS_SLAVE ao_packet_slave_stop(); +#endif ao_aprs_send(); } #endif