Attempting to moved micro enhanced shockburst into a class so that functionality can be used.
Fork of nRF51822_esb by
micro_esb.c@1:5d49c7b9f405, 2018-06-15 (annotated)
- Committer:
- jblackann
- Date:
- Fri Jun 15 12:43:11 2018 +0000
- Revision:
- 1:5d49c7b9f405
- Parent:
- 0:a01a54c0dc90
Attempting to moved micro enhanced shockburst into a class so that functionality can be used.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
joshuajnoble | 0:a01a54c0dc90 | 1 | /* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved. |
joshuajnoble | 0:a01a54c0dc90 | 2 | * |
joshuajnoble | 0:a01a54c0dc90 | 3 | * The information contained herein is property of Nordic Semiconductor ASA. |
joshuajnoble | 0:a01a54c0dc90 | 4 | * Terms and conditions of usage are described in detail in NORDIC |
joshuajnoble | 0:a01a54c0dc90 | 5 | * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. |
joshuajnoble | 0:a01a54c0dc90 | 6 | * |
joshuajnoble | 0:a01a54c0dc90 | 7 | * Licensees are granted free, non-transferable use of the information. NO |
joshuajnoble | 0:a01a54c0dc90 | 8 | * WARRANTY of ANY KIND is provided. This heading must NOT be removed from |
joshuajnoble | 0:a01a54c0dc90 | 9 | * the file. |
joshuajnoble | 0:a01a54c0dc90 | 10 | * |
joshuajnoble | 0:a01a54c0dc90 | 11 | */ |
joshuajnoble | 0:a01a54c0dc90 | 12 | |
joshuajnoble | 0:a01a54c0dc90 | 13 | #include "micro_esb.h" |
joshuajnoble | 0:a01a54c0dc90 | 14 | #include "uesb_error_codes.h" |
joshuajnoble | 0:a01a54c0dc90 | 15 | //#include "nrf_gpio.h" |
joshuajnoble | 0:a01a54c0dc90 | 16 | #include <string.h> |
joshuajnoble | 0:a01a54c0dc90 | 17 | |
jblackann | 1:5d49c7b9f405 | 18 | /* |
joshuajnoble | 0:a01a54c0dc90 | 19 | static uesb_event_handler_t m_event_handler; |
joshuajnoble | 0:a01a54c0dc90 | 20 | |
joshuajnoble | 0:a01a54c0dc90 | 21 | // RF parameters |
joshuajnoble | 0:a01a54c0dc90 | 22 | static uesb_config_t m_config_local; |
joshuajnoble | 0:a01a54c0dc90 | 23 | |
joshuajnoble | 0:a01a54c0dc90 | 24 | // TX FIFO |
joshuajnoble | 0:a01a54c0dc90 | 25 | static uesb_payload_t m_tx_fifo_payload[UESB_CORE_TX_FIFO_SIZE]; |
joshuajnoble | 0:a01a54c0dc90 | 26 | static uesb_payload_tx_fifo_t m_tx_fifo; |
joshuajnoble | 0:a01a54c0dc90 | 27 | |
joshuajnoble | 0:a01a54c0dc90 | 28 | // RX FIFO |
joshuajnoble | 0:a01a54c0dc90 | 29 | static uesb_payload_t m_rx_fifo_payload[UESB_CORE_RX_FIFO_SIZE]; |
joshuajnoble | 0:a01a54c0dc90 | 30 | static uesb_payload_rx_fifo_t m_rx_fifo; |
joshuajnoble | 0:a01a54c0dc90 | 31 | |
joshuajnoble | 0:a01a54c0dc90 | 32 | static uint8_t m_tx_payload_buffer[UESB_CORE_MAX_PAYLOAD_LENGTH + 2]; |
joshuajnoble | 0:a01a54c0dc90 | 33 | static uint8_t m_rx_payload_buffer[UESB_CORE_MAX_PAYLOAD_LENGTH + 2]; |
joshuajnoble | 0:a01a54c0dc90 | 34 | |
joshuajnoble | 0:a01a54c0dc90 | 35 | // Run time variables |
joshuajnoble | 0:a01a54c0dc90 | 36 | static volatile uint32_t m_interrupt_flags = 0; |
joshuajnoble | 0:a01a54c0dc90 | 37 | static uint32_t m_pid = 0; |
joshuajnoble | 0:a01a54c0dc90 | 38 | static volatile uint32_t m_retransmits_remaining; |
joshuajnoble | 0:a01a54c0dc90 | 39 | static volatile uint32_t m_last_tx_attempts; |
joshuajnoble | 0:a01a54c0dc90 | 40 | static volatile uint8_t m_last_rx_packet_pid = 0xFF; |
joshuajnoble | 0:a01a54c0dc90 | 41 | static volatile uint32_t m_last_rx_packet_crc = 0xFFFFFFFF; |
joshuajnoble | 0:a01a54c0dc90 | 42 | static volatile uint32_t m_wait_for_ack_timeout_us; |
joshuajnoble | 0:a01a54c0dc90 | 43 | |
joshuajnoble | 0:a01a54c0dc90 | 44 | static uesb_payload_t *current_payload; |
joshuajnoble | 0:a01a54c0dc90 | 45 | |
joshuajnoble | 0:a01a54c0dc90 | 46 | static uesb_mainstate_t m_uesb_mainstate = UESB_STATE_UNINITIALIZED; |
joshuajnoble | 0:a01a54c0dc90 | 47 | |
joshuajnoble | 0:a01a54c0dc90 | 48 | // Constant parameters |
joshuajnoble | 0:a01a54c0dc90 | 49 | #define RX_WAIT_FOR_ACK_TIMEOUT_US_2MBPS 48 // Smallest reliable value - 43 |
joshuajnoble | 0:a01a54c0dc90 | 50 | #define RX_WAIT_FOR_ACK_TIMEOUT_US_1MBPS 64 // Smallest reliable value - 59 |
joshuajnoble | 0:a01a54c0dc90 | 51 | #define RX_WAIT_FOR_ACK_TIMEOUT_US_250KBPS 250 |
joshuajnoble | 0:a01a54c0dc90 | 52 | |
joshuajnoble | 0:a01a54c0dc90 | 53 | // Macros |
joshuajnoble | 0:a01a54c0dc90 | 54 | #define DISABLE_RF_IRQ NVIC_DisableIRQ(RADIO_IRQn) |
joshuajnoble | 0:a01a54c0dc90 | 55 | #define ENABLE_RF_IRQ NVIC_EnableIRQ(RADIO_IRQn) |
joshuajnoble | 0:a01a54c0dc90 | 56 | |
joshuajnoble | 0:a01a54c0dc90 | 57 | #define RADIO_SHORTS_COMMON ( RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk | \ |
joshuajnoble | 0:a01a54c0dc90 | 58 | RADIO_SHORTS_ADDRESS_RSSISTART_Msk | RADIO_SHORTS_DISABLED_RSSISTOP_Msk ) |
joshuajnoble | 0:a01a54c0dc90 | 59 | |
joshuajnoble | 0:a01a54c0dc90 | 60 | // These function pointers are changed dynamically, depending on protocol configuration and state |
joshuajnoble | 0:a01a54c0dc90 | 61 | static void (*on_radio_disabled)(void) = 0; |
joshuajnoble | 0:a01a54c0dc90 | 62 | static void (*on_radio_end)(void) = 0; |
joshuajnoble | 0:a01a54c0dc90 | 63 | static void (*update_rf_payload_format)(uint32_t payload_length) = 0; |
joshuajnoble | 0:a01a54c0dc90 | 64 | |
joshuajnoble | 0:a01a54c0dc90 | 65 | // The following functions are assigned to the function pointers above |
joshuajnoble | 0:a01a54c0dc90 | 66 | static void on_radio_disabled_esb_dpl_tx_noack(void); |
joshuajnoble | 0:a01a54c0dc90 | 67 | static void on_radio_disabled_esb_dpl_tx(void); |
joshuajnoble | 0:a01a54c0dc90 | 68 | static void on_radio_disabled_esb_dpl_tx_wait_for_ack(void); |
joshuajnoble | 0:a01a54c0dc90 | 69 | static void on_radio_disabled_esb_dpl_rx(void); |
joshuajnoble | 0:a01a54c0dc90 | 70 | static void on_radio_disabled_esb_dpl_rx_ack(void); |
joshuajnoble | 0:a01a54c0dc90 | 71 | |
joshuajnoble | 0:a01a54c0dc90 | 72 | static void on_radio_end_sb_tx(void); |
joshuajnoble | 0:a01a54c0dc90 | 73 | static void on_radio_end_sb_rx(void); |
joshuajnoble | 0:a01a54c0dc90 | 74 | |
joshuajnoble | 0:a01a54c0dc90 | 75 | static void update_rf_payload_format_esb_dpl(uint32_t payload_length) |
joshuajnoble | 0:a01a54c0dc90 | 76 | { |
joshuajnoble | 0:a01a54c0dc90 | 77 | #if(UESB_CORE_MAX_PAYLOAD_LENGTH <= 32) |
joshuajnoble | 0:a01a54c0dc90 | 78 | NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | (6 << RADIO_PCNF0_LFLEN_Pos) | (3 << RADIO_PCNF0_S1LEN_Pos); |
joshuajnoble | 0:a01a54c0dc90 | 79 | #else |
joshuajnoble | 0:a01a54c0dc90 | 80 | NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | (8 << RADIO_PCNF0_LFLEN_Pos) | (3 << RADIO_PCNF0_S1LEN_Pos); |
joshuajnoble | 0:a01a54c0dc90 | 81 | #endif |
joshuajnoble | 0:a01a54c0dc90 | 82 | NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) | |
joshuajnoble | 0:a01a54c0dc90 | 83 | (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) | |
joshuajnoble | 0:a01a54c0dc90 | 84 | ((m_config_local.rf_addr_length - 1) << RADIO_PCNF1_BALEN_Pos) | |
joshuajnoble | 0:a01a54c0dc90 | 85 | (0 << RADIO_PCNF1_STATLEN_Pos) | |
joshuajnoble | 0:a01a54c0dc90 | 86 | (UESB_CORE_MAX_PAYLOAD_LENGTH << RADIO_PCNF1_MAXLEN_Pos); |
joshuajnoble | 0:a01a54c0dc90 | 87 | } |
joshuajnoble | 0:a01a54c0dc90 | 88 | |
joshuajnoble | 0:a01a54c0dc90 | 89 | static void update_rf_payload_format_esb(uint32_t payload_length) |
joshuajnoble | 0:a01a54c0dc90 | 90 | { |
joshuajnoble | 0:a01a54c0dc90 | 91 | NRF_RADIO->PCNF0 = (1 << RADIO_PCNF0_S0LEN_Pos) | (0 << RADIO_PCNF0_LFLEN_Pos) | (1 << RADIO_PCNF0_S1LEN_Pos); |
joshuajnoble | 0:a01a54c0dc90 | 92 | NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) | |
joshuajnoble | 0:a01a54c0dc90 | 93 | (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) | |
joshuajnoble | 0:a01a54c0dc90 | 94 | ((m_config_local.rf_addr_length - 1) << RADIO_PCNF1_BALEN_Pos) | |
joshuajnoble | 0:a01a54c0dc90 | 95 | (payload_length << RADIO_PCNF1_STATLEN_Pos) | |
joshuajnoble | 0:a01a54c0dc90 | 96 | (payload_length << RADIO_PCNF1_MAXLEN_Pos); |
joshuajnoble | 0:a01a54c0dc90 | 97 | } |
joshuajnoble | 0:a01a54c0dc90 | 98 | |
joshuajnoble | 0:a01a54c0dc90 | 99 | static void update_rf_payload_format_sb(uint32_t payload_length) |
joshuajnoble | 0:a01a54c0dc90 | 100 | { |
joshuajnoble | 0:a01a54c0dc90 | 101 | NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | (0 << RADIO_PCNF0_LFLEN_Pos) | (0 << RADIO_PCNF0_S1LEN_Pos); |
joshuajnoble | 0:a01a54c0dc90 | 102 | NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) | |
joshuajnoble | 0:a01a54c0dc90 | 103 | (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) | |
joshuajnoble | 0:a01a54c0dc90 | 104 | ((m_config_local.rf_addr_length - 1) << RADIO_PCNF1_BALEN_Pos) | |
joshuajnoble | 0:a01a54c0dc90 | 105 | (payload_length << RADIO_PCNF1_STATLEN_Pos) | |
joshuajnoble | 0:a01a54c0dc90 | 106 | (payload_length << RADIO_PCNF1_MAXLEN_Pos); |
joshuajnoble | 0:a01a54c0dc90 | 107 | } |
joshuajnoble | 0:a01a54c0dc90 | 108 | |
joshuajnoble | 0:a01a54c0dc90 | 109 | // Function that swaps the bits within each byte in a uint32. Used to convert from nRF24L type addressing to nRF51 type addressing |
joshuajnoble | 0:a01a54c0dc90 | 110 | static uint32_t bytewise_bit_swap(uint32_t inp) |
joshuajnoble | 0:a01a54c0dc90 | 111 | { |
joshuajnoble | 0:a01a54c0dc90 | 112 | inp = (inp & 0xF0F0F0F0) >> 4 | (inp & 0x0F0F0F0F) << 4; |
joshuajnoble | 0:a01a54c0dc90 | 113 | inp = (inp & 0xCCCCCCCC) >> 2 | (inp & 0x33333333) << 2; |
joshuajnoble | 0:a01a54c0dc90 | 114 | return (inp & 0xAAAAAAAA) >> 1 | (inp & 0x55555555) << 1; |
joshuajnoble | 0:a01a54c0dc90 | 115 | } |
joshuajnoble | 0:a01a54c0dc90 | 116 | |
joshuajnoble | 0:a01a54c0dc90 | 117 | static void update_radio_parameters() |
joshuajnoble | 0:a01a54c0dc90 | 118 | { |
joshuajnoble | 0:a01a54c0dc90 | 119 | // Protocol |
joshuajnoble | 0:a01a54c0dc90 | 120 | switch(m_config_local.protocol) |
joshuajnoble | 0:a01a54c0dc90 | 121 | { |
joshuajnoble | 0:a01a54c0dc90 | 122 | case UESB_PROTOCOL_ESB_DPL: |
joshuajnoble | 0:a01a54c0dc90 | 123 | update_rf_payload_format = update_rf_payload_format_esb_dpl; |
joshuajnoble | 0:a01a54c0dc90 | 124 | break; |
joshuajnoble | 0:a01a54c0dc90 | 125 | case UESB_PROTOCOL_ESB: |
joshuajnoble | 0:a01a54c0dc90 | 126 | update_rf_payload_format = update_rf_payload_format_esb; |
joshuajnoble | 0:a01a54c0dc90 | 127 | break; |
joshuajnoble | 0:a01a54c0dc90 | 128 | case UESB_PROTOCOL_SB: |
joshuajnoble | 0:a01a54c0dc90 | 129 | update_rf_payload_format = update_rf_payload_format_sb; |
joshuajnoble | 0:a01a54c0dc90 | 130 | on_radio_end = (m_config_local.mode == UESB_MODE_PTX ? on_radio_end_sb_tx : on_radio_end_sb_rx); |
joshuajnoble | 0:a01a54c0dc90 | 131 | break; |
joshuajnoble | 0:a01a54c0dc90 | 132 | } |
joshuajnoble | 0:a01a54c0dc90 | 133 | // TX power |
joshuajnoble | 0:a01a54c0dc90 | 134 | NRF_RADIO->TXPOWER = m_config_local.tx_output_power << RADIO_TXPOWER_TXPOWER_Pos; |
joshuajnoble | 0:a01a54c0dc90 | 135 | |
joshuajnoble | 0:a01a54c0dc90 | 136 | // RF bitrate |
joshuajnoble | 0:a01a54c0dc90 | 137 | NRF_RADIO->MODE = m_config_local.bitrate << RADIO_MODE_MODE_Pos; |
joshuajnoble | 0:a01a54c0dc90 | 138 | switch(m_config_local.bitrate) |
joshuajnoble | 0:a01a54c0dc90 | 139 | { |
joshuajnoble | 0:a01a54c0dc90 | 140 | case UESB_BITRATE_2MBPS: |
joshuajnoble | 0:a01a54c0dc90 | 141 | m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_2MBPS; |
joshuajnoble | 0:a01a54c0dc90 | 142 | break; |
joshuajnoble | 0:a01a54c0dc90 | 143 | case UESB_BITRATE_1MBPS: |
joshuajnoble | 0:a01a54c0dc90 | 144 | m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_1MBPS; |
joshuajnoble | 0:a01a54c0dc90 | 145 | break; |
joshuajnoble | 0:a01a54c0dc90 | 146 | case UESB_BITRATE_250KBPS: |
joshuajnoble | 0:a01a54c0dc90 | 147 | m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_250KBPS; |
joshuajnoble | 0:a01a54c0dc90 | 148 | break; |
joshuajnoble | 0:a01a54c0dc90 | 149 | } |
joshuajnoble | 0:a01a54c0dc90 | 150 | |
joshuajnoble | 0:a01a54c0dc90 | 151 | // CRC configuration |
joshuajnoble | 0:a01a54c0dc90 | 152 | NRF_RADIO->CRCCNF = m_config_local.crc << RADIO_CRCCNF_LEN_Pos; |
joshuajnoble | 0:a01a54c0dc90 | 153 | if(m_config_local.crc == RADIO_CRCCNF_LEN_Two) |
joshuajnoble | 0:a01a54c0dc90 | 154 | { |
joshuajnoble | 0:a01a54c0dc90 | 155 | NRF_RADIO->CRCINIT = 0xFFFFUL; // Initial value |
joshuajnoble | 0:a01a54c0dc90 | 156 | NRF_RADIO->CRCPOLY = 0x11021UL; // CRC poly: x^16+x^12^x^5+1 |
joshuajnoble | 0:a01a54c0dc90 | 157 | } |
joshuajnoble | 0:a01a54c0dc90 | 158 | else if(m_config_local.crc == RADIO_CRCCNF_LEN_One) |
joshuajnoble | 0:a01a54c0dc90 | 159 | { |
joshuajnoble | 0:a01a54c0dc90 | 160 | NRF_RADIO->CRCINIT = 0xFFUL; // Initial value |
joshuajnoble | 0:a01a54c0dc90 | 161 | NRF_RADIO->CRCPOLY = 0x107UL; // CRC poly: x^8+x^2^x^1+1 |
joshuajnoble | 0:a01a54c0dc90 | 162 | } |
joshuajnoble | 0:a01a54c0dc90 | 163 | |
joshuajnoble | 0:a01a54c0dc90 | 164 | // Packet format |
joshuajnoble | 0:a01a54c0dc90 | 165 | update_rf_payload_format(m_config_local.payload_length); |
joshuajnoble | 0:a01a54c0dc90 | 166 | |
joshuajnoble | 0:a01a54c0dc90 | 167 | // Radio address config |
joshuajnoble | 0:a01a54c0dc90 | 168 | NRF_RADIO->PREFIX0 = bytewise_bit_swap(m_config_local.rx_address_p3 << 24 | m_config_local.rx_address_p2 << 16 | m_config_local.rx_address_p1[0] << 8 | m_config_local.rx_address_p0[0]); |
joshuajnoble | 0:a01a54c0dc90 | 169 | NRF_RADIO->PREFIX1 = bytewise_bit_swap(m_config_local.rx_address_p7 << 24 | m_config_local.rx_address_p6 << 16 | m_config_local.rx_address_p5 << 8 | m_config_local.rx_address_p4); |
joshuajnoble | 0:a01a54c0dc90 | 170 | NRF_RADIO->BASE0 = bytewise_bit_swap(m_config_local.rx_address_p0[1] << 24 | m_config_local.rx_address_p0[2] << 16 | m_config_local.rx_address_p0[3] << 8 | m_config_local.rx_address_p0[4]); |
joshuajnoble | 0:a01a54c0dc90 | 171 | NRF_RADIO->BASE1 = bytewise_bit_swap(m_config_local.rx_address_p1[1] << 24 | m_config_local.rx_address_p1[2] << 16 | m_config_local.rx_address_p1[3] << 8 | m_config_local.rx_address_p1[4]); |
joshuajnoble | 0:a01a54c0dc90 | 172 | } |
joshuajnoble | 0:a01a54c0dc90 | 173 | |
joshuajnoble | 0:a01a54c0dc90 | 174 | static void initialize_fifos() |
joshuajnoble | 0:a01a54c0dc90 | 175 | { |
joshuajnoble | 0:a01a54c0dc90 | 176 | m_tx_fifo.entry_point = 0; |
joshuajnoble | 0:a01a54c0dc90 | 177 | m_tx_fifo.exit_point = 0; |
joshuajnoble | 0:a01a54c0dc90 | 178 | m_tx_fifo.count = 0; |
joshuajnoble | 0:a01a54c0dc90 | 179 | for(int i = 0; i < UESB_CORE_TX_FIFO_SIZE; i++) |
joshuajnoble | 0:a01a54c0dc90 | 180 | { |
joshuajnoble | 0:a01a54c0dc90 | 181 | m_tx_fifo.payload_ptr[i] = &m_tx_fifo_payload[i]; |
joshuajnoble | 0:a01a54c0dc90 | 182 | } |
joshuajnoble | 0:a01a54c0dc90 | 183 | |
joshuajnoble | 0:a01a54c0dc90 | 184 | m_rx_fifo.entry_point = 0; |
joshuajnoble | 0:a01a54c0dc90 | 185 | m_rx_fifo.exit_point = 0; |
joshuajnoble | 0:a01a54c0dc90 | 186 | m_rx_fifo.count = 0; |
joshuajnoble | 0:a01a54c0dc90 | 187 | for(int i = 0; i < UESB_CORE_RX_FIFO_SIZE; i++) |
joshuajnoble | 0:a01a54c0dc90 | 188 | { |
joshuajnoble | 0:a01a54c0dc90 | 189 | m_rx_fifo.payload_ptr[i] = &m_rx_fifo_payload[i]; |
joshuajnoble | 0:a01a54c0dc90 | 190 | } |
joshuajnoble | 0:a01a54c0dc90 | 191 | } |
joshuajnoble | 0:a01a54c0dc90 | 192 | |
joshuajnoble | 0:a01a54c0dc90 | 193 | static void tx_fifo_remove_last() |
joshuajnoble | 0:a01a54c0dc90 | 194 | { |
joshuajnoble | 0:a01a54c0dc90 | 195 | if(m_tx_fifo.count > 0) |
joshuajnoble | 0:a01a54c0dc90 | 196 | { |
joshuajnoble | 0:a01a54c0dc90 | 197 | DISABLE_RF_IRQ; |
joshuajnoble | 0:a01a54c0dc90 | 198 | m_tx_fifo.count--; |
joshuajnoble | 0:a01a54c0dc90 | 199 | m_tx_fifo.exit_point++; |
joshuajnoble | 0:a01a54c0dc90 | 200 | if(m_tx_fifo.exit_point >= UESB_CORE_TX_FIFO_SIZE) m_tx_fifo.exit_point = 0; |
joshuajnoble | 0:a01a54c0dc90 | 201 | ENABLE_RF_IRQ; |
joshuajnoble | 0:a01a54c0dc90 | 202 | } |
joshuajnoble | 0:a01a54c0dc90 | 203 | } |
joshuajnoble | 0:a01a54c0dc90 | 204 | |
joshuajnoble | 0:a01a54c0dc90 | 205 | static bool rx_fifo_push_rfbuf(uint8_t pipe) |
joshuajnoble | 0:a01a54c0dc90 | 206 | { |
joshuajnoble | 0:a01a54c0dc90 | 207 | if(m_rx_fifo.count < UESB_CORE_RX_FIFO_SIZE) |
joshuajnoble | 0:a01a54c0dc90 | 208 | { |
joshuajnoble | 0:a01a54c0dc90 | 209 | if(m_config_local.protocol == UESB_PROTOCOL_ESB_DPL) |
joshuajnoble | 0:a01a54c0dc90 | 210 | { |
joshuajnoble | 0:a01a54c0dc90 | 211 | if(m_rx_payload_buffer[0] > UESB_CORE_MAX_PAYLOAD_LENGTH) return false; |
joshuajnoble | 0:a01a54c0dc90 | 212 | m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->length = m_rx_payload_buffer[0]; |
joshuajnoble | 0:a01a54c0dc90 | 213 | } |
joshuajnoble | 0:a01a54c0dc90 | 214 | else |
joshuajnoble | 0:a01a54c0dc90 | 215 | { |
joshuajnoble | 0:a01a54c0dc90 | 216 | m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->length = m_config_local.payload_length; |
joshuajnoble | 0:a01a54c0dc90 | 217 | } |
joshuajnoble | 0:a01a54c0dc90 | 218 | if(m_config_local.protocol == UESB_PROTOCOL_SB) |
joshuajnoble | 0:a01a54c0dc90 | 219 | { |
joshuajnoble | 0:a01a54c0dc90 | 220 | memcpy(m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->data, &m_rx_payload_buffer[0], m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->length); |
joshuajnoble | 0:a01a54c0dc90 | 221 | } |
joshuajnoble | 0:a01a54c0dc90 | 222 | else |
joshuajnoble | 0:a01a54c0dc90 | 223 | { |
joshuajnoble | 0:a01a54c0dc90 | 224 | memcpy(m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->data, &m_rx_payload_buffer[2], m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->length); |
joshuajnoble | 0:a01a54c0dc90 | 225 | } |
joshuajnoble | 0:a01a54c0dc90 | 226 | m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->pipe = pipe; |
joshuajnoble | 0:a01a54c0dc90 | 227 | m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->rssi = NRF_RADIO->RSSISAMPLE; |
joshuajnoble | 0:a01a54c0dc90 | 228 | if(++m_rx_fifo.entry_point >= UESB_CORE_RX_FIFO_SIZE) m_rx_fifo.entry_point = 0; |
joshuajnoble | 0:a01a54c0dc90 | 229 | m_rx_fifo.count++; |
joshuajnoble | 0:a01a54c0dc90 | 230 | return true; |
joshuajnoble | 0:a01a54c0dc90 | 231 | } |
joshuajnoble | 0:a01a54c0dc90 | 232 | return false; |
joshuajnoble | 0:a01a54c0dc90 | 233 | } |
joshuajnoble | 0:a01a54c0dc90 | 234 | |
joshuajnoble | 0:a01a54c0dc90 | 235 | static void sys_timer_init() |
joshuajnoble | 0:a01a54c0dc90 | 236 | { |
joshuajnoble | 0:a01a54c0dc90 | 237 | // Configure the system timer with a 1 MHz base frequency |
joshuajnoble | 0:a01a54c0dc90 | 238 | UESB_SYS_TIMER->PRESCALER = 4; |
joshuajnoble | 0:a01a54c0dc90 | 239 | UESB_SYS_TIMER->BITMODE = TIMER_BITMODE_BITMODE_16Bit; |
joshuajnoble | 0:a01a54c0dc90 | 240 | UESB_SYS_TIMER->SHORTS = TIMER_SHORTS_COMPARE1_CLEAR_Msk | TIMER_SHORTS_COMPARE1_STOP_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 241 | } |
joshuajnoble | 0:a01a54c0dc90 | 242 | |
joshuajnoble | 0:a01a54c0dc90 | 243 | static void ppi_init() |
joshuajnoble | 0:a01a54c0dc90 | 244 | { |
joshuajnoble | 0:a01a54c0dc90 | 245 | NRF_PPI->CH[UESB_PPI_TIMER_START].EEP = (uint32_t)&NRF_RADIO->EVENTS_READY; |
joshuajnoble | 0:a01a54c0dc90 | 246 | NRF_PPI->CH[UESB_PPI_TIMER_START].TEP = (uint32_t)&UESB_SYS_TIMER->TASKS_START; |
joshuajnoble | 0:a01a54c0dc90 | 247 | NRF_PPI->CH[UESB_PPI_TIMER_STOP].EEP = (uint32_t)&NRF_RADIO->EVENTS_ADDRESS; |
joshuajnoble | 0:a01a54c0dc90 | 248 | NRF_PPI->CH[UESB_PPI_TIMER_STOP].TEP = (uint32_t)&UESB_SYS_TIMER->TASKS_STOP; |
joshuajnoble | 0:a01a54c0dc90 | 249 | NRF_PPI->CH[UESB_PPI_RX_TIMEOUT].EEP = (uint32_t)&UESB_SYS_TIMER->EVENTS_COMPARE[0]; |
joshuajnoble | 0:a01a54c0dc90 | 250 | NRF_PPI->CH[UESB_PPI_RX_TIMEOUT].TEP = (uint32_t)&NRF_RADIO->TASKS_DISABLE; |
joshuajnoble | 0:a01a54c0dc90 | 251 | NRF_PPI->CH[UESB_PPI_TX_START].EEP = (uint32_t)&UESB_SYS_TIMER->EVENTS_COMPARE[1]; |
joshuajnoble | 0:a01a54c0dc90 | 252 | NRF_PPI->CH[UESB_PPI_TX_START].TEP = (uint32_t)&NRF_RADIO->TASKS_TXEN; |
joshuajnoble | 0:a01a54c0dc90 | 253 | } |
joshuajnoble | 0:a01a54c0dc90 | 254 | |
joshuajnoble | 0:a01a54c0dc90 | 255 | uint32_t uesb_init(uesb_config_t *parameters) |
joshuajnoble | 0:a01a54c0dc90 | 256 | { |
joshuajnoble | 0:a01a54c0dc90 | 257 | if(m_uesb_mainstate != UESB_STATE_UNINITIALIZED) return UESB_ERROR_ALREADY_INITIALIZED; |
joshuajnoble | 0:a01a54c0dc90 | 258 | m_event_handler = parameters->event_handler; |
joshuajnoble | 0:a01a54c0dc90 | 259 | memcpy(&m_config_local, parameters, sizeof(uesb_config_t)); |
joshuajnoble | 0:a01a54c0dc90 | 260 | |
joshuajnoble | 0:a01a54c0dc90 | 261 | m_interrupt_flags = 0; |
joshuajnoble | 0:a01a54c0dc90 | 262 | m_pid = 0; |
joshuajnoble | 0:a01a54c0dc90 | 263 | m_last_rx_packet_pid = 0xFF; |
joshuajnoble | 0:a01a54c0dc90 | 264 | m_last_rx_packet_crc = 0xFFFFFFFF; |
joshuajnoble | 0:a01a54c0dc90 | 265 | |
joshuajnoble | 0:a01a54c0dc90 | 266 | update_radio_parameters(); |
joshuajnoble | 0:a01a54c0dc90 | 267 | |
joshuajnoble | 0:a01a54c0dc90 | 268 | initialize_fifos(); |
joshuajnoble | 0:a01a54c0dc90 | 269 | |
joshuajnoble | 0:a01a54c0dc90 | 270 | sys_timer_init(); |
joshuajnoble | 0:a01a54c0dc90 | 271 | |
joshuajnoble | 0:a01a54c0dc90 | 272 | ppi_init(); |
joshuajnoble | 0:a01a54c0dc90 | 273 | |
joshuajnoble | 0:a01a54c0dc90 | 274 | NVIC_SetPriority(RADIO_IRQn, m_config_local.radio_irq_priority & 0x03); |
joshuajnoble | 0:a01a54c0dc90 | 275 | |
joshuajnoble | 0:a01a54c0dc90 | 276 | //m_uesb_initialized = true; |
joshuajnoble | 0:a01a54c0dc90 | 277 | m_uesb_mainstate = UESB_STATE_IDLE; |
joshuajnoble | 0:a01a54c0dc90 | 278 | |
joshuajnoble | 0:a01a54c0dc90 | 279 | return UESB_SUCCESS; |
joshuajnoble | 0:a01a54c0dc90 | 280 | } |
joshuajnoble | 0:a01a54c0dc90 | 281 | |
joshuajnoble | 0:a01a54c0dc90 | 282 | uint32_t uesb_disable(void) |
joshuajnoble | 0:a01a54c0dc90 | 283 | { |
joshuajnoble | 0:a01a54c0dc90 | 284 | if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE; |
joshuajnoble | 0:a01a54c0dc90 | 285 | NRF_PPI->CHENCLR = (1 << UESB_PPI_TIMER_START) | (1 << UESB_PPI_TIMER_STOP) | (1 << UESB_PPI_RX_TIMEOUT) | (1 << UESB_PPI_TX_START); |
joshuajnoble | 0:a01a54c0dc90 | 286 | m_uesb_mainstate = UESB_STATE_UNINITIALIZED; |
joshuajnoble | 0:a01a54c0dc90 | 287 | return UESB_SUCCESS; |
joshuajnoble | 0:a01a54c0dc90 | 288 | } |
joshuajnoble | 0:a01a54c0dc90 | 289 | |
joshuajnoble | 0:a01a54c0dc90 | 290 | static void start_tx_transaction() |
joshuajnoble | 0:a01a54c0dc90 | 291 | { |
joshuajnoble | 0:a01a54c0dc90 | 292 | bool ack; |
joshuajnoble | 0:a01a54c0dc90 | 293 | m_last_tx_attempts = 1; |
joshuajnoble | 0:a01a54c0dc90 | 294 | // Prepare the payload |
joshuajnoble | 0:a01a54c0dc90 | 295 | current_payload = m_tx_fifo.payload_ptr[m_tx_fifo.exit_point]; |
joshuajnoble | 0:a01a54c0dc90 | 296 | m_pid = (m_pid + 1) % 4; |
joshuajnoble | 0:a01a54c0dc90 | 297 | switch(m_config_local.protocol) |
joshuajnoble | 0:a01a54c0dc90 | 298 | { |
joshuajnoble | 0:a01a54c0dc90 | 299 | case UESB_PROTOCOL_SB: |
joshuajnoble | 0:a01a54c0dc90 | 300 | update_rf_payload_format(current_payload->length); |
joshuajnoble | 0:a01a54c0dc90 | 301 | memcpy(&m_tx_payload_buffer[0], current_payload->data, current_payload->length); |
joshuajnoble | 0:a01a54c0dc90 | 302 | NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 303 | NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 304 | on_radio_disabled = on_radio_disabled_esb_dpl_tx_noack; |
joshuajnoble | 0:a01a54c0dc90 | 305 | m_uesb_mainstate = UESB_STATE_PTX_TX; |
joshuajnoble | 0:a01a54c0dc90 | 306 | break; |
joshuajnoble | 0:a01a54c0dc90 | 307 | |
joshuajnoble | 0:a01a54c0dc90 | 308 | case UESB_PROTOCOL_ESB: |
joshuajnoble | 0:a01a54c0dc90 | 309 | update_rf_payload_format(current_payload->length); |
joshuajnoble | 0:a01a54c0dc90 | 310 | m_tx_payload_buffer[0] = 0xCC | m_pid; |
joshuajnoble | 0:a01a54c0dc90 | 311 | m_tx_payload_buffer[1] = 0; |
joshuajnoble | 0:a01a54c0dc90 | 312 | memcpy(&m_tx_payload_buffer[2], current_payload->data, current_payload->length); |
joshuajnoble | 0:a01a54c0dc90 | 313 | |
joshuajnoble | 0:a01a54c0dc90 | 314 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_RXEN_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 315 | NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk | RADIO_INTENSET_READY_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 316 | |
joshuajnoble | 0:a01a54c0dc90 | 317 | // Configure the retransmit counter |
joshuajnoble | 0:a01a54c0dc90 | 318 | m_retransmits_remaining = m_config_local.retransmit_count; |
joshuajnoble | 0:a01a54c0dc90 | 319 | on_radio_disabled = on_radio_disabled_esb_dpl_tx; |
joshuajnoble | 0:a01a54c0dc90 | 320 | m_uesb_mainstate = UESB_STATE_PTX_TX_ACK; |
joshuajnoble | 0:a01a54c0dc90 | 321 | break; |
joshuajnoble | 0:a01a54c0dc90 | 322 | |
joshuajnoble | 0:a01a54c0dc90 | 323 | case UESB_PROTOCOL_ESB_DPL: |
joshuajnoble | 0:a01a54c0dc90 | 324 | ack = current_payload->noack == 0 || m_config_local.dynamic_ack_enabled == 0; |
joshuajnoble | 0:a01a54c0dc90 | 325 | m_tx_payload_buffer[0] = current_payload->length; |
joshuajnoble | 0:a01a54c0dc90 | 326 | m_tx_payload_buffer[1] = m_pid << 1 | ((current_payload->noack == 0 && m_config_local.dynamic_ack_enabled) ? 0x01 : 0x00); |
joshuajnoble | 0:a01a54c0dc90 | 327 | memcpy(&m_tx_payload_buffer[2], current_payload->data, current_payload->length); |
joshuajnoble | 0:a01a54c0dc90 | 328 | if(ack) |
joshuajnoble | 0:a01a54c0dc90 | 329 | { |
joshuajnoble | 0:a01a54c0dc90 | 330 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_RXEN_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 331 | NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk | RADIO_INTENSET_READY_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 332 | |
joshuajnoble | 0:a01a54c0dc90 | 333 | // Configure the retransmit counter |
joshuajnoble | 0:a01a54c0dc90 | 334 | m_retransmits_remaining = m_config_local.retransmit_count; |
joshuajnoble | 0:a01a54c0dc90 | 335 | on_radio_disabled = on_radio_disabled_esb_dpl_tx; |
joshuajnoble | 0:a01a54c0dc90 | 336 | m_uesb_mainstate = UESB_STATE_PTX_TX_ACK; |
joshuajnoble | 0:a01a54c0dc90 | 337 | } |
joshuajnoble | 0:a01a54c0dc90 | 338 | else |
joshuajnoble | 0:a01a54c0dc90 | 339 | { |
joshuajnoble | 0:a01a54c0dc90 | 340 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON; |
joshuajnoble | 0:a01a54c0dc90 | 341 | NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 342 | on_radio_disabled = on_radio_disabled_esb_dpl_tx_noack; |
joshuajnoble | 0:a01a54c0dc90 | 343 | m_uesb_mainstate = UESB_STATE_PTX_TX; |
joshuajnoble | 0:a01a54c0dc90 | 344 | } |
joshuajnoble | 0:a01a54c0dc90 | 345 | break; |
joshuajnoble | 0:a01a54c0dc90 | 346 | } |
joshuajnoble | 0:a01a54c0dc90 | 347 | |
joshuajnoble | 0:a01a54c0dc90 | 348 | NRF_RADIO->TXADDRESS = current_payload->pipe; |
joshuajnoble | 0:a01a54c0dc90 | 349 | NRF_RADIO->RXADDRESSES = 1 << current_payload->pipe; |
joshuajnoble | 0:a01a54c0dc90 | 350 | |
joshuajnoble | 0:a01a54c0dc90 | 351 | NRF_RADIO->FREQUENCY = m_config_local.rf_channel; |
joshuajnoble | 0:a01a54c0dc90 | 352 | |
joshuajnoble | 0:a01a54c0dc90 | 353 | NRF_RADIO->PACKETPTR = (uint32_t)m_tx_payload_buffer; |
joshuajnoble | 0:a01a54c0dc90 | 354 | |
joshuajnoble | 0:a01a54c0dc90 | 355 | NVIC_ClearPendingIRQ(RADIO_IRQn); |
joshuajnoble | 0:a01a54c0dc90 | 356 | NVIC_EnableIRQ(RADIO_IRQn); |
joshuajnoble | 0:a01a54c0dc90 | 357 | |
joshuajnoble | 0:a01a54c0dc90 | 358 | NRF_RADIO->EVENTS_ADDRESS = NRF_RADIO->EVENTS_PAYLOAD = NRF_RADIO->EVENTS_DISABLED = 0; |
joshuajnoble | 0:a01a54c0dc90 | 359 | DEBUG_PIN_SET(DEBUGPIN4); |
joshuajnoble | 0:a01a54c0dc90 | 360 | NRF_RADIO->TASKS_TXEN = 1; |
joshuajnoble | 0:a01a54c0dc90 | 361 | } |
joshuajnoble | 0:a01a54c0dc90 | 362 | |
joshuajnoble | 0:a01a54c0dc90 | 363 | static uint32_t write_tx_payload(uesb_payload_t *payload, bool noack) // ~50us @ 61 bytes SB |
joshuajnoble | 0:a01a54c0dc90 | 364 | { |
joshuajnoble | 0:a01a54c0dc90 | 365 | if(m_uesb_mainstate == UESB_STATE_UNINITIALIZED) return UESB_ERROR_NOT_INITIALIZED; |
joshuajnoble | 0:a01a54c0dc90 | 366 | if(m_tx_fifo.count >= UESB_CORE_TX_FIFO_SIZE) return UESB_ERROR_TX_FIFO_FULL; |
joshuajnoble | 0:a01a54c0dc90 | 367 | |
joshuajnoble | 0:a01a54c0dc90 | 368 | DISABLE_RF_IRQ; |
joshuajnoble | 0:a01a54c0dc90 | 369 | if(noack && m_config_local.dynamic_ack_enabled) payload->noack = 1; |
joshuajnoble | 0:a01a54c0dc90 | 370 | else payload->noack = 0; |
joshuajnoble | 0:a01a54c0dc90 | 371 | memcpy(m_tx_fifo.payload_ptr[m_tx_fifo.entry_point], payload, sizeof(uesb_payload_t)); |
joshuajnoble | 0:a01a54c0dc90 | 372 | m_tx_fifo.entry_point++; |
joshuajnoble | 0:a01a54c0dc90 | 373 | if(m_tx_fifo.entry_point >= UESB_CORE_TX_FIFO_SIZE) m_tx_fifo.entry_point = 0; |
joshuajnoble | 0:a01a54c0dc90 | 374 | m_tx_fifo.count++; |
joshuajnoble | 0:a01a54c0dc90 | 375 | ENABLE_RF_IRQ; |
joshuajnoble | 0:a01a54c0dc90 | 376 | |
joshuajnoble | 0:a01a54c0dc90 | 377 | if(m_config_local.tx_mode == UESB_TXMODE_AUTO && m_uesb_mainstate == UESB_STATE_IDLE) |
joshuajnoble | 0:a01a54c0dc90 | 378 | { |
joshuajnoble | 0:a01a54c0dc90 | 379 | start_tx_transaction(); |
joshuajnoble | 0:a01a54c0dc90 | 380 | } |
joshuajnoble | 0:a01a54c0dc90 | 381 | |
joshuajnoble | 0:a01a54c0dc90 | 382 | return UESB_SUCCESS; |
joshuajnoble | 0:a01a54c0dc90 | 383 | } |
joshuajnoble | 0:a01a54c0dc90 | 384 | |
joshuajnoble | 0:a01a54c0dc90 | 385 | uint32_t uesb_write_tx_payload(uesb_payload_t *payload) |
joshuajnoble | 0:a01a54c0dc90 | 386 | { |
joshuajnoble | 0:a01a54c0dc90 | 387 | return write_tx_payload(payload, false); |
joshuajnoble | 0:a01a54c0dc90 | 388 | } |
joshuajnoble | 0:a01a54c0dc90 | 389 | |
joshuajnoble | 0:a01a54c0dc90 | 390 | uint32_t uesb_write_tx_payload_noack(uesb_payload_t *payload) |
joshuajnoble | 0:a01a54c0dc90 | 391 | { |
joshuajnoble | 0:a01a54c0dc90 | 392 | if(m_config_local.dynamic_ack_enabled == 0) return UESB_ERROR_DYN_ACK_NOT_ENABLED; |
joshuajnoble | 0:a01a54c0dc90 | 393 | return write_tx_payload(payload, true); |
joshuajnoble | 0:a01a54c0dc90 | 394 | } |
joshuajnoble | 0:a01a54c0dc90 | 395 | |
joshuajnoble | 0:a01a54c0dc90 | 396 | uint32_t uesb_write_ack_payload(uesb_payload_t *payload) |
joshuajnoble | 0:a01a54c0dc90 | 397 | { |
joshuajnoble | 0:a01a54c0dc90 | 398 | if(m_uesb_mainstate == UESB_STATE_UNINITIALIZED) return UESB_ERROR_NOT_INITIALIZED; |
joshuajnoble | 0:a01a54c0dc90 | 399 | if((m_uesb_mainstate != UESB_STATE_PRX) && |
joshuajnoble | 0:a01a54c0dc90 | 400 | (m_uesb_mainstate != UESB_STATE_PRX_SEND_ACK) && |
joshuajnoble | 0:a01a54c0dc90 | 401 | (m_uesb_mainstate != UESB_STATE_PRX_SEND_ACK_PAYLOAD)) |
joshuajnoble | 0:a01a54c0dc90 | 402 | { |
joshuajnoble | 0:a01a54c0dc90 | 403 | return UESB_ERROR_NOT_IN_RX_MODE; |
joshuajnoble | 0:a01a54c0dc90 | 404 | } |
joshuajnoble | 0:a01a54c0dc90 | 405 | if(m_tx_fifo.count >= UESB_CORE_TX_FIFO_SIZE) return UESB_ERROR_TX_FIFO_FULL; |
joshuajnoble | 0:a01a54c0dc90 | 406 | |
joshuajnoble | 0:a01a54c0dc90 | 407 | DISABLE_RF_IRQ; |
joshuajnoble | 0:a01a54c0dc90 | 408 | memcpy(m_tx_fifo.payload_ptr[m_tx_fifo.entry_point], payload, sizeof(uesb_payload_t)); |
joshuajnoble | 0:a01a54c0dc90 | 409 | m_tx_fifo.entry_point++; |
joshuajnoble | 0:a01a54c0dc90 | 410 | if(m_tx_fifo.entry_point >= UESB_CORE_TX_FIFO_SIZE) m_tx_fifo.entry_point = 0; |
joshuajnoble | 0:a01a54c0dc90 | 411 | m_tx_fifo.count++; |
joshuajnoble | 0:a01a54c0dc90 | 412 | ENABLE_RF_IRQ; |
joshuajnoble | 0:a01a54c0dc90 | 413 | |
joshuajnoble | 0:a01a54c0dc90 | 414 | return UESB_SUCCESS; |
joshuajnoble | 0:a01a54c0dc90 | 415 | } |
joshuajnoble | 0:a01a54c0dc90 | 416 | |
joshuajnoble | 0:a01a54c0dc90 | 417 | uint32_t uesb_read_rx_payload(uesb_payload_t *payload) |
joshuajnoble | 0:a01a54c0dc90 | 418 | { |
joshuajnoble | 0:a01a54c0dc90 | 419 | if(m_uesb_mainstate == UESB_STATE_UNINITIALIZED) return UESB_ERROR_NOT_INITIALIZED; |
joshuajnoble | 0:a01a54c0dc90 | 420 | if(m_rx_fifo.count == 0) return UESB_ERROR_RX_FIFO_EMPTY; |
joshuajnoble | 0:a01a54c0dc90 | 421 | |
joshuajnoble | 0:a01a54c0dc90 | 422 | DISABLE_RF_IRQ; |
joshuajnoble | 0:a01a54c0dc90 | 423 | payload->length = m_rx_fifo.payload_ptr[m_rx_fifo.exit_point]->length; |
joshuajnoble | 0:a01a54c0dc90 | 424 | payload->pipe = m_rx_fifo.payload_ptr[m_rx_fifo.exit_point]->pipe; |
joshuajnoble | 0:a01a54c0dc90 | 425 | payload->rssi = m_rx_fifo.payload_ptr[m_rx_fifo.exit_point]->rssi; |
joshuajnoble | 0:a01a54c0dc90 | 426 | memcpy(payload->data, m_rx_fifo.payload_ptr[m_rx_fifo.exit_point]->data, payload->length); |
joshuajnoble | 0:a01a54c0dc90 | 427 | if(++m_rx_fifo.exit_point >= UESB_CORE_RX_FIFO_SIZE) m_rx_fifo.exit_point = 0; |
joshuajnoble | 0:a01a54c0dc90 | 428 | m_rx_fifo.count--; |
joshuajnoble | 0:a01a54c0dc90 | 429 | ENABLE_RF_IRQ; |
joshuajnoble | 0:a01a54c0dc90 | 430 | |
joshuajnoble | 0:a01a54c0dc90 | 431 | return UESB_SUCCESS; |
joshuajnoble | 0:a01a54c0dc90 | 432 | } |
joshuajnoble | 0:a01a54c0dc90 | 433 | |
joshuajnoble | 0:a01a54c0dc90 | 434 | uint32_t uesb_start_tx() |
joshuajnoble | 0:a01a54c0dc90 | 435 | { |
joshuajnoble | 0:a01a54c0dc90 | 436 | if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE; |
joshuajnoble | 0:a01a54c0dc90 | 437 | if(m_tx_fifo.count == 0) return UESB_ERROR_TX_FIFO_EMPTY; |
joshuajnoble | 0:a01a54c0dc90 | 438 | start_tx_transaction(); |
joshuajnoble | 0:a01a54c0dc90 | 439 | return UESB_SUCCESS; |
joshuajnoble | 0:a01a54c0dc90 | 440 | } |
joshuajnoble | 0:a01a54c0dc90 | 441 | |
joshuajnoble | 0:a01a54c0dc90 | 442 | uint32_t uesb_start_rx(void) |
joshuajnoble | 0:a01a54c0dc90 | 443 | { |
joshuajnoble | 0:a01a54c0dc90 | 444 | if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE; |
joshuajnoble | 0:a01a54c0dc90 | 445 | |
joshuajnoble | 0:a01a54c0dc90 | 446 | NRF_RADIO->INTENCLR = 0xFFFFFFFF; |
joshuajnoble | 0:a01a54c0dc90 | 447 | NRF_RADIO->EVENTS_DISABLED = 0; |
joshuajnoble | 0:a01a54c0dc90 | 448 | on_radio_disabled = on_radio_disabled_esb_dpl_rx; |
joshuajnoble | 0:a01a54c0dc90 | 449 | switch(m_config_local.protocol) |
joshuajnoble | 0:a01a54c0dc90 | 450 | { |
joshuajnoble | 0:a01a54c0dc90 | 451 | case UESB_PROTOCOL_SB: |
joshuajnoble | 0:a01a54c0dc90 | 452 | NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_START_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 453 | NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 454 | m_uesb_mainstate = UESB_STATE_PRX; |
joshuajnoble | 0:a01a54c0dc90 | 455 | break; |
joshuajnoble | 0:a01a54c0dc90 | 456 | case UESB_PROTOCOL_ESB: |
joshuajnoble | 0:a01a54c0dc90 | 457 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_TXEN_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 458 | NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 459 | m_uesb_mainstate = UESB_STATE_PRX; |
joshuajnoble | 0:a01a54c0dc90 | 460 | break; |
joshuajnoble | 0:a01a54c0dc90 | 461 | case UESB_PROTOCOL_ESB_DPL: |
joshuajnoble | 0:a01a54c0dc90 | 462 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_TXEN_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 463 | NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 464 | m_uesb_mainstate = UESB_STATE_PRX; |
joshuajnoble | 0:a01a54c0dc90 | 465 | break; |
joshuajnoble | 0:a01a54c0dc90 | 466 | } |
joshuajnoble | 0:a01a54c0dc90 | 467 | |
joshuajnoble | 0:a01a54c0dc90 | 468 | NRF_RADIO->RXADDRESSES = m_config_local.rx_pipes_enabled; |
joshuajnoble | 0:a01a54c0dc90 | 469 | |
joshuajnoble | 0:a01a54c0dc90 | 470 | NRF_RADIO->FREQUENCY = m_config_local.rf_channel; |
joshuajnoble | 0:a01a54c0dc90 | 471 | |
joshuajnoble | 0:a01a54c0dc90 | 472 | NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer; |
joshuajnoble | 0:a01a54c0dc90 | 473 | |
joshuajnoble | 0:a01a54c0dc90 | 474 | NVIC_ClearPendingIRQ(RADIO_IRQn); |
joshuajnoble | 0:a01a54c0dc90 | 475 | NVIC_EnableIRQ(RADIO_IRQn); |
joshuajnoble | 0:a01a54c0dc90 | 476 | |
joshuajnoble | 0:a01a54c0dc90 | 477 | NRF_RADIO->EVENTS_ADDRESS = NRF_RADIO->EVENTS_PAYLOAD = NRF_RADIO->EVENTS_DISABLED = 0; |
joshuajnoble | 0:a01a54c0dc90 | 478 | NRF_RADIO->TASKS_RXEN = 1; |
joshuajnoble | 0:a01a54c0dc90 | 479 | return UESB_SUCCESS; |
joshuajnoble | 0:a01a54c0dc90 | 480 | } |
joshuajnoble | 0:a01a54c0dc90 | 481 | |
joshuajnoble | 0:a01a54c0dc90 | 482 | uint32_t uesb_stop_rx(void) |
joshuajnoble | 0:a01a54c0dc90 | 483 | { |
joshuajnoble | 0:a01a54c0dc90 | 484 | if((m_uesb_mainstate == UESB_STATE_PRX) || (m_uesb_mainstate == UESB_STATE_PRX_SEND_ACK_PAYLOAD)) |
joshuajnoble | 0:a01a54c0dc90 | 485 | { |
joshuajnoble | 0:a01a54c0dc90 | 486 | NRF_RADIO->SHORTS = 0; |
joshuajnoble | 0:a01a54c0dc90 | 487 | NRF_RADIO->INTENCLR = 0xFFFFFFFF; |
joshuajnoble | 0:a01a54c0dc90 | 488 | on_radio_disabled = NULL; |
joshuajnoble | 0:a01a54c0dc90 | 489 | NRF_RADIO->EVENTS_DISABLED = 0; |
joshuajnoble | 0:a01a54c0dc90 | 490 | NRF_RADIO->TASKS_DISABLE = 1; |
joshuajnoble | 0:a01a54c0dc90 | 491 | while(NRF_RADIO->EVENTS_DISABLED == 0); |
joshuajnoble | 0:a01a54c0dc90 | 492 | m_uesb_mainstate = UESB_STATE_IDLE; |
joshuajnoble | 0:a01a54c0dc90 | 493 | return UESB_SUCCESS; |
joshuajnoble | 0:a01a54c0dc90 | 494 | } |
joshuajnoble | 0:a01a54c0dc90 | 495 | return UESB_ERROR_NOT_IN_RX_MODE; |
joshuajnoble | 0:a01a54c0dc90 | 496 | } |
joshuajnoble | 0:a01a54c0dc90 | 497 | |
joshuajnoble | 0:a01a54c0dc90 | 498 | uint32_t uesb_get_tx_attempts(uint32_t *attempts) |
joshuajnoble | 0:a01a54c0dc90 | 499 | { |
joshuajnoble | 0:a01a54c0dc90 | 500 | if(m_uesb_mainstate == UESB_STATE_UNINITIALIZED) return UESB_ERROR_NOT_INITIALIZED; |
joshuajnoble | 0:a01a54c0dc90 | 501 | *attempts = m_last_tx_attempts; |
joshuajnoble | 0:a01a54c0dc90 | 502 | return UESB_SUCCESS; |
joshuajnoble | 0:a01a54c0dc90 | 503 | } |
joshuajnoble | 0:a01a54c0dc90 | 504 | |
joshuajnoble | 0:a01a54c0dc90 | 505 | uint32_t uesb_flush_tx(void) |
joshuajnoble | 0:a01a54c0dc90 | 506 | { |
joshuajnoble | 0:a01a54c0dc90 | 507 | if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE; |
joshuajnoble | 0:a01a54c0dc90 | 508 | DISABLE_RF_IRQ; |
joshuajnoble | 0:a01a54c0dc90 | 509 | m_tx_fifo.count = 0; |
joshuajnoble | 0:a01a54c0dc90 | 510 | m_tx_fifo.entry_point = m_tx_fifo.exit_point = 0; |
joshuajnoble | 0:a01a54c0dc90 | 511 | ENABLE_RF_IRQ; |
joshuajnoble | 0:a01a54c0dc90 | 512 | return UESB_SUCCESS; |
joshuajnoble | 0:a01a54c0dc90 | 513 | } |
joshuajnoble | 0:a01a54c0dc90 | 514 | |
joshuajnoble | 0:a01a54c0dc90 | 515 | uint32_t uesb_flush_rx(void) |
joshuajnoble | 0:a01a54c0dc90 | 516 | { |
joshuajnoble | 0:a01a54c0dc90 | 517 | DISABLE_RF_IRQ; |
joshuajnoble | 0:a01a54c0dc90 | 518 | m_rx_fifo.count = 0; |
joshuajnoble | 0:a01a54c0dc90 | 519 | m_rx_fifo.entry_point = 0; |
joshuajnoble | 0:a01a54c0dc90 | 520 | ENABLE_RF_IRQ; |
joshuajnoble | 0:a01a54c0dc90 | 521 | return UESB_SUCCESS; |
joshuajnoble | 0:a01a54c0dc90 | 522 | } |
joshuajnoble | 0:a01a54c0dc90 | 523 | |
joshuajnoble | 0:a01a54c0dc90 | 524 | uint32_t uesb_get_clear_interrupts(uint32_t *interrupts) |
joshuajnoble | 0:a01a54c0dc90 | 525 | { |
joshuajnoble | 0:a01a54c0dc90 | 526 | DISABLE_RF_IRQ; |
joshuajnoble | 0:a01a54c0dc90 | 527 | *interrupts = m_interrupt_flags; |
joshuajnoble | 0:a01a54c0dc90 | 528 | m_interrupt_flags = 0; |
joshuajnoble | 0:a01a54c0dc90 | 529 | ENABLE_RF_IRQ; |
joshuajnoble | 0:a01a54c0dc90 | 530 | return UESB_SUCCESS; |
joshuajnoble | 0:a01a54c0dc90 | 531 | } |
joshuajnoble | 0:a01a54c0dc90 | 532 | |
joshuajnoble | 0:a01a54c0dc90 | 533 | uint32_t uesb_set_address(uesb_address_type_t address, const uint8_t *data_ptr) |
joshuajnoble | 0:a01a54c0dc90 | 534 | { |
joshuajnoble | 0:a01a54c0dc90 | 535 | if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE; |
joshuajnoble | 0:a01a54c0dc90 | 536 | switch(address) |
joshuajnoble | 0:a01a54c0dc90 | 537 | { |
joshuajnoble | 0:a01a54c0dc90 | 538 | case UESB_ADDRESS_PIPE0: |
joshuajnoble | 0:a01a54c0dc90 | 539 | memcpy(m_config_local.rx_address_p0, data_ptr, m_config_local.rf_addr_length); |
joshuajnoble | 0:a01a54c0dc90 | 540 | break; |
joshuajnoble | 0:a01a54c0dc90 | 541 | case UESB_ADDRESS_PIPE1: |
joshuajnoble | 0:a01a54c0dc90 | 542 | memcpy(m_config_local.rx_address_p1, data_ptr, m_config_local.rf_addr_length); |
joshuajnoble | 0:a01a54c0dc90 | 543 | break; |
joshuajnoble | 0:a01a54c0dc90 | 544 | case UESB_ADDRESS_PIPE2: |
joshuajnoble | 0:a01a54c0dc90 | 545 | m_config_local.rx_address_p2 = *data_ptr; |
joshuajnoble | 0:a01a54c0dc90 | 546 | break; |
joshuajnoble | 0:a01a54c0dc90 | 547 | case UESB_ADDRESS_PIPE3: |
joshuajnoble | 0:a01a54c0dc90 | 548 | m_config_local.rx_address_p3 = *data_ptr; |
joshuajnoble | 0:a01a54c0dc90 | 549 | break; |
joshuajnoble | 0:a01a54c0dc90 | 550 | case UESB_ADDRESS_PIPE4: |
joshuajnoble | 0:a01a54c0dc90 | 551 | m_config_local.rx_address_p4 = *data_ptr; |
joshuajnoble | 0:a01a54c0dc90 | 552 | break; |
joshuajnoble | 0:a01a54c0dc90 | 553 | case UESB_ADDRESS_PIPE5: |
joshuajnoble | 0:a01a54c0dc90 | 554 | m_config_local.rx_address_p5 = *data_ptr; |
joshuajnoble | 0:a01a54c0dc90 | 555 | break; |
joshuajnoble | 0:a01a54c0dc90 | 556 | case UESB_ADDRESS_PIPE6: |
joshuajnoble | 0:a01a54c0dc90 | 557 | m_config_local.rx_address_p6 = *data_ptr; |
joshuajnoble | 0:a01a54c0dc90 | 558 | break; |
joshuajnoble | 0:a01a54c0dc90 | 559 | case UESB_ADDRESS_PIPE7: |
joshuajnoble | 0:a01a54c0dc90 | 560 | m_config_local.rx_address_p7 = *data_ptr; |
joshuajnoble | 0:a01a54c0dc90 | 561 | break; |
joshuajnoble | 0:a01a54c0dc90 | 562 | default: |
joshuajnoble | 0:a01a54c0dc90 | 563 | return UESB_ERROR_INVALID_PARAMETERS; |
joshuajnoble | 0:a01a54c0dc90 | 564 | } |
joshuajnoble | 0:a01a54c0dc90 | 565 | update_radio_parameters(); |
joshuajnoble | 0:a01a54c0dc90 | 566 | return UESB_SUCCESS; |
joshuajnoble | 0:a01a54c0dc90 | 567 | } |
joshuajnoble | 0:a01a54c0dc90 | 568 | |
joshuajnoble | 0:a01a54c0dc90 | 569 | uint32_t uesb_set_rf_channel(uint32_t channel) |
joshuajnoble | 0:a01a54c0dc90 | 570 | { |
joshuajnoble | 0:a01a54c0dc90 | 571 | if(channel > 125) return UESB_ERROR_INVALID_PARAMETERS; |
joshuajnoble | 0:a01a54c0dc90 | 572 | m_config_local.rf_channel = channel; |
joshuajnoble | 0:a01a54c0dc90 | 573 | return UESB_SUCCESS; |
joshuajnoble | 0:a01a54c0dc90 | 574 | } |
joshuajnoble | 0:a01a54c0dc90 | 575 | |
joshuajnoble | 0:a01a54c0dc90 | 576 | uint32_t uesb_set_tx_power(uesb_tx_power_t tx_output_power) |
joshuajnoble | 0:a01a54c0dc90 | 577 | { |
joshuajnoble | 0:a01a54c0dc90 | 578 | if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE; |
joshuajnoble | 0:a01a54c0dc90 | 579 | if ( m_config_local.tx_output_power == tx_output_power ) return UESB_SUCCESS; |
joshuajnoble | 0:a01a54c0dc90 | 580 | m_config_local.tx_output_power = tx_output_power; |
joshuajnoble | 0:a01a54c0dc90 | 581 | update_radio_parameters(); |
joshuajnoble | 0:a01a54c0dc90 | 582 | return UESB_SUCCESS; |
joshuajnoble | 0:a01a54c0dc90 | 583 | } |
joshuajnoble | 0:a01a54c0dc90 | 584 | |
joshuajnoble | 0:a01a54c0dc90 | 585 | void RADIO_IRQHandler() |
joshuajnoble | 0:a01a54c0dc90 | 586 | { |
joshuajnoble | 0:a01a54c0dc90 | 587 | if(NRF_RADIO->EVENTS_READY && (NRF_RADIO->INTENSET & RADIO_INTENSET_READY_Msk)) |
joshuajnoble | 0:a01a54c0dc90 | 588 | { |
joshuajnoble | 0:a01a54c0dc90 | 589 | NRF_RADIO->EVENTS_READY = 0; |
joshuajnoble | 0:a01a54c0dc90 | 590 | |
joshuajnoble | 0:a01a54c0dc90 | 591 | DEBUG_PIN_SET(DEBUGPIN1); |
joshuajnoble | 0:a01a54c0dc90 | 592 | } |
joshuajnoble | 0:a01a54c0dc90 | 593 | |
joshuajnoble | 0:a01a54c0dc90 | 594 | if(NRF_RADIO->EVENTS_END && (NRF_RADIO->INTENSET & RADIO_INTENSET_END_Msk)) |
joshuajnoble | 0:a01a54c0dc90 | 595 | { |
joshuajnoble | 0:a01a54c0dc90 | 596 | NRF_RADIO->EVENTS_END = 0; |
joshuajnoble | 0:a01a54c0dc90 | 597 | |
joshuajnoble | 0:a01a54c0dc90 | 598 | DEBUG_PIN_SET(DEBUGPIN2); |
joshuajnoble | 0:a01a54c0dc90 | 599 | |
joshuajnoble | 0:a01a54c0dc90 | 600 | // Call the correct on_radio_end function, depending on the current protocol state |
joshuajnoble | 0:a01a54c0dc90 | 601 | if(on_radio_end) |
joshuajnoble | 0:a01a54c0dc90 | 602 | { |
joshuajnoble | 0:a01a54c0dc90 | 603 | on_radio_end(); |
joshuajnoble | 0:a01a54c0dc90 | 604 | } |
joshuajnoble | 0:a01a54c0dc90 | 605 | } |
joshuajnoble | 0:a01a54c0dc90 | 606 | |
joshuajnoble | 0:a01a54c0dc90 | 607 | if(NRF_RADIO->EVENTS_DISABLED && (NRF_RADIO->INTENSET & RADIO_INTENSET_DISABLED_Msk)) |
joshuajnoble | 0:a01a54c0dc90 | 608 | { |
joshuajnoble | 0:a01a54c0dc90 | 609 | NRF_RADIO->EVENTS_DISABLED = 0; |
joshuajnoble | 0:a01a54c0dc90 | 610 | |
joshuajnoble | 0:a01a54c0dc90 | 611 | DEBUG_PIN_SET(DEBUGPIN3); |
joshuajnoble | 0:a01a54c0dc90 | 612 | |
joshuajnoble | 0:a01a54c0dc90 | 613 | // Call the correct on_radio_disable function, depending on the current protocol state |
joshuajnoble | 0:a01a54c0dc90 | 614 | if(on_radio_disabled) |
joshuajnoble | 0:a01a54c0dc90 | 615 | { |
joshuajnoble | 0:a01a54c0dc90 | 616 | on_radio_disabled(); |
joshuajnoble | 0:a01a54c0dc90 | 617 | } |
joshuajnoble | 0:a01a54c0dc90 | 618 | } |
joshuajnoble | 0:a01a54c0dc90 | 619 | |
joshuajnoble | 0:a01a54c0dc90 | 620 | DEBUG_PIN_CLR(DEBUGPIN1); |
joshuajnoble | 0:a01a54c0dc90 | 621 | DEBUG_PIN_CLR(DEBUGPIN2); |
joshuajnoble | 0:a01a54c0dc90 | 622 | DEBUG_PIN_CLR(DEBUGPIN3); |
joshuajnoble | 0:a01a54c0dc90 | 623 | DEBUG_PIN_CLR(DEBUGPIN4); |
joshuajnoble | 0:a01a54c0dc90 | 624 | } |
joshuajnoble | 0:a01a54c0dc90 | 625 | |
joshuajnoble | 0:a01a54c0dc90 | 626 | static void on_radio_disabled_esb_dpl_tx_noack() |
joshuajnoble | 0:a01a54c0dc90 | 627 | { |
joshuajnoble | 0:a01a54c0dc90 | 628 | m_interrupt_flags |= UESB_INT_TX_SUCCESS_MSK; |
joshuajnoble | 0:a01a54c0dc90 | 629 | tx_fifo_remove_last(); |
joshuajnoble | 0:a01a54c0dc90 | 630 | |
joshuajnoble | 0:a01a54c0dc90 | 631 | if(m_tx_fifo.count == 0) |
joshuajnoble | 0:a01a54c0dc90 | 632 | { |
joshuajnoble | 0:a01a54c0dc90 | 633 | m_uesb_mainstate = UESB_STATE_IDLE; |
joshuajnoble | 0:a01a54c0dc90 | 634 | if(m_event_handler != 0) m_event_handler(); |
joshuajnoble | 0:a01a54c0dc90 | 635 | } |
joshuajnoble | 0:a01a54c0dc90 | 636 | else |
joshuajnoble | 0:a01a54c0dc90 | 637 | { |
joshuajnoble | 0:a01a54c0dc90 | 638 | if(m_event_handler != 0) m_event_handler(); |
joshuajnoble | 0:a01a54c0dc90 | 639 | start_tx_transaction(); |
joshuajnoble | 0:a01a54c0dc90 | 640 | } |
joshuajnoble | 0:a01a54c0dc90 | 641 | } |
joshuajnoble | 0:a01a54c0dc90 | 642 | |
joshuajnoble | 0:a01a54c0dc90 | 643 | static void on_radio_disabled_esb_dpl_tx() |
joshuajnoble | 0:a01a54c0dc90 | 644 | { |
joshuajnoble | 0:a01a54c0dc90 | 645 | // Remove the DISABLED -> RXEN shortcut, to make sure the radio stays disabled after the RX window |
joshuajnoble | 0:a01a54c0dc90 | 646 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON; |
joshuajnoble | 0:a01a54c0dc90 | 647 | |
joshuajnoble | 0:a01a54c0dc90 | 648 | // Make sure the timer is started the next time the radio is ready, |
joshuajnoble | 0:a01a54c0dc90 | 649 | // and that it will disable the radio automatically if no packet is received by the time defined in m_wait_for_ack_timeout_us |
joshuajnoble | 0:a01a54c0dc90 | 650 | UESB_SYS_TIMER->CC[0] = m_wait_for_ack_timeout_us; |
joshuajnoble | 0:a01a54c0dc90 | 651 | UESB_SYS_TIMER->CC[1] = m_config_local.retransmit_delay - 130; |
joshuajnoble | 0:a01a54c0dc90 | 652 | UESB_SYS_TIMER->TASKS_CLEAR = 1; |
joshuajnoble | 0:a01a54c0dc90 | 653 | UESB_SYS_TIMER->EVENTS_COMPARE[0] = 0; |
joshuajnoble | 0:a01a54c0dc90 | 654 | UESB_SYS_TIMER->EVENTS_COMPARE[1] = 0; |
joshuajnoble | 0:a01a54c0dc90 | 655 | NRF_PPI->CHENSET = (1 << UESB_PPI_TIMER_START) | (1 << UESB_PPI_RX_TIMEOUT) | (1 << UESB_PPI_TIMER_STOP); |
joshuajnoble | 0:a01a54c0dc90 | 656 | NRF_PPI->CHENCLR = (1 << UESB_PPI_TX_START); |
joshuajnoble | 0:a01a54c0dc90 | 657 | NRF_RADIO->EVENTS_END = 0; |
joshuajnoble | 0:a01a54c0dc90 | 658 | if(m_config_local.protocol == UESB_PROTOCOL_ESB) |
joshuajnoble | 0:a01a54c0dc90 | 659 | { |
joshuajnoble | 0:a01a54c0dc90 | 660 | update_rf_payload_format(0); |
joshuajnoble | 0:a01a54c0dc90 | 661 | } |
joshuajnoble | 0:a01a54c0dc90 | 662 | NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer; |
joshuajnoble | 0:a01a54c0dc90 | 663 | on_radio_disabled = on_radio_disabled_esb_dpl_tx_wait_for_ack; |
joshuajnoble | 0:a01a54c0dc90 | 664 | m_uesb_mainstate = UESB_STATE_PTX_RX_ACK; |
joshuajnoble | 0:a01a54c0dc90 | 665 | } |
joshuajnoble | 0:a01a54c0dc90 | 666 | |
joshuajnoble | 0:a01a54c0dc90 | 667 | static void on_radio_disabled_esb_dpl_tx_wait_for_ack() |
joshuajnoble | 0:a01a54c0dc90 | 668 | { |
joshuajnoble | 0:a01a54c0dc90 | 669 | // This marks the completion of a TX_RX sequence (TX with ACK) |
joshuajnoble | 0:a01a54c0dc90 | 670 | |
joshuajnoble | 0:a01a54c0dc90 | 671 | // Make sure the timer will not deactivate the radio if a packet is received |
joshuajnoble | 0:a01a54c0dc90 | 672 | NRF_PPI->CHENCLR = (1 << UESB_PPI_TIMER_START) | (1 << UESB_PPI_RX_TIMEOUT) | (1 << UESB_PPI_TIMER_STOP); |
joshuajnoble | 0:a01a54c0dc90 | 673 | |
joshuajnoble | 0:a01a54c0dc90 | 674 | // If the radio has received a packet and the CRC status is OK |
joshuajnoble | 0:a01a54c0dc90 | 675 | if(NRF_RADIO->EVENTS_END && NRF_RADIO->CRCSTATUS != 0) |
joshuajnoble | 0:a01a54c0dc90 | 676 | { |
joshuajnoble | 0:a01a54c0dc90 | 677 | UESB_SYS_TIMER->TASKS_STOP = 1; |
joshuajnoble | 0:a01a54c0dc90 | 678 | NRF_PPI->CHENCLR = (1 << UESB_PPI_TX_START); |
joshuajnoble | 0:a01a54c0dc90 | 679 | m_interrupt_flags |= UESB_INT_TX_SUCCESS_MSK; |
joshuajnoble | 0:a01a54c0dc90 | 680 | m_last_tx_attempts = m_config_local.retransmit_count - m_retransmits_remaining + 1; |
joshuajnoble | 0:a01a54c0dc90 | 681 | tx_fifo_remove_last(); |
joshuajnoble | 0:a01a54c0dc90 | 682 | if(m_rx_payload_buffer[0] > 0) |
joshuajnoble | 0:a01a54c0dc90 | 683 | { |
joshuajnoble | 0:a01a54c0dc90 | 684 | if(rx_fifo_push_rfbuf((uint8_t)NRF_RADIO->TXADDRESS)) |
joshuajnoble | 0:a01a54c0dc90 | 685 | { |
joshuajnoble | 0:a01a54c0dc90 | 686 | m_interrupt_flags |= UESB_INT_RX_DR_MSK; |
joshuajnoble | 0:a01a54c0dc90 | 687 | } |
joshuajnoble | 0:a01a54c0dc90 | 688 | } |
joshuajnoble | 0:a01a54c0dc90 | 689 | |
joshuajnoble | 0:a01a54c0dc90 | 690 | if((m_tx_fifo.count == 0) || (m_config_local.tx_mode == UESB_TXMODE_MANUAL)) |
joshuajnoble | 0:a01a54c0dc90 | 691 | { |
joshuajnoble | 0:a01a54c0dc90 | 692 | m_uesb_mainstate = UESB_STATE_IDLE; |
joshuajnoble | 0:a01a54c0dc90 | 693 | if(m_event_handler != 0) m_event_handler(); |
joshuajnoble | 0:a01a54c0dc90 | 694 | } |
joshuajnoble | 0:a01a54c0dc90 | 695 | else |
joshuajnoble | 0:a01a54c0dc90 | 696 | { |
joshuajnoble | 0:a01a54c0dc90 | 697 | if(m_event_handler != 0) m_event_handler(); |
joshuajnoble | 0:a01a54c0dc90 | 698 | start_tx_transaction(); |
joshuajnoble | 0:a01a54c0dc90 | 699 | } |
joshuajnoble | 0:a01a54c0dc90 | 700 | } |
joshuajnoble | 0:a01a54c0dc90 | 701 | else |
joshuajnoble | 0:a01a54c0dc90 | 702 | { |
joshuajnoble | 0:a01a54c0dc90 | 703 | if(m_retransmits_remaining-- == 0) |
joshuajnoble | 0:a01a54c0dc90 | 704 | { |
joshuajnoble | 0:a01a54c0dc90 | 705 | UESB_SYS_TIMER->TASKS_STOP = 1; |
joshuajnoble | 0:a01a54c0dc90 | 706 | NRF_PPI->CHENCLR = (1 << UESB_PPI_TX_START); |
joshuajnoble | 0:a01a54c0dc90 | 707 | // All retransmits are expended, and the TX operation is suspended |
joshuajnoble | 0:a01a54c0dc90 | 708 | m_last_tx_attempts = m_config_local.retransmit_count + 1; |
joshuajnoble | 0:a01a54c0dc90 | 709 | m_interrupt_flags |= UESB_INT_TX_FAILED_MSK; |
joshuajnoble | 0:a01a54c0dc90 | 710 | |
joshuajnoble | 0:a01a54c0dc90 | 711 | m_uesb_mainstate = UESB_STATE_IDLE; |
joshuajnoble | 0:a01a54c0dc90 | 712 | if(m_event_handler != 0) m_event_handler(); |
joshuajnoble | 0:a01a54c0dc90 | 713 | } |
joshuajnoble | 0:a01a54c0dc90 | 714 | else |
joshuajnoble | 0:a01a54c0dc90 | 715 | { |
joshuajnoble | 0:a01a54c0dc90 | 716 | // We still have more retransmits left, and we should enter TX mode again as soon as the system timer reaches CC[1] |
joshuajnoble | 0:a01a54c0dc90 | 717 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_RXEN_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 718 | update_rf_payload_format(current_payload->length); |
joshuajnoble | 0:a01a54c0dc90 | 719 | NRF_RADIO->PACKETPTR = (uint32_t)m_tx_payload_buffer; |
joshuajnoble | 0:a01a54c0dc90 | 720 | on_radio_disabled = on_radio_disabled_esb_dpl_tx; |
joshuajnoble | 0:a01a54c0dc90 | 721 | m_uesb_mainstate = UESB_STATE_PTX_TX_ACK; |
joshuajnoble | 0:a01a54c0dc90 | 722 | UESB_SYS_TIMER->TASKS_START = 1; |
joshuajnoble | 0:a01a54c0dc90 | 723 | NRF_PPI->CHENSET = (1 << UESB_PPI_TX_START); |
joshuajnoble | 0:a01a54c0dc90 | 724 | if(UESB_SYS_TIMER->EVENTS_COMPARE[1]) |
joshuajnoble | 0:a01a54c0dc90 | 725 | { |
joshuajnoble | 0:a01a54c0dc90 | 726 | NRF_RADIO->TASKS_TXEN = 1; |
joshuajnoble | 0:a01a54c0dc90 | 727 | } |
joshuajnoble | 0:a01a54c0dc90 | 728 | } |
joshuajnoble | 0:a01a54c0dc90 | 729 | } |
joshuajnoble | 0:a01a54c0dc90 | 730 | } |
joshuajnoble | 0:a01a54c0dc90 | 731 | |
joshuajnoble | 0:a01a54c0dc90 | 732 | static void on_radio_disabled_esb_dpl_rx(void) |
joshuajnoble | 0:a01a54c0dc90 | 733 | { |
joshuajnoble | 0:a01a54c0dc90 | 734 | bool send_ack = false; |
joshuajnoble | 0:a01a54c0dc90 | 735 | bool set_rx_interrupt = false; |
joshuajnoble | 0:a01a54c0dc90 | 736 | if(NRF_RADIO->CRCSTATUS != 0 && m_rx_fifo.count < UESB_CORE_RX_FIFO_SIZE) |
joshuajnoble | 0:a01a54c0dc90 | 737 | { |
joshuajnoble | 0:a01a54c0dc90 | 738 | send_ack = true; |
joshuajnoble | 0:a01a54c0dc90 | 739 | } |
joshuajnoble | 0:a01a54c0dc90 | 740 | if(send_ack) |
joshuajnoble | 0:a01a54c0dc90 | 741 | { |
joshuajnoble | 0:a01a54c0dc90 | 742 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_RXEN_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 743 | |
joshuajnoble | 0:a01a54c0dc90 | 744 | // For a packet to be considered new (and not a retransmit) the PID or the CRC has to be different |
joshuajnoble | 0:a01a54c0dc90 | 745 | if(NRF_RADIO->RXCRC != m_last_rx_packet_crc || (m_rx_payload_buffer[1] >> 1) != m_last_rx_packet_pid) |
joshuajnoble | 0:a01a54c0dc90 | 746 | { |
joshuajnoble | 0:a01a54c0dc90 | 747 | if((m_uesb_mainstate == UESB_STATE_PRX_SEND_ACK_PAYLOAD) && (m_tx_fifo.count > 0)) |
joshuajnoble | 0:a01a54c0dc90 | 748 | { |
joshuajnoble | 0:a01a54c0dc90 | 749 | // It is assumed that the last ACK payload was recieved. |
joshuajnoble | 0:a01a54c0dc90 | 750 | if(++m_tx_fifo.exit_point >= UESB_CORE_RX_FIFO_SIZE) m_tx_fifo.exit_point = 0; |
joshuajnoble | 0:a01a54c0dc90 | 751 | m_tx_fifo.count--; |
joshuajnoble | 0:a01a54c0dc90 | 752 | |
joshuajnoble | 0:a01a54c0dc90 | 753 | // ACK payloads also require TX_DS (page 40 of the 'nRF24LE1_Product_Specification_rev1_6.pdf'). |
joshuajnoble | 0:a01a54c0dc90 | 754 | m_interrupt_flags |= UESB_INT_TX_SUCCESS_MSK; |
joshuajnoble | 0:a01a54c0dc90 | 755 | } |
joshuajnoble | 0:a01a54c0dc90 | 756 | |
joshuajnoble | 0:a01a54c0dc90 | 757 | set_rx_interrupt = true; |
joshuajnoble | 0:a01a54c0dc90 | 758 | m_last_rx_packet_pid = m_rx_payload_buffer[1] >> 1; |
joshuajnoble | 0:a01a54c0dc90 | 759 | m_last_rx_packet_crc = NRF_RADIO->RXCRC; |
joshuajnoble | 0:a01a54c0dc90 | 760 | } |
joshuajnoble | 0:a01a54c0dc90 | 761 | |
joshuajnoble | 0:a01a54c0dc90 | 762 | if(m_config_local.protocol == UESB_PROTOCOL_ESB_DPL) |
joshuajnoble | 0:a01a54c0dc90 | 763 | { |
joshuajnoble | 0:a01a54c0dc90 | 764 | if(m_tx_fifo.count > 0) |
joshuajnoble | 0:a01a54c0dc90 | 765 | { |
joshuajnoble | 0:a01a54c0dc90 | 766 | current_payload = m_tx_fifo.payload_ptr[m_tx_fifo.exit_point]; |
joshuajnoble | 0:a01a54c0dc90 | 767 | |
joshuajnoble | 0:a01a54c0dc90 | 768 | update_rf_payload_format(current_payload->length); |
joshuajnoble | 0:a01a54c0dc90 | 769 | m_tx_payload_buffer[0] = current_payload->length; |
joshuajnoble | 0:a01a54c0dc90 | 770 | memcpy(&m_tx_payload_buffer[2], current_payload->data, current_payload->length); |
joshuajnoble | 0:a01a54c0dc90 | 771 | |
joshuajnoble | 0:a01a54c0dc90 | 772 | m_uesb_mainstate = UESB_STATE_PRX_SEND_ACK_PAYLOAD; |
joshuajnoble | 0:a01a54c0dc90 | 773 | } |
joshuajnoble | 0:a01a54c0dc90 | 774 | else |
joshuajnoble | 0:a01a54c0dc90 | 775 | { |
joshuajnoble | 0:a01a54c0dc90 | 776 | update_rf_payload_format(0); |
joshuajnoble | 0:a01a54c0dc90 | 777 | m_tx_payload_buffer[0] = 0; |
joshuajnoble | 0:a01a54c0dc90 | 778 | |
joshuajnoble | 0:a01a54c0dc90 | 779 | m_uesb_mainstate = UESB_STATE_PRX_SEND_ACK; |
joshuajnoble | 0:a01a54c0dc90 | 780 | } |
joshuajnoble | 0:a01a54c0dc90 | 781 | |
joshuajnoble | 0:a01a54c0dc90 | 782 | m_tx_payload_buffer[1] = m_rx_payload_buffer[1]; |
joshuajnoble | 0:a01a54c0dc90 | 783 | } |
joshuajnoble | 0:a01a54c0dc90 | 784 | else if(m_config_local.protocol == UESB_PROTOCOL_ESB) |
joshuajnoble | 0:a01a54c0dc90 | 785 | { |
joshuajnoble | 0:a01a54c0dc90 | 786 | m_tx_payload_buffer[0] = m_rx_payload_buffer[0]; |
joshuajnoble | 0:a01a54c0dc90 | 787 | m_tx_payload_buffer[1] = 0; |
joshuajnoble | 0:a01a54c0dc90 | 788 | |
joshuajnoble | 0:a01a54c0dc90 | 789 | m_uesb_mainstate = UESB_STATE_PRX_SEND_ACK; |
joshuajnoble | 0:a01a54c0dc90 | 790 | } |
joshuajnoble | 0:a01a54c0dc90 | 791 | |
joshuajnoble | 0:a01a54c0dc90 | 792 | NRF_RADIO->TXADDRESS = NRF_RADIO->RXMATCH; |
joshuajnoble | 0:a01a54c0dc90 | 793 | NRF_RADIO->PACKETPTR = (uint32_t)m_tx_payload_buffer; |
joshuajnoble | 0:a01a54c0dc90 | 794 | |
joshuajnoble | 0:a01a54c0dc90 | 795 | on_radio_disabled = on_radio_disabled_esb_dpl_rx_ack; |
joshuajnoble | 0:a01a54c0dc90 | 796 | } |
joshuajnoble | 0:a01a54c0dc90 | 797 | else |
joshuajnoble | 0:a01a54c0dc90 | 798 | { |
joshuajnoble | 0:a01a54c0dc90 | 799 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON; |
joshuajnoble | 0:a01a54c0dc90 | 800 | update_rf_payload_format(m_config_local.payload_length); |
joshuajnoble | 0:a01a54c0dc90 | 801 | NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer; |
joshuajnoble | 0:a01a54c0dc90 | 802 | NRF_RADIO->EVENTS_DISABLED = 0; |
joshuajnoble | 0:a01a54c0dc90 | 803 | NRF_RADIO->TASKS_DISABLE = 1; |
joshuajnoble | 0:a01a54c0dc90 | 804 | while(NRF_RADIO->EVENTS_DISABLED == 0); |
joshuajnoble | 0:a01a54c0dc90 | 805 | NRF_RADIO->EVENTS_DISABLED = 0; |
joshuajnoble | 0:a01a54c0dc90 | 806 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_TXEN_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 807 | NRF_RADIO->TASKS_RXEN = 1; |
joshuajnoble | 0:a01a54c0dc90 | 808 | } |
joshuajnoble | 0:a01a54c0dc90 | 809 | if(set_rx_interrupt) |
joshuajnoble | 0:a01a54c0dc90 | 810 | { |
joshuajnoble | 0:a01a54c0dc90 | 811 | rx_fifo_push_rfbuf(NRF_RADIO->RXMATCH); |
joshuajnoble | 0:a01a54c0dc90 | 812 | m_interrupt_flags |= UESB_INT_RX_DR_MSK; |
joshuajnoble | 0:a01a54c0dc90 | 813 | if(m_event_handler != 0) m_event_handler(); |
joshuajnoble | 0:a01a54c0dc90 | 814 | } |
joshuajnoble | 0:a01a54c0dc90 | 815 | } |
joshuajnoble | 0:a01a54c0dc90 | 816 | |
joshuajnoble | 0:a01a54c0dc90 | 817 | static void on_radio_disabled_esb_dpl_rx_ack(void) |
joshuajnoble | 0:a01a54c0dc90 | 818 | { |
joshuajnoble | 0:a01a54c0dc90 | 819 | NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_TXEN_Msk; |
joshuajnoble | 0:a01a54c0dc90 | 820 | update_rf_payload_format(m_config_local.payload_length); |
joshuajnoble | 0:a01a54c0dc90 | 821 | NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer; |
joshuajnoble | 0:a01a54c0dc90 | 822 | on_radio_disabled = on_radio_disabled_esb_dpl_rx; |
joshuajnoble | 0:a01a54c0dc90 | 823 | |
joshuajnoble | 0:a01a54c0dc90 | 824 | if(m_uesb_mainstate == UESB_STATE_PRX_SEND_ACK) |
joshuajnoble | 0:a01a54c0dc90 | 825 | { |
joshuajnoble | 0:a01a54c0dc90 | 826 | // In the case of UESB_STATE_PRX_SEND_ACK_PAYLOAD the state will be updated when the next packet is received. |
joshuajnoble | 0:a01a54c0dc90 | 827 | m_uesb_mainstate = UESB_STATE_PRX; |
joshuajnoble | 0:a01a54c0dc90 | 828 | } |
joshuajnoble | 0:a01a54c0dc90 | 829 | } |
joshuajnoble | 0:a01a54c0dc90 | 830 | |
joshuajnoble | 0:a01a54c0dc90 | 831 | static void on_radio_end_sb_tx(void) |
joshuajnoble | 0:a01a54c0dc90 | 832 | { |
joshuajnoble | 0:a01a54c0dc90 | 833 | m_interrupt_flags |= UESB_INT_TX_SUCCESS_MSK; |
joshuajnoble | 0:a01a54c0dc90 | 834 | tx_fifo_remove_last(); |
joshuajnoble | 0:a01a54c0dc90 | 835 | if(m_config_local.tx_mode == UESB_TXMODE_MANUAL || m_tx_fifo.count == 0) |
joshuajnoble | 0:a01a54c0dc90 | 836 | { |
joshuajnoble | 0:a01a54c0dc90 | 837 | // No more packets to send. Disable the radio and set the state to idle. |
joshuajnoble | 0:a01a54c0dc90 | 838 | NRF_RADIO->EVENTS_DISABLED = 0; |
joshuajnoble | 0:a01a54c0dc90 | 839 | NRF_RADIO->TASKS_DISABLE = 1; |
joshuajnoble | 0:a01a54c0dc90 | 840 | while(!NRF_RADIO->EVENTS_DISABLED); |
joshuajnoble | 0:a01a54c0dc90 | 841 | NRF_RADIO->EVENTS_DISABLED = 0; |
joshuajnoble | 0:a01a54c0dc90 | 842 | m_uesb_mainstate = UESB_STATE_IDLE; |
joshuajnoble | 0:a01a54c0dc90 | 843 | if(m_event_handler != 0) m_event_handler(); |
joshuajnoble | 0:a01a54c0dc90 | 844 | } |
joshuajnoble | 0:a01a54c0dc90 | 845 | else |
joshuajnoble | 0:a01a54c0dc90 | 846 | { |
joshuajnoble | 0:a01a54c0dc90 | 847 | // Send another packet automatically without disabling the radio first. |
joshuajnoble | 0:a01a54c0dc90 | 848 | current_payload = m_tx_fifo.payload_ptr[m_tx_fifo.exit_point]; |
joshuajnoble | 0:a01a54c0dc90 | 849 | |
joshuajnoble | 0:a01a54c0dc90 | 850 | update_rf_payload_format(current_payload->length); |
joshuajnoble | 0:a01a54c0dc90 | 851 | memcpy(&m_tx_payload_buffer[0], current_payload->data, current_payload->length); |
joshuajnoble | 0:a01a54c0dc90 | 852 | |
joshuajnoble | 0:a01a54c0dc90 | 853 | NRF_RADIO->TXADDRESS = current_payload->pipe; |
joshuajnoble | 0:a01a54c0dc90 | 854 | |
joshuajnoble | 0:a01a54c0dc90 | 855 | NVIC_ClearPendingIRQ(RADIO_IRQn); |
joshuajnoble | 0:a01a54c0dc90 | 856 | NVIC_EnableIRQ(RADIO_IRQn); |
joshuajnoble | 0:a01a54c0dc90 | 857 | |
joshuajnoble | 0:a01a54c0dc90 | 858 | NRF_RADIO->EVENTS_ADDRESS = NRF_RADIO->EVENTS_PAYLOAD = 0; |
joshuajnoble | 0:a01a54c0dc90 | 859 | NRF_RADIO->TASKS_START = 1; |
joshuajnoble | 0:a01a54c0dc90 | 860 | |
joshuajnoble | 0:a01a54c0dc90 | 861 | } |
joshuajnoble | 0:a01a54c0dc90 | 862 | } |
joshuajnoble | 0:a01a54c0dc90 | 863 | |
joshuajnoble | 0:a01a54c0dc90 | 864 | static void on_radio_end_sb_rx(void) |
joshuajnoble | 0:a01a54c0dc90 | 865 | { |
joshuajnoble | 0:a01a54c0dc90 | 866 | if(NRF_RADIO->CRCSTATUS != 0 && rx_fifo_push_rfbuf(NRF_RADIO->RXMATCH)) |
joshuajnoble | 0:a01a54c0dc90 | 867 | { |
joshuajnoble | 0:a01a54c0dc90 | 868 | m_interrupt_flags |= UESB_INT_RX_DR_MSK; |
joshuajnoble | 0:a01a54c0dc90 | 869 | if(m_event_handler != 0) m_event_handler(); |
joshuajnoble | 0:a01a54c0dc90 | 870 | } |
joshuajnoble | 0:a01a54c0dc90 | 871 | } |
jblackann | 1:5d49c7b9f405 | 872 | */ |