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 /**
wkleunen 1:66f95e364222 2 * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
wkleunen 1:66f95e364222 3 *
wkleunen 1:66f95e364222 4 * All rights reserved.
wkleunen 1:66f95e364222 5 *
wkleunen 1:66f95e364222 6 * Redistribution and use in source and binary forms, with or without modification,
wkleunen 1:66f95e364222 7 * are permitted provided that the following conditions are met:
wkleunen 1:66f95e364222 8 *
wkleunen 1:66f95e364222 9 * 1. Redistributions of source code must retain the above copyright notice, this
wkleunen 1:66f95e364222 10 * list of conditions and the following disclaimer.
wkleunen 1:66f95e364222 11 *
wkleunen 1:66f95e364222 12 * 2. Redistributions in binary form, except as embedded into a Nordic
wkleunen 1:66f95e364222 13 * Semiconductor ASA integrated circuit in a product or a software update for
wkleunen 1:66f95e364222 14 * such product, must reproduce the above copyright notice, this list of
wkleunen 1:66f95e364222 15 * conditions and the following disclaimer in the documentation and/or other
wkleunen 1:66f95e364222 16 * materials provided with the distribution.
wkleunen 1:66f95e364222 17 *
wkleunen 1:66f95e364222 18 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
wkleunen 1:66f95e364222 19 * contributors may be used to endorse or promote products derived from this
wkleunen 1:66f95e364222 20 * software without specific prior written permission.
wkleunen 1:66f95e364222 21 *
wkleunen 1:66f95e364222 22 * 4. This software, with or without modification, must only be used with a
wkleunen 1:66f95e364222 23 * Nordic Semiconductor ASA integrated circuit.
wkleunen 1:66f95e364222 24 *
wkleunen 1:66f95e364222 25 * 5. Any software provided in binary form under this license must not be reverse
wkleunen 1:66f95e364222 26 * engineered, decompiled, modified and/or disassembled.
wkleunen 1:66f95e364222 27 *
wkleunen 1:66f95e364222 28 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
wkleunen 1:66f95e364222 29 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
wkleunen 1:66f95e364222 30 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
wkleunen 1:66f95e364222 31 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
wkleunen 1:66f95e364222 32 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
wkleunen 1:66f95e364222 33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
wkleunen 1:66f95e364222 34 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
wkleunen 1:66f95e364222 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
wkleunen 1:66f95e364222 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
wkleunen 1:66f95e364222 37 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
wkleunen 1:66f95e364222 38 *
wkleunen 1:66f95e364222 39 */
wkleunen 1:66f95e364222 40
wkleunen 1:66f95e364222 41 #include "nrf_error.h"
wkleunen 1:66f95e364222 42 #include "nrf_esb.h"
wkleunen 1:66f95e364222 43 #include "nrf_esb_error_codes.h"
wkleunen 1:66f95e364222 44 #include "nrf_gpio.h"
wkleunen 1:66f95e364222 45 #include <string.h>
wkleunen 1:66f95e364222 46 #include <stddef.h>
wkleunen 1:66f95e364222 47 #include "sdk_common.h"
wkleunen 1:66f95e364222 48 #include "sdk_macros.h"
wkleunen 1:66f95e364222 49 #include "app_util.h"
wkleunen 1:66f95e364222 50 #include "nrf_log.h"
wkleunen 1:66f95e364222 51 #include "nrf_delay.h"
wkleunen 1:66f95e364222 52
wkleunen 1:66f95e364222 53 #define BIT_MASK_UINT_8(x) (0xFF >> (8 - (x)))
wkleunen 1:66f95e364222 54 #define NRF_ESB_PIPE_COUNT 8
wkleunen 1:66f95e364222 55
wkleunen 1:66f95e364222 56 // Constant parameters
wkleunen 1:66f95e364222 57 #define RX_WAIT_FOR_ACK_TIMEOUT_US_2MBPS (48) /**< 2 Mb RX wait for acknowledgment time-out value. Smallest reliable value - 43. */
wkleunen 1:66f95e364222 58 #define RX_WAIT_FOR_ACK_TIMEOUT_US_1MBPS (64) /**< 1 Mb RX wait for acknowledgment time-out value. Smallest reliable value - 59. */
wkleunen 1:66f95e364222 59 #define RX_WAIT_FOR_ACK_TIMEOUT_US_250KBPS (250) /**< 250 Kb RX wait for acknowledgment time-out value. */
wkleunen 1:66f95e364222 60 #define RX_WAIT_FOR_ACK_TIMEOUT_US_1MBPS_BLE (73) /**< 1 Mb RX wait for acknowledgment time-out (combined with BLE). Smallest reliable value - 68.*/
wkleunen 1:66f95e364222 61
wkleunen 1:66f95e364222 62 // Interrupt flags
wkleunen 1:66f95e364222 63 #define NRF_ESB_INT_TX_SUCCESS_MSK 0x01 /**< Interrupt mask value for TX success. */
wkleunen 1:66f95e364222 64 #define NRF_ESB_INT_TX_FAILED_MSK 0x02 /**< Interrupt mask value for TX failure. */
wkleunen 1:66f95e364222 65 #define NRF_ESB_INT_RX_DATA_RECEIVED_MSK 0x04 /**< Interrupt mask value for RX_DR. */
wkleunen 1:66f95e364222 66
wkleunen 1:66f95e364222 67 #define NRF_ESB_PID_RESET_VALUE 0xFF /**< Invalid PID value which is guaranteed to not collide with any valid PID value. */
wkleunen 1:66f95e364222 68 #define NRF_ESB_PID_MAX 3 /**< Maximum value for PID. */
wkleunen 1:66f95e364222 69 #define NRF_ESB_CRC_RESET_VALUE 0xFFFF /**< CRC reset value. */
wkleunen 1:66f95e364222 70
wkleunen 1:66f95e364222 71 // Internal Enhanced ShockBurst module state.
wkleunen 1:66f95e364222 72 typedef enum {
wkleunen 1:66f95e364222 73 NRF_ESB_STATE_IDLE, /**< Module idle. */
wkleunen 1:66f95e364222 74 NRF_ESB_STATE_PTX_TX, /**< Module transmitting without acknowledgment. */
wkleunen 1:66f95e364222 75 NRF_ESB_STATE_PTX_TX_ACK, /**< Module transmitting with acknowledgment. */
wkleunen 1:66f95e364222 76 NRF_ESB_STATE_PTX_RX_ACK, /**< Module transmitting with acknowledgment and reception of payload with the acknowledgment response. */
wkleunen 1:66f95e364222 77 NRF_ESB_STATE_PRX, /**< Module receiving packets without acknowledgment. */
wkleunen 1:66f95e364222 78 NRF_ESB_STATE_PRX_SEND_ACK, /**< Module transmitting acknowledgment in RX mode. */
wkleunen 1:66f95e364222 79 } nrf_esb_mainstate_t;
wkleunen 1:66f95e364222 80
wkleunen 1:66f95e364222 81
wkleunen 1:66f95e364222 82 #define DISABLE_RF_IRQ() NVIC_DisableIRQ(RADIO_IRQn)
wkleunen 1:66f95e364222 83 #define ENABLE_RF_IRQ() NVIC_EnableIRQ(RADIO_IRQn)
wkleunen 1:66f95e364222 84
wkleunen 1:66f95e364222 85 #define _RADIO_SHORTS_COMMON ( RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk | \
wkleunen 1:66f95e364222 86 RADIO_SHORTS_ADDRESS_RSSISTART_Msk | RADIO_SHORTS_DISABLED_RSSISTOP_Msk )
wkleunen 1:66f95e364222 87
wkleunen 1:66f95e364222 88 #define VERIFY_PAYLOAD_LENGTH(p) \
wkleunen 1:66f95e364222 89 do \
wkleunen 1:66f95e364222 90 { \
wkleunen 1:66f95e364222 91 if (p->length == 0 || \
wkleunen 1:66f95e364222 92 p->length > NRF_ESB_MAX_PAYLOAD_LENGTH || \
wkleunen 1:66f95e364222 93 (m_config_local.protocol == NRF_ESB_PROTOCOL_ESB && \
wkleunen 1:66f95e364222 94 p->length > m_config_local.payload_length)) \
wkleunen 1:66f95e364222 95 { \
wkleunen 1:66f95e364222 96 return NRF_ERROR_INVALID_LENGTH; \
wkleunen 1:66f95e364222 97 } \
wkleunen 1:66f95e364222 98 }while (0)
wkleunen 1:66f95e364222 99
wkleunen 1:66f95e364222 100
wkleunen 1:66f95e364222 101 /* @brief Structure holding pipe info PID and CRC and acknowledgment payload. */
wkleunen 1:66f95e364222 102 typedef struct
wkleunen 1:66f95e364222 103 {
wkleunen 1:66f95e364222 104 uint16_t crc; /**< CRC value of the last received packet (Used to detect retransmits). */
wkleunen 1:66f95e364222 105 uint8_t pid; /**< Packet ID of the last received packet (Used to detect retransmits). */
wkleunen 1:66f95e364222 106 bool ack_payload; /**< Flag indicating the state of the transmission of acknowledgment payloads. */
wkleunen 1:66f95e364222 107 } pipe_info_t;
wkleunen 1:66f95e364222 108
wkleunen 1:66f95e364222 109
wkleunen 1:66f95e364222 110 /* @brief First-in, first-out queue of payloads to be transmitted. */
wkleunen 1:66f95e364222 111 typedef struct
wkleunen 1:66f95e364222 112 {
wkleunen 1:66f95e364222 113 nrf_esb_payload_t * p_payload[NRF_ESB_TX_FIFO_SIZE]; /**< Pointer to the actual queue. */
wkleunen 1:66f95e364222 114 uint32_t entry_point; /**< Current start of queue. */
wkleunen 1:66f95e364222 115 uint32_t exit_point; /**< Current end of queue. */
wkleunen 1:66f95e364222 116 uint32_t count; /**< Current number of elements in the queue. */
wkleunen 1:66f95e364222 117 } nrf_esb_payload_tx_fifo_t;
wkleunen 1:66f95e364222 118
wkleunen 1:66f95e364222 119
wkleunen 1:66f95e364222 120 /* @brief First-in, first-out queue of received payloads. */
wkleunen 1:66f95e364222 121 typedef struct
wkleunen 1:66f95e364222 122 {
wkleunen 1:66f95e364222 123 nrf_esb_payload_t * p_payload[NRF_ESB_RX_FIFO_SIZE]; /**< Pointer to the actual queue. */
wkleunen 1:66f95e364222 124 uint32_t entry_point; /**< Current start of queue. */
wkleunen 1:66f95e364222 125 uint32_t exit_point; /**< Current end of queue. */
wkleunen 1:66f95e364222 126 uint32_t count; /**< Current number of elements in the queue. */
wkleunen 1:66f95e364222 127 } nrf_esb_payload_rx_fifo_t;
wkleunen 1:66f95e364222 128
wkleunen 1:66f95e364222 129
wkleunen 1:66f95e364222 130 /**@brief Enhanced ShockBurst address.
wkleunen 1:66f95e364222 131 *
wkleunen 1:66f95e364222 132 * Enhanced ShockBurst addresses consist of a base address and a prefix
wkleunen 1:66f95e364222 133 * that is unique for each pipe. See @ref esb_addressing in the ESB user
wkleunen 1:66f95e364222 134 * guide for more information.
wkleunen 1:66f95e364222 135 */
wkleunen 1:66f95e364222 136 typedef struct
wkleunen 1:66f95e364222 137 {
wkleunen 1:66f95e364222 138 uint8_t base_addr_p0[4]; /**< Base address for pipe 0 encoded in big endian. */
wkleunen 1:66f95e364222 139 uint8_t base_addr_p1[4]; /**< Base address for pipe 1-7 encoded in big endian. */
wkleunen 1:66f95e364222 140 uint8_t pipe_prefixes[8]; /**< Address prefix for pipe 0 to 7. */
wkleunen 1:66f95e364222 141 uint8_t num_pipes; /**< Number of pipes available. */
wkleunen 1:66f95e364222 142 uint8_t addr_length; /**< Length of the address including the prefix. */
wkleunen 1:66f95e364222 143 uint8_t rx_pipes_enabled; /**< Bitfield for enabled pipes. */
wkleunen 1:66f95e364222 144 uint8_t rf_channel; /**< Channel to use (must be between 0 and 100). */
wkleunen 1:66f95e364222 145 } nrf_esb_address_t;
wkleunen 1:66f95e364222 146
wkleunen 1:66f95e364222 147
wkleunen 1:66f95e364222 148 // Module state
wkleunen 1:66f95e364222 149 static bool m_esb_initialized = false;
wkleunen 1:66f95e364222 150 static nrf_esb_mainstate_t m_nrf_esb_mainstate = NRF_ESB_STATE_IDLE;
wkleunen 1:66f95e364222 151 static nrf_esb_payload_t * mp_current_payload;
wkleunen 1:66f95e364222 152
wkleunen 1:66f95e364222 153 static nrf_esb_event_handler_t m_event_handler;
wkleunen 1:66f95e364222 154
wkleunen 1:66f95e364222 155 // Address parameters
wkleunen 1:66f95e364222 156 __ALIGN(4) static nrf_esb_address_t m_esb_addr = NRF_ESB_ADDR_DEFAULT;
wkleunen 1:66f95e364222 157
wkleunen 1:66f95e364222 158 // RF parameters
wkleunen 1:66f95e364222 159 static nrf_esb_config_t m_config_local;
wkleunen 1:66f95e364222 160
wkleunen 1:66f95e364222 161 // TX FIFO
wkleunen 1:66f95e364222 162 static nrf_esb_payload_t m_tx_fifo_payload[NRF_ESB_TX_FIFO_SIZE];
wkleunen 1:66f95e364222 163 static nrf_esb_payload_tx_fifo_t m_tx_fifo;
wkleunen 1:66f95e364222 164
wkleunen 1:66f95e364222 165 // RX FIFO
wkleunen 1:66f95e364222 166 static nrf_esb_payload_t m_rx_fifo_payload[NRF_ESB_RX_FIFO_SIZE];
wkleunen 1:66f95e364222 167 static nrf_esb_payload_rx_fifo_t m_rx_fifo;
wkleunen 1:66f95e364222 168
wkleunen 1:66f95e364222 169 // Payload buffers
wkleunen 1:66f95e364222 170 static uint8_t m_tx_payload_buffer[NRF_ESB_MAX_PAYLOAD_LENGTH + 2];
wkleunen 1:66f95e364222 171 static uint8_t m_rx_payload_buffer[NRF_ESB_MAX_PAYLOAD_LENGTH + 2];
wkleunen 1:66f95e364222 172
wkleunen 1:66f95e364222 173 // Run time variables
wkleunen 1:66f95e364222 174 static volatile uint32_t m_interrupt_flags = 0;
wkleunen 1:66f95e364222 175 static uint8_t m_pids[NRF_ESB_PIPE_COUNT];
wkleunen 1:66f95e364222 176 static pipe_info_t m_rx_pipe_info[NRF_ESB_PIPE_COUNT];
wkleunen 1:66f95e364222 177 static volatile uint32_t m_retransmits_remaining;
wkleunen 1:66f95e364222 178 static volatile uint32_t m_last_tx_attempts;
wkleunen 1:66f95e364222 179 static volatile uint32_t m_wait_for_ack_timeout_us;
wkleunen 1:66f95e364222 180
wkleunen 1:66f95e364222 181 // nRF52 address workaround enable
wkleunen 1:66f95e364222 182 #ifdef NRF52
wkleunen 1:66f95e364222 183 static bool m_address_hang_fix_enable = true;
wkleunen 1:66f95e364222 184 #endif
wkleunen 1:66f95e364222 185 static uint32_t m_radio_shorts_common = _RADIO_SHORTS_COMMON;
wkleunen 1:66f95e364222 186
wkleunen 1:66f95e364222 187 // These function pointers are changed dynamically, depending on protocol configuration and state.
wkleunen 1:66f95e364222 188 static void (*on_radio_disabled)(void) = 0;
wkleunen 1:66f95e364222 189 static void (*on_radio_end)(void) = 0;
wkleunen 1:66f95e364222 190 static void (*update_rf_payload_format)(uint32_t payload_length) = 0;
wkleunen 1:66f95e364222 191
wkleunen 1:66f95e364222 192
wkleunen 1:66f95e364222 193 // The following functions are assigned to the function pointers above.
wkleunen 1:66f95e364222 194 static void on_radio_disabled_tx_noack(void);
wkleunen 1:66f95e364222 195 static void on_radio_disabled_tx(void);
wkleunen 1:66f95e364222 196 static void on_radio_disabled_tx_wait_for_ack(void);
wkleunen 1:66f95e364222 197 static void on_radio_disabled_rx(void);
wkleunen 1:66f95e364222 198 static void on_radio_disabled_rx_ack(void);
wkleunen 1:66f95e364222 199
wkleunen 1:66f95e364222 200
wkleunen 1:66f95e364222 201 #define NRF_ESB_ADDR_UPDATE_MASK_BASE0 (1 << 0) /*< Mask value to signal updating BASE0 radio address. */
wkleunen 1:66f95e364222 202 #define NRF_ESB_ADDR_UPDATE_MASK_BASE1 (1 << 1) /*< Mask value to signal updating BASE1 radio address. */
wkleunen 1:66f95e364222 203 #define NRF_ESB_ADDR_UPDATE_MASK_PREFIX (1 << 2) /*< Mask value to signal updating radio prefixes. */
wkleunen 1:66f95e364222 204
wkleunen 1:66f95e364222 205
wkleunen 1:66f95e364222 206 // Function to do bytewise bit-swap on an unsigned 32-bit value
wkleunen 1:66f95e364222 207 static uint32_t bytewise_bit_swap(uint8_t const * p_inp)
wkleunen 1:66f95e364222 208 {
wkleunen 1:66f95e364222 209 uint32_t inp = (*(uint32_t*)p_inp);
wkleunen 1:66f95e364222 210 #if __CORTEX_M == (0x04U)
wkleunen 1:66f95e364222 211 return __REV((uint32_t)__RBIT(inp)); //lint -esym(628, __rev) -esym(526, __rev) -esym(628, __rbit) -esym(526, __rbit) */
wkleunen 1:66f95e364222 212 #else
wkleunen 1:66f95e364222 213 inp = (inp & 0xF0F0F0F0) >> 4 | (inp & 0x0F0F0F0F) << 4;
wkleunen 1:66f95e364222 214 inp = (inp & 0xCCCCCCCC) >> 2 | (inp & 0x33333333) << 2;
wkleunen 1:66f95e364222 215 inp = (inp & 0xAAAAAAAA) >> 1 | (inp & 0x55555555) << 1;
wkleunen 1:66f95e364222 216 return inp;
wkleunen 1:66f95e364222 217 #endif
wkleunen 1:66f95e364222 218 }
wkleunen 1:66f95e364222 219
wkleunen 1:66f95e364222 220
wkleunen 1:66f95e364222 221 // Internal function to convert base addresses from nRF24L type addressing to nRF51 type addressing
wkleunen 1:66f95e364222 222 static uint32_t addr_conv(uint8_t const* p_addr)
wkleunen 1:66f95e364222 223 {
wkleunen 1:66f95e364222 224 return __REV(bytewise_bit_swap(p_addr)); //lint -esym(628, __rev) -esym(526, __rev) */
wkleunen 1:66f95e364222 225 }
wkleunen 1:66f95e364222 226
wkleunen 1:66f95e364222 227
wkleunen 1:66f95e364222 228 static ret_code_t apply_address_workarounds()
wkleunen 1:66f95e364222 229 {
wkleunen 1:66f95e364222 230 #ifdef NRF52
wkleunen 1:66f95e364222 231 // Set up radio parameters.
wkleunen 1:66f95e364222 232 NRF_RADIO->MODECNF0 = (NRF_RADIO->MODECNF0 & ~RADIO_MODECNF0_RU_Msk) | RADIO_MODECNF0_RU_Default << RADIO_MODECNF0_RU_Pos;
wkleunen 1:66f95e364222 233
wkleunen 1:66f95e364222 234 // Workaround for nRF52832 Rev 1 Errata 102 and nRF52832 Rev 1 Errata 106. This will reduce sensitivity by 3dB.
wkleunen 1:66f95e364222 235 *((volatile uint32_t *)0x40001774) = (*((volatile uint32_t *)0x40001774) & 0xFFFFFFFE) | 0x01000000;
wkleunen 1:66f95e364222 236 #endif
wkleunen 1:66f95e364222 237 return NRF_SUCCESS;
wkleunen 1:66f95e364222 238 }
wkleunen 1:66f95e364222 239
wkleunen 1:66f95e364222 240
wkleunen 1:66f95e364222 241 static void update_rf_payload_format_esb_dpl(uint32_t payload_length)
wkleunen 1:66f95e364222 242 {
wkleunen 1:66f95e364222 243 #if (NRF_ESB_MAX_PAYLOAD_LENGTH <= 32)
wkleunen 1:66f95e364222 244 // Using 6 bits for length
wkleunen 1:66f95e364222 245 NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) |
wkleunen 1:66f95e364222 246 (6 << RADIO_PCNF0_LFLEN_Pos) |
wkleunen 1:66f95e364222 247 (3 << RADIO_PCNF0_S1LEN_Pos) ;
wkleunen 1:66f95e364222 248 #else
wkleunen 1:66f95e364222 249 // Using 8 bits for length
wkleunen 1:66f95e364222 250 NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) |
wkleunen 1:66f95e364222 251 (8 << RADIO_PCNF0_LFLEN_Pos) |
wkleunen 1:66f95e364222 252 (3 << RADIO_PCNF0_S1LEN_Pos) ;
wkleunen 1:66f95e364222 253 #endif
wkleunen 1:66f95e364222 254 NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) |
wkleunen 1:66f95e364222 255 (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) |
wkleunen 1:66f95e364222 256 ((m_esb_addr.addr_length - 1) << RADIO_PCNF1_BALEN_Pos) |
wkleunen 1:66f95e364222 257 (0 << RADIO_PCNF1_STATLEN_Pos) |
wkleunen 1:66f95e364222 258 (NRF_ESB_MAX_PAYLOAD_LENGTH << RADIO_PCNF1_MAXLEN_Pos);
wkleunen 1:66f95e364222 259 }
wkleunen 1:66f95e364222 260
wkleunen 1:66f95e364222 261
wkleunen 1:66f95e364222 262 static void update_rf_payload_format_esb(uint32_t payload_length)
wkleunen 1:66f95e364222 263 {
wkleunen 1:66f95e364222 264 NRF_RADIO->PCNF0 = (1 << RADIO_PCNF0_S0LEN_Pos) |
wkleunen 1:66f95e364222 265 (0 << RADIO_PCNF0_LFLEN_Pos) |
wkleunen 1:66f95e364222 266 (1 << RADIO_PCNF0_S1LEN_Pos);
wkleunen 1:66f95e364222 267
wkleunen 1:66f95e364222 268 NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) |
wkleunen 1:66f95e364222 269 (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) |
wkleunen 1:66f95e364222 270 ((m_esb_addr.addr_length - 1) << RADIO_PCNF1_BALEN_Pos) |
wkleunen 1:66f95e364222 271 (payload_length << RADIO_PCNF1_STATLEN_Pos) |
wkleunen 1:66f95e364222 272 (payload_length << RADIO_PCNF1_MAXLEN_Pos);
wkleunen 1:66f95e364222 273 }
wkleunen 1:66f95e364222 274
wkleunen 1:66f95e364222 275
wkleunen 1:66f95e364222 276 static void update_radio_addresses(uint8_t update_mask)
wkleunen 1:66f95e364222 277 {
wkleunen 1:66f95e364222 278 if ((update_mask & NRF_ESB_ADDR_UPDATE_MASK_BASE0) != 0)
wkleunen 1:66f95e364222 279 {
wkleunen 1:66f95e364222 280 NRF_RADIO->BASE0 = addr_conv(m_esb_addr.base_addr_p0);
wkleunen 1:66f95e364222 281 }
wkleunen 1:66f95e364222 282
wkleunen 1:66f95e364222 283 if ((update_mask & NRF_ESB_ADDR_UPDATE_MASK_BASE1) != 0)
wkleunen 1:66f95e364222 284 {
wkleunen 1:66f95e364222 285 NRF_RADIO->BASE1 = addr_conv(m_esb_addr.base_addr_p1);
wkleunen 1:66f95e364222 286 }
wkleunen 1:66f95e364222 287
wkleunen 1:66f95e364222 288 if ((update_mask & NRF_ESB_ADDR_UPDATE_MASK_PREFIX) != 0)
wkleunen 1:66f95e364222 289 {
wkleunen 1:66f95e364222 290 NRF_RADIO->PREFIX0 = bytewise_bit_swap(&m_esb_addr.pipe_prefixes[0]);
wkleunen 1:66f95e364222 291 NRF_RADIO->PREFIX1 = bytewise_bit_swap(&m_esb_addr.pipe_prefixes[4]);
wkleunen 1:66f95e364222 292 }
wkleunen 1:66f95e364222 293 }
wkleunen 1:66f95e364222 294
wkleunen 1:66f95e364222 295
wkleunen 1:66f95e364222 296 static void update_radio_tx_power()
wkleunen 1:66f95e364222 297 {
wkleunen 1:66f95e364222 298 NRF_RADIO->TXPOWER = m_config_local.tx_output_power << RADIO_TXPOWER_TXPOWER_Pos;
wkleunen 1:66f95e364222 299 }
wkleunen 1:66f95e364222 300
wkleunen 1:66f95e364222 301
wkleunen 1:66f95e364222 302 static bool update_radio_bitrate()
wkleunen 1:66f95e364222 303 {
wkleunen 1:66f95e364222 304 NRF_RADIO->MODE = m_config_local.bitrate << RADIO_MODE_MODE_Pos;
wkleunen 1:66f95e364222 305
wkleunen 1:66f95e364222 306 switch (m_config_local.bitrate)
wkleunen 1:66f95e364222 307 {
wkleunen 1:66f95e364222 308 case NRF_ESB_BITRATE_2MBPS:
wkleunen 1:66f95e364222 309 #ifdef NRF52
wkleunen 1:66f95e364222 310 case NRF_ESB_BITRATE_2MBPS_BLE:
wkleunen 1:66f95e364222 311 #endif
wkleunen 1:66f95e364222 312 m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_2MBPS;
wkleunen 1:66f95e364222 313 break;
wkleunen 1:66f95e364222 314
wkleunen 1:66f95e364222 315 case NRF_ESB_BITRATE_1MBPS:
wkleunen 1:66f95e364222 316 m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_1MBPS;
wkleunen 1:66f95e364222 317 break;
wkleunen 1:66f95e364222 318
wkleunen 1:66f95e364222 319 #ifdef NRF51
wkleunen 1:66f95e364222 320 case NRF_ESB_BITRATE_250KBPS:
wkleunen 1:66f95e364222 321 m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_250KBPS;
wkleunen 1:66f95e364222 322 break;
wkleunen 1:66f95e364222 323 #endif
wkleunen 1:66f95e364222 324
wkleunen 1:66f95e364222 325 case NRF_ESB_BITRATE_1MBPS_BLE:
wkleunen 1:66f95e364222 326 m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_1MBPS_BLE;
wkleunen 1:66f95e364222 327 break;
wkleunen 1:66f95e364222 328
wkleunen 1:66f95e364222 329 default:
wkleunen 1:66f95e364222 330 // Should not be reached
wkleunen 1:66f95e364222 331 return false;
wkleunen 1:66f95e364222 332 }
wkleunen 1:66f95e364222 333 return true;
wkleunen 1:66f95e364222 334 }
wkleunen 1:66f95e364222 335
wkleunen 1:66f95e364222 336
wkleunen 1:66f95e364222 337 static bool update_radio_protocol()
wkleunen 1:66f95e364222 338 {
wkleunen 1:66f95e364222 339 switch (m_config_local.protocol)
wkleunen 1:66f95e364222 340 {
wkleunen 1:66f95e364222 341 case NRF_ESB_PROTOCOL_ESB_DPL:
wkleunen 1:66f95e364222 342 update_rf_payload_format = update_rf_payload_format_esb_dpl;
wkleunen 1:66f95e364222 343 break;
wkleunen 1:66f95e364222 344
wkleunen 1:66f95e364222 345 case NRF_ESB_PROTOCOL_ESB:
wkleunen 1:66f95e364222 346 update_rf_payload_format = update_rf_payload_format_esb;
wkleunen 1:66f95e364222 347 break;
wkleunen 1:66f95e364222 348
wkleunen 1:66f95e364222 349 default:
wkleunen 1:66f95e364222 350 // Should not be reached
wkleunen 1:66f95e364222 351 return false;
wkleunen 1:66f95e364222 352 }
wkleunen 1:66f95e364222 353 return true;
wkleunen 1:66f95e364222 354 }
wkleunen 1:66f95e364222 355
wkleunen 1:66f95e364222 356
wkleunen 1:66f95e364222 357 static bool update_radio_crc()
wkleunen 1:66f95e364222 358 {
wkleunen 1:66f95e364222 359 switch(m_config_local.crc)
wkleunen 1:66f95e364222 360 {
wkleunen 1:66f95e364222 361 case NRF_ESB_CRC_16BIT:
wkleunen 1:66f95e364222 362 NRF_RADIO->CRCINIT = 0xFFFFUL; // Initial value
wkleunen 1:66f95e364222 363 NRF_RADIO->CRCPOLY = 0x11021UL; // CRC poly: x^16+x^12^x^5+1
wkleunen 1:66f95e364222 364 break;
wkleunen 1:66f95e364222 365
wkleunen 1:66f95e364222 366 case NRF_ESB_CRC_8BIT:
wkleunen 1:66f95e364222 367 NRF_RADIO->CRCINIT = 0xFFUL; // Initial value
wkleunen 1:66f95e364222 368 NRF_RADIO->CRCPOLY = 0x107UL; // CRC poly: x^8+x^2^x^1+1
wkleunen 1:66f95e364222 369 break;
wkleunen 1:66f95e364222 370
wkleunen 1:66f95e364222 371 case NRF_ESB_CRC_OFF:
wkleunen 1:66f95e364222 372 break;
wkleunen 1:66f95e364222 373
wkleunen 1:66f95e364222 374 default:
wkleunen 1:66f95e364222 375 return false;
wkleunen 1:66f95e364222 376 }
wkleunen 1:66f95e364222 377 NRF_RADIO->CRCCNF = m_config_local.crc << RADIO_CRCCNF_LEN_Pos;
wkleunen 1:66f95e364222 378 return true;
wkleunen 1:66f95e364222 379 }
wkleunen 1:66f95e364222 380
wkleunen 1:66f95e364222 381
wkleunen 1:66f95e364222 382 static bool update_radio_parameters()
wkleunen 1:66f95e364222 383 {
wkleunen 1:66f95e364222 384 bool params_valid = true;
wkleunen 1:66f95e364222 385 update_radio_tx_power();
wkleunen 1:66f95e364222 386 params_valid &= update_radio_bitrate();
wkleunen 1:66f95e364222 387 params_valid &= update_radio_protocol();
wkleunen 1:66f95e364222 388 params_valid &= update_radio_crc();
wkleunen 1:66f95e364222 389 update_rf_payload_format(m_config_local.payload_length);
wkleunen 1:66f95e364222 390 params_valid &= (m_config_local.retransmit_delay >= NRF_ESB_RETRANSMIT_DELAY_MIN);
wkleunen 1:66f95e364222 391 return params_valid;
wkleunen 1:66f95e364222 392 }
wkleunen 1:66f95e364222 393
wkleunen 1:66f95e364222 394
wkleunen 1:66f95e364222 395 static void reset_fifos()
wkleunen 1:66f95e364222 396 {
wkleunen 1:66f95e364222 397 m_tx_fifo.entry_point = 0;
wkleunen 1:66f95e364222 398 m_tx_fifo.exit_point = 0;
wkleunen 1:66f95e364222 399 m_tx_fifo.count = 0;
wkleunen 1:66f95e364222 400
wkleunen 1:66f95e364222 401 m_rx_fifo.entry_point = 0;
wkleunen 1:66f95e364222 402 m_rx_fifo.exit_point = 0;
wkleunen 1:66f95e364222 403 m_rx_fifo.count = 0;
wkleunen 1:66f95e364222 404 }
wkleunen 1:66f95e364222 405
wkleunen 1:66f95e364222 406
wkleunen 1:66f95e364222 407 static void initialize_fifos()
wkleunen 1:66f95e364222 408 {
wkleunen 1:66f95e364222 409 reset_fifos();
wkleunen 1:66f95e364222 410
wkleunen 1:66f95e364222 411 for (int i = 0; i < NRF_ESB_TX_FIFO_SIZE; i++)
wkleunen 1:66f95e364222 412 {
wkleunen 1:66f95e364222 413 m_tx_fifo.p_payload[i] = &m_tx_fifo_payload[i];
wkleunen 1:66f95e364222 414 }
wkleunen 1:66f95e364222 415
wkleunen 1:66f95e364222 416 for (int i = 0; i < NRF_ESB_RX_FIFO_SIZE; i++)
wkleunen 1:66f95e364222 417 {
wkleunen 1:66f95e364222 418 m_rx_fifo.p_payload[i] = &m_rx_fifo_payload[i];
wkleunen 1:66f95e364222 419 }
wkleunen 1:66f95e364222 420 }
wkleunen 1:66f95e364222 421
wkleunen 1:66f95e364222 422
wkleunen 1:66f95e364222 423 static void tx_fifo_remove_last()
wkleunen 1:66f95e364222 424 {
wkleunen 1:66f95e364222 425 if (m_tx_fifo.count > 0)
wkleunen 1:66f95e364222 426 {
wkleunen 1:66f95e364222 427 DISABLE_RF_IRQ();
wkleunen 1:66f95e364222 428
wkleunen 1:66f95e364222 429 m_tx_fifo.count--;
wkleunen 1:66f95e364222 430 if (++m_tx_fifo.exit_point >= NRF_ESB_TX_FIFO_SIZE)
wkleunen 1:66f95e364222 431 {
wkleunen 1:66f95e364222 432 m_tx_fifo.exit_point = 0;
wkleunen 1:66f95e364222 433 }
wkleunen 1:66f95e364222 434
wkleunen 1:66f95e364222 435 ENABLE_RF_IRQ();
wkleunen 1:66f95e364222 436 }
wkleunen 1:66f95e364222 437 }
wkleunen 1:66f95e364222 438
wkleunen 1:66f95e364222 439 /** @brief Function to push the content of the rx_buffer to the RX FIFO.
wkleunen 1:66f95e364222 440 *
wkleunen 1:66f95e364222 441 * The module will point the register NRF_RADIO->PACKETPTR to a buffer for receiving packets.
wkleunen 1:66f95e364222 442 * After receiving a packet the module will call this function to copy the received data to
wkleunen 1:66f95e364222 443 * the RX FIFO.
wkleunen 1:66f95e364222 444 *
wkleunen 1:66f95e364222 445 * @param pipe Pipe number to set for the packet.
wkleunen 1:66f95e364222 446 * @param pid Packet ID.
wkleunen 1:66f95e364222 447 *
wkleunen 1:66f95e364222 448 * @retval true Operation successful.
wkleunen 1:66f95e364222 449 * @retval false Operation failed.
wkleunen 1:66f95e364222 450 */
wkleunen 1:66f95e364222 451 static bool rx_fifo_push_rfbuf(uint8_t pipe, uint8_t pid)
wkleunen 1:66f95e364222 452 {
wkleunen 1:66f95e364222 453 if (m_rx_fifo.count < NRF_ESB_RX_FIFO_SIZE)
wkleunen 1:66f95e364222 454 {
wkleunen 1:66f95e364222 455 if (m_config_local.protocol == NRF_ESB_PROTOCOL_ESB_DPL)
wkleunen 1:66f95e364222 456 {
wkleunen 1:66f95e364222 457 if (m_rx_payload_buffer[0] > NRF_ESB_MAX_PAYLOAD_LENGTH)
wkleunen 1:66f95e364222 458 {
wkleunen 1:66f95e364222 459 return false;
wkleunen 1:66f95e364222 460 }
wkleunen 1:66f95e364222 461
wkleunen 1:66f95e364222 462 m_rx_fifo.p_payload[m_rx_fifo.entry_point]->length = m_rx_payload_buffer[0];
wkleunen 1:66f95e364222 463 }
wkleunen 1:66f95e364222 464 else if (m_config_local.mode == NRF_ESB_MODE_PTX)
wkleunen 1:66f95e364222 465 {
wkleunen 1:66f95e364222 466 // Received packet is an acknowledgment
wkleunen 1:66f95e364222 467 m_rx_fifo.p_payload[m_rx_fifo.entry_point]->length = 0;
wkleunen 1:66f95e364222 468 }
wkleunen 1:66f95e364222 469 else
wkleunen 1:66f95e364222 470 {
wkleunen 1:66f95e364222 471 m_rx_fifo.p_payload[m_rx_fifo.entry_point]->length = m_config_local.payload_length;
wkleunen 1:66f95e364222 472 }
wkleunen 1:66f95e364222 473
wkleunen 1:66f95e364222 474 memcpy(m_rx_fifo.p_payload[m_rx_fifo.entry_point]->data, &m_rx_payload_buffer[2],
wkleunen 1:66f95e364222 475 m_rx_fifo.p_payload[m_rx_fifo.entry_point]->length);
wkleunen 1:66f95e364222 476
wkleunen 1:66f95e364222 477 m_rx_fifo.p_payload[m_rx_fifo.entry_point]->pipe = pipe;
wkleunen 1:66f95e364222 478 m_rx_fifo.p_payload[m_rx_fifo.entry_point]->rssi = NRF_RADIO->RSSISAMPLE;
wkleunen 1:66f95e364222 479 m_rx_fifo.p_payload[m_rx_fifo.entry_point]->pid = pid;
wkleunen 1:66f95e364222 480 m_rx_fifo.p_payload[m_rx_fifo.entry_point]->noack = !(m_rx_payload_buffer[1] & 0x01);
wkleunen 1:66f95e364222 481 if (++m_rx_fifo.entry_point >= NRF_ESB_RX_FIFO_SIZE)
wkleunen 1:66f95e364222 482 {
wkleunen 1:66f95e364222 483 m_rx_fifo.entry_point = 0;
wkleunen 1:66f95e364222 484 }
wkleunen 1:66f95e364222 485 m_rx_fifo.count++;
wkleunen 1:66f95e364222 486
wkleunen 1:66f95e364222 487 return true;
wkleunen 1:66f95e364222 488 }
wkleunen 1:66f95e364222 489
wkleunen 1:66f95e364222 490 return false;
wkleunen 1:66f95e364222 491 }
wkleunen 1:66f95e364222 492
wkleunen 1:66f95e364222 493
wkleunen 1:66f95e364222 494 static void sys_timer_init()
wkleunen 1:66f95e364222 495 {
wkleunen 1:66f95e364222 496 // Configure the system timer with a 1 MHz base frequency
wkleunen 1:66f95e364222 497 NRF_ESB_SYS_TIMER->PRESCALER = 4;
wkleunen 1:66f95e364222 498 NRF_ESB_SYS_TIMER->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
wkleunen 1:66f95e364222 499 NRF_ESB_SYS_TIMER->SHORTS = TIMER_SHORTS_COMPARE1_CLEAR_Msk | TIMER_SHORTS_COMPARE1_STOP_Msk;
wkleunen 1:66f95e364222 500 }
wkleunen 1:66f95e364222 501
wkleunen 1:66f95e364222 502
wkleunen 1:66f95e364222 503 static void ppi_init()
wkleunen 1:66f95e364222 504 {
wkleunen 1:66f95e364222 505 NRF_PPI->CH[NRF_ESB_PPI_TIMER_START].EEP = (uint32_t)&NRF_RADIO->EVENTS_READY;
wkleunen 1:66f95e364222 506 NRF_PPI->CH[NRF_ESB_PPI_TIMER_START].TEP = (uint32_t)&NRF_ESB_SYS_TIMER->TASKS_START;
wkleunen 1:66f95e364222 507
wkleunen 1:66f95e364222 508 NRF_PPI->CH[NRF_ESB_PPI_TIMER_STOP].EEP = (uint32_t)&NRF_RADIO->EVENTS_ADDRESS;
wkleunen 1:66f95e364222 509 NRF_PPI->CH[NRF_ESB_PPI_TIMER_STOP].TEP = (uint32_t)&NRF_ESB_SYS_TIMER->TASKS_STOP;
wkleunen 1:66f95e364222 510
wkleunen 1:66f95e364222 511 NRF_PPI->CH[NRF_ESB_PPI_RX_TIMEOUT].EEP = (uint32_t)&NRF_ESB_SYS_TIMER->EVENTS_COMPARE[0];
wkleunen 1:66f95e364222 512 NRF_PPI->CH[NRF_ESB_PPI_RX_TIMEOUT].TEP = (uint32_t)&NRF_RADIO->TASKS_DISABLE;
wkleunen 1:66f95e364222 513
wkleunen 1:66f95e364222 514 NRF_PPI->CH[NRF_ESB_PPI_TX_START].EEP = (uint32_t)&NRF_ESB_SYS_TIMER->EVENTS_COMPARE[1];
wkleunen 1:66f95e364222 515 NRF_PPI->CH[NRF_ESB_PPI_TX_START].TEP = (uint32_t)&NRF_RADIO->TASKS_TXEN;
wkleunen 1:66f95e364222 516 }
wkleunen 1:66f95e364222 517
wkleunen 1:66f95e364222 518
wkleunen 1:66f95e364222 519 static void start_tx_transaction()
wkleunen 1:66f95e364222 520 {
wkleunen 1:66f95e364222 521 bool ack;
wkleunen 1:66f95e364222 522
wkleunen 1:66f95e364222 523 m_last_tx_attempts = 1;
wkleunen 1:66f95e364222 524 // Prepare the payload
wkleunen 1:66f95e364222 525 mp_current_payload = m_tx_fifo.p_payload[m_tx_fifo.exit_point];
wkleunen 1:66f95e364222 526
wkleunen 1:66f95e364222 527
wkleunen 1:66f95e364222 528 switch (m_config_local.protocol)
wkleunen 1:66f95e364222 529 {
wkleunen 1:66f95e364222 530 case NRF_ESB_PROTOCOL_ESB:
wkleunen 1:66f95e364222 531 update_rf_payload_format(mp_current_payload->length);
wkleunen 1:66f95e364222 532 m_tx_payload_buffer[0] = mp_current_payload->pid;
wkleunen 1:66f95e364222 533 m_tx_payload_buffer[1] = 0;
wkleunen 1:66f95e364222 534 memcpy(&m_tx_payload_buffer[2], mp_current_payload->data, mp_current_payload->length);
wkleunen 1:66f95e364222 535
wkleunen 1:66f95e364222 536 NRF_RADIO->SHORTS = m_radio_shorts_common | RADIO_SHORTS_DISABLED_RXEN_Msk;
wkleunen 1:66f95e364222 537 NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk | RADIO_INTENSET_READY_Msk;
wkleunen 1:66f95e364222 538
wkleunen 1:66f95e364222 539 // Configure the retransmit counter
wkleunen 1:66f95e364222 540 m_retransmits_remaining = m_config_local.retransmit_count;
wkleunen 1:66f95e364222 541 on_radio_disabled = on_radio_disabled_tx;
wkleunen 1:66f95e364222 542 m_nrf_esb_mainstate = NRF_ESB_STATE_PTX_TX_ACK;
wkleunen 1:66f95e364222 543 break;
wkleunen 1:66f95e364222 544
wkleunen 1:66f95e364222 545 case NRF_ESB_PROTOCOL_ESB_DPL:
wkleunen 1:66f95e364222 546 ack = !mp_current_payload->noack || !m_config_local.selective_auto_ack;
wkleunen 1:66f95e364222 547 m_tx_payload_buffer[0] = mp_current_payload->length;
wkleunen 1:66f95e364222 548 m_tx_payload_buffer[1] = mp_current_payload->pid << 1;
wkleunen 1:66f95e364222 549 m_tx_payload_buffer[1] |= mp_current_payload->noack ? 0x00 : 0x01;
wkleunen 1:66f95e364222 550 memcpy(&m_tx_payload_buffer[2], mp_current_payload->data, mp_current_payload->length);
wkleunen 1:66f95e364222 551
wkleunen 1:66f95e364222 552 // Handling ack if noack is set to false or if selective auto ack is turned off
wkleunen 1:66f95e364222 553 if (ack)
wkleunen 1:66f95e364222 554 {
wkleunen 1:66f95e364222 555 NRF_RADIO->SHORTS = m_radio_shorts_common | RADIO_SHORTS_DISABLED_RXEN_Msk;
wkleunen 1:66f95e364222 556 NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk | RADIO_INTENSET_READY_Msk;
wkleunen 1:66f95e364222 557
wkleunen 1:66f95e364222 558 // Configure the retransmit counter
wkleunen 1:66f95e364222 559 m_retransmits_remaining = m_config_local.retransmit_count;
wkleunen 1:66f95e364222 560 on_radio_disabled = on_radio_disabled_tx;
wkleunen 1:66f95e364222 561 m_nrf_esb_mainstate = NRF_ESB_STATE_PTX_TX_ACK;
wkleunen 1:66f95e364222 562 }
wkleunen 1:66f95e364222 563 else
wkleunen 1:66f95e364222 564 {
wkleunen 1:66f95e364222 565 NRF_RADIO->SHORTS = m_radio_shorts_common;
wkleunen 1:66f95e364222 566 NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk;
wkleunen 1:66f95e364222 567 on_radio_disabled = on_radio_disabled_tx_noack;
wkleunen 1:66f95e364222 568 m_nrf_esb_mainstate = NRF_ESB_STATE_PTX_TX;
wkleunen 1:66f95e364222 569 }
wkleunen 1:66f95e364222 570 break;
wkleunen 1:66f95e364222 571
wkleunen 1:66f95e364222 572 default:
wkleunen 1:66f95e364222 573 // Should not be reached
wkleunen 1:66f95e364222 574 break;
wkleunen 1:66f95e364222 575 }
wkleunen 1:66f95e364222 576
wkleunen 1:66f95e364222 577 NRF_RADIO->TXADDRESS = mp_current_payload->pipe;
wkleunen 1:66f95e364222 578 NRF_RADIO->RXADDRESSES = 1 << mp_current_payload->pipe;
wkleunen 1:66f95e364222 579
wkleunen 1:66f95e364222 580 NRF_RADIO->FREQUENCY = m_esb_addr.rf_channel;
wkleunen 1:66f95e364222 581 NRF_RADIO->PACKETPTR = (uint32_t)m_tx_payload_buffer;
wkleunen 1:66f95e364222 582
wkleunen 1:66f95e364222 583 NVIC_ClearPendingIRQ(RADIO_IRQn);
wkleunen 1:66f95e364222 584 NVIC_EnableIRQ(RADIO_IRQn);
wkleunen 1:66f95e364222 585
wkleunen 1:66f95e364222 586 NRF_RADIO->EVENTS_ADDRESS = 0;
wkleunen 1:66f95e364222 587 NRF_RADIO->EVENTS_PAYLOAD = 0;
wkleunen 1:66f95e364222 588 NRF_RADIO->EVENTS_DISABLED = 0;
wkleunen 1:66f95e364222 589
wkleunen 1:66f95e364222 590 DEBUG_PIN_SET(DEBUGPIN4);
wkleunen 1:66f95e364222 591 NRF_RADIO->TASKS_TXEN = 1;
wkleunen 1:66f95e364222 592 }
wkleunen 1:66f95e364222 593
wkleunen 1:66f95e364222 594
wkleunen 1:66f95e364222 595 static void on_radio_disabled_tx_noack()
wkleunen 1:66f95e364222 596 {
wkleunen 1:66f95e364222 597 m_interrupt_flags |= NRF_ESB_INT_TX_SUCCESS_MSK;
wkleunen 1:66f95e364222 598 tx_fifo_remove_last();
wkleunen 1:66f95e364222 599
wkleunen 1:66f95e364222 600 if (m_tx_fifo.count == 0)
wkleunen 1:66f95e364222 601 {
wkleunen 1:66f95e364222 602 m_nrf_esb_mainstate = NRF_ESB_STATE_IDLE;
wkleunen 1:66f95e364222 603 NVIC_SetPendingIRQ(ESB_EVT_IRQ);
wkleunen 1:66f95e364222 604 }
wkleunen 1:66f95e364222 605 else
wkleunen 1:66f95e364222 606 {
wkleunen 1:66f95e364222 607 NVIC_SetPendingIRQ(ESB_EVT_IRQ);
wkleunen 1:66f95e364222 608 start_tx_transaction();
wkleunen 1:66f95e364222 609 }
wkleunen 1:66f95e364222 610 }
wkleunen 1:66f95e364222 611
wkleunen 1:66f95e364222 612
wkleunen 1:66f95e364222 613 static void on_radio_disabled_tx()
wkleunen 1:66f95e364222 614 {
wkleunen 1:66f95e364222 615 // Remove the DISABLED -> RXEN shortcut, to make sure the radio stays
wkleunen 1:66f95e364222 616 // disabled after the RX window
wkleunen 1:66f95e364222 617 NRF_RADIO->SHORTS = m_radio_shorts_common;
wkleunen 1:66f95e364222 618
wkleunen 1:66f95e364222 619 // Make sure the timer is started the next time the radio is ready,
wkleunen 1:66f95e364222 620 // and that it will disable the radio automatically if no packet is
wkleunen 1:66f95e364222 621 // received by the time defined in m_wait_for_ack_timeout_us
wkleunen 1:66f95e364222 622 NRF_ESB_SYS_TIMER->CC[0] = m_wait_for_ack_timeout_us;
wkleunen 1:66f95e364222 623 NRF_ESB_SYS_TIMER->CC[1] = m_config_local.retransmit_delay - 130;
wkleunen 1:66f95e364222 624 NRF_ESB_SYS_TIMER->TASKS_CLEAR = 1;
wkleunen 1:66f95e364222 625 NRF_ESB_SYS_TIMER->EVENTS_COMPARE[0] = 0;
wkleunen 1:66f95e364222 626 NRF_ESB_SYS_TIMER->EVENTS_COMPARE[1] = 0;
wkleunen 1:66f95e364222 627
wkleunen 1:66f95e364222 628 NRF_PPI->CHENSET = (1 << NRF_ESB_PPI_TIMER_START) |
wkleunen 1:66f95e364222 629 (1 << NRF_ESB_PPI_RX_TIMEOUT) |
wkleunen 1:66f95e364222 630 (1 << NRF_ESB_PPI_TIMER_STOP);
wkleunen 1:66f95e364222 631 NRF_PPI->CHENCLR = (1 << NRF_ESB_PPI_TX_START);
wkleunen 1:66f95e364222 632 NRF_RADIO->EVENTS_END = 0;
wkleunen 1:66f95e364222 633
wkleunen 1:66f95e364222 634 if (m_config_local.protocol == NRF_ESB_PROTOCOL_ESB)
wkleunen 1:66f95e364222 635 {
wkleunen 1:66f95e364222 636 update_rf_payload_format(0);
wkleunen 1:66f95e364222 637 }
wkleunen 1:66f95e364222 638
wkleunen 1:66f95e364222 639 NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer;
wkleunen 1:66f95e364222 640 on_radio_disabled = on_radio_disabled_tx_wait_for_ack;
wkleunen 1:66f95e364222 641 m_nrf_esb_mainstate = NRF_ESB_STATE_PTX_RX_ACK;
wkleunen 1:66f95e364222 642 }
wkleunen 1:66f95e364222 643
wkleunen 1:66f95e364222 644
wkleunen 1:66f95e364222 645 static void on_radio_disabled_tx_wait_for_ack()
wkleunen 1:66f95e364222 646 {
wkleunen 1:66f95e364222 647 // This marks the completion of a TX_RX sequence (TX with ACK)
wkleunen 1:66f95e364222 648
wkleunen 1:66f95e364222 649 // Make sure the timer will not deactivate the radio if a packet is received
wkleunen 1:66f95e364222 650 NRF_PPI->CHENCLR = (1 << NRF_ESB_PPI_TIMER_START) |
wkleunen 1:66f95e364222 651 (1 << NRF_ESB_PPI_RX_TIMEOUT) |
wkleunen 1:66f95e364222 652 (1 << NRF_ESB_PPI_TIMER_STOP);
wkleunen 1:66f95e364222 653
wkleunen 1:66f95e364222 654 // If the radio has received a packet and the CRC status is OK
wkleunen 1:66f95e364222 655 if (NRF_RADIO->EVENTS_END && NRF_RADIO->CRCSTATUS != 0)
wkleunen 1:66f95e364222 656 {
wkleunen 1:66f95e364222 657 NRF_ESB_SYS_TIMER->TASKS_STOP = 1;
wkleunen 1:66f95e364222 658 NRF_PPI->CHENCLR = (1 << NRF_ESB_PPI_TX_START);
wkleunen 1:66f95e364222 659 m_interrupt_flags |= NRF_ESB_INT_TX_SUCCESS_MSK;
wkleunen 1:66f95e364222 660 m_last_tx_attempts = m_config_local.retransmit_count - m_retransmits_remaining + 1;
wkleunen 1:66f95e364222 661
wkleunen 1:66f95e364222 662 tx_fifo_remove_last();
wkleunen 1:66f95e364222 663
wkleunen 1:66f95e364222 664 if (m_config_local.protocol != NRF_ESB_PROTOCOL_ESB && m_rx_payload_buffer[0] > 0)
wkleunen 1:66f95e364222 665 {
wkleunen 1:66f95e364222 666 if (rx_fifo_push_rfbuf((uint8_t)NRF_RADIO->TXADDRESS, m_rx_payload_buffer[1] >> 1))
wkleunen 1:66f95e364222 667 {
wkleunen 1:66f95e364222 668 m_interrupt_flags |= NRF_ESB_INT_RX_DATA_RECEIVED_MSK;
wkleunen 1:66f95e364222 669 }
wkleunen 1:66f95e364222 670 }
wkleunen 1:66f95e364222 671
wkleunen 1:66f95e364222 672 if ((m_tx_fifo.count == 0) || (m_config_local.tx_mode == NRF_ESB_TXMODE_MANUAL))
wkleunen 1:66f95e364222 673 {
wkleunen 1:66f95e364222 674 m_nrf_esb_mainstate = NRF_ESB_STATE_IDLE;
wkleunen 1:66f95e364222 675 NVIC_SetPendingIRQ(ESB_EVT_IRQ);
wkleunen 1:66f95e364222 676 }
wkleunen 1:66f95e364222 677 else
wkleunen 1:66f95e364222 678 {
wkleunen 1:66f95e364222 679 NVIC_SetPendingIRQ(ESB_EVT_IRQ);
wkleunen 1:66f95e364222 680 start_tx_transaction();
wkleunen 1:66f95e364222 681 }
wkleunen 1:66f95e364222 682 }
wkleunen 1:66f95e364222 683 else
wkleunen 1:66f95e364222 684 {
wkleunen 1:66f95e364222 685 if (m_retransmits_remaining-- == 0)
wkleunen 1:66f95e364222 686 {
wkleunen 1:66f95e364222 687 NRF_ESB_SYS_TIMER->TASKS_STOP = 1;
wkleunen 1:66f95e364222 688 NRF_PPI->CHENCLR = (1 << NRF_ESB_PPI_TX_START);
wkleunen 1:66f95e364222 689 // All retransmits are expended, and the TX operation is suspended
wkleunen 1:66f95e364222 690 m_last_tx_attempts = m_config_local.retransmit_count + 1;
wkleunen 1:66f95e364222 691 m_interrupt_flags |= NRF_ESB_INT_TX_FAILED_MSK;
wkleunen 1:66f95e364222 692
wkleunen 1:66f95e364222 693 m_nrf_esb_mainstate = NRF_ESB_STATE_IDLE;
wkleunen 1:66f95e364222 694 NVIC_SetPendingIRQ(ESB_EVT_IRQ);
wkleunen 1:66f95e364222 695 }
wkleunen 1:66f95e364222 696 else
wkleunen 1:66f95e364222 697 {
wkleunen 1:66f95e364222 698 // There are still more retransmits left, TX mode should be
wkleunen 1:66f95e364222 699 // entered again as soon as the system timer reaches CC[1].
wkleunen 1:66f95e364222 700 NRF_RADIO->SHORTS = m_radio_shorts_common | RADIO_SHORTS_DISABLED_RXEN_Msk;
wkleunen 1:66f95e364222 701 update_rf_payload_format(mp_current_payload->length);
wkleunen 1:66f95e364222 702 NRF_RADIO->PACKETPTR = (uint32_t)m_tx_payload_buffer;
wkleunen 1:66f95e364222 703 on_radio_disabled = on_radio_disabled_tx;
wkleunen 1:66f95e364222 704 m_nrf_esb_mainstate = NRF_ESB_STATE_PTX_TX_ACK;
wkleunen 1:66f95e364222 705 NRF_ESB_SYS_TIMER->TASKS_START = 1;
wkleunen 1:66f95e364222 706 NRF_PPI->CHENSET = (1 << NRF_ESB_PPI_TX_START);
wkleunen 1:66f95e364222 707 if (NRF_ESB_SYS_TIMER->EVENTS_COMPARE[1])
wkleunen 1:66f95e364222 708 {
wkleunen 1:66f95e364222 709 NRF_RADIO->TASKS_TXEN = 1;
wkleunen 1:66f95e364222 710 }
wkleunen 1:66f95e364222 711 }
wkleunen 1:66f95e364222 712 }
wkleunen 1:66f95e364222 713 }
wkleunen 1:66f95e364222 714
wkleunen 1:66f95e364222 715 static void clear_events_restart_rx(void)
wkleunen 1:66f95e364222 716 {
wkleunen 1:66f95e364222 717 NRF_RADIO->SHORTS = m_radio_shorts_common;
wkleunen 1:66f95e364222 718 update_rf_payload_format(m_config_local.payload_length);
wkleunen 1:66f95e364222 719 NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer;
wkleunen 1:66f95e364222 720 NRF_RADIO->EVENTS_DISABLED = 0;
wkleunen 1:66f95e364222 721 NRF_RADIO->TASKS_DISABLE = 1;
wkleunen 1:66f95e364222 722
wkleunen 1:66f95e364222 723 while (NRF_RADIO->EVENTS_DISABLED == 0);
wkleunen 1:66f95e364222 724
wkleunen 1:66f95e364222 725 NRF_RADIO->EVENTS_DISABLED = 0;
wkleunen 1:66f95e364222 726 NRF_RADIO->SHORTS = m_radio_shorts_common | RADIO_SHORTS_DISABLED_TXEN_Msk;
wkleunen 1:66f95e364222 727
wkleunen 1:66f95e364222 728 NRF_RADIO->TASKS_RXEN = 1;
wkleunen 1:66f95e364222 729 }
wkleunen 1:66f95e364222 730
wkleunen 1:66f95e364222 731 static void on_radio_disabled_rx(void)
wkleunen 1:66f95e364222 732 {
wkleunen 1:66f95e364222 733 bool ack = false;
wkleunen 1:66f95e364222 734 bool retransmit_payload = false;
wkleunen 1:66f95e364222 735 bool send_rx_event = true;
wkleunen 1:66f95e364222 736 pipe_info_t * p_pipe_info;
wkleunen 1:66f95e364222 737
wkleunen 1:66f95e364222 738 if (NRF_RADIO->CRCSTATUS == 0)
wkleunen 1:66f95e364222 739 {
wkleunen 1:66f95e364222 740 clear_events_restart_rx();
wkleunen 1:66f95e364222 741 return;
wkleunen 1:66f95e364222 742 }
wkleunen 1:66f95e364222 743
wkleunen 1:66f95e364222 744 if (m_rx_fifo.count >= NRF_ESB_RX_FIFO_SIZE)
wkleunen 1:66f95e364222 745 {
wkleunen 1:66f95e364222 746 clear_events_restart_rx();
wkleunen 1:66f95e364222 747 return;
wkleunen 1:66f95e364222 748 }
wkleunen 1:66f95e364222 749
wkleunen 1:66f95e364222 750 p_pipe_info = &m_rx_pipe_info[NRF_RADIO->RXMATCH];
wkleunen 1:66f95e364222 751 if (NRF_RADIO->RXCRC == p_pipe_info->crc &&
wkleunen 1:66f95e364222 752 (m_rx_payload_buffer[1] >> 1) == p_pipe_info->pid
wkleunen 1:66f95e364222 753 )
wkleunen 1:66f95e364222 754 {
wkleunen 1:66f95e364222 755 retransmit_payload = true;
wkleunen 1:66f95e364222 756 send_rx_event = false;
wkleunen 1:66f95e364222 757 }
wkleunen 1:66f95e364222 758
wkleunen 1:66f95e364222 759 p_pipe_info->pid = m_rx_payload_buffer[1] >> 1;
wkleunen 1:66f95e364222 760 p_pipe_info->crc = NRF_RADIO->RXCRC;
wkleunen 1:66f95e364222 761
wkleunen 1:66f95e364222 762 if ((m_config_local.selective_auto_ack == false) || ((m_rx_payload_buffer[1] & 0x01) == 1))
wkleunen 1:66f95e364222 763 {
wkleunen 1:66f95e364222 764 ack = true;
wkleunen 1:66f95e364222 765 }
wkleunen 1:66f95e364222 766
wkleunen 1:66f95e364222 767 if (ack)
wkleunen 1:66f95e364222 768 {
wkleunen 1:66f95e364222 769 NRF_RADIO->SHORTS = m_radio_shorts_common | RADIO_SHORTS_DISABLED_RXEN_Msk;
wkleunen 1:66f95e364222 770
wkleunen 1:66f95e364222 771 switch (m_config_local.protocol)
wkleunen 1:66f95e364222 772 {
wkleunen 1:66f95e364222 773 case NRF_ESB_PROTOCOL_ESB_DPL:
wkleunen 1:66f95e364222 774 {
wkleunen 1:66f95e364222 775 if (m_tx_fifo.count > 0 &&
wkleunen 1:66f95e364222 776 (m_tx_fifo.p_payload[m_tx_fifo.exit_point]->pipe == NRF_RADIO->RXMATCH)
wkleunen 1:66f95e364222 777 )
wkleunen 1:66f95e364222 778 {
wkleunen 1:66f95e364222 779 // Pipe stays in ACK with payload until TX FIFO is empty
wkleunen 1:66f95e364222 780 // Do not report TX success on first ack payload or retransmit
wkleunen 1:66f95e364222 781 if (p_pipe_info->ack_payload == true && !retransmit_payload)
wkleunen 1:66f95e364222 782 {
wkleunen 1:66f95e364222 783 if (++m_tx_fifo.exit_point >= NRF_ESB_TX_FIFO_SIZE)
wkleunen 1:66f95e364222 784 {
wkleunen 1:66f95e364222 785 m_tx_fifo.exit_point = 0;
wkleunen 1:66f95e364222 786 }
wkleunen 1:66f95e364222 787
wkleunen 1:66f95e364222 788 m_tx_fifo.count--;
wkleunen 1:66f95e364222 789
wkleunen 1:66f95e364222 790 // ACK payloads also require TX_DS
wkleunen 1:66f95e364222 791 // (page 40 of the 'nRF24LE1_Product_Specification_rev1_6.pdf').
wkleunen 1:66f95e364222 792 m_interrupt_flags |= NRF_ESB_INT_TX_SUCCESS_MSK;
wkleunen 1:66f95e364222 793 }
wkleunen 1:66f95e364222 794
wkleunen 1:66f95e364222 795 p_pipe_info->ack_payload = true;
wkleunen 1:66f95e364222 796
wkleunen 1:66f95e364222 797 mp_current_payload = m_tx_fifo.p_payload[m_tx_fifo.exit_point];
wkleunen 1:66f95e364222 798
wkleunen 1:66f95e364222 799 update_rf_payload_format(mp_current_payload->length);
wkleunen 1:66f95e364222 800 m_tx_payload_buffer[0] = mp_current_payload->length;
wkleunen 1:66f95e364222 801 memcpy(&m_tx_payload_buffer[2],
wkleunen 1:66f95e364222 802 mp_current_payload->data,
wkleunen 1:66f95e364222 803 mp_current_payload->length);
wkleunen 1:66f95e364222 804 }
wkleunen 1:66f95e364222 805 else
wkleunen 1:66f95e364222 806 {
wkleunen 1:66f95e364222 807 p_pipe_info->ack_payload = false;
wkleunen 1:66f95e364222 808 update_rf_payload_format(0);
wkleunen 1:66f95e364222 809 m_tx_payload_buffer[0] = 0;
wkleunen 1:66f95e364222 810 }
wkleunen 1:66f95e364222 811
wkleunen 1:66f95e364222 812 m_tx_payload_buffer[1] = m_rx_payload_buffer[1];
wkleunen 1:66f95e364222 813 }
wkleunen 1:66f95e364222 814 break;
wkleunen 1:66f95e364222 815
wkleunen 1:66f95e364222 816 case NRF_ESB_PROTOCOL_ESB:
wkleunen 1:66f95e364222 817 {
wkleunen 1:66f95e364222 818 update_rf_payload_format(0);
wkleunen 1:66f95e364222 819 m_tx_payload_buffer[0] = m_rx_payload_buffer[0];
wkleunen 1:66f95e364222 820 m_tx_payload_buffer[1] = 0;
wkleunen 1:66f95e364222 821 }
wkleunen 1:66f95e364222 822 break;
wkleunen 1:66f95e364222 823 }
wkleunen 1:66f95e364222 824
wkleunen 1:66f95e364222 825 m_nrf_esb_mainstate = NRF_ESB_STATE_PRX_SEND_ACK;
wkleunen 1:66f95e364222 826 NRF_RADIO->TXADDRESS = NRF_RADIO->RXMATCH;
wkleunen 1:66f95e364222 827 NRF_RADIO->PACKETPTR = (uint32_t)m_tx_payload_buffer;
wkleunen 1:66f95e364222 828 on_radio_disabled = on_radio_disabled_rx_ack;
wkleunen 1:66f95e364222 829 }
wkleunen 1:66f95e364222 830 else
wkleunen 1:66f95e364222 831 {
wkleunen 1:66f95e364222 832 clear_events_restart_rx();
wkleunen 1:66f95e364222 833 }
wkleunen 1:66f95e364222 834
wkleunen 1:66f95e364222 835 if (send_rx_event)
wkleunen 1:66f95e364222 836 {
wkleunen 1:66f95e364222 837 // Push the new packet to the RX buffer and trigger a received event if the operation was
wkleunen 1:66f95e364222 838 // successful.
wkleunen 1:66f95e364222 839 if (rx_fifo_push_rfbuf(NRF_RADIO->RXMATCH, p_pipe_info->pid))
wkleunen 1:66f95e364222 840 {
wkleunen 1:66f95e364222 841 m_interrupt_flags |= NRF_ESB_INT_RX_DATA_RECEIVED_MSK;
wkleunen 1:66f95e364222 842 NVIC_SetPendingIRQ(ESB_EVT_IRQ);
wkleunen 1:66f95e364222 843 }
wkleunen 1:66f95e364222 844 }
wkleunen 1:66f95e364222 845 }
wkleunen 1:66f95e364222 846
wkleunen 1:66f95e364222 847
wkleunen 1:66f95e364222 848 static void on_radio_disabled_rx_ack(void)
wkleunen 1:66f95e364222 849 {
wkleunen 1:66f95e364222 850 NRF_RADIO->SHORTS = m_radio_shorts_common | RADIO_SHORTS_DISABLED_TXEN_Msk;
wkleunen 1:66f95e364222 851 update_rf_payload_format(m_config_local.payload_length);
wkleunen 1:66f95e364222 852
wkleunen 1:66f95e364222 853 NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer;
wkleunen 1:66f95e364222 854 on_radio_disabled = on_radio_disabled_rx;
wkleunen 1:66f95e364222 855
wkleunen 1:66f95e364222 856 m_nrf_esb_mainstate = NRF_ESB_STATE_PRX;
wkleunen 1:66f95e364222 857 }
wkleunen 1:66f95e364222 858
wkleunen 1:66f95e364222 859
wkleunen 1:66f95e364222 860 /**@brief Function for clearing pending interrupts.
wkleunen 1:66f95e364222 861 *
wkleunen 1:66f95e364222 862 * @param[in,out] p_interrupts Pointer to the value that holds the current interrupts.
wkleunen 1:66f95e364222 863 *
wkleunen 1:66f95e364222 864 * @retval NRF_SUCCESS If the interrupts were cleared successfully.
wkleunen 1:66f95e364222 865 * @retval NRF_ERROR_NULL If the required parameter was NULL.
wkleunen 1:66f95e364222 866 * @retval NRF_INVALID_STATE If the module is not initialized.
wkleunen 1:66f95e364222 867 */
wkleunen 1:66f95e364222 868 static uint32_t nrf_esb_get_clear_interrupts(uint32_t * p_interrupts)
wkleunen 1:66f95e364222 869 {
wkleunen 1:66f95e364222 870 VERIFY_TRUE(m_esb_initialized, NRF_ERROR_INVALID_STATE);
wkleunen 1:66f95e364222 871 VERIFY_PARAM_NOT_NULL(p_interrupts);
wkleunen 1:66f95e364222 872
wkleunen 1:66f95e364222 873 DISABLE_RF_IRQ();
wkleunen 1:66f95e364222 874
wkleunen 1:66f95e364222 875 *p_interrupts = m_interrupt_flags;
wkleunen 1:66f95e364222 876 m_interrupt_flags = 0;
wkleunen 1:66f95e364222 877
wkleunen 1:66f95e364222 878 ENABLE_RF_IRQ();
wkleunen 1:66f95e364222 879
wkleunen 1:66f95e364222 880 return NRF_SUCCESS;
wkleunen 1:66f95e364222 881 }
wkleunen 1:66f95e364222 882
wkleunen 1:66f95e364222 883
wkleunen 1:66f95e364222 884 /*
wkleunen 1:66f95e364222 885 void RADIO_IRQHandler()
wkleunen 1:66f95e364222 886 {
wkleunen 1:66f95e364222 887 if (NRF_RADIO->EVENTS_READY && (NRF_RADIO->INTENSET & RADIO_INTENSET_READY_Msk))
wkleunen 1:66f95e364222 888 {
wkleunen 1:66f95e364222 889 NRF_RADIO->EVENTS_READY = 0;
wkleunen 1:66f95e364222 890 DEBUG_PIN_SET(DEBUGPIN1);
wkleunen 1:66f95e364222 891 }
wkleunen 1:66f95e364222 892
wkleunen 1:66f95e364222 893 if (NRF_RADIO->EVENTS_END && (NRF_RADIO->INTENSET & RADIO_INTENSET_END_Msk))
wkleunen 1:66f95e364222 894 {
wkleunen 1:66f95e364222 895 NRF_RADIO->EVENTS_END = 0;
wkleunen 1:66f95e364222 896 DEBUG_PIN_SET(DEBUGPIN2);
wkleunen 1:66f95e364222 897
wkleunen 1:66f95e364222 898 // Call the correct on_radio_end function, depending on the current protocol state
wkleunen 1:66f95e364222 899 if (on_radio_end)
wkleunen 1:66f95e364222 900 {
wkleunen 1:66f95e364222 901 on_radio_end();
wkleunen 1:66f95e364222 902 }
wkleunen 1:66f95e364222 903 }
wkleunen 1:66f95e364222 904
wkleunen 1:66f95e364222 905 if (NRF_RADIO->EVENTS_DISABLED && (NRF_RADIO->INTENSET & RADIO_INTENSET_DISABLED_Msk))
wkleunen 1:66f95e364222 906 {
wkleunen 1:66f95e364222 907 NRF_RADIO->EVENTS_DISABLED = 0;
wkleunen 1:66f95e364222 908 DEBUG_PIN_SET(DEBUGPIN3);
wkleunen 1:66f95e364222 909
wkleunen 1:66f95e364222 910 // Call the correct on_radio_disable function, depending on the current protocol state
wkleunen 1:66f95e364222 911 if (on_radio_disabled)
wkleunen 1:66f95e364222 912 {
wkleunen 1:66f95e364222 913 on_radio_disabled();
wkleunen 1:66f95e364222 914 }
wkleunen 1:66f95e364222 915 }
wkleunen 1:66f95e364222 916
wkleunen 1:66f95e364222 917 DEBUG_PIN_CLR(DEBUGPIN1);
wkleunen 1:66f95e364222 918 DEBUG_PIN_CLR(DEBUGPIN2);
wkleunen 1:66f95e364222 919 DEBUG_PIN_CLR(DEBUGPIN3);
wkleunen 1:66f95e364222 920 DEBUG_PIN_CLR(DEBUGPIN4);
wkleunen 1:66f95e364222 921 } */
wkleunen 1:66f95e364222 922
wkleunen 1:66f95e364222 923
wkleunen 1:66f95e364222 924 uint32_t nrf_esb_init(nrf_esb_config_t const * p_config)
wkleunen 1:66f95e364222 925 {
wkleunen 1:66f95e364222 926 uint32_t err_code;
wkleunen 1:66f95e364222 927
wkleunen 1:66f95e364222 928 VERIFY_PARAM_NOT_NULL(p_config);
wkleunen 1:66f95e364222 929
wkleunen 1:66f95e364222 930 if (m_esb_initialized)
wkleunen 1:66f95e364222 931 {
wkleunen 1:66f95e364222 932 err_code = nrf_esb_disable();
wkleunen 1:66f95e364222 933 if (err_code != NRF_SUCCESS)
wkleunen 1:66f95e364222 934 {
wkleunen 1:66f95e364222 935 return err_code;
wkleunen 1:66f95e364222 936 }
wkleunen 1:66f95e364222 937 }
wkleunen 1:66f95e364222 938
wkleunen 1:66f95e364222 939 m_event_handler = p_config->event_handler;
wkleunen 1:66f95e364222 940
wkleunen 1:66f95e364222 941 memcpy(&m_config_local, p_config, sizeof(nrf_esb_config_t));
wkleunen 1:66f95e364222 942
wkleunen 1:66f95e364222 943 m_interrupt_flags = 0;
wkleunen 1:66f95e364222 944
wkleunen 1:66f95e364222 945 memset(m_rx_pipe_info, 0, sizeof(m_rx_pipe_info));
wkleunen 1:66f95e364222 946 memset(m_pids, 0, sizeof(m_pids));
wkleunen 1:66f95e364222 947
wkleunen 1:66f95e364222 948 VERIFY_TRUE(update_radio_parameters(), NRF_ERROR_INVALID_PARAM);
wkleunen 1:66f95e364222 949
wkleunen 1:66f95e364222 950 // Configure radio address registers according to ESB default values
wkleunen 1:66f95e364222 951 NRF_RADIO->BASE0 = 0xE7E7E7E7;
wkleunen 1:66f95e364222 952 NRF_RADIO->BASE1 = 0x43434343;
wkleunen 1:66f95e364222 953 NRF_RADIO->PREFIX0 = 0x23C343E7;
wkleunen 1:66f95e364222 954 NRF_RADIO->PREFIX1 = 0x13E363A3;
wkleunen 1:66f95e364222 955
wkleunen 1:66f95e364222 956 initialize_fifos();
wkleunen 1:66f95e364222 957
wkleunen 1:66f95e364222 958 sys_timer_init();
wkleunen 1:66f95e364222 959
wkleunen 1:66f95e364222 960 ppi_init();
wkleunen 1:66f95e364222 961
wkleunen 1:66f95e364222 962 NVIC_SetPriority(RADIO_IRQn, m_config_local.radio_irq_priority & ESB_IRQ_PRIORITY_MSK);
wkleunen 1:66f95e364222 963 NVIC_SetPriority(ESB_EVT_IRQ, m_config_local.event_irq_priority & ESB_IRQ_PRIORITY_MSK);
wkleunen 1:66f95e364222 964 NVIC_EnableIRQ(ESB_EVT_IRQ);
wkleunen 1:66f95e364222 965
wkleunen 1:66f95e364222 966 #ifdef NRF52
wkleunen 1:66f95e364222 967 if(m_address_hang_fix_enable)
wkleunen 1:66f95e364222 968 {
wkleunen 1:66f95e364222 969 // Setup a timeout timer to start on an ADDRESS match, and stop on a BCMATCH event.
wkleunen 1:66f95e364222 970 // If the BCMATCH event never occurs the CC[0] event will fire, and the timer interrupt will disable the radio to recover.
wkleunen 1:66f95e364222 971 m_radio_shorts_common |= RADIO_SHORTS_ADDRESS_BCSTART_Msk;
wkleunen 1:66f95e364222 972 NRF_RADIO->BCC = 2;
wkleunen 1:66f95e364222 973 NRF_ESB_BUGFIX_TIMER->BITMODE = TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos;
wkleunen 1:66f95e364222 974 NRF_ESB_BUGFIX_TIMER->PRESCALER = 4;
wkleunen 1:66f95e364222 975 NRF_ESB_BUGFIX_TIMER->CC[0] = 5;
wkleunen 1:66f95e364222 976 NRF_ESB_BUGFIX_TIMER->SHORTS = TIMER_SHORTS_COMPARE0_STOP_Msk | TIMER_SHORTS_COMPARE0_CLEAR_Msk;
wkleunen 1:66f95e364222 977 NRF_ESB_BUGFIX_TIMER->MODE = TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos;
wkleunen 1:66f95e364222 978 NRF_ESB_BUGFIX_TIMER->INTENSET = TIMER_INTENSET_COMPARE0_Msk;
wkleunen 1:66f95e364222 979 NRF_ESB_BUGFIX_TIMER->TASKS_CLEAR = 1;
wkleunen 1:66f95e364222 980 NVIC_SetPriority(NRF_ESB_BUGFIX_TIMER_IRQn, 5);
wkleunen 1:66f95e364222 981 NVIC_EnableIRQ(NRF_ESB_BUGFIX_TIMER_IRQn);
wkleunen 1:66f95e364222 982
wkleunen 1:66f95e364222 983 NRF_PPI->CH[NRF_ESB_PPI_BUGFIX1].EEP = (uint32_t)&NRF_RADIO->EVENTS_ADDRESS;
wkleunen 1:66f95e364222 984 NRF_PPI->CH[NRF_ESB_PPI_BUGFIX1].TEP = (uint32_t)&NRF_ESB_BUGFIX_TIMER->TASKS_START;
wkleunen 1:66f95e364222 985
wkleunen 1:66f95e364222 986 NRF_PPI->CH[NRF_ESB_PPI_BUGFIX2].EEP = (uint32_t)&NRF_RADIO->EVENTS_BCMATCH;
wkleunen 1:66f95e364222 987 NRF_PPI->CH[NRF_ESB_PPI_BUGFIX2].TEP = (uint32_t)&NRF_ESB_BUGFIX_TIMER->TASKS_STOP;
wkleunen 1:66f95e364222 988
wkleunen 1:66f95e364222 989 NRF_PPI->CH[NRF_ESB_PPI_BUGFIX3].EEP = (uint32_t)&NRF_RADIO->EVENTS_BCMATCH;
wkleunen 1:66f95e364222 990 NRF_PPI->CH[NRF_ESB_PPI_BUGFIX3].TEP = (uint32_t)&NRF_ESB_BUGFIX_TIMER->TASKS_CLEAR;
wkleunen 1:66f95e364222 991
wkleunen 1:66f95e364222 992 NRF_PPI->CHENSET = (1 << NRF_ESB_PPI_BUGFIX1) | (1 << NRF_ESB_PPI_BUGFIX2) | (1 << NRF_ESB_PPI_BUGFIX3);
wkleunen 1:66f95e364222 993 }
wkleunen 1:66f95e364222 994 #endif
wkleunen 1:66f95e364222 995
wkleunen 1:66f95e364222 996 m_nrf_esb_mainstate = NRF_ESB_STATE_IDLE;
wkleunen 1:66f95e364222 997 m_esb_initialized = true;
wkleunen 1:66f95e364222 998
wkleunen 1:66f95e364222 999 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1000 }
wkleunen 1:66f95e364222 1001
wkleunen 1:66f95e364222 1002
wkleunen 1:66f95e364222 1003 uint32_t nrf_esb_suspend(void)
wkleunen 1:66f95e364222 1004 {
wkleunen 1:66f95e364222 1005 VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
wkleunen 1:66f95e364222 1006
wkleunen 1:66f95e364222 1007 // Clear PPI
wkleunen 1:66f95e364222 1008 NRF_PPI->CHENCLR = (1 << NRF_ESB_PPI_TIMER_START) |
wkleunen 1:66f95e364222 1009 (1 << NRF_ESB_PPI_TIMER_STOP) |
wkleunen 1:66f95e364222 1010 (1 << NRF_ESB_PPI_RX_TIMEOUT) |
wkleunen 1:66f95e364222 1011 (1 << NRF_ESB_PPI_TX_START);
wkleunen 1:66f95e364222 1012
wkleunen 1:66f95e364222 1013 m_nrf_esb_mainstate = NRF_ESB_STATE_IDLE;
wkleunen 1:66f95e364222 1014
wkleunen 1:66f95e364222 1015 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1016 }
wkleunen 1:66f95e364222 1017
wkleunen 1:66f95e364222 1018
wkleunen 1:66f95e364222 1019 uint32_t nrf_esb_disable(void)
wkleunen 1:66f95e364222 1020 {
wkleunen 1:66f95e364222 1021 // Clear PPI
wkleunen 1:66f95e364222 1022 NRF_PPI->CHENCLR = (1 << NRF_ESB_PPI_TIMER_START) |
wkleunen 1:66f95e364222 1023 (1 << NRF_ESB_PPI_TIMER_STOP) |
wkleunen 1:66f95e364222 1024 (1 << NRF_ESB_PPI_RX_TIMEOUT) |
wkleunen 1:66f95e364222 1025 (1 << NRF_ESB_PPI_TX_START);
wkleunen 1:66f95e364222 1026
wkleunen 1:66f95e364222 1027 m_nrf_esb_mainstate = NRF_ESB_STATE_IDLE;
wkleunen 1:66f95e364222 1028
wkleunen 1:66f95e364222 1029 reset_fifos();
wkleunen 1:66f95e364222 1030
wkleunen 1:66f95e364222 1031 memset(m_rx_pipe_info, 0, sizeof(m_rx_pipe_info));
wkleunen 1:66f95e364222 1032 memset(m_pids, 0, sizeof(m_pids));
wkleunen 1:66f95e364222 1033
wkleunen 1:66f95e364222 1034 // Disable the radio
wkleunen 1:66f95e364222 1035 NVIC_DisableIRQ(ESB_EVT_IRQ);
wkleunen 1:66f95e364222 1036 NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Enabled << RADIO_SHORTS_READY_START_Pos |
wkleunen 1:66f95e364222 1037 RADIO_SHORTS_END_DISABLE_Enabled << RADIO_SHORTS_END_DISABLE_Pos;
wkleunen 1:66f95e364222 1038
wkleunen 1:66f95e364222 1039 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1040 }
wkleunen 1:66f95e364222 1041
wkleunen 1:66f95e364222 1042
wkleunen 1:66f95e364222 1043 bool nrf_esb_is_idle(void)
wkleunen 1:66f95e364222 1044 {
wkleunen 1:66f95e364222 1045 return m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE;
wkleunen 1:66f95e364222 1046 }
wkleunen 1:66f95e364222 1047
wkleunen 1:66f95e364222 1048
wkleunen 1:66f95e364222 1049 void ESB_EVT_IRQHandler(void)
wkleunen 1:66f95e364222 1050 {
wkleunen 1:66f95e364222 1051 ret_code_t err_code;
wkleunen 1:66f95e364222 1052 uint32_t interrupts;
wkleunen 1:66f95e364222 1053 nrf_esb_evt_t event;
wkleunen 1:66f95e364222 1054
wkleunen 1:66f95e364222 1055 event.tx_attempts = m_last_tx_attempts;
wkleunen 1:66f95e364222 1056
wkleunen 1:66f95e364222 1057 err_code = nrf_esb_get_clear_interrupts(&interrupts);
wkleunen 1:66f95e364222 1058 if (err_code == NRF_SUCCESS && m_event_handler != 0)
wkleunen 1:66f95e364222 1059 {
wkleunen 1:66f95e364222 1060 if (interrupts & NRF_ESB_INT_TX_SUCCESS_MSK)
wkleunen 1:66f95e364222 1061 {
wkleunen 1:66f95e364222 1062 event.evt_id = NRF_ESB_EVENT_TX_SUCCESS;
wkleunen 1:66f95e364222 1063 m_event_handler(&event);
wkleunen 1:66f95e364222 1064 }
wkleunen 1:66f95e364222 1065 if (interrupts & NRF_ESB_INT_TX_FAILED_MSK)
wkleunen 1:66f95e364222 1066 {
wkleunen 1:66f95e364222 1067 event.evt_id = NRF_ESB_EVENT_TX_FAILED;
wkleunen 1:66f95e364222 1068 m_event_handler(&event);
wkleunen 1:66f95e364222 1069 }
wkleunen 1:66f95e364222 1070 if (interrupts & NRF_ESB_INT_RX_DATA_RECEIVED_MSK)
wkleunen 1:66f95e364222 1071 {
wkleunen 1:66f95e364222 1072 event.evt_id = NRF_ESB_EVENT_RX_RECEIVED;
wkleunen 1:66f95e364222 1073 m_event_handler(&event);
wkleunen 1:66f95e364222 1074 }
wkleunen 1:66f95e364222 1075 }
wkleunen 1:66f95e364222 1076 }
wkleunen 1:66f95e364222 1077
wkleunen 1:66f95e364222 1078 uint32_t nrf_esb_write_payload(nrf_esb_payload_t const * p_payload)
wkleunen 1:66f95e364222 1079 {
wkleunen 1:66f95e364222 1080 VERIFY_TRUE(m_esb_initialized, NRF_ERROR_INVALID_STATE);
wkleunen 1:66f95e364222 1081 VERIFY_PARAM_NOT_NULL(p_payload);
wkleunen 1:66f95e364222 1082 VERIFY_PAYLOAD_LENGTH(p_payload);
wkleunen 1:66f95e364222 1083 VERIFY_FALSE(m_tx_fifo.count >= NRF_ESB_TX_FIFO_SIZE, NRF_ERROR_NO_MEM);
wkleunen 1:66f95e364222 1084 VERIFY_TRUE(p_payload->pipe < NRF_ESB_PIPE_COUNT, NRF_ERROR_INVALID_PARAM);
wkleunen 1:66f95e364222 1085
wkleunen 1:66f95e364222 1086 DISABLE_RF_IRQ();
wkleunen 1:66f95e364222 1087
wkleunen 1:66f95e364222 1088 memcpy(m_tx_fifo.p_payload[m_tx_fifo.entry_point], p_payload, sizeof(nrf_esb_payload_t));
wkleunen 1:66f95e364222 1089
wkleunen 1:66f95e364222 1090 m_pids[p_payload->pipe] = (m_pids[p_payload->pipe] + 1) % (NRF_ESB_PID_MAX + 1);
wkleunen 1:66f95e364222 1091 m_tx_fifo.p_payload[m_tx_fifo.entry_point]->pid = m_pids[p_payload->pipe];
wkleunen 1:66f95e364222 1092
wkleunen 1:66f95e364222 1093 if (++m_tx_fifo.entry_point >= NRF_ESB_TX_FIFO_SIZE)
wkleunen 1:66f95e364222 1094 {
wkleunen 1:66f95e364222 1095 m_tx_fifo.entry_point = 0;
wkleunen 1:66f95e364222 1096 }
wkleunen 1:66f95e364222 1097
wkleunen 1:66f95e364222 1098 m_tx_fifo.count++;
wkleunen 1:66f95e364222 1099
wkleunen 1:66f95e364222 1100 ENABLE_RF_IRQ();
wkleunen 1:66f95e364222 1101
wkleunen 1:66f95e364222 1102
wkleunen 1:66f95e364222 1103 if (m_config_local.mode == NRF_ESB_MODE_PTX &&
wkleunen 1:66f95e364222 1104 m_config_local.tx_mode == NRF_ESB_TXMODE_AUTO &&
wkleunen 1:66f95e364222 1105 m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE)
wkleunen 1:66f95e364222 1106 {
wkleunen 1:66f95e364222 1107 start_tx_transaction();
wkleunen 1:66f95e364222 1108 }
wkleunen 1:66f95e364222 1109
wkleunen 1:66f95e364222 1110 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1111 }
wkleunen 1:66f95e364222 1112
wkleunen 1:66f95e364222 1113
wkleunen 1:66f95e364222 1114 uint32_t nrf_esb_read_rx_payload(nrf_esb_payload_t * p_payload)
wkleunen 1:66f95e364222 1115 {
wkleunen 1:66f95e364222 1116 VERIFY_TRUE(m_esb_initialized, NRF_ERROR_INVALID_STATE);
wkleunen 1:66f95e364222 1117 VERIFY_PARAM_NOT_NULL(p_payload);
wkleunen 1:66f95e364222 1118
wkleunen 1:66f95e364222 1119 if (m_rx_fifo.count == 0)
wkleunen 1:66f95e364222 1120 {
wkleunen 1:66f95e364222 1121 return NRF_ERROR_NOT_FOUND;
wkleunen 1:66f95e364222 1122 }
wkleunen 1:66f95e364222 1123
wkleunen 1:66f95e364222 1124 DISABLE_RF_IRQ();
wkleunen 1:66f95e364222 1125
wkleunen 1:66f95e364222 1126 p_payload->length = m_rx_fifo.p_payload[m_rx_fifo.exit_point]->length;
wkleunen 1:66f95e364222 1127 p_payload->pipe = m_rx_fifo.p_payload[m_rx_fifo.exit_point]->pipe;
wkleunen 1:66f95e364222 1128 p_payload->rssi = m_rx_fifo.p_payload[m_rx_fifo.exit_point]->rssi;
wkleunen 1:66f95e364222 1129 p_payload->pid = m_rx_fifo.p_payload[m_rx_fifo.exit_point]->pid;
wkleunen 1:66f95e364222 1130 p_payload->noack = m_rx_fifo.p_payload[m_rx_fifo.exit_point]->noack;
wkleunen 1:66f95e364222 1131 memcpy(p_payload->data, m_rx_fifo.p_payload[m_rx_fifo.exit_point]->data, p_payload->length);
wkleunen 1:66f95e364222 1132
wkleunen 1:66f95e364222 1133 if (++m_rx_fifo.exit_point >= NRF_ESB_RX_FIFO_SIZE)
wkleunen 1:66f95e364222 1134 {
wkleunen 1:66f95e364222 1135 m_rx_fifo.exit_point = 0;
wkleunen 1:66f95e364222 1136 }
wkleunen 1:66f95e364222 1137
wkleunen 1:66f95e364222 1138 m_rx_fifo.count--;
wkleunen 1:66f95e364222 1139
wkleunen 1:66f95e364222 1140 ENABLE_RF_IRQ();
wkleunen 1:66f95e364222 1141
wkleunen 1:66f95e364222 1142 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1143 }
wkleunen 1:66f95e364222 1144
wkleunen 1:66f95e364222 1145
wkleunen 1:66f95e364222 1146 uint32_t nrf_esb_start_tx(void)
wkleunen 1:66f95e364222 1147 {
wkleunen 1:66f95e364222 1148 VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
wkleunen 1:66f95e364222 1149
wkleunen 1:66f95e364222 1150 if (m_tx_fifo.count == 0)
wkleunen 1:66f95e364222 1151 {
wkleunen 1:66f95e364222 1152 return NRF_ERROR_BUFFER_EMPTY;
wkleunen 1:66f95e364222 1153 }
wkleunen 1:66f95e364222 1154
wkleunen 1:66f95e364222 1155 start_tx_transaction();
wkleunen 1:66f95e364222 1156
wkleunen 1:66f95e364222 1157 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1158 }
wkleunen 1:66f95e364222 1159
wkleunen 1:66f95e364222 1160
wkleunen 1:66f95e364222 1161 uint32_t nrf_esb_start_rx(void)
wkleunen 1:66f95e364222 1162 {
wkleunen 1:66f95e364222 1163 VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
wkleunen 1:66f95e364222 1164
wkleunen 1:66f95e364222 1165 NRF_RADIO->INTENCLR = 0xFFFFFFFF;
wkleunen 1:66f95e364222 1166 NRF_RADIO->EVENTS_DISABLED = 0;
wkleunen 1:66f95e364222 1167 on_radio_disabled = on_radio_disabled_rx;
wkleunen 1:66f95e364222 1168
wkleunen 1:66f95e364222 1169 NRF_RADIO->SHORTS = m_radio_shorts_common | RADIO_SHORTS_DISABLED_TXEN_Msk;
wkleunen 1:66f95e364222 1170 NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk;
wkleunen 1:66f95e364222 1171 m_nrf_esb_mainstate = NRF_ESB_STATE_PRX;
wkleunen 1:66f95e364222 1172
wkleunen 1:66f95e364222 1173 NRF_RADIO->RXADDRESSES = m_esb_addr.rx_pipes_enabled;
wkleunen 1:66f95e364222 1174 NRF_RADIO->FREQUENCY = m_esb_addr.rf_channel;
wkleunen 1:66f95e364222 1175 NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer;
wkleunen 1:66f95e364222 1176
wkleunen 1:66f95e364222 1177 NVIC_ClearPendingIRQ(RADIO_IRQn);
wkleunen 1:66f95e364222 1178 NVIC_EnableIRQ(RADIO_IRQn);
wkleunen 1:66f95e364222 1179
wkleunen 1:66f95e364222 1180 NRF_RADIO->EVENTS_ADDRESS = 0;
wkleunen 1:66f95e364222 1181 NRF_RADIO->EVENTS_PAYLOAD = 0;
wkleunen 1:66f95e364222 1182 NRF_RADIO->EVENTS_DISABLED = 0;
wkleunen 1:66f95e364222 1183
wkleunen 1:66f95e364222 1184 NRF_RADIO->TASKS_RXEN = 1;
wkleunen 1:66f95e364222 1185
wkleunen 1:66f95e364222 1186 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1187 }
wkleunen 1:66f95e364222 1188
wkleunen 1:66f95e364222 1189
wkleunen 1:66f95e364222 1190 uint32_t nrf_esb_stop_rx(void)
wkleunen 1:66f95e364222 1191 {
wkleunen 1:66f95e364222 1192 if (m_nrf_esb_mainstate == NRF_ESB_STATE_PRX)
wkleunen 1:66f95e364222 1193 {
wkleunen 1:66f95e364222 1194 NRF_RADIO->SHORTS = 0;
wkleunen 1:66f95e364222 1195 NRF_RADIO->INTENCLR = 0xFFFFFFFF;
wkleunen 1:66f95e364222 1196 on_radio_disabled = NULL;
wkleunen 1:66f95e364222 1197 NRF_RADIO->EVENTS_DISABLED = 0;
wkleunen 1:66f95e364222 1198 NRF_RADIO->TASKS_DISABLE = 1;
wkleunen 1:66f95e364222 1199 while (NRF_RADIO->EVENTS_DISABLED == 0);
wkleunen 1:66f95e364222 1200 m_nrf_esb_mainstate = NRF_ESB_STATE_IDLE;
wkleunen 1:66f95e364222 1201
wkleunen 1:66f95e364222 1202 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1203 }
wkleunen 1:66f95e364222 1204
wkleunen 1:66f95e364222 1205 return NRF_ESB_ERROR_NOT_IN_RX_MODE;
wkleunen 1:66f95e364222 1206 }
wkleunen 1:66f95e364222 1207
wkleunen 1:66f95e364222 1208
wkleunen 1:66f95e364222 1209 uint32_t nrf_esb_flush_tx(void)
wkleunen 1:66f95e364222 1210 {
wkleunen 1:66f95e364222 1211 VERIFY_TRUE(m_esb_initialized, NRF_ERROR_INVALID_STATE);
wkleunen 1:66f95e364222 1212
wkleunen 1:66f95e364222 1213 DISABLE_RF_IRQ();
wkleunen 1:66f95e364222 1214
wkleunen 1:66f95e364222 1215 m_tx_fifo.count = 0;
wkleunen 1:66f95e364222 1216 m_tx_fifo.entry_point = 0;
wkleunen 1:66f95e364222 1217 m_tx_fifo.exit_point = 0;
wkleunen 1:66f95e364222 1218
wkleunen 1:66f95e364222 1219 ENABLE_RF_IRQ();
wkleunen 1:66f95e364222 1220
wkleunen 1:66f95e364222 1221 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1222 }
wkleunen 1:66f95e364222 1223
wkleunen 1:66f95e364222 1224
wkleunen 1:66f95e364222 1225 uint32_t nrf_esb_pop_tx(void)
wkleunen 1:66f95e364222 1226 {
wkleunen 1:66f95e364222 1227 VERIFY_TRUE(m_esb_initialized, NRF_ERROR_INVALID_STATE);
wkleunen 1:66f95e364222 1228 VERIFY_TRUE(m_tx_fifo.count > 0, NRF_ERROR_BUFFER_EMPTY);
wkleunen 1:66f95e364222 1229
wkleunen 1:66f95e364222 1230 DISABLE_RF_IRQ();
wkleunen 1:66f95e364222 1231
wkleunen 1:66f95e364222 1232 if (++m_tx_fifo.entry_point >= NRF_ESB_TX_FIFO_SIZE)
wkleunen 1:66f95e364222 1233 {
wkleunen 1:66f95e364222 1234 m_tx_fifo.entry_point = 0;
wkleunen 1:66f95e364222 1235 }
wkleunen 1:66f95e364222 1236 m_tx_fifo.count--;
wkleunen 1:66f95e364222 1237
wkleunen 1:66f95e364222 1238 ENABLE_RF_IRQ();
wkleunen 1:66f95e364222 1239
wkleunen 1:66f95e364222 1240 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1241 }
wkleunen 1:66f95e364222 1242
wkleunen 1:66f95e364222 1243
wkleunen 1:66f95e364222 1244 uint32_t nrf_esb_flush_rx(void)
wkleunen 1:66f95e364222 1245 {
wkleunen 1:66f95e364222 1246 VERIFY_TRUE(m_esb_initialized, NRF_ERROR_INVALID_STATE);
wkleunen 1:66f95e364222 1247
wkleunen 1:66f95e364222 1248 DISABLE_RF_IRQ();
wkleunen 1:66f95e364222 1249
wkleunen 1:66f95e364222 1250 m_rx_fifo.count = 0;
wkleunen 1:66f95e364222 1251 m_rx_fifo.entry_point = 0;
wkleunen 1:66f95e364222 1252 m_rx_fifo.exit_point = 0;
wkleunen 1:66f95e364222 1253
wkleunen 1:66f95e364222 1254 memset(m_rx_pipe_info, 0, sizeof(m_rx_pipe_info));
wkleunen 1:66f95e364222 1255
wkleunen 1:66f95e364222 1256 ENABLE_RF_IRQ();
wkleunen 1:66f95e364222 1257
wkleunen 1:66f95e364222 1258 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1259 }
wkleunen 1:66f95e364222 1260
wkleunen 1:66f95e364222 1261
wkleunen 1:66f95e364222 1262 uint32_t nrf_esb_set_address_length(uint8_t length)
wkleunen 1:66f95e364222 1263 {
wkleunen 1:66f95e364222 1264 VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
wkleunen 1:66f95e364222 1265 VERIFY_TRUE(length > 2 && length < 6, NRF_ERROR_INVALID_PARAM);
wkleunen 1:66f95e364222 1266
wkleunen 1:66f95e364222 1267 /*
wkleunen 1:66f95e364222 1268 Workaround for nRF52832 Rev 1 Errata 107
wkleunen 1:66f95e364222 1269 Check if pipe 0 or pipe 1-7 has a 'zero address'.
wkleunen 1:66f95e364222 1270 Avoid using access addresses in the following pattern (where X is don't care):
wkleunen 1:66f95e364222 1271 ADDRLEN=5
wkleunen 1:66f95e364222 1272 BASE0 = 0x0000XXXX, PREFIX0 = 0xXXXXXX00
wkleunen 1:66f95e364222 1273 BASE1 = 0x0000XXXX, PREFIX0 = 0xXXXX00XX
wkleunen 1:66f95e364222 1274 BASE1 = 0x0000XXXX, PREFIX0 = 0xXX00XXXX
wkleunen 1:66f95e364222 1275 BASE1 = 0x0000XXXX, PREFIX0 = 0x00XXXXXX
wkleunen 1:66f95e364222 1276 BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXXXX00
wkleunen 1:66f95e364222 1277 BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXX00XX
wkleunen 1:66f95e364222 1278 BASE1 = 0x0000XXXX, PREFIX1 = 0xXX00XXXX
wkleunen 1:66f95e364222 1279 BASE1 = 0x0000XXXX, PREFIX1 = 0x00XXXXXX
wkleunen 1:66f95e364222 1280
wkleunen 1:66f95e364222 1281 ADDRLEN=4
wkleunen 1:66f95e364222 1282 BASE0 = 0x00XXXXXX, PREFIX0 = 0xXXXXXX00
wkleunen 1:66f95e364222 1283 BASE1 = 0x00XXXXXX, PREFIX0 = 0xXXXX00XX
wkleunen 1:66f95e364222 1284 BASE1 = 0x00XXXXXX, PREFIX0 = 0xXX00XXXX
wkleunen 1:66f95e364222 1285 BASE1 = 0x00XXXXXX, PREFIX0 = 0x00XXXXXX
wkleunen 1:66f95e364222 1286 BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXXXX00
wkleunen 1:66f95e364222 1287 BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXX00XX
wkleunen 1:66f95e364222 1288 BASE1 = 0x00XXXXXX, PREFIX1 = 0xXX00XXXX
wkleunen 1:66f95e364222 1289 BASE1 = 0x00XXXXXX, PREFIX1 = 0x00XXXXXX
wkleunen 1:66f95e364222 1290 */
wkleunen 1:66f95e364222 1291 uint32_t base_address_mask = length == 5 ? 0xFFFF0000 : 0xFF000000;
wkleunen 1:66f95e364222 1292 if((NRF_RADIO->BASE0 & base_address_mask) == 0 && (NRF_RADIO->PREFIX0 & 0x000000FF) == 0)
wkleunen 1:66f95e364222 1293 {
wkleunen 1:66f95e364222 1294 return NRF_ERROR_INVALID_PARAM;
wkleunen 1:66f95e364222 1295 }
wkleunen 1:66f95e364222 1296 if((NRF_RADIO->BASE1 & base_address_mask) == 0 && ((NRF_RADIO->PREFIX0 & 0x0000FF00) == 0 ||(NRF_RADIO->PREFIX0 & 0x00FF0000) == 0 || (NRF_RADIO->PREFIX0 & 0xFF000000) == 0 ||
wkleunen 1:66f95e364222 1297 (NRF_RADIO->PREFIX1 & 0xFF000000) == 0 || (NRF_RADIO->PREFIX1 & 0x00FF0000) == 0 ||(NRF_RADIO->PREFIX1 & 0x0000FF00) == 0 || (NRF_RADIO->PREFIX1 & 0x000000FF) == 0))
wkleunen 1:66f95e364222 1298 {
wkleunen 1:66f95e364222 1299 return NRF_ERROR_INVALID_PARAM;
wkleunen 1:66f95e364222 1300 }
wkleunen 1:66f95e364222 1301
wkleunen 1:66f95e364222 1302 m_esb_addr.addr_length = length;
wkleunen 1:66f95e364222 1303
wkleunen 1:66f95e364222 1304 update_rf_payload_format(m_config_local.payload_length);
wkleunen 1:66f95e364222 1305
wkleunen 1:66f95e364222 1306 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1307 }
wkleunen 1:66f95e364222 1308
wkleunen 1:66f95e364222 1309
wkleunen 1:66f95e364222 1310 uint32_t nrf_esb_set_base_address_0(uint8_t const * p_addr)
wkleunen 1:66f95e364222 1311 {
wkleunen 1:66f95e364222 1312 VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
wkleunen 1:66f95e364222 1313 VERIFY_PARAM_NOT_NULL(p_addr);
wkleunen 1:66f95e364222 1314
wkleunen 1:66f95e364222 1315 /*
wkleunen 1:66f95e364222 1316 Workaround for nRF52832 Rev 1 Errata 107
wkleunen 1:66f95e364222 1317 Check if pipe 0 or pipe 1-7 has a 'zero address'.
wkleunen 1:66f95e364222 1318 Avoid using access addresses in the following pattern (where X is don't care):
wkleunen 1:66f95e364222 1319 ADDRLEN=5
wkleunen 1:66f95e364222 1320 BASE0 = 0x0000XXXX, PREFIX0 = 0xXXXXXX00
wkleunen 1:66f95e364222 1321 BASE1 = 0x0000XXXX, PREFIX0 = 0xXXXX00XX
wkleunen 1:66f95e364222 1322 BASE1 = 0x0000XXXX, PREFIX0 = 0xXX00XXXX
wkleunen 1:66f95e364222 1323 BASE1 = 0x0000XXXX, PREFIX0 = 0x00XXXXXX
wkleunen 1:66f95e364222 1324 BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXXXX00
wkleunen 1:66f95e364222 1325 BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXX00XX
wkleunen 1:66f95e364222 1326 BASE1 = 0x0000XXXX, PREFIX1 = 0xXX00XXXX
wkleunen 1:66f95e364222 1327 BASE1 = 0x0000XXXX, PREFIX1 = 0x00XXXXXX
wkleunen 1:66f95e364222 1328
wkleunen 1:66f95e364222 1329 ADDRLEN=4
wkleunen 1:66f95e364222 1330 BASE0 = 0x00XXXXXX, PREFIX0 = 0xXXXXXX00
wkleunen 1:66f95e364222 1331 BASE1 = 0x00XXXXXX, PREFIX0 = 0xXXXX00XX
wkleunen 1:66f95e364222 1332 BASE1 = 0x00XXXXXX, PREFIX0 = 0xXX00XXXX
wkleunen 1:66f95e364222 1333 BASE1 = 0x00XXXXXX, PREFIX0 = 0x00XXXXXX
wkleunen 1:66f95e364222 1334 BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXXXX00
wkleunen 1:66f95e364222 1335 BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXX00XX
wkleunen 1:66f95e364222 1336 BASE1 = 0x00XXXXXX, PREFIX1 = 0xXX00XXXX
wkleunen 1:66f95e364222 1337 BASE1 = 0x00XXXXXX, PREFIX1 = 0x00XXXXXX
wkleunen 1:66f95e364222 1338 */
wkleunen 1:66f95e364222 1339 uint32_t base_address_mask = m_esb_addr.addr_length == 5 ? 0xFFFF0000 : 0xFF000000;
wkleunen 1:66f95e364222 1340 if((addr_conv(p_addr) & base_address_mask) == 0 && (NRF_RADIO->PREFIX0 & 0x000000FF) == 0)
wkleunen 1:66f95e364222 1341 {
wkleunen 1:66f95e364222 1342 return NRF_ERROR_INVALID_PARAM;
wkleunen 1:66f95e364222 1343 }
wkleunen 1:66f95e364222 1344
wkleunen 1:66f95e364222 1345 memcpy(m_esb_addr.base_addr_p0, p_addr, 4);
wkleunen 1:66f95e364222 1346
wkleunen 1:66f95e364222 1347 update_radio_addresses(NRF_ESB_ADDR_UPDATE_MASK_BASE0);
wkleunen 1:66f95e364222 1348
wkleunen 1:66f95e364222 1349 return apply_address_workarounds();
wkleunen 1:66f95e364222 1350 }
wkleunen 1:66f95e364222 1351
wkleunen 1:66f95e364222 1352
wkleunen 1:66f95e364222 1353 uint32_t nrf_esb_set_base_address_1(uint8_t const * p_addr)
wkleunen 1:66f95e364222 1354 {
wkleunen 1:66f95e364222 1355 VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
wkleunen 1:66f95e364222 1356 VERIFY_PARAM_NOT_NULL(p_addr);
wkleunen 1:66f95e364222 1357
wkleunen 1:66f95e364222 1358 /*
wkleunen 1:66f95e364222 1359 Workaround for nRF52832 Rev 1 Errata 107
wkleunen 1:66f95e364222 1360 Check if pipe 0 or pipe 1-7 has a 'zero address'.
wkleunen 1:66f95e364222 1361 Avoid using access addresses in the following pattern (where X is don't care):
wkleunen 1:66f95e364222 1362 ADDRLEN=5
wkleunen 1:66f95e364222 1363 BASE0 = 0x0000XXXX, PREFIX0 = 0xXXXXXX00
wkleunen 1:66f95e364222 1364 BASE1 = 0x0000XXXX, PREFIX0 = 0xXXXX00XX
wkleunen 1:66f95e364222 1365 BASE1 = 0x0000XXXX, PREFIX0 = 0xXX00XXXX
wkleunen 1:66f95e364222 1366 BASE1 = 0x0000XXXX, PREFIX0 = 0x00XXXXXX
wkleunen 1:66f95e364222 1367 BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXXXX00
wkleunen 1:66f95e364222 1368 BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXX00XX
wkleunen 1:66f95e364222 1369 BASE1 = 0x0000XXXX, PREFIX1 = 0xXX00XXXX
wkleunen 1:66f95e364222 1370 BASE1 = 0x0000XXXX, PREFIX1 = 0x00XXXXXX
wkleunen 1:66f95e364222 1371
wkleunen 1:66f95e364222 1372 ADDRLEN=4
wkleunen 1:66f95e364222 1373 BASE0 = 0x00XXXXXX, PREFIX0 = 0xXXXXXX00
wkleunen 1:66f95e364222 1374 BASE1 = 0x00XXXXXX, PREFIX0 = 0xXXXX00XX
wkleunen 1:66f95e364222 1375 BASE1 = 0x00XXXXXX, PREFIX0 = 0xXX00XXXX
wkleunen 1:66f95e364222 1376 BASE1 = 0x00XXXXXX, PREFIX0 = 0x00XXXXXX
wkleunen 1:66f95e364222 1377 BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXXXX00
wkleunen 1:66f95e364222 1378 BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXX00XX
wkleunen 1:66f95e364222 1379 BASE1 = 0x00XXXXXX, PREFIX1 = 0xXX00XXXX
wkleunen 1:66f95e364222 1380 BASE1 = 0x00XXXXXX, PREFIX1 = 0x00XXXXXX
wkleunen 1:66f95e364222 1381 */
wkleunen 1:66f95e364222 1382 uint32_t base_address_mask = m_esb_addr.addr_length == 5 ? 0xFFFF0000 : 0xFF000000;
wkleunen 1:66f95e364222 1383 if((addr_conv(p_addr) & base_address_mask) == 0 && ((NRF_RADIO->PREFIX0 & 0x0000FF00) == 0 ||(NRF_RADIO->PREFIX0 & 0x00FF0000) == 0 || (NRF_RADIO->PREFIX0 & 0xFF000000) == 0 ||
wkleunen 1:66f95e364222 1384 (NRF_RADIO->PREFIX1 & 0xFF000000) == 0 || (NRF_RADIO->PREFIX1 & 0x00FF0000) == 0 ||(NRF_RADIO->PREFIX1 & 0x0000FF00) == 0 || (NRF_RADIO->PREFIX1 & 0x000000FF) == 0))
wkleunen 1:66f95e364222 1385 {
wkleunen 1:66f95e364222 1386 return NRF_ERROR_INVALID_PARAM;
wkleunen 1:66f95e364222 1387 }
wkleunen 1:66f95e364222 1388
wkleunen 1:66f95e364222 1389 memcpy(m_esb_addr.base_addr_p1, p_addr, 4);
wkleunen 1:66f95e364222 1390
wkleunen 1:66f95e364222 1391 update_radio_addresses(NRF_ESB_ADDR_UPDATE_MASK_BASE1);
wkleunen 1:66f95e364222 1392
wkleunen 1:66f95e364222 1393 return apply_address_workarounds();
wkleunen 1:66f95e364222 1394 }
wkleunen 1:66f95e364222 1395
wkleunen 1:66f95e364222 1396
wkleunen 1:66f95e364222 1397 uint32_t nrf_esb_set_prefixes(uint8_t const * p_prefixes, uint8_t num_pipes)
wkleunen 1:66f95e364222 1398 {
wkleunen 1:66f95e364222 1399 VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
wkleunen 1:66f95e364222 1400 VERIFY_PARAM_NOT_NULL(p_prefixes);
wkleunen 1:66f95e364222 1401 VERIFY_TRUE(num_pipes < 9, NRF_ERROR_INVALID_PARAM);
wkleunen 1:66f95e364222 1402
wkleunen 1:66f95e364222 1403 /*
wkleunen 1:66f95e364222 1404 Workaround for nRF52832 Rev 1 Errata 107
wkleunen 1:66f95e364222 1405 Check if pipe 0 or pipe 1-7 has a 'zero address'.
wkleunen 1:66f95e364222 1406 Avoid using access addresses in the following pattern (where X is don't care):
wkleunen 1:66f95e364222 1407 ADDRLEN=5
wkleunen 1:66f95e364222 1408 BASE0 = 0x0000XXXX, PREFIX0 = 0xXXXXXX00
wkleunen 1:66f95e364222 1409 BASE1 = 0x0000XXXX, PREFIX0 = 0xXXXX00XX
wkleunen 1:66f95e364222 1410 BASE1 = 0x0000XXXX, PREFIX0 = 0xXX00XXXX
wkleunen 1:66f95e364222 1411 BASE1 = 0x0000XXXX, PREFIX0 = 0x00XXXXXX
wkleunen 1:66f95e364222 1412 BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXXXX00
wkleunen 1:66f95e364222 1413 BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXX00XX
wkleunen 1:66f95e364222 1414 BASE1 = 0x0000XXXX, PREFIX1 = 0xXX00XXXX
wkleunen 1:66f95e364222 1415 BASE1 = 0x0000XXXX, PREFIX1 = 0x00XXXXXX
wkleunen 1:66f95e364222 1416
wkleunen 1:66f95e364222 1417 ADDRLEN=4
wkleunen 1:66f95e364222 1418 BASE0 = 0x00XXXXXX, PREFIX0 = 0xXXXXXX00
wkleunen 1:66f95e364222 1419 BASE1 = 0x00XXXXXX, PREFIX0 = 0xXXXX00XX
wkleunen 1:66f95e364222 1420 BASE1 = 0x00XXXXXX, PREFIX0 = 0xXX00XXXX
wkleunen 1:66f95e364222 1421 BASE1 = 0x00XXXXXX, PREFIX0 = 0x00XXXXXX
wkleunen 1:66f95e364222 1422 BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXXXX00
wkleunen 1:66f95e364222 1423 BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXX00XX
wkleunen 1:66f95e364222 1424 BASE1 = 0x00XXXXXX, PREFIX1 = 0xXX00XXXX
wkleunen 1:66f95e364222 1425 BASE1 = 0x00XXXXXX, PREFIX1 = 0x00XXXXXX
wkleunen 1:66f95e364222 1426 */
wkleunen 1:66f95e364222 1427 uint32_t base_address_mask = m_esb_addr.addr_length == 5 ? 0xFFFF0000 : 0xFF000000;
wkleunen 1:66f95e364222 1428 if(num_pipes >= 1 && (NRF_RADIO->BASE0 & base_address_mask) == 0 && p_prefixes[0] == 0)
wkleunen 1:66f95e364222 1429 {
wkleunen 1:66f95e364222 1430 return NRF_ERROR_INVALID_PARAM;
wkleunen 1:66f95e364222 1431 }
wkleunen 1:66f95e364222 1432
wkleunen 1:66f95e364222 1433 if((NRF_RADIO->BASE1 & base_address_mask) == 0)
wkleunen 1:66f95e364222 1434 {
wkleunen 1:66f95e364222 1435 for (uint8_t i = 1; i < num_pipes; i++)
wkleunen 1:66f95e364222 1436 {
wkleunen 1:66f95e364222 1437 if (p_prefixes[i] == 0)
wkleunen 1:66f95e364222 1438 {
wkleunen 1:66f95e364222 1439 return NRF_ERROR_INVALID_PARAM;
wkleunen 1:66f95e364222 1440 }
wkleunen 1:66f95e364222 1441 }
wkleunen 1:66f95e364222 1442 }
wkleunen 1:66f95e364222 1443
wkleunen 1:66f95e364222 1444 memcpy(m_esb_addr.pipe_prefixes, p_prefixes, num_pipes);
wkleunen 1:66f95e364222 1445 m_esb_addr.num_pipes = num_pipes;
wkleunen 1:66f95e364222 1446 m_esb_addr.rx_pipes_enabled = BIT_MASK_UINT_8(num_pipes);
wkleunen 1:66f95e364222 1447
wkleunen 1:66f95e364222 1448 update_radio_addresses(NRF_ESB_ADDR_UPDATE_MASK_PREFIX);
wkleunen 1:66f95e364222 1449
wkleunen 1:66f95e364222 1450 return apply_address_workarounds();
wkleunen 1:66f95e364222 1451 }
wkleunen 1:66f95e364222 1452
wkleunen 1:66f95e364222 1453
wkleunen 1:66f95e364222 1454 uint32_t nrf_esb_update_prefix(uint8_t pipe, uint8_t prefix)
wkleunen 1:66f95e364222 1455 {
wkleunen 1:66f95e364222 1456 VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
wkleunen 1:66f95e364222 1457 VERIFY_TRUE(pipe < 8, NRF_ERROR_INVALID_PARAM);
wkleunen 1:66f95e364222 1458
wkleunen 1:66f95e364222 1459 /*
wkleunen 1:66f95e364222 1460 Workaround for nRF52832 Rev 1 Errata 107
wkleunen 1:66f95e364222 1461 Check if pipe 0 or pipe 1-7 has a 'zero address'.
wkleunen 1:66f95e364222 1462 Avoid using access addresses in the following pattern (where X is don't care):
wkleunen 1:66f95e364222 1463 ADDRLEN=5
wkleunen 1:66f95e364222 1464 BASE0 = 0x0000XXXX, PREFIX0 = 0xXXXXXX00
wkleunen 1:66f95e364222 1465 BASE1 = 0x0000XXXX, PREFIX0 = 0xXXXX00XX
wkleunen 1:66f95e364222 1466 BASE1 = 0x0000XXXX, PREFIX0 = 0xXX00XXXX
wkleunen 1:66f95e364222 1467 BASE1 = 0x0000XXXX, PREFIX0 = 0x00XXXXXX
wkleunen 1:66f95e364222 1468 BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXXXX00
wkleunen 1:66f95e364222 1469 BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXX00XX
wkleunen 1:66f95e364222 1470 BASE1 = 0x0000XXXX, PREFIX1 = 0xXX00XXXX
wkleunen 1:66f95e364222 1471 BASE1 = 0x0000XXXX, PREFIX1 = 0x00XXXXXX
wkleunen 1:66f95e364222 1472
wkleunen 1:66f95e364222 1473 ADDRLEN=4
wkleunen 1:66f95e364222 1474 BASE0 = 0x00XXXXXX, PREFIX0 = 0xXXXXXX00
wkleunen 1:66f95e364222 1475 BASE1 = 0x00XXXXXX, PREFIX0 = 0xXXXX00XX
wkleunen 1:66f95e364222 1476 BASE1 = 0x00XXXXXX, PREFIX0 = 0xXX00XXXX
wkleunen 1:66f95e364222 1477 BASE1 = 0x00XXXXXX, PREFIX0 = 0x00XXXXXX
wkleunen 1:66f95e364222 1478 BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXXXX00
wkleunen 1:66f95e364222 1479 BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXX00XX
wkleunen 1:66f95e364222 1480 BASE1 = 0x00XXXXXX, PREFIX1 = 0xXX00XXXX
wkleunen 1:66f95e364222 1481 BASE1 = 0x00XXXXXX, PREFIX1 = 0x00XXXXXX
wkleunen 1:66f95e364222 1482 */
wkleunen 1:66f95e364222 1483 uint32_t base_address_mask = m_esb_addr.addr_length == 5 ? 0xFFFF0000 : 0xFF000000;
wkleunen 1:66f95e364222 1484 if (pipe == 0)
wkleunen 1:66f95e364222 1485 {
wkleunen 1:66f95e364222 1486 if((NRF_RADIO->BASE0 & base_address_mask) == 0 && prefix == 0)
wkleunen 1:66f95e364222 1487 {
wkleunen 1:66f95e364222 1488 return NRF_ERROR_INVALID_PARAM;
wkleunen 1:66f95e364222 1489 }
wkleunen 1:66f95e364222 1490 }
wkleunen 1:66f95e364222 1491 else{
wkleunen 1:66f95e364222 1492 if((NRF_RADIO->BASE1 & base_address_mask) == 0 && prefix == 0)
wkleunen 1:66f95e364222 1493 {
wkleunen 1:66f95e364222 1494 return NRF_ERROR_INVALID_PARAM;
wkleunen 1:66f95e364222 1495 }
wkleunen 1:66f95e364222 1496 }
wkleunen 1:66f95e364222 1497
wkleunen 1:66f95e364222 1498 m_esb_addr.pipe_prefixes[pipe] = prefix;
wkleunen 1:66f95e364222 1499
wkleunen 1:66f95e364222 1500 update_radio_addresses(NRF_ESB_ADDR_UPDATE_MASK_PREFIX);
wkleunen 1:66f95e364222 1501
wkleunen 1:66f95e364222 1502 return apply_address_workarounds();
wkleunen 1:66f95e364222 1503 }
wkleunen 1:66f95e364222 1504
wkleunen 1:66f95e364222 1505
wkleunen 1:66f95e364222 1506 uint32_t nrf_esb_enable_pipes(uint8_t enable_mask)
wkleunen 1:66f95e364222 1507 {
wkleunen 1:66f95e364222 1508 VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
wkleunen 1:66f95e364222 1509
wkleunen 1:66f95e364222 1510 m_esb_addr.rx_pipes_enabled = enable_mask;
wkleunen 1:66f95e364222 1511
wkleunen 1:66f95e364222 1512 return apply_address_workarounds();
wkleunen 1:66f95e364222 1513 }
wkleunen 1:66f95e364222 1514
wkleunen 1:66f95e364222 1515
wkleunen 1:66f95e364222 1516 uint32_t nrf_esb_set_rf_channel(uint32_t channel)
wkleunen 1:66f95e364222 1517 {
wkleunen 1:66f95e364222 1518 VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
wkleunen 1:66f95e364222 1519 VERIFY_TRUE(channel <= 100, NRF_ERROR_INVALID_PARAM);
wkleunen 1:66f95e364222 1520
wkleunen 1:66f95e364222 1521 m_esb_addr.rf_channel = channel;
wkleunen 1:66f95e364222 1522
wkleunen 1:66f95e364222 1523 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1524 }
wkleunen 1:66f95e364222 1525
wkleunen 1:66f95e364222 1526
wkleunen 1:66f95e364222 1527 uint32_t nrf_esb_get_rf_channel(uint32_t * p_channel)
wkleunen 1:66f95e364222 1528 {
wkleunen 1:66f95e364222 1529 VERIFY_PARAM_NOT_NULL(p_channel);
wkleunen 1:66f95e364222 1530
wkleunen 1:66f95e364222 1531 *p_channel = m_esb_addr.rf_channel;
wkleunen 1:66f95e364222 1532
wkleunen 1:66f95e364222 1533 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1534 }
wkleunen 1:66f95e364222 1535
wkleunen 1:66f95e364222 1536
wkleunen 1:66f95e364222 1537 uint32_t nrf_esb_set_tx_power(nrf_esb_tx_power_t tx_output_power)
wkleunen 1:66f95e364222 1538 {
wkleunen 1:66f95e364222 1539 VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
wkleunen 1:66f95e364222 1540
wkleunen 1:66f95e364222 1541 if ( m_config_local.tx_output_power != tx_output_power )
wkleunen 1:66f95e364222 1542 {
wkleunen 1:66f95e364222 1543 m_config_local.tx_output_power = tx_output_power;
wkleunen 1:66f95e364222 1544 update_radio_tx_power();
wkleunen 1:66f95e364222 1545 }
wkleunen 1:66f95e364222 1546
wkleunen 1:66f95e364222 1547 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1548 }
wkleunen 1:66f95e364222 1549
wkleunen 1:66f95e364222 1550
wkleunen 1:66f95e364222 1551 uint32_t nrf_esb_set_retransmit_delay(uint16_t delay)
wkleunen 1:66f95e364222 1552 {
wkleunen 1:66f95e364222 1553 VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
wkleunen 1:66f95e364222 1554 VERIFY_TRUE(delay >= NRF_ESB_RETRANSMIT_DELAY_MIN, NRF_ERROR_INVALID_PARAM);
wkleunen 1:66f95e364222 1555
wkleunen 1:66f95e364222 1556 m_config_local.retransmit_delay = delay;
wkleunen 1:66f95e364222 1557 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1558 }
wkleunen 1:66f95e364222 1559
wkleunen 1:66f95e364222 1560
wkleunen 1:66f95e364222 1561 uint32_t nrf_esb_set_retransmit_count(uint16_t count)
wkleunen 1:66f95e364222 1562 {
wkleunen 1:66f95e364222 1563 VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
wkleunen 1:66f95e364222 1564
wkleunen 1:66f95e364222 1565 m_config_local.retransmit_count = count;
wkleunen 1:66f95e364222 1566 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1567 }
wkleunen 1:66f95e364222 1568
wkleunen 1:66f95e364222 1569
wkleunen 1:66f95e364222 1570 uint32_t nrf_esb_set_bitrate(nrf_esb_bitrate_t bitrate)
wkleunen 1:66f95e364222 1571 {
wkleunen 1:66f95e364222 1572 VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
wkleunen 1:66f95e364222 1573
wkleunen 1:66f95e364222 1574 m_config_local.bitrate = bitrate;
wkleunen 1:66f95e364222 1575 return update_radio_bitrate() ? NRF_SUCCESS : NRF_ERROR_INVALID_PARAM;
wkleunen 1:66f95e364222 1576 }
wkleunen 1:66f95e364222 1577
wkleunen 1:66f95e364222 1578
wkleunen 1:66f95e364222 1579 uint32_t nrf_esb_reuse_pid(uint8_t pipe)
wkleunen 1:66f95e364222 1580 {
wkleunen 1:66f95e364222 1581 VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
wkleunen 1:66f95e364222 1582 VERIFY_TRUE(pipe < 8, NRF_ERROR_INVALID_PARAM);
wkleunen 1:66f95e364222 1583
wkleunen 1:66f95e364222 1584 m_pids[pipe] = (m_pids[pipe] + NRF_ESB_PID_MAX) % (NRF_ESB_PID_MAX + 1);
wkleunen 1:66f95e364222 1585 return NRF_SUCCESS;
wkleunen 1:66f95e364222 1586 }
wkleunen 1:66f95e364222 1587
wkleunen 1:66f95e364222 1588
wkleunen 1:66f95e364222 1589 // Handler for
wkleunen 1:66f95e364222 1590 #ifdef NRF52
wkleunen 1:66f95e364222 1591 void NRF_ESB_BUGFIX_TIMER_IRQHandler(void)
wkleunen 1:66f95e364222 1592 {
wkleunen 1:66f95e364222 1593 if(NRF_ESB_BUGFIX_TIMER->EVENTS_COMPARE[0])
wkleunen 1:66f95e364222 1594 {
wkleunen 1:66f95e364222 1595 NRF_ESB_BUGFIX_TIMER->EVENTS_COMPARE[0] = 0;
wkleunen 1:66f95e364222 1596
wkleunen 1:66f95e364222 1597 // If the timeout timer fires and we are in the PTX receive ACK state, disable the radio
wkleunen 1:66f95e364222 1598 if(m_nrf_esb_mainstate == NRF_ESB_STATE_PTX_RX_ACK)
wkleunen 1:66f95e364222 1599 {
wkleunen 1:66f95e364222 1600 NRF_RADIO->TASKS_DISABLE = 1;
wkleunen 1:66f95e364222 1601 }
wkleunen 1:66f95e364222 1602 }
wkleunen 1:66f95e364222 1603 }
wkleunen 1:66f95e364222 1604 #endif