Wouter van Kleunen
/
nrf52_esb
NRF52_esb
nrf_esb.c@1:66f95e364222, 2021-02-04 (annotated)
- Committer:
- wkleunen
- Date:
- Thu Feb 04 10:36:44 2021 +0000
- Revision:
- 1:66f95e364222
Initial compile;
Who changed what in which revision?
User | Revision | Line number | New 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 |