NRF52_esb

Committer:
wkleunen
Date:
Thu Feb 04 10:36:44 2021 +0000
Revision:
1:66f95e364222
Initial compile;

Who changed what in which revision?

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