Wouter van Kleunen
/
nrf52_esb
NRF52_esb
Embed:
(wiki syntax)
Show/hide line numbers
micro_esb.cpp
00001 /* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved. 00002 * 00003 * The information contained herein is property of Nordic Semiconductor ASA. 00004 * Terms and conditions of usage are described in detail in NORDIC 00005 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. 00006 * 00007 * Licensees are granted free, non-transferable use of the information. NO 00008 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from 00009 * the file. 00010 * 00011 */ 00012 00013 #include "micro_esb.h" 00014 #include "uesb_error_codes.h" 00015 //#include "nrf_gpio.h" 00016 #include <string.h> 00017 00018 00019 static uesb_event_handler_t m_event_handler; 00020 00021 // RF parameters 00022 static uesb_config_t m_config_local; 00023 00024 // TX FIFO 00025 static uesb_payload_t m_tx_fifo_payload[UESB_CORE_TX_FIFO_SIZE]; 00026 static uesb_payload_tx_fifo_t m_tx_fifo; 00027 00028 // RX FIFO 00029 static uesb_payload_t m_rx_fifo_payload[UESB_CORE_RX_FIFO_SIZE]; 00030 static uesb_payload_rx_fifo_t m_rx_fifo; 00031 00032 static uint8_t m_tx_payload_buffer[UESB_CORE_MAX_PAYLOAD_LENGTH + 2]; 00033 static uint8_t m_rx_payload_buffer[UESB_CORE_MAX_PAYLOAD_LENGTH + 2]; 00034 00035 // Run time variables 00036 static volatile uint32_t m_interrupt_flags = 0; 00037 static uint32_t m_pid = 0; 00038 static volatile uint32_t m_retransmits_remaining; 00039 static volatile uint32_t m_last_tx_attempts; 00040 static volatile uint8_t m_last_rx_packet_pid = 0xFF; 00041 static volatile uint32_t m_last_rx_packet_crc = 0xFFFFFFFF; 00042 static volatile uint32_t m_wait_for_ack_timeout_us; 00043 00044 static uesb_payload_t *current_payload; 00045 00046 static uesb_mainstate_t m_uesb_mainstate = UESB_STATE_UNINITIALIZED; 00047 00048 // Constant parameters 00049 #define RX_WAIT_FOR_ACK_TIMEOUT_US_2MBPS 48 // Smallest reliable value - 43 00050 #define RX_WAIT_FOR_ACK_TIMEOUT_US_1MBPS 64 // Smallest reliable value - 59 00051 #define RX_WAIT_FOR_ACK_TIMEOUT_US_250KBPS 250 00052 00053 // Macros 00054 #define DISABLE_RF_IRQ NVIC_DisableIRQ(RADIO_IRQn) 00055 #define ENABLE_RF_IRQ NVIC_EnableIRQ(RADIO_IRQn) 00056 00057 #define RADIO_SHORTS_COMMON ( RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk | \ 00058 RADIO_SHORTS_ADDRESS_RSSISTART_Msk | RADIO_SHORTS_DISABLED_RSSISTOP_Msk ) 00059 00060 // These function pointers are changed dynamically, depending on protocol configuration and state 00061 static void (*on_radio_disabled)(void) = 0; 00062 static void (*on_radio_end)(void) = 0; 00063 static void (*update_rf_payload_format)(uint32_t payload_length) = 0; 00064 00065 // The following functions are assigned to the function pointers above 00066 static void on_radio_disabled_esb_dpl_tx_noack(void); 00067 static void on_radio_disabled_esb_dpl_tx(void); 00068 static void on_radio_disabled_esb_dpl_tx_wait_for_ack(void); 00069 static void on_radio_disabled_esb_dpl_rx(void); 00070 static void on_radio_disabled_esb_dpl_rx_ack(void); 00071 00072 static void on_radio_end_sb_tx(void); 00073 static void on_radio_end_sb_rx(void); 00074 00075 static void update_rf_payload_format_esb_dpl(uint32_t payload_length) 00076 { 00077 #if(UESB_CORE_MAX_PAYLOAD_LENGTH <= 32) 00078 NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | (6 << RADIO_PCNF0_LFLEN_Pos) | (3 << RADIO_PCNF0_S1LEN_Pos); 00079 #else 00080 NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | (8 << RADIO_PCNF0_LFLEN_Pos) | (3 << RADIO_PCNF0_S1LEN_Pos); 00081 #endif 00082 NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) | 00083 (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) | 00084 ((m_config_local.rf_addr_length - 1) << RADIO_PCNF1_BALEN_Pos) | 00085 (0 << RADIO_PCNF1_STATLEN_Pos) | 00086 (UESB_CORE_MAX_PAYLOAD_LENGTH << RADIO_PCNF1_MAXLEN_Pos); 00087 } 00088 00089 static void update_rf_payload_format_esb(uint32_t payload_length) 00090 { 00091 NRF_RADIO->PCNF0 = (1 << RADIO_PCNF0_S0LEN_Pos) | (0 << RADIO_PCNF0_LFLEN_Pos) | (1 << RADIO_PCNF0_S1LEN_Pos); 00092 NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) | 00093 (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) | 00094 ((m_config_local.rf_addr_length - 1) << RADIO_PCNF1_BALEN_Pos) | 00095 (payload_length << RADIO_PCNF1_STATLEN_Pos) | 00096 (payload_length << RADIO_PCNF1_MAXLEN_Pos); 00097 } 00098 00099 static void update_rf_payload_format_sb(uint32_t payload_length) 00100 { 00101 NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) | (0 << RADIO_PCNF0_LFLEN_Pos) | (0 << RADIO_PCNF0_S1LEN_Pos); 00102 NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) | 00103 (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) | 00104 ((m_config_local.rf_addr_length - 1) << RADIO_PCNF1_BALEN_Pos) | 00105 (payload_length << RADIO_PCNF1_STATLEN_Pos) | 00106 (payload_length << RADIO_PCNF1_MAXLEN_Pos); 00107 } 00108 00109 // Function that swaps the bits within each byte in a uint32. Used to convert from nRF24L type addressing to nRF51 type addressing 00110 static uint32_t bytewise_bit_swap(uint32_t inp) 00111 { 00112 inp = (inp & 0xF0F0F0F0) >> 4 | (inp & 0x0F0F0F0F) << 4; 00113 inp = (inp & 0xCCCCCCCC) >> 2 | (inp & 0x33333333) << 2; 00114 return (inp & 0xAAAAAAAA) >> 1 | (inp & 0x55555555) << 1; 00115 } 00116 00117 static void update_radio_parameters() 00118 { 00119 // Protocol 00120 switch(m_config_local.protocol) 00121 { 00122 case UESB_PROTOCOL_ESB_DPL: 00123 update_rf_payload_format = update_rf_payload_format_esb_dpl; 00124 break; 00125 case UESB_PROTOCOL_ESB: 00126 update_rf_payload_format = update_rf_payload_format_esb; 00127 break; 00128 case UESB_PROTOCOL_SB: 00129 update_rf_payload_format = update_rf_payload_format_sb; 00130 on_radio_end = (m_config_local.mode == UESB_MODE_PTX ? on_radio_end_sb_tx : on_radio_end_sb_rx); 00131 break; 00132 } 00133 // TX power 00134 NRF_RADIO->TXPOWER = m_config_local.tx_output_power << RADIO_TXPOWER_TXPOWER_Pos; 00135 00136 // RF bitrate 00137 NRF_RADIO->MODE = m_config_local.bitrate << RADIO_MODE_MODE_Pos; 00138 switch(m_config_local.bitrate) 00139 { 00140 case UESB_BITRATE_2MBPS: 00141 m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_2MBPS; 00142 break; 00143 case UESB_BITRATE_1MBPS: 00144 m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_1MBPS; 00145 break; 00146 case UESB_BITRATE_250KBPS: 00147 m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_250KBPS; 00148 break; 00149 } 00150 00151 // CRC configuration 00152 NRF_RADIO->CRCCNF = m_config_local.crc << RADIO_CRCCNF_LEN_Pos; 00153 if(m_config_local.crc == RADIO_CRCCNF_LEN_Two) 00154 { 00155 NRF_RADIO->CRCINIT = 0xFFFFUL; // Initial value 00156 NRF_RADIO->CRCPOLY = 0x11021UL; // CRC poly: x^16+x^12^x^5+1 00157 } 00158 else if(m_config_local.crc == RADIO_CRCCNF_LEN_One) 00159 { 00160 NRF_RADIO->CRCINIT = 0xFFUL; // Initial value 00161 NRF_RADIO->CRCPOLY = 0x107UL; // CRC poly: x^8+x^2^x^1+1 00162 } 00163 00164 // Packet format 00165 update_rf_payload_format(m_config_local.payload_length); 00166 00167 // Radio address config 00168 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]); 00169 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); 00170 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]); 00171 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]); 00172 } 00173 00174 static void initialize_fifos() 00175 { 00176 m_tx_fifo.entry_point = 0; 00177 m_tx_fifo.exit_point = 0; 00178 m_tx_fifo.count = 0; 00179 for(int i = 0; i < UESB_CORE_TX_FIFO_SIZE; i++) 00180 { 00181 m_tx_fifo.payload_ptr[i] = &m_tx_fifo_payload[i]; 00182 } 00183 00184 m_rx_fifo.entry_point = 0; 00185 m_rx_fifo.exit_point = 0; 00186 m_rx_fifo.count = 0; 00187 for(int i = 0; i < UESB_CORE_RX_FIFO_SIZE; i++) 00188 { 00189 m_rx_fifo.payload_ptr[i] = &m_rx_fifo_payload[i]; 00190 } 00191 } 00192 00193 static void tx_fifo_remove_last() 00194 { 00195 if(m_tx_fifo.count > 0) 00196 { 00197 DISABLE_RF_IRQ; 00198 m_tx_fifo.count--; 00199 m_tx_fifo.exit_point++; 00200 if(m_tx_fifo.exit_point >= UESB_CORE_TX_FIFO_SIZE) m_tx_fifo.exit_point = 0; 00201 ENABLE_RF_IRQ; 00202 } 00203 } 00204 00205 static bool rx_fifo_push_rfbuf(uint8_t pipe) 00206 { 00207 if(m_rx_fifo.count < UESB_CORE_RX_FIFO_SIZE) 00208 { 00209 if(m_config_local.protocol == UESB_PROTOCOL_ESB_DPL) 00210 { 00211 if(m_rx_payload_buffer[0] > UESB_CORE_MAX_PAYLOAD_LENGTH) return false; 00212 m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->length = m_rx_payload_buffer[0]; 00213 } 00214 else 00215 { 00216 m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->length = m_config_local.payload_length; 00217 } 00218 if(m_config_local.protocol == UESB_PROTOCOL_SB) 00219 { 00220 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); 00221 } 00222 else 00223 { 00224 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); 00225 } 00226 m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->pipe = pipe; 00227 m_rx_fifo.payload_ptr[m_rx_fifo.entry_point]->rssi = NRF_RADIO->RSSISAMPLE; 00228 if(++m_rx_fifo.entry_point >= UESB_CORE_RX_FIFO_SIZE) m_rx_fifo.entry_point = 0; 00229 m_rx_fifo.count++; 00230 return true; 00231 } 00232 return false; 00233 } 00234 00235 static void sys_timer_init() 00236 { 00237 // Configure the system timer with a 1 MHz base frequency 00238 UESB_SYS_TIMER->PRESCALER = 4; 00239 UESB_SYS_TIMER->BITMODE = TIMER_BITMODE_BITMODE_16Bit; 00240 UESB_SYS_TIMER->SHORTS = TIMER_SHORTS_COMPARE1_CLEAR_Msk | TIMER_SHORTS_COMPARE1_STOP_Msk; 00241 } 00242 00243 static void ppi_init() 00244 { 00245 NRF_PPI->CH[UESB_PPI_TIMER_START].EEP = (uint32_t)&NRF_RADIO->EVENTS_READY; 00246 NRF_PPI->CH[UESB_PPI_TIMER_START].TEP = (uint32_t)&UESB_SYS_TIMER->TASKS_START; 00247 NRF_PPI->CH[UESB_PPI_TIMER_STOP].EEP = (uint32_t)&NRF_RADIO->EVENTS_ADDRESS; 00248 NRF_PPI->CH[UESB_PPI_TIMER_STOP].TEP = (uint32_t)&UESB_SYS_TIMER->TASKS_STOP; 00249 NRF_PPI->CH[UESB_PPI_RX_TIMEOUT].EEP = (uint32_t)&UESB_SYS_TIMER->EVENTS_COMPARE[0]; 00250 NRF_PPI->CH[UESB_PPI_RX_TIMEOUT].TEP = (uint32_t)&NRF_RADIO->TASKS_DISABLE; 00251 NRF_PPI->CH[UESB_PPI_TX_START].EEP = (uint32_t)&UESB_SYS_TIMER->EVENTS_COMPARE[1]; 00252 NRF_PPI->CH[UESB_PPI_TX_START].TEP = (uint32_t)&NRF_RADIO->TASKS_TXEN; 00253 } 00254 00255 uint32_t uesb_read_rx_payload(uesb_payload_t *payload) 00256 { 00257 if(m_uesb_mainstate == UESB_STATE_UNINITIALIZED) return UESB_ERROR_NOT_INITIALIZED; 00258 if(m_rx_fifo.count == 0) return UESB_ERROR_RX_FIFO_EMPTY; 00259 00260 DISABLE_RF_IRQ; 00261 payload->length = m_rx_fifo.payload_ptr[m_rx_fifo.exit_point]->length; 00262 payload->pipe = m_rx_fifo.payload_ptr[m_rx_fifo.exit_point]->pipe; 00263 payload->rssi = m_rx_fifo.payload_ptr[m_rx_fifo.exit_point]->rssi; 00264 memcpy(payload->data, m_rx_fifo.payload_ptr[m_rx_fifo.exit_point]->data, payload->length); 00265 if(++m_rx_fifo.exit_point >= UESB_CORE_RX_FIFO_SIZE) m_rx_fifo.exit_point = 0; 00266 m_rx_fifo.count--; 00267 ENABLE_RF_IRQ; 00268 00269 return UESB_SUCCESS; 00270 } 00271 00272 00273 uint32_t uesb_init(uesb_config_t *parameters) 00274 { 00275 if(m_uesb_mainstate != UESB_STATE_UNINITIALIZED) return UESB_ERROR_ALREADY_INITIALIZED; 00276 m_event_handler = parameters->event_handler; 00277 memcpy(&m_config_local, parameters, sizeof(uesb_config_t)); 00278 00279 m_interrupt_flags = 0; 00280 m_pid = 0; 00281 m_last_rx_packet_pid = 0xFF; 00282 m_last_rx_packet_crc = 0xFFFFFFFF; 00283 00284 update_radio_parameters(); 00285 00286 initialize_fifos(); 00287 00288 sys_timer_init(); 00289 00290 ppi_init(); 00291 00292 NVIC_SetPriority(RADIO_IRQn, m_config_local.radio_irq_priority & 0x03); 00293 00294 //m_uesb_initialized = true; 00295 m_uesb_mainstate = UESB_STATE_IDLE; 00296 00297 return UESB_SUCCESS; 00298 } 00299 00300 uint32_t uesb_disable(void) 00301 { 00302 if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE; 00303 NRF_PPI->CHENCLR = (1 << UESB_PPI_TIMER_START) | (1 << UESB_PPI_TIMER_STOP) | (1 << UESB_PPI_RX_TIMEOUT) | (1 << UESB_PPI_TX_START); 00304 m_uesb_mainstate = UESB_STATE_UNINITIALIZED; 00305 return UESB_SUCCESS; 00306 } 00307 00308 static void start_tx_transaction() 00309 { 00310 bool ack; 00311 m_last_tx_attempts = 1; 00312 // Prepare the payload 00313 current_payload = m_tx_fifo.payload_ptr[m_tx_fifo.exit_point]; 00314 m_pid = (m_pid + 1) % 4; 00315 switch(m_config_local.protocol) 00316 { 00317 case UESB_PROTOCOL_SB: 00318 update_rf_payload_format(current_payload->length); 00319 memcpy(&m_tx_payload_buffer[0], current_payload->data, current_payload->length); 00320 NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk; 00321 NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk; 00322 on_radio_disabled = on_radio_disabled_esb_dpl_tx_noack; 00323 m_uesb_mainstate = UESB_STATE_PTX_TX; 00324 break; 00325 00326 case UESB_PROTOCOL_ESB: 00327 update_rf_payload_format(current_payload->length); 00328 m_tx_payload_buffer[0] = 0xCC | m_pid; 00329 m_tx_payload_buffer[1] = 0; 00330 memcpy(&m_tx_payload_buffer[2], current_payload->data, current_payload->length); 00331 00332 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_RXEN_Msk; 00333 NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk | RADIO_INTENSET_READY_Msk; 00334 00335 // Configure the retransmit counter 00336 m_retransmits_remaining = m_config_local.retransmit_count; 00337 on_radio_disabled = on_radio_disabled_esb_dpl_tx; 00338 m_uesb_mainstate = UESB_STATE_PTX_TX_ACK; 00339 break; 00340 00341 case UESB_PROTOCOL_ESB_DPL: 00342 ack = current_payload->noack == 0 || m_config_local.dynamic_ack_enabled == 0; 00343 m_tx_payload_buffer[0] = current_payload->length; 00344 m_tx_payload_buffer[1] = m_pid << 1 | ((current_payload->noack == 0 && m_config_local.dynamic_ack_enabled) ? 0x01 : 0x00); 00345 memcpy(&m_tx_payload_buffer[2], current_payload->data, current_payload->length); 00346 if(ack) 00347 { 00348 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_RXEN_Msk; 00349 NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk | RADIO_INTENSET_READY_Msk; 00350 00351 // Configure the retransmit counter 00352 m_retransmits_remaining = m_config_local.retransmit_count; 00353 on_radio_disabled = on_radio_disabled_esb_dpl_tx; 00354 m_uesb_mainstate = UESB_STATE_PTX_TX_ACK; 00355 } 00356 else 00357 { 00358 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON; 00359 NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; 00360 on_radio_disabled = on_radio_disabled_esb_dpl_tx_noack; 00361 m_uesb_mainstate = UESB_STATE_PTX_TX; 00362 } 00363 break; 00364 } 00365 00366 NRF_RADIO->TXADDRESS = current_payload->pipe; 00367 NRF_RADIO->RXADDRESSES = 1 << current_payload->pipe; 00368 00369 NRF_RADIO->FREQUENCY = m_config_local.rf_channel; 00370 00371 NRF_RADIO->PACKETPTR = (uint32_t)m_tx_payload_buffer; 00372 00373 NVIC_ClearPendingIRQ(RADIO_IRQn); 00374 NVIC_EnableIRQ(RADIO_IRQn); 00375 00376 NRF_RADIO->EVENTS_ADDRESS = NRF_RADIO->EVENTS_PAYLOAD = NRF_RADIO->EVENTS_DISABLED = 0; 00377 DEBUG_PIN_SET(DEBUGPIN4); 00378 NRF_RADIO->TASKS_TXEN = 1; 00379 } 00380 00381 static uint32_t write_tx_payload(uesb_payload_t *payload, bool noack) // ~50us @ 61 bytes SB 00382 { 00383 if(m_uesb_mainstate == UESB_STATE_UNINITIALIZED) return UESB_ERROR_NOT_INITIALIZED; 00384 if(m_tx_fifo.count >= UESB_CORE_TX_FIFO_SIZE) return UESB_ERROR_TX_FIFO_FULL; 00385 00386 DISABLE_RF_IRQ; 00387 if(noack && m_config_local.dynamic_ack_enabled) payload->noack = 1; 00388 else payload->noack = 0; 00389 memcpy(m_tx_fifo.payload_ptr[m_tx_fifo.entry_point], payload, sizeof(uesb_payload_t)); 00390 m_tx_fifo.entry_point++; 00391 if(m_tx_fifo.entry_point >= UESB_CORE_TX_FIFO_SIZE) m_tx_fifo.entry_point = 0; 00392 m_tx_fifo.count++; 00393 ENABLE_RF_IRQ; 00394 00395 if(m_config_local.tx_mode == UESB_TXMODE_AUTO && m_uesb_mainstate == UESB_STATE_IDLE) 00396 { 00397 start_tx_transaction(); 00398 } 00399 00400 return UESB_SUCCESS; 00401 } 00402 00403 uint32_t uesb_write_tx_payload(uesb_payload_t *payload) 00404 { 00405 return write_tx_payload(payload, false); 00406 } 00407 00408 uint32_t uesb_write_tx_payload_noack(uesb_payload_t *payload) 00409 { 00410 if(m_config_local.dynamic_ack_enabled == 0) return UESB_ERROR_DYN_ACK_NOT_ENABLED; 00411 return write_tx_payload(payload, true); 00412 } 00413 00414 uint32_t uesb_write_ack_payload(uesb_payload_t *payload) 00415 { 00416 if(m_uesb_mainstate == UESB_STATE_UNINITIALIZED) return UESB_ERROR_NOT_INITIALIZED; 00417 if((m_uesb_mainstate != UESB_STATE_PRX) && 00418 (m_uesb_mainstate != UESB_STATE_PRX_SEND_ACK) && 00419 (m_uesb_mainstate != UESB_STATE_PRX_SEND_ACK_PAYLOAD)) 00420 { 00421 return UESB_ERROR_NOT_IN_RX_MODE; 00422 } 00423 if(m_tx_fifo.count >= UESB_CORE_TX_FIFO_SIZE) return UESB_ERROR_TX_FIFO_FULL; 00424 00425 DISABLE_RF_IRQ; 00426 memcpy(m_tx_fifo.payload_ptr[m_tx_fifo.entry_point], payload, sizeof(uesb_payload_t)); 00427 m_tx_fifo.entry_point++; 00428 if(m_tx_fifo.entry_point >= UESB_CORE_TX_FIFO_SIZE) m_tx_fifo.entry_point = 0; 00429 m_tx_fifo.count++; 00430 ENABLE_RF_IRQ; 00431 00432 return UESB_SUCCESS; 00433 } 00434 00435 00436 uint32_t uesb_start_tx() 00437 { 00438 if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE; 00439 if(m_tx_fifo.count == 0) return UESB_ERROR_TX_FIFO_EMPTY; 00440 start_tx_transaction(); 00441 return UESB_SUCCESS; 00442 } 00443 00444 uint32_t uesb_start_rx(void) 00445 { 00446 if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE; 00447 00448 NRF_RADIO->INTENCLR = 0xFFFFFFFF; 00449 NRF_RADIO->EVENTS_DISABLED = 0; 00450 on_radio_disabled = on_radio_disabled_esb_dpl_rx; 00451 switch(m_config_local.protocol) 00452 { 00453 case UESB_PROTOCOL_SB: 00454 NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_START_Msk; 00455 NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk; 00456 m_uesb_mainstate = UESB_STATE_PRX; 00457 break; 00458 case UESB_PROTOCOL_ESB: 00459 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_TXEN_Msk; 00460 NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; 00461 m_uesb_mainstate = UESB_STATE_PRX; 00462 break; 00463 case UESB_PROTOCOL_ESB_DPL: 00464 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_TXEN_Msk; 00465 NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; 00466 m_uesb_mainstate = UESB_STATE_PRX; 00467 break; 00468 } 00469 00470 NRF_RADIO->RXADDRESSES = m_config_local.rx_pipes_enabled; 00471 00472 NRF_RADIO->FREQUENCY = m_config_local.rf_channel; 00473 00474 NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer; 00475 00476 NVIC_ClearPendingIRQ(RADIO_IRQn); 00477 NVIC_EnableIRQ(RADIO_IRQn); 00478 00479 NRF_RADIO->EVENTS_ADDRESS = NRF_RADIO->EVENTS_PAYLOAD = NRF_RADIO->EVENTS_DISABLED = 0; 00480 NRF_RADIO->TASKS_RXEN = 1; 00481 return UESB_SUCCESS; 00482 } 00483 00484 uint32_t uesb_stop_rx(void) 00485 { 00486 if((m_uesb_mainstate == UESB_STATE_PRX) || (m_uesb_mainstate == UESB_STATE_PRX_SEND_ACK_PAYLOAD)) 00487 { 00488 NRF_RADIO->SHORTS = 0; 00489 NRF_RADIO->INTENCLR = 0xFFFFFFFF; 00490 on_radio_disabled = NULL; 00491 NRF_RADIO->EVENTS_DISABLED = 0; 00492 NRF_RADIO->TASKS_DISABLE = 1; 00493 while(NRF_RADIO->EVENTS_DISABLED == 0); 00494 m_uesb_mainstate = UESB_STATE_IDLE; 00495 return UESB_SUCCESS; 00496 } 00497 return UESB_ERROR_NOT_IN_RX_MODE; 00498 } 00499 00500 uint32_t uesb_get_tx_attempts(uint32_t *attempts) 00501 { 00502 if(m_uesb_mainstate == UESB_STATE_UNINITIALIZED) return UESB_ERROR_NOT_INITIALIZED; 00503 *attempts = m_last_tx_attempts; 00504 return UESB_SUCCESS; 00505 } 00506 00507 uint32_t uesb_flush_tx(void) 00508 { 00509 if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE; 00510 DISABLE_RF_IRQ; 00511 m_tx_fifo.count = 0; 00512 m_tx_fifo.entry_point = m_tx_fifo.exit_point = 0; 00513 ENABLE_RF_IRQ; 00514 return UESB_SUCCESS; 00515 } 00516 00517 uint32_t uesb_flush_rx(void) 00518 { 00519 DISABLE_RF_IRQ; 00520 m_rx_fifo.count = 0; 00521 m_rx_fifo.entry_point = 0; 00522 ENABLE_RF_IRQ; 00523 return UESB_SUCCESS; 00524 } 00525 00526 uint32_t uesb_get_clear_interrupts(uint32_t *interrupts) 00527 { 00528 DISABLE_RF_IRQ; 00529 *interrupts = m_interrupt_flags; 00530 m_interrupt_flags = 0; 00531 ENABLE_RF_IRQ; 00532 return UESB_SUCCESS; 00533 } 00534 00535 uint32_t uesb_set_address(uesb_address_type_t address, const uint8_t *data_ptr) 00536 { 00537 if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE; 00538 switch(address) 00539 { 00540 case UESB_ADDRESS_PIPE0: 00541 memcpy(m_config_local.rx_address_p0, data_ptr, m_config_local.rf_addr_length); 00542 break; 00543 case UESB_ADDRESS_PIPE1: 00544 memcpy(m_config_local.rx_address_p1, data_ptr, m_config_local.rf_addr_length); 00545 break; 00546 case UESB_ADDRESS_PIPE2: 00547 m_config_local.rx_address_p2 = *data_ptr; 00548 break; 00549 case UESB_ADDRESS_PIPE3: 00550 m_config_local.rx_address_p3 = *data_ptr; 00551 break; 00552 case UESB_ADDRESS_PIPE4: 00553 m_config_local.rx_address_p4 = *data_ptr; 00554 break; 00555 case UESB_ADDRESS_PIPE5: 00556 m_config_local.rx_address_p5 = *data_ptr; 00557 break; 00558 case UESB_ADDRESS_PIPE6: 00559 m_config_local.rx_address_p6 = *data_ptr; 00560 break; 00561 case UESB_ADDRESS_PIPE7: 00562 m_config_local.rx_address_p7 = *data_ptr; 00563 break; 00564 default: 00565 return UESB_ERROR_INVALID_PARAMETERS; 00566 } 00567 update_radio_parameters(); 00568 return UESB_SUCCESS; 00569 } 00570 00571 uint32_t uesb_set_rf_channel(uint32_t channel) 00572 { 00573 if(channel > 125) return UESB_ERROR_INVALID_PARAMETERS; 00574 m_config_local.rf_channel = channel; 00575 return UESB_SUCCESS; 00576 } 00577 00578 uint32_t uesb_set_tx_power(uesb_tx_power_t tx_output_power) 00579 { 00580 if(m_uesb_mainstate != UESB_STATE_IDLE) return UESB_ERROR_NOT_IDLE; 00581 if ( m_config_local.tx_output_power == tx_output_power ) return UESB_SUCCESS; 00582 m_config_local.tx_output_power = tx_output_power; 00583 update_radio_parameters(); 00584 return UESB_SUCCESS; 00585 } 00586 00587 /* 00588 00589 void RADIO_IRQHandler() 00590 { 00591 if(NRF_RADIO->EVENTS_READY && (NRF_RADIO->INTENSET & RADIO_INTENSET_READY_Msk)) 00592 { 00593 NRF_RADIO->EVENTS_READY = 0; 00594 00595 DEBUG_PIN_SET(DEBUGPIN1); 00596 } 00597 00598 if(NRF_RADIO->EVENTS_END && (NRF_RADIO->INTENSET & RADIO_INTENSET_END_Msk)) 00599 { 00600 NRF_RADIO->EVENTS_END = 0; 00601 00602 DEBUG_PIN_SET(DEBUGPIN2); 00603 00604 // Call the correct on_radio_end function, depending on the current protocol state 00605 if(on_radio_end) 00606 { 00607 on_radio_end(); 00608 } 00609 } 00610 00611 if(NRF_RADIO->EVENTS_DISABLED && (NRF_RADIO->INTENSET & RADIO_INTENSET_DISABLED_Msk)) 00612 { 00613 NRF_RADIO->EVENTS_DISABLED = 0; 00614 00615 DEBUG_PIN_SET(DEBUGPIN3); 00616 00617 // Call the correct on_radio_disable function, depending on the current protocol state 00618 if(on_radio_disabled) 00619 { 00620 on_radio_disabled(); 00621 } 00622 } 00623 00624 DEBUG_PIN_CLR(DEBUGPIN1); 00625 DEBUG_PIN_CLR(DEBUGPIN2); 00626 DEBUG_PIN_CLR(DEBUGPIN3); 00627 DEBUG_PIN_CLR(DEBUGPIN4); 00628 } */ 00629 00630 static void on_radio_disabled_esb_dpl_tx_noack() 00631 { 00632 m_interrupt_flags |= UESB_INT_TX_SUCCESS_MSK; 00633 tx_fifo_remove_last(); 00634 00635 if(m_tx_fifo.count == 0) 00636 { 00637 m_uesb_mainstate = UESB_STATE_IDLE; 00638 if(m_event_handler != 0) m_event_handler(); 00639 } 00640 else 00641 { 00642 if(m_event_handler != 0) m_event_handler(); 00643 start_tx_transaction(); 00644 } 00645 } 00646 00647 static void on_radio_disabled_esb_dpl_tx() 00648 { 00649 // Remove the DISABLED -> RXEN shortcut, to make sure the radio stays disabled after the RX window 00650 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON; 00651 00652 // Make sure the timer is started the next time the radio is ready, 00653 // and that it will disable the radio automatically if no packet is received by the time defined in m_wait_for_ack_timeout_us 00654 UESB_SYS_TIMER->CC[0] = m_wait_for_ack_timeout_us; 00655 UESB_SYS_TIMER->CC[1] = m_config_local.retransmit_delay - 130; 00656 UESB_SYS_TIMER->TASKS_CLEAR = 1; 00657 UESB_SYS_TIMER->EVENTS_COMPARE[0] = 0; 00658 UESB_SYS_TIMER->EVENTS_COMPARE[1] = 0; 00659 NRF_PPI->CHENSET = (1 << UESB_PPI_TIMER_START) | (1 << UESB_PPI_RX_TIMEOUT) | (1 << UESB_PPI_TIMER_STOP); 00660 NRF_PPI->CHENCLR = (1 << UESB_PPI_TX_START); 00661 NRF_RADIO->EVENTS_END = 0; 00662 if(m_config_local.protocol == UESB_PROTOCOL_ESB) 00663 { 00664 update_rf_payload_format(0); 00665 } 00666 NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer; 00667 on_radio_disabled = on_radio_disabled_esb_dpl_tx_wait_for_ack; 00668 m_uesb_mainstate = UESB_STATE_PTX_RX_ACK; 00669 } 00670 00671 static void on_radio_disabled_esb_dpl_tx_wait_for_ack() 00672 { 00673 // This marks the completion of a TX_RX sequence (TX with ACK) 00674 00675 // Make sure the timer will not deactivate the radio if a packet is received 00676 NRF_PPI->CHENCLR = (1 << UESB_PPI_TIMER_START) | (1 << UESB_PPI_RX_TIMEOUT) | (1 << UESB_PPI_TIMER_STOP); 00677 00678 // If the radio has received a packet and the CRC status is OK 00679 if(NRF_RADIO->EVENTS_END && NRF_RADIO->CRCSTATUS != 0) 00680 { 00681 UESB_SYS_TIMER->TASKS_STOP = 1; 00682 NRF_PPI->CHENCLR = (1 << UESB_PPI_TX_START); 00683 m_interrupt_flags |= UESB_INT_TX_SUCCESS_MSK; 00684 m_last_tx_attempts = m_config_local.retransmit_count - m_retransmits_remaining + 1; 00685 tx_fifo_remove_last(); 00686 if(m_rx_payload_buffer[0] > 0) 00687 { 00688 if(rx_fifo_push_rfbuf((uint8_t)NRF_RADIO->TXADDRESS)) 00689 { 00690 m_interrupt_flags |= UESB_INT_RX_DR_MSK; 00691 } 00692 } 00693 00694 if((m_tx_fifo.count == 0) || (m_config_local.tx_mode == UESB_TXMODE_MANUAL)) 00695 { 00696 m_uesb_mainstate = UESB_STATE_IDLE; 00697 if(m_event_handler != 0) m_event_handler(); 00698 } 00699 else 00700 { 00701 if(m_event_handler != 0) m_event_handler(); 00702 start_tx_transaction(); 00703 } 00704 } 00705 else 00706 { 00707 if(m_retransmits_remaining-- == 0) 00708 { 00709 UESB_SYS_TIMER->TASKS_STOP = 1; 00710 NRF_PPI->CHENCLR = (1 << UESB_PPI_TX_START); 00711 // All retransmits are expended, and the TX operation is suspended 00712 m_last_tx_attempts = m_config_local.retransmit_count + 1; 00713 m_interrupt_flags |= UESB_INT_TX_FAILED_MSK; 00714 00715 m_uesb_mainstate = UESB_STATE_IDLE; 00716 if(m_event_handler != 0) m_event_handler(); 00717 } 00718 else 00719 { 00720 // We still have more retransmits left, and we should enter TX mode again as soon as the system timer reaches CC[1] 00721 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_RXEN_Msk; 00722 update_rf_payload_format(current_payload->length); 00723 NRF_RADIO->PACKETPTR = (uint32_t)m_tx_payload_buffer; 00724 on_radio_disabled = on_radio_disabled_esb_dpl_tx; 00725 m_uesb_mainstate = UESB_STATE_PTX_TX_ACK; 00726 UESB_SYS_TIMER->TASKS_START = 1; 00727 NRF_PPI->CHENSET = (1 << UESB_PPI_TX_START); 00728 if(UESB_SYS_TIMER->EVENTS_COMPARE[1]) 00729 { 00730 NRF_RADIO->TASKS_TXEN = 1; 00731 } 00732 } 00733 } 00734 } 00735 00736 static void on_radio_disabled_esb_dpl_rx(void) 00737 { 00738 bool send_ack = false; 00739 bool set_rx_interrupt = false; 00740 if(NRF_RADIO->CRCSTATUS != 0 && m_rx_fifo.count < UESB_CORE_RX_FIFO_SIZE) 00741 { 00742 send_ack = true; 00743 } 00744 if(send_ack) 00745 { 00746 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_RXEN_Msk; 00747 00748 // For a packet to be considered new (and not a retransmit) the PID or the CRC has to be different 00749 if(NRF_RADIO->RXCRC != m_last_rx_packet_crc || (m_rx_payload_buffer[1] >> 1) != m_last_rx_packet_pid) 00750 { 00751 if((m_uesb_mainstate == UESB_STATE_PRX_SEND_ACK_PAYLOAD) && (m_tx_fifo.count > 0)) 00752 { 00753 // It is assumed that the last ACK payload was recieved. 00754 if(++m_tx_fifo.exit_point >= UESB_CORE_RX_FIFO_SIZE) m_tx_fifo.exit_point = 0; 00755 m_tx_fifo.count--; 00756 00757 // ACK payloads also require TX_DS (page 40 of the 'nRF24LE1_Product_Specification_rev1_6.pdf'). 00758 m_interrupt_flags |= UESB_INT_TX_SUCCESS_MSK; 00759 } 00760 00761 set_rx_interrupt = true; 00762 m_last_rx_packet_pid = m_rx_payload_buffer[1] >> 1; 00763 m_last_rx_packet_crc = NRF_RADIO->RXCRC; 00764 } 00765 00766 if(m_config_local.protocol == UESB_PROTOCOL_ESB_DPL) 00767 { 00768 if(m_tx_fifo.count > 0) 00769 { 00770 current_payload = m_tx_fifo.payload_ptr[m_tx_fifo.exit_point]; 00771 00772 update_rf_payload_format(current_payload->length); 00773 m_tx_payload_buffer[0] = current_payload->length; 00774 memcpy(&m_tx_payload_buffer[2], current_payload->data, current_payload->length); 00775 00776 m_uesb_mainstate = UESB_STATE_PRX_SEND_ACK_PAYLOAD; 00777 } 00778 else 00779 { 00780 update_rf_payload_format(0); 00781 m_tx_payload_buffer[0] = 0; 00782 00783 m_uesb_mainstate = UESB_STATE_PRX_SEND_ACK; 00784 } 00785 00786 m_tx_payload_buffer[1] = m_rx_payload_buffer[1]; 00787 } 00788 else if(m_config_local.protocol == UESB_PROTOCOL_ESB) 00789 { 00790 m_tx_payload_buffer[0] = m_rx_payload_buffer[0]; 00791 m_tx_payload_buffer[1] = 0; 00792 00793 m_uesb_mainstate = UESB_STATE_PRX_SEND_ACK; 00794 } 00795 00796 NRF_RADIO->TXADDRESS = NRF_RADIO->RXMATCH; 00797 NRF_RADIO->PACKETPTR = (uint32_t)m_tx_payload_buffer; 00798 00799 on_radio_disabled = on_radio_disabled_esb_dpl_rx_ack; 00800 } 00801 else 00802 { 00803 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON; 00804 update_rf_payload_format(m_config_local.payload_length); 00805 NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer; 00806 NRF_RADIO->EVENTS_DISABLED = 0; 00807 NRF_RADIO->TASKS_DISABLE = 1; 00808 while(NRF_RADIO->EVENTS_DISABLED == 0); 00809 NRF_RADIO->EVENTS_DISABLED = 0; 00810 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_TXEN_Msk; 00811 NRF_RADIO->TASKS_RXEN = 1; 00812 } 00813 if(set_rx_interrupt) 00814 { 00815 rx_fifo_push_rfbuf(NRF_RADIO->RXMATCH); 00816 m_interrupt_flags |= UESB_INT_RX_DR_MSK; 00817 if(m_event_handler != 0) m_event_handler(); 00818 } 00819 } 00820 00821 static void on_radio_disabled_esb_dpl_rx_ack(void) 00822 { 00823 NRF_RADIO->SHORTS = RADIO_SHORTS_COMMON | RADIO_SHORTS_DISABLED_TXEN_Msk; 00824 update_rf_payload_format(m_config_local.payload_length); 00825 NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer; 00826 on_radio_disabled = on_radio_disabled_esb_dpl_rx; 00827 00828 if(m_uesb_mainstate == UESB_STATE_PRX_SEND_ACK) 00829 { 00830 // In the case of UESB_STATE_PRX_SEND_ACK_PAYLOAD the state will be updated when the next packet is received. 00831 m_uesb_mainstate = UESB_STATE_PRX; 00832 } 00833 } 00834 00835 static void on_radio_end_sb_tx(void) 00836 { 00837 m_interrupt_flags |= UESB_INT_TX_SUCCESS_MSK; 00838 tx_fifo_remove_last(); 00839 if(m_config_local.tx_mode == UESB_TXMODE_MANUAL || m_tx_fifo.count == 0) 00840 { 00841 // No more packets to send. Disable the radio and set the state to idle. 00842 NRF_RADIO->EVENTS_DISABLED = 0; 00843 NRF_RADIO->TASKS_DISABLE = 1; 00844 while(!NRF_RADIO->EVENTS_DISABLED); 00845 NRF_RADIO->EVENTS_DISABLED = 0; 00846 m_uesb_mainstate = UESB_STATE_IDLE; 00847 if(m_event_handler != 0) m_event_handler(); 00848 } 00849 else 00850 { 00851 // Send another packet automatically without disabling the radio first. 00852 current_payload = m_tx_fifo.payload_ptr[m_tx_fifo.exit_point]; 00853 00854 update_rf_payload_format(current_payload->length); 00855 memcpy(&m_tx_payload_buffer[0], current_payload->data, current_payload->length); 00856 00857 NRF_RADIO->TXADDRESS = current_payload->pipe; 00858 00859 NVIC_ClearPendingIRQ(RADIO_IRQn); 00860 NVIC_EnableIRQ(RADIO_IRQn); 00861 00862 NRF_RADIO->EVENTS_ADDRESS = NRF_RADIO->EVENTS_PAYLOAD = 0; 00863 NRF_RADIO->TASKS_START = 1; 00864 00865 } 00866 } 00867 00868 static void on_radio_end_sb_rx(void) 00869 { 00870 if(NRF_RADIO->CRCSTATUS != 0 && rx_fifo_push_rfbuf(NRF_RADIO->RXMATCH)) 00871 { 00872 m_interrupt_flags |= UESB_INT_RX_DR_MSK; 00873 if(m_event_handler != 0) m_event_handler(); 00874 } 00875 } 00876
Generated on Sun Jul 17 2022 00:47:52 by 1.7.2