NRF52_esb

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers micro_esb.cpp Source File

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