aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/esb/nrf_esb.c1603
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/esb/nrf_esb.h609
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/esb/nrf_esb_error_codes.h56
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/esb/nrf_esb_resources.h72
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf51_arm.libbin0 -> 162642 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf51_sd_resources_arm.libbin0 -> 162838 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf52840_arm.libbin0 -> 191998 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf52840_sd_resources_arm.libbin0 -> 192194 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf52_arm.libbin0 -> 192158 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf52_sd_resources_arm.libbin0 -> 192354 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/license.txt37
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/config/nrf_gzp_config.h168
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf51_gcc.abin0 -> 86218 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf51_sd_resources_gcc.abin0 -> 86258 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf52840_gcc.abin0 -> 89436 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf52840_sd_resources_gcc.abin0 -> 89452 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf52_gcc.abin0 -> 89436 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf52_sd_resources_gcc.abin0 -> 89452 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/license.txt37
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf51_iar.abin0 -> 150676 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf51_sd_resources_iar.abin0 -> 150276 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf52840_iar.abin0 -> 185650 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf52840_sd_resources_iar.abin0 -> 185224 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf52_iar.abin0 -> 185276 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf52_sd_resources_iar.abin0 -> 184858 bytes
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/license.txt37
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzll.h937
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzll_constants.h188
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzll_error.h72
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzll_resources.h66
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp.c363
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp.h665
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp_device.c1146
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp_host.c821
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp_host_nrf5x.c74
35 files changed, 6951 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/esb/nrf_esb.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/esb/nrf_esb.c
new file mode 100644
index 0000000..5624d19
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/esb/nrf_esb.c
@@ -0,0 +1,1603 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "nrf_error.h"
+#include "nrf_esb.h"
+#include "nrf_esb_error_codes.h"
+#include "nrf_gpio.h"
+#include <string.h>
+#include <stddef.h>
+#include "sdk_common.h"
+#include "sdk_macros.h"
+#include "app_util.h"
+#include "nrf_log.h"
+#include "nrf_delay.h"
+
+#define BIT_MASK_UINT_8(x) (0xFF >> (8 - (x)))
+#define NRF_ESB_PIPE_COUNT 8
+
+// Constant parameters
+#define RX_WAIT_FOR_ACK_TIMEOUT_US_2MBPS (48) /**< 2 Mb RX wait for acknowledgment time-out value. Smallest reliable value - 43. */
+#define RX_WAIT_FOR_ACK_TIMEOUT_US_1MBPS (64) /**< 1 Mb RX wait for acknowledgment time-out value. Smallest reliable value - 59. */
+#define RX_WAIT_FOR_ACK_TIMEOUT_US_250KBPS (250) /**< 250 Kb RX wait for acknowledgment time-out value. */
+#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.*/
+
+// Interrupt flags
+#define NRF_ESB_INT_TX_SUCCESS_MSK 0x01 /**< Interrupt mask value for TX success. */
+#define NRF_ESB_INT_TX_FAILED_MSK 0x02 /**< Interrupt mask value for TX failure. */
+#define NRF_ESB_INT_RX_DATA_RECEIVED_MSK 0x04 /**< Interrupt mask value for RX_DR. */
+
+#define NRF_ESB_PID_RESET_VALUE 0xFF /**< Invalid PID value which is guaranteed to not collide with any valid PID value. */
+#define NRF_ESB_PID_MAX 3 /**< Maximum value for PID. */
+#define NRF_ESB_CRC_RESET_VALUE 0xFFFF /**< CRC reset value. */
+
+// Internal Enhanced ShockBurst module state.
+typedef enum {
+ NRF_ESB_STATE_IDLE, /**< Module idle. */
+ NRF_ESB_STATE_PTX_TX, /**< Module transmitting without acknowledgment. */
+ NRF_ESB_STATE_PTX_TX_ACK, /**< Module transmitting with acknowledgment. */
+ NRF_ESB_STATE_PTX_RX_ACK, /**< Module transmitting with acknowledgment and reception of payload with the acknowledgment response. */
+ NRF_ESB_STATE_PRX, /**< Module receiving packets without acknowledgment. */
+ NRF_ESB_STATE_PRX_SEND_ACK, /**< Module transmitting acknowledgment in RX mode. */
+} nrf_esb_mainstate_t;
+
+
+#define DISABLE_RF_IRQ() NVIC_DisableIRQ(RADIO_IRQn)
+#define ENABLE_RF_IRQ() NVIC_EnableIRQ(RADIO_IRQn)
+
+#define _RADIO_SHORTS_COMMON ( RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_END_DISABLE_Msk | \
+ RADIO_SHORTS_ADDRESS_RSSISTART_Msk | RADIO_SHORTS_DISABLED_RSSISTOP_Msk )
+
+#define VERIFY_PAYLOAD_LENGTH(p) \
+do \
+{ \
+ if (p->length == 0 || \
+ p->length > NRF_ESB_MAX_PAYLOAD_LENGTH || \
+ (m_config_local.protocol == NRF_ESB_PROTOCOL_ESB && \
+ p->length > m_config_local.payload_length)) \
+ { \
+ return NRF_ERROR_INVALID_LENGTH; \
+ } \
+}while (0)
+
+
+/* @brief Structure holding pipe info PID and CRC and acknowledgment payload. */
+typedef struct
+{
+ uint16_t crc; /**< CRC value of the last received packet (Used to detect retransmits). */
+ uint8_t pid; /**< Packet ID of the last received packet (Used to detect retransmits). */
+ bool ack_payload; /**< Flag indicating the state of the transmission of acknowledgment payloads. */
+} pipe_info_t;
+
+
+/* @brief First-in, first-out queue of payloads to be transmitted. */
+typedef struct
+{
+ nrf_esb_payload_t * p_payload[NRF_ESB_TX_FIFO_SIZE]; /**< Pointer to the actual queue. */
+ uint32_t entry_point; /**< Current start of queue. */
+ uint32_t exit_point; /**< Current end of queue. */
+ uint32_t count; /**< Current number of elements in the queue. */
+} nrf_esb_payload_tx_fifo_t;
+
+
+/* @brief First-in, first-out queue of received payloads. */
+typedef struct
+{
+ nrf_esb_payload_t * p_payload[NRF_ESB_RX_FIFO_SIZE]; /**< Pointer to the actual queue. */
+ uint32_t entry_point; /**< Current start of queue. */
+ uint32_t exit_point; /**< Current end of queue. */
+ uint32_t count; /**< Current number of elements in the queue. */
+} nrf_esb_payload_rx_fifo_t;
+
+
+/**@brief Enhanced ShockBurst address.
+ *
+ * Enhanced ShockBurst addresses consist of a base address and a prefix
+ * that is unique for each pipe. See @ref esb_addressing in the ESB user
+ * guide for more information.
+*/
+typedef struct
+{
+ uint8_t base_addr_p0[4]; /**< Base address for pipe 0 encoded in big endian. */
+ uint8_t base_addr_p1[4]; /**< Base address for pipe 1-7 encoded in big endian. */
+ uint8_t pipe_prefixes[8]; /**< Address prefix for pipe 0 to 7. */
+ uint8_t num_pipes; /**< Number of pipes available. */
+ uint8_t addr_length; /**< Length of the address including the prefix. */
+ uint8_t rx_pipes_enabled; /**< Bitfield for enabled pipes. */
+ uint8_t rf_channel; /**< Channel to use (must be between 0 and 100). */
+} nrf_esb_address_t;
+
+
+// Module state
+static bool m_esb_initialized = false;
+static nrf_esb_mainstate_t m_nrf_esb_mainstate = NRF_ESB_STATE_IDLE;
+static nrf_esb_payload_t * mp_current_payload;
+
+static nrf_esb_event_handler_t m_event_handler;
+
+// Address parameters
+__ALIGN(4) static nrf_esb_address_t m_esb_addr = NRF_ESB_ADDR_DEFAULT;
+
+// RF parameters
+static nrf_esb_config_t m_config_local;
+
+// TX FIFO
+static nrf_esb_payload_t m_tx_fifo_payload[NRF_ESB_TX_FIFO_SIZE];
+static nrf_esb_payload_tx_fifo_t m_tx_fifo;
+
+// RX FIFO
+static nrf_esb_payload_t m_rx_fifo_payload[NRF_ESB_RX_FIFO_SIZE];
+static nrf_esb_payload_rx_fifo_t m_rx_fifo;
+
+// Payload buffers
+static uint8_t m_tx_payload_buffer[NRF_ESB_MAX_PAYLOAD_LENGTH + 2];
+static uint8_t m_rx_payload_buffer[NRF_ESB_MAX_PAYLOAD_LENGTH + 2];
+
+// Run time variables
+static volatile uint32_t m_interrupt_flags = 0;
+static uint8_t m_pids[NRF_ESB_PIPE_COUNT];
+static pipe_info_t m_rx_pipe_info[NRF_ESB_PIPE_COUNT];
+static volatile uint32_t m_retransmits_remaining;
+static volatile uint32_t m_last_tx_attempts;
+static volatile uint32_t m_wait_for_ack_timeout_us;
+
+// nRF52 address workaround enable
+#ifdef NRF52
+static bool m_address_hang_fix_enable = true;
+#endif
+static uint32_t m_radio_shorts_common = _RADIO_SHORTS_COMMON;
+
+// These function pointers are changed dynamically, depending on protocol configuration and state.
+static void (*on_radio_disabled)(void) = 0;
+static void (*on_radio_end)(void) = 0;
+static void (*update_rf_payload_format)(uint32_t payload_length) = 0;
+
+
+// The following functions are assigned to the function pointers above.
+static void on_radio_disabled_tx_noack(void);
+static void on_radio_disabled_tx(void);
+static void on_radio_disabled_tx_wait_for_ack(void);
+static void on_radio_disabled_rx(void);
+static void on_radio_disabled_rx_ack(void);
+
+
+#define NRF_ESB_ADDR_UPDATE_MASK_BASE0 (1 << 0) /*< Mask value to signal updating BASE0 radio address. */
+#define NRF_ESB_ADDR_UPDATE_MASK_BASE1 (1 << 1) /*< Mask value to signal updating BASE1 radio address. */
+#define NRF_ESB_ADDR_UPDATE_MASK_PREFIX (1 << 2) /*< Mask value to signal updating radio prefixes. */
+
+
+// Function to do bytewise bit-swap on an unsigned 32-bit value
+static uint32_t bytewise_bit_swap(uint8_t const * p_inp)
+{
+ uint32_t inp = (*(uint32_t*)p_inp);
+#if __CORTEX_M == (0x04U)
+ return __REV((uint32_t)__RBIT(inp)); //lint -esym(628, __rev) -esym(526, __rev) -esym(628, __rbit) -esym(526, __rbit) */
+#else
+ inp = (inp & 0xF0F0F0F0) >> 4 | (inp & 0x0F0F0F0F) << 4;
+ inp = (inp & 0xCCCCCCCC) >> 2 | (inp & 0x33333333) << 2;
+ inp = (inp & 0xAAAAAAAA) >> 1 | (inp & 0x55555555) << 1;
+ return inp;
+#endif
+}
+
+
+// Internal function to convert base addresses from nRF24L type addressing to nRF51 type addressing
+static uint32_t addr_conv(uint8_t const* p_addr)
+{
+ return __REV(bytewise_bit_swap(p_addr)); //lint -esym(628, __rev) -esym(526, __rev) */
+}
+
+
+static ret_code_t apply_address_workarounds()
+{
+#ifdef NRF52
+ // Set up radio parameters.
+ NRF_RADIO->MODECNF0 = (NRF_RADIO->MODECNF0 & ~RADIO_MODECNF0_RU_Msk) | RADIO_MODECNF0_RU_Default << RADIO_MODECNF0_RU_Pos;
+
+ // Workaround for nRF52832 Rev 1 Errata 102 and nRF52832 Rev 1 Errata 106. This will reduce sensitivity by 3dB.
+ *((volatile uint32_t *)0x40001774) = (*((volatile uint32_t *)0x40001774) & 0xFFFFFFFE) | 0x01000000;
+#endif
+ return NRF_SUCCESS;
+}
+
+
+static void update_rf_payload_format_esb_dpl(uint32_t payload_length)
+{
+#if (NRF_ESB_MAX_PAYLOAD_LENGTH <= 32)
+ // Using 6 bits for length
+ NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) |
+ (6 << RADIO_PCNF0_LFLEN_Pos) |
+ (3 << RADIO_PCNF0_S1LEN_Pos) ;
+#else
+ // Using 8 bits for length
+ NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S0LEN_Pos) |
+ (8 << RADIO_PCNF0_LFLEN_Pos) |
+ (3 << RADIO_PCNF0_S1LEN_Pos) ;
+#endif
+ NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) |
+ (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) |
+ ((m_esb_addr.addr_length - 1) << RADIO_PCNF1_BALEN_Pos) |
+ (0 << RADIO_PCNF1_STATLEN_Pos) |
+ (NRF_ESB_MAX_PAYLOAD_LENGTH << RADIO_PCNF1_MAXLEN_Pos);
+}
+
+
+static void update_rf_payload_format_esb(uint32_t payload_length)
+{
+ NRF_RADIO->PCNF0 = (1 << RADIO_PCNF0_S0LEN_Pos) |
+ (0 << RADIO_PCNF0_LFLEN_Pos) |
+ (1 << RADIO_PCNF0_S1LEN_Pos);
+
+ NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) |
+ (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) |
+ ((m_esb_addr.addr_length - 1) << RADIO_PCNF1_BALEN_Pos) |
+ (payload_length << RADIO_PCNF1_STATLEN_Pos) |
+ (payload_length << RADIO_PCNF1_MAXLEN_Pos);
+}
+
+
+static void update_radio_addresses(uint8_t update_mask)
+{
+ if ((update_mask & NRF_ESB_ADDR_UPDATE_MASK_BASE0) != 0)
+ {
+ NRF_RADIO->BASE0 = addr_conv(m_esb_addr.base_addr_p0);
+ }
+
+ if ((update_mask & NRF_ESB_ADDR_UPDATE_MASK_BASE1) != 0)
+ {
+ NRF_RADIO->BASE1 = addr_conv(m_esb_addr.base_addr_p1);
+ }
+
+ if ((update_mask & NRF_ESB_ADDR_UPDATE_MASK_PREFIX) != 0)
+ {
+ NRF_RADIO->PREFIX0 = bytewise_bit_swap(&m_esb_addr.pipe_prefixes[0]);
+ NRF_RADIO->PREFIX1 = bytewise_bit_swap(&m_esb_addr.pipe_prefixes[4]);
+ }
+}
+
+
+static void update_radio_tx_power()
+{
+ NRF_RADIO->TXPOWER = m_config_local.tx_output_power << RADIO_TXPOWER_TXPOWER_Pos;
+}
+
+
+static bool update_radio_bitrate()
+{
+ NRF_RADIO->MODE = m_config_local.bitrate << RADIO_MODE_MODE_Pos;
+
+ switch (m_config_local.bitrate)
+ {
+ case NRF_ESB_BITRATE_2MBPS:
+#ifdef NRF52
+ case NRF_ESB_BITRATE_2MBPS_BLE:
+#endif
+ m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_2MBPS;
+ break;
+
+ case NRF_ESB_BITRATE_1MBPS:
+ m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_1MBPS;
+ break;
+
+#ifdef NRF51
+ case NRF_ESB_BITRATE_250KBPS:
+ m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_250KBPS;
+ break;
+#endif
+
+ case NRF_ESB_BITRATE_1MBPS_BLE:
+ m_wait_for_ack_timeout_us = RX_WAIT_FOR_ACK_TIMEOUT_US_1MBPS_BLE;
+ break;
+
+ default:
+ // Should not be reached
+ return false;
+ }
+ return true;
+}
+
+
+static bool update_radio_protocol()
+{
+ switch (m_config_local.protocol)
+ {
+ case NRF_ESB_PROTOCOL_ESB_DPL:
+ update_rf_payload_format = update_rf_payload_format_esb_dpl;
+ break;
+
+ case NRF_ESB_PROTOCOL_ESB:
+ update_rf_payload_format = update_rf_payload_format_esb;
+ break;
+
+ default:
+ // Should not be reached
+ return false;
+ }
+ return true;
+}
+
+
+static bool update_radio_crc()
+{
+ switch(m_config_local.crc)
+ {
+ case NRF_ESB_CRC_16BIT:
+ NRF_RADIO->CRCINIT = 0xFFFFUL; // Initial value
+ NRF_RADIO->CRCPOLY = 0x11021UL; // CRC poly: x^16+x^12^x^5+1
+ break;
+
+ case NRF_ESB_CRC_8BIT:
+ NRF_RADIO->CRCINIT = 0xFFUL; // Initial value
+ NRF_RADIO->CRCPOLY = 0x107UL; // CRC poly: x^8+x^2^x^1+1
+ break;
+
+ case NRF_ESB_CRC_OFF:
+ break;
+
+ default:
+ return false;
+ }
+ NRF_RADIO->CRCCNF = m_config_local.crc << RADIO_CRCCNF_LEN_Pos;
+ return true;
+}
+
+
+static bool update_radio_parameters()
+{
+ bool params_valid = true;
+ update_radio_tx_power();
+ params_valid &= update_radio_bitrate();
+ params_valid &= update_radio_protocol();
+ params_valid &= update_radio_crc();
+ update_rf_payload_format(m_config_local.payload_length);
+ params_valid &= (m_config_local.retransmit_delay >= NRF_ESB_RETRANSMIT_DELAY_MIN);
+ return params_valid;
+}
+
+
+static void reset_fifos()
+{
+ m_tx_fifo.entry_point = 0;
+ m_tx_fifo.exit_point = 0;
+ m_tx_fifo.count = 0;
+
+ m_rx_fifo.entry_point = 0;
+ m_rx_fifo.exit_point = 0;
+ m_rx_fifo.count = 0;
+}
+
+
+static void initialize_fifos()
+{
+ reset_fifos();
+
+ for (int i = 0; i < NRF_ESB_TX_FIFO_SIZE; i++)
+ {
+ m_tx_fifo.p_payload[i] = &m_tx_fifo_payload[i];
+ }
+
+ for (int i = 0; i < NRF_ESB_RX_FIFO_SIZE; i++)
+ {
+ m_rx_fifo.p_payload[i] = &m_rx_fifo_payload[i];
+ }
+}
+
+
+static void tx_fifo_remove_last()
+{
+ if (m_tx_fifo.count > 0)
+ {
+ DISABLE_RF_IRQ();
+
+ m_tx_fifo.count--;
+ if (++m_tx_fifo.exit_point >= NRF_ESB_TX_FIFO_SIZE)
+ {
+ m_tx_fifo.exit_point = 0;
+ }
+
+ ENABLE_RF_IRQ();
+ }
+}
+
+/** @brief Function to push the content of the rx_buffer to the RX FIFO.
+ *
+ * The module will point the register NRF_RADIO->PACKETPTR to a buffer for receiving packets.
+ * After receiving a packet the module will call this function to copy the received data to
+ * the RX FIFO.
+ *
+ * @param pipe Pipe number to set for the packet.
+ * @param pid Packet ID.
+ *
+ * @retval true Operation successful.
+ * @retval false Operation failed.
+ */
+static bool rx_fifo_push_rfbuf(uint8_t pipe, uint8_t pid)
+{
+ if (m_rx_fifo.count < NRF_ESB_RX_FIFO_SIZE)
+ {
+ if (m_config_local.protocol == NRF_ESB_PROTOCOL_ESB_DPL)
+ {
+ if (m_rx_payload_buffer[0] > NRF_ESB_MAX_PAYLOAD_LENGTH)
+ {
+ return false;
+ }
+
+ m_rx_fifo.p_payload[m_rx_fifo.entry_point]->length = m_rx_payload_buffer[0];
+ }
+ else if (m_config_local.mode == NRF_ESB_MODE_PTX)
+ {
+ // Received packet is an acknowledgment
+ m_rx_fifo.p_payload[m_rx_fifo.entry_point]->length = 0;
+ }
+ else
+ {
+ m_rx_fifo.p_payload[m_rx_fifo.entry_point]->length = m_config_local.payload_length;
+ }
+
+ memcpy(m_rx_fifo.p_payload[m_rx_fifo.entry_point]->data, &m_rx_payload_buffer[2],
+ m_rx_fifo.p_payload[m_rx_fifo.entry_point]->length);
+
+ m_rx_fifo.p_payload[m_rx_fifo.entry_point]->pipe = pipe;
+ m_rx_fifo.p_payload[m_rx_fifo.entry_point]->rssi = NRF_RADIO->RSSISAMPLE;
+ m_rx_fifo.p_payload[m_rx_fifo.entry_point]->pid = pid;
+ m_rx_fifo.p_payload[m_rx_fifo.entry_point]->noack = !(m_rx_payload_buffer[1] & 0x01);
+ if (++m_rx_fifo.entry_point >= NRF_ESB_RX_FIFO_SIZE)
+ {
+ m_rx_fifo.entry_point = 0;
+ }
+ m_rx_fifo.count++;
+
+ return true;
+ }
+
+ return false;
+}
+
+
+static void sys_timer_init()
+{
+ // Configure the system timer with a 1 MHz base frequency
+ NRF_ESB_SYS_TIMER->PRESCALER = 4;
+ NRF_ESB_SYS_TIMER->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
+ NRF_ESB_SYS_TIMER->SHORTS = TIMER_SHORTS_COMPARE1_CLEAR_Msk | TIMER_SHORTS_COMPARE1_STOP_Msk;
+}
+
+
+static void ppi_init()
+{
+ NRF_PPI->CH[NRF_ESB_PPI_TIMER_START].EEP = (uint32_t)&NRF_RADIO->EVENTS_READY;
+ NRF_PPI->CH[NRF_ESB_PPI_TIMER_START].TEP = (uint32_t)&NRF_ESB_SYS_TIMER->TASKS_START;
+
+ NRF_PPI->CH[NRF_ESB_PPI_TIMER_STOP].EEP = (uint32_t)&NRF_RADIO->EVENTS_ADDRESS;
+ NRF_PPI->CH[NRF_ESB_PPI_TIMER_STOP].TEP = (uint32_t)&NRF_ESB_SYS_TIMER->TASKS_STOP;
+
+ NRF_PPI->CH[NRF_ESB_PPI_RX_TIMEOUT].EEP = (uint32_t)&NRF_ESB_SYS_TIMER->EVENTS_COMPARE[0];
+ NRF_PPI->CH[NRF_ESB_PPI_RX_TIMEOUT].TEP = (uint32_t)&NRF_RADIO->TASKS_DISABLE;
+
+ NRF_PPI->CH[NRF_ESB_PPI_TX_START].EEP = (uint32_t)&NRF_ESB_SYS_TIMER->EVENTS_COMPARE[1];
+ NRF_PPI->CH[NRF_ESB_PPI_TX_START].TEP = (uint32_t)&NRF_RADIO->TASKS_TXEN;
+}
+
+
+static void start_tx_transaction()
+{
+ bool ack;
+
+ m_last_tx_attempts = 1;
+ // Prepare the payload
+ mp_current_payload = m_tx_fifo.p_payload[m_tx_fifo.exit_point];
+
+
+ switch (m_config_local.protocol)
+ {
+ case NRF_ESB_PROTOCOL_ESB:
+ update_rf_payload_format(mp_current_payload->length);
+ m_tx_payload_buffer[0] = mp_current_payload->pid;
+ m_tx_payload_buffer[1] = 0;
+ memcpy(&m_tx_payload_buffer[2], mp_current_payload->data, mp_current_payload->length);
+
+ NRF_RADIO->SHORTS = m_radio_shorts_common | RADIO_SHORTS_DISABLED_RXEN_Msk;
+ NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk | RADIO_INTENSET_READY_Msk;
+
+ // Configure the retransmit counter
+ m_retransmits_remaining = m_config_local.retransmit_count;
+ on_radio_disabled = on_radio_disabled_tx;
+ m_nrf_esb_mainstate = NRF_ESB_STATE_PTX_TX_ACK;
+ break;
+
+ case NRF_ESB_PROTOCOL_ESB_DPL:
+ ack = !mp_current_payload->noack || !m_config_local.selective_auto_ack;
+ m_tx_payload_buffer[0] = mp_current_payload->length;
+ m_tx_payload_buffer[1] = mp_current_payload->pid << 1;
+ m_tx_payload_buffer[1] |= mp_current_payload->noack ? 0x00 : 0x01;
+ memcpy(&m_tx_payload_buffer[2], mp_current_payload->data, mp_current_payload->length);
+
+ // Handling ack if noack is set to false or if selective auto ack is turned off
+ if (ack)
+ {
+ NRF_RADIO->SHORTS = m_radio_shorts_common | RADIO_SHORTS_DISABLED_RXEN_Msk;
+ NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk | RADIO_INTENSET_READY_Msk;
+
+ // Configure the retransmit counter
+ m_retransmits_remaining = m_config_local.retransmit_count;
+ on_radio_disabled = on_radio_disabled_tx;
+ m_nrf_esb_mainstate = NRF_ESB_STATE_PTX_TX_ACK;
+ }
+ else
+ {
+ NRF_RADIO->SHORTS = m_radio_shorts_common;
+ NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk;
+ on_radio_disabled = on_radio_disabled_tx_noack;
+ m_nrf_esb_mainstate = NRF_ESB_STATE_PTX_TX;
+ }
+ break;
+
+ default:
+ // Should not be reached
+ break;
+ }
+
+ NRF_RADIO->TXADDRESS = mp_current_payload->pipe;
+ NRF_RADIO->RXADDRESSES = 1 << mp_current_payload->pipe;
+
+ NRF_RADIO->FREQUENCY = m_esb_addr.rf_channel;
+ NRF_RADIO->PACKETPTR = (uint32_t)m_tx_payload_buffer;
+
+ NVIC_ClearPendingIRQ(RADIO_IRQn);
+ NVIC_EnableIRQ(RADIO_IRQn);
+
+ NRF_RADIO->EVENTS_ADDRESS = 0;
+ NRF_RADIO->EVENTS_PAYLOAD = 0;
+ NRF_RADIO->EVENTS_DISABLED = 0;
+
+ DEBUG_PIN_SET(DEBUGPIN4);
+ NRF_RADIO->TASKS_TXEN = 1;
+}
+
+
+static void on_radio_disabled_tx_noack()
+{
+ m_interrupt_flags |= NRF_ESB_INT_TX_SUCCESS_MSK;
+ tx_fifo_remove_last();
+
+ if (m_tx_fifo.count == 0)
+ {
+ m_nrf_esb_mainstate = NRF_ESB_STATE_IDLE;
+ NVIC_SetPendingIRQ(ESB_EVT_IRQ);
+ }
+ else
+ {
+ NVIC_SetPendingIRQ(ESB_EVT_IRQ);
+ start_tx_transaction();
+ }
+}
+
+
+static void on_radio_disabled_tx()
+{
+ // Remove the DISABLED -> RXEN shortcut, to make sure the radio stays
+ // disabled after the RX window
+ NRF_RADIO->SHORTS = m_radio_shorts_common;
+
+ // Make sure the timer is started the next time the radio is ready,
+ // and that it will disable the radio automatically if no packet is
+ // received by the time defined in m_wait_for_ack_timeout_us
+ NRF_ESB_SYS_TIMER->CC[0] = m_wait_for_ack_timeout_us;
+ NRF_ESB_SYS_TIMER->CC[1] = m_config_local.retransmit_delay - 130;
+ NRF_ESB_SYS_TIMER->TASKS_CLEAR = 1;
+ NRF_ESB_SYS_TIMER->EVENTS_COMPARE[0] = 0;
+ NRF_ESB_SYS_TIMER->EVENTS_COMPARE[1] = 0;
+
+ NRF_PPI->CHENSET = (1 << NRF_ESB_PPI_TIMER_START) |
+ (1 << NRF_ESB_PPI_RX_TIMEOUT) |
+ (1 << NRF_ESB_PPI_TIMER_STOP);
+ NRF_PPI->CHENCLR = (1 << NRF_ESB_PPI_TX_START);
+ NRF_RADIO->EVENTS_END = 0;
+
+ if (m_config_local.protocol == NRF_ESB_PROTOCOL_ESB)
+ {
+ update_rf_payload_format(0);
+ }
+
+ NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer;
+ on_radio_disabled = on_radio_disabled_tx_wait_for_ack;
+ m_nrf_esb_mainstate = NRF_ESB_STATE_PTX_RX_ACK;
+}
+
+
+static void on_radio_disabled_tx_wait_for_ack()
+{
+ // This marks the completion of a TX_RX sequence (TX with ACK)
+
+ // Make sure the timer will not deactivate the radio if a packet is received
+ NRF_PPI->CHENCLR = (1 << NRF_ESB_PPI_TIMER_START) |
+ (1 << NRF_ESB_PPI_RX_TIMEOUT) |
+ (1 << NRF_ESB_PPI_TIMER_STOP);
+
+ // If the radio has received a packet and the CRC status is OK
+ if (NRF_RADIO->EVENTS_END && NRF_RADIO->CRCSTATUS != 0)
+ {
+ NRF_ESB_SYS_TIMER->TASKS_STOP = 1;
+ NRF_PPI->CHENCLR = (1 << NRF_ESB_PPI_TX_START);
+ m_interrupt_flags |= NRF_ESB_INT_TX_SUCCESS_MSK;
+ m_last_tx_attempts = m_config_local.retransmit_count - m_retransmits_remaining + 1;
+
+ tx_fifo_remove_last();
+
+ if (m_config_local.protocol != NRF_ESB_PROTOCOL_ESB && m_rx_payload_buffer[0] > 0)
+ {
+ if (rx_fifo_push_rfbuf((uint8_t)NRF_RADIO->TXADDRESS, m_rx_payload_buffer[1] >> 1))
+ {
+ m_interrupt_flags |= NRF_ESB_INT_RX_DATA_RECEIVED_MSK;
+ }
+ }
+
+ if ((m_tx_fifo.count == 0) || (m_config_local.tx_mode == NRF_ESB_TXMODE_MANUAL))
+ {
+ m_nrf_esb_mainstate = NRF_ESB_STATE_IDLE;
+ NVIC_SetPendingIRQ(ESB_EVT_IRQ);
+ }
+ else
+ {
+ NVIC_SetPendingIRQ(ESB_EVT_IRQ);
+ start_tx_transaction();
+ }
+ }
+ else
+ {
+ if (m_retransmits_remaining-- == 0)
+ {
+ NRF_ESB_SYS_TIMER->TASKS_STOP = 1;
+ NRF_PPI->CHENCLR = (1 << NRF_ESB_PPI_TX_START);
+ // All retransmits are expended, and the TX operation is suspended
+ m_last_tx_attempts = m_config_local.retransmit_count + 1;
+ m_interrupt_flags |= NRF_ESB_INT_TX_FAILED_MSK;
+
+ m_nrf_esb_mainstate = NRF_ESB_STATE_IDLE;
+ NVIC_SetPendingIRQ(ESB_EVT_IRQ);
+ }
+ else
+ {
+ // There are still more retransmits left, TX mode should be
+ // entered again as soon as the system timer reaches CC[1].
+ NRF_RADIO->SHORTS = m_radio_shorts_common | RADIO_SHORTS_DISABLED_RXEN_Msk;
+ update_rf_payload_format(mp_current_payload->length);
+ NRF_RADIO->PACKETPTR = (uint32_t)m_tx_payload_buffer;
+ on_radio_disabled = on_radio_disabled_tx;
+ m_nrf_esb_mainstate = NRF_ESB_STATE_PTX_TX_ACK;
+ NRF_ESB_SYS_TIMER->TASKS_START = 1;
+ NRF_PPI->CHENSET = (1 << NRF_ESB_PPI_TX_START);
+ if (NRF_ESB_SYS_TIMER->EVENTS_COMPARE[1])
+ {
+ NRF_RADIO->TASKS_TXEN = 1;
+ }
+ }
+ }
+}
+
+static void clear_events_restart_rx(void)
+{
+ NRF_RADIO->SHORTS = m_radio_shorts_common;
+ update_rf_payload_format(m_config_local.payload_length);
+ NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer;
+ NRF_RADIO->EVENTS_DISABLED = 0;
+ NRF_RADIO->TASKS_DISABLE = 1;
+
+ while (NRF_RADIO->EVENTS_DISABLED == 0);
+
+ NRF_RADIO->EVENTS_DISABLED = 0;
+ NRF_RADIO->SHORTS = m_radio_shorts_common | RADIO_SHORTS_DISABLED_TXEN_Msk;
+
+ NRF_RADIO->TASKS_RXEN = 1;
+}
+
+static void on_radio_disabled_rx(void)
+{
+ bool ack = false;
+ bool retransmit_payload = false;
+ bool send_rx_event = true;
+ pipe_info_t * p_pipe_info;
+
+ if (NRF_RADIO->CRCSTATUS == 0)
+ {
+ clear_events_restart_rx();
+ return;
+ }
+
+ if (m_rx_fifo.count >= NRF_ESB_RX_FIFO_SIZE)
+ {
+ clear_events_restart_rx();
+ return;
+ }
+
+ p_pipe_info = &m_rx_pipe_info[NRF_RADIO->RXMATCH];
+ if (NRF_RADIO->RXCRC == p_pipe_info->crc &&
+ (m_rx_payload_buffer[1] >> 1) == p_pipe_info->pid
+ )
+ {
+ retransmit_payload = true;
+ send_rx_event = false;
+ }
+
+ p_pipe_info->pid = m_rx_payload_buffer[1] >> 1;
+ p_pipe_info->crc = NRF_RADIO->RXCRC;
+
+ if ((m_config_local.selective_auto_ack == false) || ((m_rx_payload_buffer[1] & 0x01) == 1))
+ {
+ ack = true;
+ }
+
+ if (ack)
+ {
+ NRF_RADIO->SHORTS = m_radio_shorts_common | RADIO_SHORTS_DISABLED_RXEN_Msk;
+
+ switch (m_config_local.protocol)
+ {
+ case NRF_ESB_PROTOCOL_ESB_DPL:
+ {
+ if (m_tx_fifo.count > 0 &&
+ (m_tx_fifo.p_payload[m_tx_fifo.exit_point]->pipe == NRF_RADIO->RXMATCH)
+ )
+ {
+ // Pipe stays in ACK with payload until TX FIFO is empty
+ // Do not report TX success on first ack payload or retransmit
+ if (p_pipe_info->ack_payload == true && !retransmit_payload)
+ {
+ if (++m_tx_fifo.exit_point >= NRF_ESB_TX_FIFO_SIZE)
+ {
+ m_tx_fifo.exit_point = 0;
+ }
+
+ m_tx_fifo.count--;
+
+ // ACK payloads also require TX_DS
+ // (page 40 of the 'nRF24LE1_Product_Specification_rev1_6.pdf').
+ m_interrupt_flags |= NRF_ESB_INT_TX_SUCCESS_MSK;
+ }
+
+ p_pipe_info->ack_payload = true;
+
+ mp_current_payload = m_tx_fifo.p_payload[m_tx_fifo.exit_point];
+
+ update_rf_payload_format(mp_current_payload->length);
+ m_tx_payload_buffer[0] = mp_current_payload->length;
+ memcpy(&m_tx_payload_buffer[2],
+ mp_current_payload->data,
+ mp_current_payload->length);
+ }
+ else
+ {
+ p_pipe_info->ack_payload = false;
+ update_rf_payload_format(0);
+ m_tx_payload_buffer[0] = 0;
+ }
+
+ m_tx_payload_buffer[1] = m_rx_payload_buffer[1];
+ }
+ break;
+
+ case NRF_ESB_PROTOCOL_ESB:
+ {
+ update_rf_payload_format(0);
+ m_tx_payload_buffer[0] = m_rx_payload_buffer[0];
+ m_tx_payload_buffer[1] = 0;
+ }
+ break;
+ }
+
+ m_nrf_esb_mainstate = NRF_ESB_STATE_PRX_SEND_ACK;
+ NRF_RADIO->TXADDRESS = NRF_RADIO->RXMATCH;
+ NRF_RADIO->PACKETPTR = (uint32_t)m_tx_payload_buffer;
+ on_radio_disabled = on_radio_disabled_rx_ack;
+ }
+ else
+ {
+ clear_events_restart_rx();
+ }
+
+ if (send_rx_event)
+ {
+ // Push the new packet to the RX buffer and trigger a received event if the operation was
+ // successful.
+ if (rx_fifo_push_rfbuf(NRF_RADIO->RXMATCH, p_pipe_info->pid))
+ {
+ m_interrupt_flags |= NRF_ESB_INT_RX_DATA_RECEIVED_MSK;
+ NVIC_SetPendingIRQ(ESB_EVT_IRQ);
+ }
+ }
+}
+
+
+static void on_radio_disabled_rx_ack(void)
+{
+ NRF_RADIO->SHORTS = m_radio_shorts_common | RADIO_SHORTS_DISABLED_TXEN_Msk;
+ update_rf_payload_format(m_config_local.payload_length);
+
+ NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer;
+ on_radio_disabled = on_radio_disabled_rx;
+
+ m_nrf_esb_mainstate = NRF_ESB_STATE_PRX;
+}
+
+
+/**@brief Function for clearing pending interrupts.
+ *
+ * @param[in,out] p_interrupts Pointer to the value that holds the current interrupts.
+ *
+ * @retval NRF_SUCCESS If the interrupts were cleared successfully.
+ * @retval NRF_ERROR_NULL If the required parameter was NULL.
+ * @retval NRF_INVALID_STATE If the module is not initialized.
+ */
+static uint32_t nrf_esb_get_clear_interrupts(uint32_t * p_interrupts)
+{
+ VERIFY_TRUE(m_esb_initialized, NRF_ERROR_INVALID_STATE);
+ VERIFY_PARAM_NOT_NULL(p_interrupts);
+
+ DISABLE_RF_IRQ();
+
+ *p_interrupts = m_interrupt_flags;
+ m_interrupt_flags = 0;
+
+ ENABLE_RF_IRQ();
+
+ return NRF_SUCCESS;
+}
+
+
+void RADIO_IRQHandler()
+{
+ if (NRF_RADIO->EVENTS_READY && (NRF_RADIO->INTENSET & RADIO_INTENSET_READY_Msk))
+ {
+ NRF_RADIO->EVENTS_READY = 0;
+ DEBUG_PIN_SET(DEBUGPIN1);
+ }
+
+ if (NRF_RADIO->EVENTS_END && (NRF_RADIO->INTENSET & RADIO_INTENSET_END_Msk))
+ {
+ NRF_RADIO->EVENTS_END = 0;
+ DEBUG_PIN_SET(DEBUGPIN2);
+
+ // Call the correct on_radio_end function, depending on the current protocol state
+ if (on_radio_end)
+ {
+ on_radio_end();
+ }
+ }
+
+ if (NRF_RADIO->EVENTS_DISABLED && (NRF_RADIO->INTENSET & RADIO_INTENSET_DISABLED_Msk))
+ {
+ NRF_RADIO->EVENTS_DISABLED = 0;
+ DEBUG_PIN_SET(DEBUGPIN3);
+
+ // Call the correct on_radio_disable function, depending on the current protocol state
+ if (on_radio_disabled)
+ {
+ on_radio_disabled();
+ }
+ }
+
+ DEBUG_PIN_CLR(DEBUGPIN1);
+ DEBUG_PIN_CLR(DEBUGPIN2);
+ DEBUG_PIN_CLR(DEBUGPIN3);
+ DEBUG_PIN_CLR(DEBUGPIN4);
+}
+
+
+uint32_t nrf_esb_init(nrf_esb_config_t const * p_config)
+{
+ uint32_t err_code;
+
+ VERIFY_PARAM_NOT_NULL(p_config);
+
+ if (m_esb_initialized)
+ {
+ err_code = nrf_esb_disable();
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ }
+
+ m_event_handler = p_config->event_handler;
+
+ memcpy(&m_config_local, p_config, sizeof(nrf_esb_config_t));
+
+ m_interrupt_flags = 0;
+
+ memset(m_rx_pipe_info, 0, sizeof(m_rx_pipe_info));
+ memset(m_pids, 0, sizeof(m_pids));
+
+ VERIFY_TRUE(update_radio_parameters(), NRF_ERROR_INVALID_PARAM);
+
+ // Configure radio address registers according to ESB default values
+ NRF_RADIO->BASE0 = 0xE7E7E7E7;
+ NRF_RADIO->BASE1 = 0x43434343;
+ NRF_RADIO->PREFIX0 = 0x23C343E7;
+ NRF_RADIO->PREFIX1 = 0x13E363A3;
+
+ initialize_fifos();
+
+ sys_timer_init();
+
+ ppi_init();
+
+ NVIC_SetPriority(RADIO_IRQn, m_config_local.radio_irq_priority & ESB_IRQ_PRIORITY_MSK);
+ NVIC_SetPriority(ESB_EVT_IRQ, m_config_local.event_irq_priority & ESB_IRQ_PRIORITY_MSK);
+ NVIC_EnableIRQ(ESB_EVT_IRQ);
+
+#ifdef NRF52
+ if(m_address_hang_fix_enable)
+ {
+ // Setup a timeout timer to start on an ADDRESS match, and stop on a BCMATCH event.
+ // If the BCMATCH event never occurs the CC[0] event will fire, and the timer interrupt will disable the radio to recover.
+ m_radio_shorts_common |= RADIO_SHORTS_ADDRESS_BCSTART_Msk;
+ NRF_RADIO->BCC = 2;
+ NRF_ESB_BUGFIX_TIMER->BITMODE = TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos;
+ NRF_ESB_BUGFIX_TIMER->PRESCALER = 4;
+ NRF_ESB_BUGFIX_TIMER->CC[0] = 5;
+ NRF_ESB_BUGFIX_TIMER->SHORTS = TIMER_SHORTS_COMPARE0_STOP_Msk | TIMER_SHORTS_COMPARE0_CLEAR_Msk;
+ NRF_ESB_BUGFIX_TIMER->MODE = TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos;
+ NRF_ESB_BUGFIX_TIMER->INTENSET = TIMER_INTENSET_COMPARE0_Msk;
+ NRF_ESB_BUGFIX_TIMER->TASKS_CLEAR = 1;
+ NVIC_SetPriority(NRF_ESB_BUGFIX_TIMER_IRQn, 5);
+ NVIC_EnableIRQ(NRF_ESB_BUGFIX_TIMER_IRQn);
+
+ NRF_PPI->CH[NRF_ESB_PPI_BUGFIX1].EEP = (uint32_t)&NRF_RADIO->EVENTS_ADDRESS;
+ NRF_PPI->CH[NRF_ESB_PPI_BUGFIX1].TEP = (uint32_t)&NRF_ESB_BUGFIX_TIMER->TASKS_START;
+
+ NRF_PPI->CH[NRF_ESB_PPI_BUGFIX2].EEP = (uint32_t)&NRF_RADIO->EVENTS_BCMATCH;
+ NRF_PPI->CH[NRF_ESB_PPI_BUGFIX2].TEP = (uint32_t)&NRF_ESB_BUGFIX_TIMER->TASKS_STOP;
+
+ NRF_PPI->CH[NRF_ESB_PPI_BUGFIX3].EEP = (uint32_t)&NRF_RADIO->EVENTS_BCMATCH;
+ NRF_PPI->CH[NRF_ESB_PPI_BUGFIX3].TEP = (uint32_t)&NRF_ESB_BUGFIX_TIMER->TASKS_CLEAR;
+
+ NRF_PPI->CHENSET = (1 << NRF_ESB_PPI_BUGFIX1) | (1 << NRF_ESB_PPI_BUGFIX2) | (1 << NRF_ESB_PPI_BUGFIX3);
+ }
+#endif
+
+ m_nrf_esb_mainstate = NRF_ESB_STATE_IDLE;
+ m_esb_initialized = true;
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t nrf_esb_suspend(void)
+{
+ VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
+
+ // Clear PPI
+ NRF_PPI->CHENCLR = (1 << NRF_ESB_PPI_TIMER_START) |
+ (1 << NRF_ESB_PPI_TIMER_STOP) |
+ (1 << NRF_ESB_PPI_RX_TIMEOUT) |
+ (1 << NRF_ESB_PPI_TX_START);
+
+ m_nrf_esb_mainstate = NRF_ESB_STATE_IDLE;
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t nrf_esb_disable(void)
+{
+ // Clear PPI
+ NRF_PPI->CHENCLR = (1 << NRF_ESB_PPI_TIMER_START) |
+ (1 << NRF_ESB_PPI_TIMER_STOP) |
+ (1 << NRF_ESB_PPI_RX_TIMEOUT) |
+ (1 << NRF_ESB_PPI_TX_START);
+
+ m_nrf_esb_mainstate = NRF_ESB_STATE_IDLE;
+
+ reset_fifos();
+
+ memset(m_rx_pipe_info, 0, sizeof(m_rx_pipe_info));
+ memset(m_pids, 0, sizeof(m_pids));
+
+ // Disable the radio
+ NVIC_DisableIRQ(ESB_EVT_IRQ);
+ NRF_RADIO->SHORTS = RADIO_SHORTS_READY_START_Enabled << RADIO_SHORTS_READY_START_Pos |
+ RADIO_SHORTS_END_DISABLE_Enabled << RADIO_SHORTS_END_DISABLE_Pos;
+
+ return NRF_SUCCESS;
+}
+
+
+bool nrf_esb_is_idle(void)
+{
+ return m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE;
+}
+
+
+void ESB_EVT_IRQHandler(void)
+{
+ ret_code_t err_code;
+ uint32_t interrupts;
+ nrf_esb_evt_t event;
+
+ event.tx_attempts = m_last_tx_attempts;
+
+ err_code = nrf_esb_get_clear_interrupts(&interrupts);
+ if (err_code == NRF_SUCCESS && m_event_handler != 0)
+ {
+ if (interrupts & NRF_ESB_INT_TX_SUCCESS_MSK)
+ {
+ event.evt_id = NRF_ESB_EVENT_TX_SUCCESS;
+ m_event_handler(&event);
+ }
+ if (interrupts & NRF_ESB_INT_TX_FAILED_MSK)
+ {
+ event.evt_id = NRF_ESB_EVENT_TX_FAILED;
+ m_event_handler(&event);
+ }
+ if (interrupts & NRF_ESB_INT_RX_DATA_RECEIVED_MSK)
+ {
+ event.evt_id = NRF_ESB_EVENT_RX_RECEIVED;
+ m_event_handler(&event);
+ }
+ }
+}
+
+uint32_t nrf_esb_write_payload(nrf_esb_payload_t const * p_payload)
+{
+ VERIFY_TRUE(m_esb_initialized, NRF_ERROR_INVALID_STATE);
+ VERIFY_PARAM_NOT_NULL(p_payload);
+ VERIFY_PAYLOAD_LENGTH(p_payload);
+ VERIFY_FALSE(m_tx_fifo.count >= NRF_ESB_TX_FIFO_SIZE, NRF_ERROR_NO_MEM);
+ VERIFY_TRUE(p_payload->pipe < NRF_ESB_PIPE_COUNT, NRF_ERROR_INVALID_PARAM);
+
+ DISABLE_RF_IRQ();
+
+ memcpy(m_tx_fifo.p_payload[m_tx_fifo.entry_point], p_payload, sizeof(nrf_esb_payload_t));
+
+ m_pids[p_payload->pipe] = (m_pids[p_payload->pipe] + 1) % (NRF_ESB_PID_MAX + 1);
+ m_tx_fifo.p_payload[m_tx_fifo.entry_point]->pid = m_pids[p_payload->pipe];
+
+ if (++m_tx_fifo.entry_point >= NRF_ESB_TX_FIFO_SIZE)
+ {
+ m_tx_fifo.entry_point = 0;
+ }
+
+ m_tx_fifo.count++;
+
+ ENABLE_RF_IRQ();
+
+
+ if (m_config_local.mode == NRF_ESB_MODE_PTX &&
+ m_config_local.tx_mode == NRF_ESB_TXMODE_AUTO &&
+ m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE)
+ {
+ start_tx_transaction();
+ }
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t nrf_esb_read_rx_payload(nrf_esb_payload_t * p_payload)
+{
+ VERIFY_TRUE(m_esb_initialized, NRF_ERROR_INVALID_STATE);
+ VERIFY_PARAM_NOT_NULL(p_payload);
+
+ if (m_rx_fifo.count == 0)
+ {
+ return NRF_ERROR_NOT_FOUND;
+ }
+
+ DISABLE_RF_IRQ();
+
+ p_payload->length = m_rx_fifo.p_payload[m_rx_fifo.exit_point]->length;
+ p_payload->pipe = m_rx_fifo.p_payload[m_rx_fifo.exit_point]->pipe;
+ p_payload->rssi = m_rx_fifo.p_payload[m_rx_fifo.exit_point]->rssi;
+ p_payload->pid = m_rx_fifo.p_payload[m_rx_fifo.exit_point]->pid;
+ p_payload->noack = m_rx_fifo.p_payload[m_rx_fifo.exit_point]->noack;
+ memcpy(p_payload->data, m_rx_fifo.p_payload[m_rx_fifo.exit_point]->data, p_payload->length);
+
+ if (++m_rx_fifo.exit_point >= NRF_ESB_RX_FIFO_SIZE)
+ {
+ m_rx_fifo.exit_point = 0;
+ }
+
+ m_rx_fifo.count--;
+
+ ENABLE_RF_IRQ();
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t nrf_esb_start_tx(void)
+{
+ VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
+
+ if (m_tx_fifo.count == 0)
+ {
+ return NRF_ERROR_BUFFER_EMPTY;
+ }
+
+ start_tx_transaction();
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t nrf_esb_start_rx(void)
+{
+ VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
+
+ NRF_RADIO->INTENCLR = 0xFFFFFFFF;
+ NRF_RADIO->EVENTS_DISABLED = 0;
+ on_radio_disabled = on_radio_disabled_rx;
+
+ NRF_RADIO->SHORTS = m_radio_shorts_common | RADIO_SHORTS_DISABLED_TXEN_Msk;
+ NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk;
+ m_nrf_esb_mainstate = NRF_ESB_STATE_PRX;
+
+ NRF_RADIO->RXADDRESSES = m_esb_addr.rx_pipes_enabled;
+ NRF_RADIO->FREQUENCY = m_esb_addr.rf_channel;
+ NRF_RADIO->PACKETPTR = (uint32_t)m_rx_payload_buffer;
+
+ NVIC_ClearPendingIRQ(RADIO_IRQn);
+ NVIC_EnableIRQ(RADIO_IRQn);
+
+ NRF_RADIO->EVENTS_ADDRESS = 0;
+ NRF_RADIO->EVENTS_PAYLOAD = 0;
+ NRF_RADIO->EVENTS_DISABLED = 0;
+
+ NRF_RADIO->TASKS_RXEN = 1;
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t nrf_esb_stop_rx(void)
+{
+ if (m_nrf_esb_mainstate == NRF_ESB_STATE_PRX)
+ {
+ NRF_RADIO->SHORTS = 0;
+ NRF_RADIO->INTENCLR = 0xFFFFFFFF;
+ on_radio_disabled = NULL;
+ NRF_RADIO->EVENTS_DISABLED = 0;
+ NRF_RADIO->TASKS_DISABLE = 1;
+ while (NRF_RADIO->EVENTS_DISABLED == 0);
+ m_nrf_esb_mainstate = NRF_ESB_STATE_IDLE;
+
+ return NRF_SUCCESS;
+ }
+
+ return NRF_ESB_ERROR_NOT_IN_RX_MODE;
+}
+
+
+uint32_t nrf_esb_flush_tx(void)
+{
+ VERIFY_TRUE(m_esb_initialized, NRF_ERROR_INVALID_STATE);
+
+ DISABLE_RF_IRQ();
+
+ m_tx_fifo.count = 0;
+ m_tx_fifo.entry_point = 0;
+ m_tx_fifo.exit_point = 0;
+
+ ENABLE_RF_IRQ();
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t nrf_esb_pop_tx(void)
+{
+ VERIFY_TRUE(m_esb_initialized, NRF_ERROR_INVALID_STATE);
+ VERIFY_TRUE(m_tx_fifo.count > 0, NRF_ERROR_BUFFER_EMPTY);
+
+ DISABLE_RF_IRQ();
+
+ if (++m_tx_fifo.entry_point >= NRF_ESB_TX_FIFO_SIZE)
+ {
+ m_tx_fifo.entry_point = 0;
+ }
+ m_tx_fifo.count--;
+
+ ENABLE_RF_IRQ();
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t nrf_esb_flush_rx(void)
+{
+ VERIFY_TRUE(m_esb_initialized, NRF_ERROR_INVALID_STATE);
+
+ DISABLE_RF_IRQ();
+
+ m_rx_fifo.count = 0;
+ m_rx_fifo.entry_point = 0;
+ m_rx_fifo.exit_point = 0;
+
+ memset(m_rx_pipe_info, 0, sizeof(m_rx_pipe_info));
+
+ ENABLE_RF_IRQ();
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t nrf_esb_set_address_length(uint8_t length)
+{
+ VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
+ VERIFY_TRUE(length > 2 && length < 6, NRF_ERROR_INVALID_PARAM);
+
+ /*
+ Workaround for nRF52832 Rev 1 Errata 107
+ Check if pipe 0 or pipe 1-7 has a 'zero address'.
+ Avoid using access addresses in the following pattern (where X is don't care):
+ ADDRLEN=5
+ BASE0 = 0x0000XXXX, PREFIX0 = 0xXXXXXX00
+ BASE1 = 0x0000XXXX, PREFIX0 = 0xXXXX00XX
+ BASE1 = 0x0000XXXX, PREFIX0 = 0xXX00XXXX
+ BASE1 = 0x0000XXXX, PREFIX0 = 0x00XXXXXX
+ BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXXXX00
+ BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXX00XX
+ BASE1 = 0x0000XXXX, PREFIX1 = 0xXX00XXXX
+ BASE1 = 0x0000XXXX, PREFIX1 = 0x00XXXXXX
+
+ ADDRLEN=4
+ BASE0 = 0x00XXXXXX, PREFIX0 = 0xXXXXXX00
+ BASE1 = 0x00XXXXXX, PREFIX0 = 0xXXXX00XX
+ BASE1 = 0x00XXXXXX, PREFIX0 = 0xXX00XXXX
+ BASE1 = 0x00XXXXXX, PREFIX0 = 0x00XXXXXX
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXXXX00
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXX00XX
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0xXX00XXXX
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0x00XXXXXX
+ */
+ uint32_t base_address_mask = length == 5 ? 0xFFFF0000 : 0xFF000000;
+ if((NRF_RADIO->BASE0 & base_address_mask) == 0 && (NRF_RADIO->PREFIX0 & 0x000000FF) == 0)
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+ if((NRF_RADIO->BASE1 & base_address_mask) == 0 && ((NRF_RADIO->PREFIX0 & 0x0000FF00) == 0 ||(NRF_RADIO->PREFIX0 & 0x00FF0000) == 0 || (NRF_RADIO->PREFIX0 & 0xFF000000) == 0 ||
+ (NRF_RADIO->PREFIX1 & 0xFF000000) == 0 || (NRF_RADIO->PREFIX1 & 0x00FF0000) == 0 ||(NRF_RADIO->PREFIX1 & 0x0000FF00) == 0 || (NRF_RADIO->PREFIX1 & 0x000000FF) == 0))
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+
+ m_esb_addr.addr_length = length;
+
+ update_rf_payload_format(m_config_local.payload_length);
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t nrf_esb_set_base_address_0(uint8_t const * p_addr)
+{
+ VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
+ VERIFY_PARAM_NOT_NULL(p_addr);
+
+ /*
+ Workaround for nRF52832 Rev 1 Errata 107
+ Check if pipe 0 or pipe 1-7 has a 'zero address'.
+ Avoid using access addresses in the following pattern (where X is don't care):
+ ADDRLEN=5
+ BASE0 = 0x0000XXXX, PREFIX0 = 0xXXXXXX00
+ BASE1 = 0x0000XXXX, PREFIX0 = 0xXXXX00XX
+ BASE1 = 0x0000XXXX, PREFIX0 = 0xXX00XXXX
+ BASE1 = 0x0000XXXX, PREFIX0 = 0x00XXXXXX
+ BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXXXX00
+ BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXX00XX
+ BASE1 = 0x0000XXXX, PREFIX1 = 0xXX00XXXX
+ BASE1 = 0x0000XXXX, PREFIX1 = 0x00XXXXXX
+
+ ADDRLEN=4
+ BASE0 = 0x00XXXXXX, PREFIX0 = 0xXXXXXX00
+ BASE1 = 0x00XXXXXX, PREFIX0 = 0xXXXX00XX
+ BASE1 = 0x00XXXXXX, PREFIX0 = 0xXX00XXXX
+ BASE1 = 0x00XXXXXX, PREFIX0 = 0x00XXXXXX
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXXXX00
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXX00XX
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0xXX00XXXX
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0x00XXXXXX
+ */
+ uint32_t base_address_mask = m_esb_addr.addr_length == 5 ? 0xFFFF0000 : 0xFF000000;
+ if((addr_conv(p_addr) & base_address_mask) == 0 && (NRF_RADIO->PREFIX0 & 0x000000FF) == 0)
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+
+ memcpy(m_esb_addr.base_addr_p0, p_addr, 4);
+
+ update_radio_addresses(NRF_ESB_ADDR_UPDATE_MASK_BASE0);
+
+ return apply_address_workarounds();
+}
+
+
+uint32_t nrf_esb_set_base_address_1(uint8_t const * p_addr)
+{
+ VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
+ VERIFY_PARAM_NOT_NULL(p_addr);
+
+ /*
+ Workaround for nRF52832 Rev 1 Errata 107
+ Check if pipe 0 or pipe 1-7 has a 'zero address'.
+ Avoid using access addresses in the following pattern (where X is don't care):
+ ADDRLEN=5
+ BASE0 = 0x0000XXXX, PREFIX0 = 0xXXXXXX00
+ BASE1 = 0x0000XXXX, PREFIX0 = 0xXXXX00XX
+ BASE1 = 0x0000XXXX, PREFIX0 = 0xXX00XXXX
+ BASE1 = 0x0000XXXX, PREFIX0 = 0x00XXXXXX
+ BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXXXX00
+ BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXX00XX
+ BASE1 = 0x0000XXXX, PREFIX1 = 0xXX00XXXX
+ BASE1 = 0x0000XXXX, PREFIX1 = 0x00XXXXXX
+
+ ADDRLEN=4
+ BASE0 = 0x00XXXXXX, PREFIX0 = 0xXXXXXX00
+ BASE1 = 0x00XXXXXX, PREFIX0 = 0xXXXX00XX
+ BASE1 = 0x00XXXXXX, PREFIX0 = 0xXX00XXXX
+ BASE1 = 0x00XXXXXX, PREFIX0 = 0x00XXXXXX
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXXXX00
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXX00XX
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0xXX00XXXX
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0x00XXXXXX
+ */
+ uint32_t base_address_mask = m_esb_addr.addr_length == 5 ? 0xFFFF0000 : 0xFF000000;
+ if((addr_conv(p_addr) & base_address_mask) == 0 && ((NRF_RADIO->PREFIX0 & 0x0000FF00) == 0 ||(NRF_RADIO->PREFIX0 & 0x00FF0000) == 0 || (NRF_RADIO->PREFIX0 & 0xFF000000) == 0 ||
+ (NRF_RADIO->PREFIX1 & 0xFF000000) == 0 || (NRF_RADIO->PREFIX1 & 0x00FF0000) == 0 ||(NRF_RADIO->PREFIX1 & 0x0000FF00) == 0 || (NRF_RADIO->PREFIX1 & 0x000000FF) == 0))
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+
+ memcpy(m_esb_addr.base_addr_p1, p_addr, 4);
+
+ update_radio_addresses(NRF_ESB_ADDR_UPDATE_MASK_BASE1);
+
+ return apply_address_workarounds();
+}
+
+
+uint32_t nrf_esb_set_prefixes(uint8_t const * p_prefixes, uint8_t num_pipes)
+{
+ VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
+ VERIFY_PARAM_NOT_NULL(p_prefixes);
+ VERIFY_TRUE(num_pipes < 9, NRF_ERROR_INVALID_PARAM);
+
+ /*
+ Workaround for nRF52832 Rev 1 Errata 107
+ Check if pipe 0 or pipe 1-7 has a 'zero address'.
+ Avoid using access addresses in the following pattern (where X is don't care):
+ ADDRLEN=5
+ BASE0 = 0x0000XXXX, PREFIX0 = 0xXXXXXX00
+ BASE1 = 0x0000XXXX, PREFIX0 = 0xXXXX00XX
+ BASE1 = 0x0000XXXX, PREFIX0 = 0xXX00XXXX
+ BASE1 = 0x0000XXXX, PREFIX0 = 0x00XXXXXX
+ BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXXXX00
+ BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXX00XX
+ BASE1 = 0x0000XXXX, PREFIX1 = 0xXX00XXXX
+ BASE1 = 0x0000XXXX, PREFIX1 = 0x00XXXXXX
+
+ ADDRLEN=4
+ BASE0 = 0x00XXXXXX, PREFIX0 = 0xXXXXXX00
+ BASE1 = 0x00XXXXXX, PREFIX0 = 0xXXXX00XX
+ BASE1 = 0x00XXXXXX, PREFIX0 = 0xXX00XXXX
+ BASE1 = 0x00XXXXXX, PREFIX0 = 0x00XXXXXX
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXXXX00
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXX00XX
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0xXX00XXXX
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0x00XXXXXX
+ */
+ uint32_t base_address_mask = m_esb_addr.addr_length == 5 ? 0xFFFF0000 : 0xFF000000;
+ if(num_pipes >= 1 && (NRF_RADIO->BASE0 & base_address_mask) == 0 && p_prefixes[0] == 0)
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+
+ if((NRF_RADIO->BASE1 & base_address_mask) == 0)
+ {
+ for (uint8_t i = 1; i < num_pipes; i++)
+ {
+ if (p_prefixes[i] == 0)
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+ }
+ }
+
+ memcpy(m_esb_addr.pipe_prefixes, p_prefixes, num_pipes);
+ m_esb_addr.num_pipes = num_pipes;
+ m_esb_addr.rx_pipes_enabled = BIT_MASK_UINT_8(num_pipes);
+
+ update_radio_addresses(NRF_ESB_ADDR_UPDATE_MASK_PREFIX);
+
+ return apply_address_workarounds();
+}
+
+
+uint32_t nrf_esb_update_prefix(uint8_t pipe, uint8_t prefix)
+{
+ VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
+ VERIFY_TRUE(pipe < 8, NRF_ERROR_INVALID_PARAM);
+
+ /*
+ Workaround for nRF52832 Rev 1 Errata 107
+ Check if pipe 0 or pipe 1-7 has a 'zero address'.
+ Avoid using access addresses in the following pattern (where X is don't care):
+ ADDRLEN=5
+ BASE0 = 0x0000XXXX, PREFIX0 = 0xXXXXXX00
+ BASE1 = 0x0000XXXX, PREFIX0 = 0xXXXX00XX
+ BASE1 = 0x0000XXXX, PREFIX0 = 0xXX00XXXX
+ BASE1 = 0x0000XXXX, PREFIX0 = 0x00XXXXXX
+ BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXXXX00
+ BASE1 = 0x0000XXXX, PREFIX1 = 0xXXXX00XX
+ BASE1 = 0x0000XXXX, PREFIX1 = 0xXX00XXXX
+ BASE1 = 0x0000XXXX, PREFIX1 = 0x00XXXXXX
+
+ ADDRLEN=4
+ BASE0 = 0x00XXXXXX, PREFIX0 = 0xXXXXXX00
+ BASE1 = 0x00XXXXXX, PREFIX0 = 0xXXXX00XX
+ BASE1 = 0x00XXXXXX, PREFIX0 = 0xXX00XXXX
+ BASE1 = 0x00XXXXXX, PREFIX0 = 0x00XXXXXX
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXXXX00
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0xXXXX00XX
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0xXX00XXXX
+ BASE1 = 0x00XXXXXX, PREFIX1 = 0x00XXXXXX
+ */
+ uint32_t base_address_mask = m_esb_addr.addr_length == 5 ? 0xFFFF0000 : 0xFF000000;
+ if (pipe == 0)
+ {
+ if((NRF_RADIO->BASE0 & base_address_mask) == 0 && prefix == 0)
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+ }
+ else{
+ if((NRF_RADIO->BASE1 & base_address_mask) == 0 && prefix == 0)
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+ }
+
+ m_esb_addr.pipe_prefixes[pipe] = prefix;
+
+ update_radio_addresses(NRF_ESB_ADDR_UPDATE_MASK_PREFIX);
+
+ return apply_address_workarounds();
+}
+
+
+uint32_t nrf_esb_enable_pipes(uint8_t enable_mask)
+{
+ VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
+
+ m_esb_addr.rx_pipes_enabled = enable_mask;
+
+ return apply_address_workarounds();
+}
+
+
+uint32_t nrf_esb_set_rf_channel(uint32_t channel)
+{
+ VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
+ VERIFY_TRUE(channel <= 100, NRF_ERROR_INVALID_PARAM);
+
+ m_esb_addr.rf_channel = channel;
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t nrf_esb_get_rf_channel(uint32_t * p_channel)
+{
+ VERIFY_PARAM_NOT_NULL(p_channel);
+
+ *p_channel = m_esb_addr.rf_channel;
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t nrf_esb_set_tx_power(nrf_esb_tx_power_t tx_output_power)
+{
+ VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
+
+ if ( m_config_local.tx_output_power != tx_output_power )
+ {
+ m_config_local.tx_output_power = tx_output_power;
+ update_radio_tx_power();
+ }
+
+ return NRF_SUCCESS;
+}
+
+
+uint32_t nrf_esb_set_retransmit_delay(uint16_t delay)
+{
+ VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
+ VERIFY_TRUE(delay >= NRF_ESB_RETRANSMIT_DELAY_MIN, NRF_ERROR_INVALID_PARAM);
+
+ m_config_local.retransmit_delay = delay;
+ return NRF_SUCCESS;
+}
+
+
+uint32_t nrf_esb_set_retransmit_count(uint16_t count)
+{
+ VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
+
+ m_config_local.retransmit_count = count;
+ return NRF_SUCCESS;
+}
+
+
+uint32_t nrf_esb_set_bitrate(nrf_esb_bitrate_t bitrate)
+{
+ VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
+
+ m_config_local.bitrate = bitrate;
+ return update_radio_bitrate() ? NRF_SUCCESS : NRF_ERROR_INVALID_PARAM;
+}
+
+
+uint32_t nrf_esb_reuse_pid(uint8_t pipe)
+{
+ VERIFY_TRUE(m_nrf_esb_mainstate == NRF_ESB_STATE_IDLE, NRF_ERROR_BUSY);
+ VERIFY_TRUE(pipe < 8, NRF_ERROR_INVALID_PARAM);
+
+ m_pids[pipe] = (m_pids[pipe] + NRF_ESB_PID_MAX) % (NRF_ESB_PID_MAX + 1);
+ return NRF_SUCCESS;
+}
+
+
+// Handler for
+#ifdef NRF52
+void NRF_ESB_BUGFIX_TIMER_IRQHandler(void)
+{
+ if(NRF_ESB_BUGFIX_TIMER->EVENTS_COMPARE[0])
+ {
+ NRF_ESB_BUGFIX_TIMER->EVENTS_COMPARE[0] = 0;
+
+ // If the timeout timer fires and we are in the PTX receive ACK state, disable the radio
+ if(m_nrf_esb_mainstate == NRF_ESB_STATE_PTX_RX_ACK)
+ {
+ NRF_RADIO->TASKS_DISABLE = 1;
+ }
+ }
+}
+#endif
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/esb/nrf_esb.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/esb/nrf_esb.h
new file mode 100644
index 0000000..0c80efb
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/esb/nrf_esb.h
@@ -0,0 +1,609 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __NRF_ESB_H
+#define __NRF_ESB_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "nrf.h"
+#include "app_util.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @defgroup nrf_esb Enhanced ShockBurst
+ * @{
+ * @ingroup proprietary_api
+ *
+ * @brief Enhanced ShockBurst (ESB) is a basic protocol that supports two-way data
+ * packet communication including packet buffering, packet acknowledgment,
+ * and automatic retransmission of lost packets.
+ */
+
+/** @name Debug pins
+ * @{
+ * @brief If NRF_ESB_DEBUG is defined, these GPIO pins can be used for debug timing.
+ */
+
+#define DEBUGPIN1 12 //!< If NRF_ESB_DEBUG is defined, this GPIO pin is set with every radio interrupt.
+#define DEBUGPIN2 13 //!< If NRF_ESB_DEBUG is defined, this GPIO pin is set with every NRF_RADIO->EVENTS_END.
+#define DEBUGPIN3 14 //!< If NRF_ESB_DEBUG is defined, this GPIO pin is set with every NRF_RADIO->EVENTS_DISABLED.
+#define DEBUGPIN4 15 //!< If NRF_ESB_DEBUG is defined, this GPIO pin is set when the radio is set to start transmission.
+
+
+#ifdef NRF_ESB_DEBUG
+#define DEBUG_PIN_SET(a) (NRF_GPIO->OUTSET = (1 << (a))) //!< Used internally to set debug pins.
+#define DEBUG_PIN_CLR(a) (NRF_GPIO->OUTCLR = (1 << (a))) //!< Used internally to clear debug pins.
+#else
+#define DEBUG_PIN_SET(a) //!< Used internally to set debug pins.
+#define DEBUG_PIN_CLR(a) //!< Used internally to clear debug pins.
+#endif
+
+ /** @} */
+
+#define NRF_ESB_RETRANSMIT_DELAY_MIN 135
+
+// Hardcoded parameters - change if necessary
+#ifndef NRF_ESB_MAX_PAYLOAD_LENGTH
+#define NRF_ESB_MAX_PAYLOAD_LENGTH 32 //!< The maximum size of the payload. Valid values are 1 to 252.
+#endif
+
+#define NRF_ESB_TX_FIFO_SIZE 8 //!< The size of the transmission first-in, first-out buffer.
+#define NRF_ESB_RX_FIFO_SIZE 8 //!< The size of the reception first-in, first-out buffer.
+
+// 252 is the largest possible payload size according to the nRF5 architecture.
+STATIC_ASSERT(NRF_ESB_MAX_PAYLOAD_LENGTH <= 252);
+
+#define NRF_ESB_SYS_TIMER NRF_TIMER2 //!< The timer that is used by the module.
+#define NRF_ESB_SYS_TIMER_IRQ_Handler TIMER2_IRQHandler //!< The handler that is used by @ref NRF_ESB_SYS_TIMER.
+
+#define NRF_ESB_PPI_TIMER_START 10 //!< The PPI channel used for starting the timer.
+#define NRF_ESB_PPI_TIMER_STOP 11 //!< The PPI channel used for stopping the timer.
+#define NRF_ESB_PPI_RX_TIMEOUT 12 //!< The PPI channel used for RX time-out.
+#define NRF_ESB_PPI_TX_START 13 //!< The PPI channel used for starting TX.
+
+/**@cond NO_DOXYGEN */
+
+// nRF52 address fix timer and PPI defines
+#ifdef NRF52
+#define NRF_ESB_PPI_BUGFIX1 9
+#define NRF_ESB_PPI_BUGFIX2 8
+#define NRF_ESB_PPI_BUGFIX3 7
+
+#define NRF_ESB_BUGFIX_TIMER NRF_TIMER3
+#define NRF_ESB_BUGFIX_TIMER_IRQn TIMER3_IRQn
+#define NRF_ESB_BUGFIX_TIMER_IRQHandler TIMER3_IRQHandler
+#endif
+
+/** @endcond */
+
+// Interrupt flags
+#define NRF_ESB_INT_TX_SUCCESS_MSK 0x01 //!< The flag used to indicate a success since the last event.
+#define NRF_ESB_INT_TX_FAILED_MSK 0x02 //!< The flag used to indicate a failure since the last event.
+#define NRF_ESB_INT_RX_DR_MSK 0x04 //!< The flag used to indicate that a packet was received since the last event.
+
+#define NRF_ESB_PID_RESET_VALUE 0xFF //!< Invalid PID value that is guaranteed to not collide with any valid PID value.
+#define NRF_ESB_PID_MAX 3 //!< The maximum value for PID.
+#define NRF_ESB_CRC_RESET_VALUE 0xFFFF //!< The CRC reset value.
+
+#define ESB_EVT_IRQ SWI0_IRQn //!< The ESB event IRQ number when running on an nRF5 device.
+#define ESB_EVT_IRQHandler SWI0_IRQHandler //!< The handler for @ref ESB_EVT_IRQ when running on an nRF5 device.
+
+#if defined(NRF52)
+#define ESB_IRQ_PRIORITY_MSK 0x07 //!< The mask used to enforce a valid IRQ priority.
+#else
+#define ESB_IRQ_PRIORITY_MSK 0x03 //!< The mask used to enforce a valid IRQ priority.
+#endif
+
+/** @brief Default address configuration for ESB.
+ * @details Roughly equal to the nRF24Lxx default (except for the number of pipes, because more pipes are supported). */
+#define NRF_ESB_ADDR_DEFAULT \
+{ \
+ .base_addr_p0 = { 0xE7, 0xE7, 0xE7, 0xE7 }, \
+ .base_addr_p1 = { 0xC2, 0xC2, 0xC2, 0xC2 }, \
+ .pipe_prefixes = { 0xE7, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8 }, \
+ .addr_length = 5, \
+ .num_pipes = 8, \
+ .rf_channel = 2, \
+ .rx_pipes_enabled = 0xFF \
+}
+
+
+/** @brief Default radio parameters.
+ * @details Roughly equal to the nRF24Lxx default parameters (except for CRC, which is set to 16 bit, and protocol, which is set to DPL). */
+#define NRF_ESB_DEFAULT_CONFIG {.protocol = NRF_ESB_PROTOCOL_ESB_DPL, \
+ .mode = NRF_ESB_MODE_PTX, \
+ .event_handler = 0, \
+ .bitrate = NRF_ESB_BITRATE_2MBPS, \
+ .crc = NRF_ESB_CRC_16BIT, \
+ .tx_output_power = NRF_ESB_TX_POWER_0DBM, \
+ .retransmit_delay = 250, \
+ .retransmit_count = 3, \
+ .tx_mode = NRF_ESB_TXMODE_AUTO, \
+ .radio_irq_priority = 1, \
+ .event_irq_priority = 2, \
+ .payload_length = 32, \
+ .selective_auto_ack = false \
+}
+
+
+/** @brief Default legacy radio parameters. Identical to the nRF24Lxx defaults. */
+#define NRF_ESB_LEGACY_CONFIG {.protocol = NRF_ESB_PROTOCOL_ESB, \
+ .mode = NRF_ESB_MODE_PTX, \
+ .event_handler = 0, \
+ .bitrate = NRF_ESB_BITRATE_2MBPS, \
+ .crc = NRF_ESB_CRC_8BIT, \
+ .tx_output_power = NRF_ESB_TX_POWER_0DBM, \
+ .retransmit_delay = 600, \
+ .retransmit_count = 3, \
+ .tx_mode = NRF_ESB_TXMODE_AUTO, \
+ .radio_irq_priority = 1, \
+ .event_irq_priority = 2, \
+ .payload_length = 32, \
+ .selective_auto_ack = false \
+}
+
+
+/** @brief Macro to create an initializer for a TX data packet.
+ *
+ * @details This macro generates an initializer. Using the initializer is more efficient
+ * than setting the individual parameters dynamically.
+ *
+ * @param[in] _pipe The pipe to use for the data packet.
+ * @param[in] ... Comma separated list of character data to put in the TX buffer.
+ * Supported values consist of 1 to 63 characters.
+ *
+ * @return Initializer that sets up the pipe, length, and byte array for content of the TX data.
+ */
+#define NRF_ESB_CREATE_PAYLOAD(_pipe, ...) \
+ {.pipe = _pipe, .length = NUM_VA_ARGS(__VA_ARGS__), .data = {__VA_ARGS__}}; \
+ STATIC_ASSERT(NUM_VA_ARGS(__VA_ARGS__) > 0 && NUM_VA_ARGS(__VA_ARGS__) <= 63)
+
+
+/**@brief Enhanced ShockBurst protocols. */
+typedef enum {
+ NRF_ESB_PROTOCOL_ESB, /**< Enhanced ShockBurst with fixed payload length. */
+ NRF_ESB_PROTOCOL_ESB_DPL /**< Enhanced ShockBurst with dynamic payload length. */
+} nrf_esb_protocol_t;
+
+
+/**@brief Enhanced ShockBurst modes. */
+typedef enum {
+ NRF_ESB_MODE_PTX, /**< Primary transmitter mode. */
+ NRF_ESB_MODE_PRX /**< Primary receiver mode. */
+} nrf_esb_mode_t;
+
+
+/**@brief Enhanced ShockBurst bitrate modes. */
+typedef enum {
+ NRF_ESB_BITRATE_2MBPS = RADIO_MODE_MODE_Nrf_2Mbit, /**< 2 Mb radio mode. */
+ NRF_ESB_BITRATE_1MBPS = RADIO_MODE_MODE_Nrf_1Mbit, /**< 1 Mb radio mode. */
+ NRF_ESB_BITRATE_250KBPS = RADIO_MODE_MODE_Nrf_250Kbit, /**< 250 Kb radio mode. */
+ NRF_ESB_BITRATE_1MBPS_BLE = RADIO_MODE_MODE_Ble_1Mbit, /**< 1 Mb radio mode using @e Bluetooth low energy radio parameters. */
+#if defined(NRF52)
+ NRF_ESB_BITRATE_2MBPS_BLE = 4 /**< 2 Mb radio mode using @e Bluetooth low energy radio parameters. */
+#endif
+} nrf_esb_bitrate_t;
+
+
+/**@brief Enhanced ShockBurst CRC modes. */
+typedef enum {
+ NRF_ESB_CRC_16BIT = RADIO_CRCCNF_LEN_Two, /**< Use two-byte CRC. */
+ NRF_ESB_CRC_8BIT = RADIO_CRCCNF_LEN_One, /**< Use one-byte CRC. */
+ NRF_ESB_CRC_OFF = RADIO_CRCCNF_LEN_Disabled /**< Disable CRC. */
+} nrf_esb_crc_t;
+
+
+/**@brief Enhanced ShockBurst radio transmission power modes. */
+typedef enum {
+ NRF_ESB_TX_POWER_4DBM = RADIO_TXPOWER_TXPOWER_Pos4dBm, /**< 4 dBm radio transmit power. */
+#if defined(NRF52)
+ NRF_ESB_TX_POWER_3DBM = RADIO_TXPOWER_TXPOWER_Pos3dBm, /**< 3 dBm radio transmit power. */
+#endif
+ NRF_ESB_TX_POWER_0DBM = RADIO_TXPOWER_TXPOWER_0dBm, /**< 0 dBm radio transmit power. */
+ NRF_ESB_TX_POWER_NEG4DBM = RADIO_TXPOWER_TXPOWER_Neg4dBm, /**< -4 dBm radio transmit power. */
+ NRF_ESB_TX_POWER_NEG8DBM = RADIO_TXPOWER_TXPOWER_Neg8dBm, /**< -8 dBm radio transmit power. */
+ NRF_ESB_TX_POWER_NEG12DBM = RADIO_TXPOWER_TXPOWER_Neg12dBm, /**< -12 dBm radio transmit power. */
+ NRF_ESB_TX_POWER_NEG16DBM = RADIO_TXPOWER_TXPOWER_Neg16dBm, /**< -16 dBm radio transmit power. */
+ NRF_ESB_TX_POWER_NEG20DBM = RADIO_TXPOWER_TXPOWER_Neg20dBm, /**< -20 dBm radio transmit power. */
+ NRF_ESB_TX_POWER_NEG30DBM = RADIO_TXPOWER_TXPOWER_Neg30dBm /**< -30 dBm radio transmit power. */
+} nrf_esb_tx_power_t;
+
+
+/**@brief Enhanced ShockBurst transmission modes. */
+typedef enum {
+ NRF_ESB_TXMODE_AUTO, /**< Automatic TX mode: When the TX FIFO contains packets and the radio is idle, packets are sent automatically. */
+ NRF_ESB_TXMODE_MANUAL, /**< Manual TX mode: Packets are not sent until @ref nrf_esb_start_tx is called. This mode can be used to ensure consistent packet timing. */
+ NRF_ESB_TXMODE_MANUAL_START /**< Manual start TX mode: Packets are not sent until @ref nrf_esb_start_tx is called. Then, transmission continues automatically until the TX FIFO is empty. */
+} nrf_esb_tx_mode_t;
+
+
+/**@brief Enhanced ShockBurst event IDs used to indicate the type of the event. */
+typedef enum
+{
+ NRF_ESB_EVENT_TX_SUCCESS, /**< Event triggered on TX success. */
+ NRF_ESB_EVENT_TX_FAILED, /**< Event triggered on TX failure. */
+ NRF_ESB_EVENT_RX_RECEIVED /**< Event triggered on RX received. */
+} nrf_esb_evt_id_t;
+
+
+/**@brief Enhanced ShockBurst payload.
+ *
+ * @details The payload is used both for transmissions and for acknowledging a
+ * received packet with a payload.
+*/
+typedef struct
+{
+ uint8_t length; //!< Length of the packet (maximum value is @ref NRF_ESB_MAX_PAYLOAD_LENGTH).
+ uint8_t pipe; //!< Pipe used for this payload.
+ int8_t rssi; //!< RSSI for the received packet.
+ uint8_t noack; //!< Flag indicating that this packet will not be acknowledgement.
+ uint8_t pid; //!< PID assigned during communication.
+ uint8_t data[NRF_ESB_MAX_PAYLOAD_LENGTH]; //!< The payload data.
+} nrf_esb_payload_t;
+
+
+/**@brief Enhanced ShockBurst event. */
+typedef struct
+{
+ nrf_esb_evt_id_t evt_id; //!< Enhanced ShockBurst event ID.
+ uint32_t tx_attempts; //!< Number of TX retransmission attempts.
+} nrf_esb_evt_t;
+
+
+/**@brief Definition of the event handler for the module. */
+typedef void (* nrf_esb_event_handler_t)(nrf_esb_evt_t const * p_event);
+
+
+/**@brief Main configuration structure for the module. */
+typedef struct
+{
+ nrf_esb_protocol_t protocol; //!< Enhanced ShockBurst protocol.
+ nrf_esb_mode_t mode; //!< Enhanced ShockBurst mode.
+ nrf_esb_event_handler_t event_handler; //!< Enhanced ShockBurst event handler.
+
+ // General RF parameters
+ nrf_esb_bitrate_t bitrate; //!< Enhanced ShockBurst bitrate mode.
+ nrf_esb_crc_t crc; //!< Enhanced ShockBurst CRC mode.
+
+ nrf_esb_tx_power_t tx_output_power; //!< Enhanced ShockBurst radio transmission power mode.
+
+ uint16_t retransmit_delay; //!< The delay between each retransmission of unacknowledged packets.
+ uint16_t retransmit_count; //!< The number of retransmission attempts before transmission fail.
+
+ // Control settings
+ nrf_esb_tx_mode_t tx_mode; //!< Enhanced ShockBurst transmission mode.
+
+ uint8_t radio_irq_priority; //!< nRF radio interrupt priority.
+ uint8_t event_irq_priority; //!< ESB event interrupt priority.
+ uint8_t payload_length; //!< Length of the payload (maximum length depends on the platforms that are used on each side).
+
+ bool selective_auto_ack; //!< Enable or disable selective auto acknowledgement.
+} nrf_esb_config_t;
+
+
+/**@brief Function for initializing the Enhanced ShockBurst module.
+ *
+ * @param p_config Parameters for initializing the module.
+ *
+ * @retval NRF_SUCCESS If initialization was successful.
+ * @retval NRF_ERROR_NULL If the @p p_config argument was NULL.
+ * @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
+ */
+uint32_t nrf_esb_init(nrf_esb_config_t const * p_config);
+
+
+/**@brief Function for suspending the Enhanced ShockBurst module.
+ *
+ * Calling this function stops ongoing communications without changing the queues.
+ *
+ * @retval NRF_SUCCESS If Enhanced ShockBurst was suspended.
+ * @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
+ */
+uint32_t nrf_esb_suspend(void);
+
+
+/**@brief Function for disabling the Enhanced ShockBurst module.
+ *
+ * Calling this function disables the Enhanced ShockBurst module immediately.
+ * Doing so might stop ongoing communications.
+ *
+ * @note All queues are flushed by this function.
+ *
+ * @retval NRF_SUCCESS If Enhanced ShockBurst was disabled.
+ */
+uint32_t nrf_esb_disable(void);
+
+
+/**@brief Function for checking if the Enhanced ShockBurst module is idle.
+ *
+ * @retval true If the module is idle.
+ * @retval false If the module is busy.
+ */
+bool nrf_esb_is_idle(void);
+
+
+/**@brief Function for writing a payload for transmission or acknowledgement.
+ *
+ * This function writes a payload that is added to the queue. When the module is in PTX mode, the
+ * payload is queued for a regular transmission. When the module is in PRX mode, the payload
+ * is queued for when a packet is received that requires an acknowledgement with payload.
+ *
+ * @param[in] p_payload Pointer to the structure that contains information and state of the payload.
+ *
+ * @retval NRF_SUCCESS If the payload was successfully queued for writing.
+ * @retval NRF_ERROR_NULL If the required parameter was NULL.
+ * @retval NRF_INVALID_STATE If the module is not initialized.
+ * @retval NRF_ERROR_NOT_SUPPORTED If @p p_payload->noack was false, but selective acknowledgement is not enabled.
+ * @retval NRF_ERROR_NO_MEM If the TX FIFO is full.
+ * @retval NRF_ERROR_INVALID_LENGTH If the payload length was invalid (zero or larger than the allowed maximum).
+ */
+uint32_t nrf_esb_write_payload(nrf_esb_payload_t const * p_payload);
+
+
+/**@brief Function for reading an RX payload.
+ *
+ * @param[in,out] p_payload Pointer to the structure that contains information and state of the payload.
+ *
+ * @retval NRF_SUCCESS If the data was read successfully.
+ * @retval NRF_ERROR_NULL If the required parameter was NULL.
+ * @retval NRF_INVALID_STATE If the module is not initialized.
+ */
+uint32_t nrf_esb_read_rx_payload(nrf_esb_payload_t * p_payload);
+
+
+/**@brief Function for starting transmission.
+ *
+ * @retval NRF_SUCCESS If the TX started successfully.
+ * @retval NRF_ERROR_BUFFER_EMPTY If the TX did not start because the FIFO buffer is empty.
+ * @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
+ */
+uint32_t nrf_esb_start_tx(void);
+
+
+/**@brief Function for starting to transmit data from the FIFO buffer.
+ *
+ * @retval NRF_SUCCESS If the transmission was started successfully.
+ * @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
+ */
+uint32_t nrf_esb_start_rx(void);
+
+
+/** @brief Function for stopping data reception.
+ *
+ * @retval NRF_SUCCESS If data reception was stopped successfully.
+ * @retval NRF_ESB_ERROR_NOT_IN_RX_MODE If the function failed because the module is not in RX mode.
+ */
+uint32_t nrf_esb_stop_rx(void);
+
+
+/**@brief Function for removing remaining items from the TX buffer.
+ *
+ * This function clears the TX FIFO buffer.
+ *
+ * @retval NRF_SUCCESS If pending items in the TX buffer were successfully cleared.
+ * @retval NRF_INVALID_STATE If the module is not initialized.
+ */
+uint32_t nrf_esb_flush_tx(void);
+
+
+/**@brief Function for removing the first item from the TX buffer.
+ *
+ * @retval NRF_SUCCESS If the operation completed successfully.
+ * @retval NRF_INVALID_STATE If the module is not initialized.
+ * @retval NRF_ERROR_BUFFER_EMPTY If there are no items in the queue to remove.
+ */
+uint32_t nrf_esb_pop_tx(void);
+
+
+/**@brief Function for removing remaining items from the RX buffer.
+ *
+ * @retval NRF_SUCCESS If the pending items in the RX buffer were successfully cleared.
+ * @retval NRF_INVALID_STATE If the module is not initialized.
+ */
+uint32_t nrf_esb_flush_rx(void);
+
+
+/**@brief Function for setting the length of the address.
+ *
+ * @param[in] length Length of the ESB address (in bytes).
+ *
+ * @retval NRF_SUCCESS If the address length was set successfully.
+ * @retval NRF_ERROR_INVALID_PARAM If the address length was invalid.
+ * @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
+ */
+uint32_t nrf_esb_set_address_length(uint8_t length);
+
+
+/**@brief Function for setting the base address for pipe 0.
+ *
+ * @param[in] p_addr Pointer to the address data.
+ *
+ * @retval NRF_SUCCESS If the base address was set successfully.
+ * @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
+ * @retval NRF_ERROR_INVALID_PARAM If the function failed because the address given was too close to a zero address.
+ * @retval NRF_ERROR_NULL If the required parameter was NULL.
+ */
+uint32_t nrf_esb_set_base_address_0(uint8_t const * p_addr);
+
+
+/**@brief Function for setting the base address for pipe 1 to pipe 7.
+ *
+ * @param[in] p_addr Pointer to the address data.
+ *
+ * @retval NRF_SUCCESS If the base address was set successfully.
+ * @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
+ * @retval NRF_ERROR_INVALID_PARAM If the function failed because the address given was too close to a zero address.
+ * @retval NRF_ERROR_NULL If the required parameter was NULL.
+ */
+uint32_t nrf_esb_set_base_address_1(uint8_t const * p_addr);
+
+
+/**@brief Function for setting the number of pipes and the pipe prefix addresses.
+ *
+ * This function configures the number of available pipes, enables the pipes,
+ * and sets their prefix addresses.
+ *
+ * @param[in] p_prefixes Pointer to a char array that contains the prefix for each pipe.
+ * @param[in] num_pipes Number of pipes.
+ *
+ * @retval NRF_SUCCESS If the prefix addresses were set successfully.
+ * @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
+ * @retval NRF_ERROR_NULL If a required parameter was NULL.
+ * @retval NRF_ERROR_INVALID_PARAM If an invalid number of pipes was given or if the address given was too close to a zero address.
+ */
+uint32_t nrf_esb_set_prefixes(uint8_t const * p_prefixes, uint8_t num_pipes);
+
+
+/**@brief Function for enabling pipes.
+ *
+ * The @p enable_mask parameter must contain the same number of pipes as has been configured
+ * with @ref nrf_esb_set_prefixes.
+ *
+ * @param enable_mask Bitfield mask to enable or disable pipes. Setting a bit to
+ * 0 disables the pipe. Setting a bit to 1 enables the pipe.
+ *
+ * @retval NRF_SUCCESS If the pipes were enabled and disabled successfully.
+ * @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
+ * @retval NRF_ERROR_INVALID_PARAM If the function failed because the address given was too close to a zero address.
+ */
+uint32_t nrf_esb_enable_pipes(uint8_t enable_mask);
+
+
+/**@brief Function for updating the prefix for a pipe.
+ *
+ * @param pipe Pipe for which to set the prefix.
+ * @param prefix Prefix to set for the pipe.
+ *
+ * @retval NRF_SUCCESS If the operation completed successfully.
+ * @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
+ * @retval NRF_ERROR_INVALID_PARAM If the given pipe number was invalid or if the address given was too close to a zero address.
+ */
+uint32_t nrf_esb_update_prefix(uint8_t pipe, uint8_t prefix);
+
+
+/** @brief Function for setting the channel to use for the radio.
+ *
+ * The module must be in an idle state to call this function. As a PTX, the
+ * application must wait for an idle state and as a PRX, the application must stop RX
+ * before changing the channel. After changing the channel, operation can be resumed.
+ *
+ * @param[in] channel Channel to use for radio.
+ *
+ * @retval NRF_SUCCESS If the operation completed successfully.
+ * @retval NRF_INVALID_STATE If the module is not initialized.
+ * @retval NRF_ERROR_BUSY If the module was not in idle state.
+ * @retval NRF_ERROR_INVALID_PARAM If the channel is invalid (larger than 100).
+ */
+uint32_t nrf_esb_set_rf_channel(uint32_t channel);
+
+
+/**@brief Function for getting the current radio channel.
+ *
+ * @param[in, out] p_channel Pointer to the channel data.
+ *
+ * @retval NRF_SUCCESS If the operation completed successfully.
+ * @retval NRF_ERROR_NULL If the required parameter was NULL.
+ */
+uint32_t nrf_esb_get_rf_channel(uint32_t * p_channel);
+
+
+/**@brief Function for setting the radio output power.
+ *
+ * @param[in] tx_output_power Output power.
+ *
+ * @retval NRF_SUCCESS If the operation completed successfully.
+ * @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
+ */
+uint32_t nrf_esb_set_tx_power(nrf_esb_tx_power_t tx_output_power);
+
+
+/**@brief Function for setting the packet retransmit delay.
+ *
+ * @param[in] delay Delay between retransmissions.
+ *
+ * @retval NRF_SUCCESS If the operation completed successfully.
+ * @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
+ */
+uint32_t nrf_esb_set_retransmit_delay(uint16_t delay);
+
+
+/**@brief Function for setting the number of retransmission attempts.
+ *
+ * @param[in] count Number of retransmissions.
+ *
+ * @retval NRF_SUCCESS If the operation completed successfully.
+ * @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
+ */
+uint32_t nrf_esb_set_retransmit_count(uint16_t count);
+
+
+/**@brief Function for setting the radio bitrate.
+ *
+ * @param[in] bitrate Radio bitrate.
+ *
+ * @retval NRF_SUCCESS If the operation completed successfully.
+ * @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
+ */
+uint32_t nrf_esb_set_bitrate(nrf_esb_bitrate_t bitrate);
+
+
+/**@brief Function for reusing a packet ID for a specific pipe.
+ *
+ * The ESB protocol uses a 2-bit sequence number (packet ID) to identify
+ * retransmitted packets. By default, the packet ID is incremented for every
+ * uploaded packet. Use this function to prevent this and send two different
+ * packets with the same packet ID.
+ *
+ * @param[in] pipe Pipe.
+ *
+ * @retval NRF_SUCCESS If the operation completed successfully.
+ * @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
+ */
+uint32_t nrf_esb_reuse_pid(uint8_t pipe);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRF_ESB
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/esb/nrf_esb_error_codes.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/esb/nrf_esb_error_codes.h
new file mode 100644
index 0000000..88b24ff
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/esb/nrf_esb_error_codes.h
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __NRF_ESB_ERROR_CODES_H__
+#define __NRF_ESB_ERROR_CODES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NRF_ERROR_BUFFER_EMPTY (0x0100)
+
+#define NRF_ESB_ERROR_NOT_IN_RX_MODE (0x0101)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/esb/nrf_esb_resources.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/esb/nrf_esb_resources.h
new file mode 100644
index 0000000..3e1af51
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/esb/nrf_esb_resources.h
@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef NRF_ESB_RESOURCES_H__
+#define NRF_ESB_RESOURCES_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup nrf_esb_resources ESB resources
+ * @{
+ * @ingroup nrf_esb
+ */
+
+#ifndef ESB_ALTERNATIVE_RESOURCES
+ #define ESB_PPI_CHANNELS_USED 0x00000007uL /**< PPI channels used by ESB (not available to the application). */
+ #define ESB_TIMERS_USED 0x00000004uL /**< Timers used by ESB. */
+ #define ESB_SWI_USED 0x00000001uL /**< Software interrupts used by ESB. */
+#else
+ #define ESB_PPI_CHANNELS_USED 0x00000700uL /**< PPI channels used by ESB (not available to the application). */
+ #define ESB_TIMERS_USED 0x00000001uL /**< Timers used by ESB. */
+ #define ESB_SWI_USED 0x00000002uL /**< Software interrupts used by ESB. */
+#endif
+
+/** @} */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NRF_ESB_RESOURCES_H__ */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf51_arm.lib b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf51_arm.lib
new file mode 100644
index 0000000..e0e9915
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf51_arm.lib
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf51_sd_resources_arm.lib b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf51_sd_resources_arm.lib
new file mode 100644
index 0000000..aedb24e
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf51_sd_resources_arm.lib
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf52840_arm.lib b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf52840_arm.lib
new file mode 100644
index 0000000..63503ab
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf52840_arm.lib
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf52840_sd_resources_arm.lib b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf52840_sd_resources_arm.lib
new file mode 100644
index 0000000..25cb7d3
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf52840_sd_resources_arm.lib
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf52_arm.lib b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf52_arm.lib
new file mode 100644
index 0000000..afd9a9b
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf52_arm.lib
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf52_sd_resources_arm.lib b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf52_sd_resources_arm.lib
new file mode 100644
index 0000000..12596fc
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/gzll_nrf52_sd_resources_arm.lib
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/license.txt b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/license.txt
new file mode 100644
index 0000000..957d928
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/arm/license.txt
@@ -0,0 +1,37 @@
+Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form, except as embedded into a Nordic
+ Semiconductor ASA integrated circuit in a product or a software update for
+ such product, must reproduce the above copyright notice, this list of
+ conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+4. This software, with or without modification, must only be used with a
+ Nordic Semiconductor ASA integrated circuit.
+
+5. Any software provided in binary form under this license must not be reverse
+ engineered, decompiled, modified and/or disassembled.
+
+THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/config/nrf_gzp_config.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/config/nrf_gzp_config.h
new file mode 100644
index 0000000..801cc3f
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/config/nrf_gzp_config.h
@@ -0,0 +1,168 @@
+/**
+ * Copyright (c) 2008 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __GZP_CONFIG_H
+#define __GZP_CONFIG_H
+
+#include "nrf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * Definition of "secret key" used during "Host ID exchange".
+ */
+
+#define GZP_SECRET_KEY {1, 23, 45, 57, 26, 68, 12, 64, 13, 73, 13, 62, 26, 45, 12, 77}
+
+//-----------------------------------------------------------------------------
+
+/**
+ Definition of the first static selected pairing channel. Should be located in
+ the lower Nth of the channel range, where N is the size if the channel subset
+ selected by the application.
+*/
+#define GZP_CHANNEL_LOW 2
+
+/**
+ Definition of the second static selected pairing channel. Should be located in
+ the upper Nth of the channel range, where N is the size if the channel subset
+ selected by the application.
+*/
+#define GZP_CHANNEL_HIGH 79
+
+/**
+ Definition of the static "global" pairing address.
+*/
+#define GZP_ADDRESS 4, 6, 8, 10
+
+/**
+ Reduced TX power for use during close proximity pairing.
+ */
+#define GZP_POWER NRF_GZLL_TX_POWER_N16_DBM
+
+/**
+ Definition of pairing request timeout.
+*/
+#define GZP_REQ_TX_TIMEOUT 200
+
+/**
+ Definition of the maximimum number of "backoff" packets (step 0) to be transmitted.
+*/
+#define GZP_MAX_BACKOFF_PACKETS 100
+
+/**
+ Definition of the period a device shall wait before attempting to send the packet for
+ fetching the pairing response (step 1).
+*/
+#define GZP_TX_ACK_WAIT_TIMEOUT (GZP_CLOSE_PROXIMITY_BACKOFF_RX_TIMEOUT + 50)
+
+/**
+ Definition of the period a device in close proximity shall back off on the pairing
+ address after a backoff packet has been received.
+*/
+#define GZP_CLOSE_PROXIMITY_BACKOFF_RX_TIMEOUT ((GZP_REQ_TX_TIMEOUT / 2) + 50)
+
+/**
+ Definition of the period a device NOT in close proximity shall back off on the pairing
+ address after a backoff packet has been received.
+*/
+#define GZP_NOT_PROXIMITY_BACKOFF_RX_TIMEOUT (GZP_CLOSE_PROXIMITY_BACKOFF_RX_TIMEOUT + GZP_STEP1_RX_TIMEOUT)
+
+/**
+ Definition of the time the host waits for a device to complete
+ transmission of the pairing request step 1 packet.
+*/
+#define GZP_STEP1_RX_TIMEOUT (((GZP_REQ_TX_TIMEOUT / 2) + GZP_TX_ACK_WAIT_TIMEOUT) + 50)
+
+/**
+ Definition of the lowest boundary for the channel range to be used.
+*/
+#define GZP_CHANNEL_MIN 2
+
+/**
+ Definition of the upper boundary for the channel range to be used.
+*/
+#define GZP_CHANNEL_MAX 80
+
+/**
+ Definition of the minimum channel spacing for the channel subset generated
+ during pairing.
+*/
+#define GZP_CHANNEL_SPACING_MIN 5
+
+/**
+ Non volatile memory (Flash or OTP) storage address. A device will
+ require GZP_DEVICE_PARAMS_STORAGE_SIZE bytes of memory, and
+ Host 11 bytes. When using flash memory, storage address should
+ be a multiple of chip page size.
+*/
+#define GZP_PARAMS_STORAGE_ADR 0x00001000
+
+/**
+ Number of bytes available for parameter storage in Device.
+ It is equal to flash page size on nRF5x chips.
+*/
+#if defined (NRF51)
+ #define GZP_DEVICE_PARAMS_STORAGE_SIZE 1024
+#elif defined (NRF52_SERIES)
+ #define GZP_DEVICE_PARAMS_STORAGE_SIZE 4096
+#else
+ #error Chip type is undefined!
+#endif
+
+/**
+ Maximum Device TX payload length [bytes].
+ */
+#define GZP_MAX_FW_PAYLOAD_LENGTH 17
+
+/**
+ Maximum Host ACK payload length [bytes].
+ */
+#define GZP_MAX_ACK_PAYLOAD_LENGTH 10
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf51_gcc.a b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf51_gcc.a
new file mode 100644
index 0000000..8c9fe0a
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf51_gcc.a
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf51_sd_resources_gcc.a b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf51_sd_resources_gcc.a
new file mode 100644
index 0000000..4896b0c
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf51_sd_resources_gcc.a
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf52840_gcc.a b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf52840_gcc.a
new file mode 100644
index 0000000..911ae7d
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf52840_gcc.a
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf52840_sd_resources_gcc.a b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf52840_sd_resources_gcc.a
new file mode 100644
index 0000000..46284ef
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf52840_sd_resources_gcc.a
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf52_gcc.a b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf52_gcc.a
new file mode 100644
index 0000000..d463ca4
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf52_gcc.a
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf52_sd_resources_gcc.a b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf52_sd_resources_gcc.a
new file mode 100644
index 0000000..052634c
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/gzll_nrf52_sd_resources_gcc.a
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/license.txt b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/license.txt
new file mode 100644
index 0000000..957d928
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/gcc/license.txt
@@ -0,0 +1,37 @@
+Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form, except as embedded into a Nordic
+ Semiconductor ASA integrated circuit in a product or a software update for
+ such product, must reproduce the above copyright notice, this list of
+ conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+4. This software, with or without modification, must only be used with a
+ Nordic Semiconductor ASA integrated circuit.
+
+5. Any software provided in binary form under this license must not be reverse
+ engineered, decompiled, modified and/or disassembled.
+
+THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf51_iar.a b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf51_iar.a
new file mode 100644
index 0000000..bf4ad39
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf51_iar.a
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf51_sd_resources_iar.a b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf51_sd_resources_iar.a
new file mode 100644
index 0000000..23fcdd1
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf51_sd_resources_iar.a
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf52840_iar.a b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf52840_iar.a
new file mode 100644
index 0000000..755dbfd
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf52840_iar.a
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf52840_sd_resources_iar.a b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf52840_sd_resources_iar.a
new file mode 100644
index 0000000..b7971e6
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf52840_sd_resources_iar.a
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf52_iar.a b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf52_iar.a
new file mode 100644
index 0000000..36e7653
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf52_iar.a
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf52_sd_resources_iar.a b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf52_sd_resources_iar.a
new file mode 100644
index 0000000..d09ca0f
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/gzll_nrf52_sd_resources_iar.a
Binary files differ
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/license.txt b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/license.txt
new file mode 100644
index 0000000..957d928
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/iar/license.txt
@@ -0,0 +1,37 @@
+Copyright (c) 2010 - 2018, Nordic Semiconductor ASA
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form, except as embedded into a Nordic
+ Semiconductor ASA integrated circuit in a product or a software update for
+ such product, must reproduce the above copyright notice, this list of
+ conditions and the following disclaimer in the documentation and/or other
+ materials provided with the distribution.
+
+3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+4. This software, with or without modification, must only be used with a
+ Nordic Semiconductor ASA integrated circuit.
+
+5. Any software provided in binary form under this license must not be reverse
+ engineered, decompiled, modified and/or disassembled.
+
+THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzll.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzll.h
new file mode 100644
index 0000000..79a9ee8
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzll.h
@@ -0,0 +1,937 @@
+/**
+ * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/**
+ * @file
+ * @brief Gazell Link Layer API.
+ */
+
+#ifndef NRF_GZLL_H__
+#define NRF_GZLL_H__
+
+#include <stdbool.h>
+#include "nrf.h"
+#include "nrf_gzll_constants.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+* @defgroup gzll_02_api Gazell Link Layer
+* @{
+* @ingroup modules_01_gzll
+* @brief Gazell Link Layer Application Programming Interface (API).
+*/
+
+/**
+ * @enum nrf_gzll_mode_t
+ * @brief Enumerator used for selecting Gazell mode.
+ */
+typedef enum
+{
+ NRF_GZLL_MODE_DEVICE, ///< Device mode
+ NRF_GZLL_MODE_HOST, ///< Host mode
+ NRF_GZLL_MODE_SUSPEND, ///< Suspend mode ("disabled with timer running")
+} nrf_gzll_mode_t;
+
+/**
+ * @enum nrf_gzll_device_channel_selection_policy_t
+ * @brief Enumerator used for selecting Gazell Device channel
+ * selection policy.
+ */
+typedef enum
+{
+ NRF_GZLL_DEVICE_CHANNEL_SELECTION_POLICY_USE_SUCCESSFUL, ///< Start on previous successful channel
+ NRF_GZLL_DEVICE_CHANNEL_SELECTION_POLICY_USE_CURRENT, ///< Start on channel currently monitored by Host
+} nrf_gzll_device_channel_selection_policy_t;
+
+/**
+ * @enum nrf_gzll_tx_power_t
+ * @brief Enumerator used for selecting the transmit (TX) power.
+ */
+typedef enum
+{
+ NRF_GZLL_TX_POWER_4_DBM, ///< 4 dBm transmit power.
+ NRF_GZLL_TX_POWER_0_DBM, ///< 0 dBm transmit power.
+ NRF_GZLL_TX_POWER_N4_DBM, ///< -4 dBm transmit power.
+ NRF_GZLL_TX_POWER_N8_DBM, ///< -8 dBm transmit power.
+ NRF_GZLL_TX_POWER_N12_DBM, ///< -12 dBm transmit power.
+ NRF_GZLL_TX_POWER_N16_DBM, ///< -16 dBm transmit power.
+ NRF_GZLL_TX_POWER_N20_DBM ///< -20 dBm transmit power.
+} nrf_gzll_tx_power_t;
+
+/**
+ * @enum nrf_gzll_datarate_t
+ * @brief Enumerator used for selecting the radio datarate.
+ */
+typedef enum
+{
+#ifdef NRF51
+ NRF_GZLL_DATARATE_250KBIT = 0, ///< 250 Kbps datarate, available only for the nRF51.
+#endif
+ NRF_GZLL_DATARATE_1MBIT = 1, ///< 1 Mbps datarate.
+ NRF_GZLL_DATARATE_2MBIT = 2 ///< 2 Mbps datarate.
+} nrf_gzll_datarate_t;
+
+/**
+ * @enum nrf_gzll_xosc_ctl_t
+ * @brief Enumerator used for specifying whether switching the
+ * external 16 MHz oscillator on/off shall be handled automatically
+ * inside Gazell or manually by the application.
+ */
+typedef enum
+{
+ NRF_GZLL_XOSC_CTL_AUTO, ///< Switch XOSC on/off automatically
+ NRF_GZLL_XOSC_CTL_MANUAL ///< Switch XOSC on/off manually
+} nrf_gzll_xosc_ctl_t;
+
+/**
+ * @enum nrf_gzll_error_code_t
+ * @brief Enumerator used for error codes for Gazell API functions
+ */
+typedef enum
+{
+ NRF_GZLL_ERROR_CODE_NO_ERROR = 0, ///< No error has been detected.
+ NRF_GZLL_ERROR_CODE_FAILED_TO_INITIALIZE = 1, ///< The function NRF_GZLL_init failed.
+ NRF_GZLL_ERROR_CODE_ATTEMPTED_TO_CONFIGURE_WHEN_ENABLED = 2, ///< A call to a configuration 'set' function was made while Gazell was enabled.
+ NRF_GZLL_ERROR_CODE_POINTER_IS_NULL = 3, ///< A null pointer was given as an input to a function.
+ NRF_GZLL_ERROR_CODE_INVALID_PIPE = 4, ///< An invalid pipe number was given as an input to a function.
+ NRF_GZLL_ERROR_CODE_INVALID_MODE = 5, ///< An invalid value for the nrf_gzll_mode_t enumerator was given as input to a function.
+ NRF_GZLL_ERROR_CODE_INVALID_PAYLOAD_LENGTH = 6, ///< An invalid payload length was given as an input to a function.
+ NRF_GZLL_ERROR_CODE_INVALID_CHANNEL_TABLE_SIZE = 7, ///< An invalid channel table size was given as an input to a function.
+ NRF_GZLL_ERROR_CODE_INSUFFICIENT_PACKETS_AVAILABLE = 8, ///< There are insufficient packets in the Gazell memory pool to successfully execute the operation.
+ NRF_GZLL_ERROR_CODE_ATTEMPTED_TO_ADD_TO_FULL_FIFO = 9, ///< There is insufficient space in the TX FIFO for the data packet.
+ NRF_GZLL_ERROR_CODE_NO_SPACE_IN_RX_FIFO_FOR_ACK = 10, ///< There is insufficient space in the RX FIFO for the ACK.
+ NRF_GZLL_ERROR_CODE_ATTEMPTED_TO_FETCH_FROM_EMPTY_FIFO = 11, ///< Attempted to fetch a packet from an empty FIFO. Use the functions nrf_gzll_get_tx_fifo_packet_count() or nrf_gzll_get_rx_fifo_packet_count()
+ NRF_GZLL_ERROR_CODE_ATTEMPTED_TO_FLUSH_WHEN_ENABLED = 12, ///< Attempted to fetch a packet from an empty FIFO. Use the functions nrf_gzll_get_tx_fifo_packet_count() or nrf_gzll_get_rx_fifo_packet_count()
+ NRF_GZLL_ERROR_CODE_INVALID_PARAMETER = 14, ///< Attempted to set a variable which was not valid.
+ NRF_GZLL_ERROR_CODE_INTERNAL_ASSERT_OCCURRED = 15, ///< An internal assert occurred.
+ NRF_GZLL_ERROR_CODE_CALLBACK_NOT_IMPLEMENTED = 16, ///< A callback was called but not implemented by the application.
+ NRF_GZLL_ERROR_CODE_INVALID_ADDRESS = 17, ///< Invalid pipe 0 address detected, see Anomaly 107 at nRF52832 errata document.
+ NRF_GZLL_ERROR_CODE_NUMBER_OF_ERROR_CODES = 18, ///< Number of possible error codes.
+} nrf_gzll_error_code_t;
+
+/**
+ * @struct nrf_gzll_device_tx_info_t;
+ * @brief Data structure containing information about the last packet
+ * transmission.
+ */
+typedef struct
+{
+ bool payload_received_in_ack; ///< A payload was received in the ACK.
+ uint16_t num_tx_attempts; ///< Number of attempts used on previous Device packet transmission.
+ uint16_t num_channel_switches; ///< Number of channel switches needed during previous packet transmission.
+ int8_t rssi; ///< Received signal strength indicator in dBm. @sa nrf_gzll_enable_rssi().
+ uint8_t rf_channel; ///< Channel on which packet has been transmitted.
+} nrf_gzll_device_tx_info_t;
+
+
+/**
+ * @struct nrf_gzll_host_rx_info_t;
+ * @brief Data structure containing information about the last packet
+ * received.
+ */
+typedef struct
+{
+ bool packet_removed_from_tx_fifo; ///< A payload was received in the ACK.
+ int8_t rssi; ///< Received signal strength indicator in dBm. @sa nrf_gzll_enable_rssi().
+ uint8_t rf_channel; ///< Channel on which packet has been received.
+} nrf_gzll_host_rx_info_t;
+
+
+typedef struct
+{
+ uint32_t packets_num; ///< Number of succesfully transmitted packets
+ uint32_t timeouts_num; ///< Total timeouts number
+ uint32_t channel_timeouts[NRF_GZLL_CONST_MAX_CHANNEL_TABLE_SIZE]; ///< Transmission timeouts per channel
+ uint32_t channel_packets[NRF_GZLL_CONST_MAX_CHANNEL_TABLE_SIZE]; ///< Succesfully transmitted packets per channel
+} nrf_gzll_tx_statistics_t;
+
+
+/**< Transmission timeout callback function definition */
+typedef void (*nrf_gzll_tx_timeout_callback)(uint32_t pipe, uint8_t rf_channel);
+
+
+/**< Transmission CRC failure callback function definition */
+typedef void (*nrf_gzll_crc_failure_callback)(uint32_t pipe, uint8_t rf_channel);
+
+
+#if defined(NRF52_SERIES) || defined(__SDK_DOXYGEN__)
+/**
+ * @brief Data structure holding external front
+ * end control configuration.
+ */
+typedef struct
+{
+ bool pa_enabled; ///< Flag indicating if PA control is enabled.
+ bool pa_active_high; ///< Flag indicating if PA is active in high input state.
+ uint8_t pa_gpio_pin; ///< Number of output pin used for PA control.
+ uint8_t pa_gpiote_channel; ///< Number of GPIOTE channel used for PA control.
+ bool lna_enabled; ///< Flag indicating if LNA control is enabled.
+ bool lna_active_high; ///< Flag indicating if LNA is active in high input state.
+ uint8_t lna_gpio_pin; ///< Number of output pin used for LNA control.
+ uint8_t lna_gpiote_channel; ///< Number of GPIOTE channel used for LNA control.
+ NRF_TIMER_Type * timer; ///< Pointer to the TIMER instance.
+ uint8_t ppi_channels[NRF_GZLL_PA_LNA_PPI_CHANNELS_NUM]; ///< PPI channels used to control front end.
+ uint8_t ramp_up_time; ///< Determines how early should the PA/LNA be turned one before RADIO activity. Should be less than @ref NRF_GZLL_PA_LNA_MAX_RAMP_UP_TIME.
+} nrf_gzll_pa_lna_cfg_t;
+#endif
+
+/******************************************************************************/
+/** @name General API functions
+ * @{ */
+/******************************************************************************/
+
+/**
+ * @brief Initialize Gazell.
+ *
+ * @param mode The mode to initialize Gazell in.
+ *
+ * @retval true if Gazell initialized.
+ * @retval false if Gazell failed to initialize.
+ */
+bool nrf_gzll_init(nrf_gzll_mode_t mode);
+
+/**
+ * @brief Enable Gazell.
+ *
+ * When enabled the behaviour described for the current Gazell Link Layer mode
+ * will apply.
+ *
+ * @retval false if nrf_gzll_init has not previously been called or invalid address
+ * has been set - see Anomaly 107 at nRF52832 errata document.
+ */
+bool nrf_gzll_enable(void);
+
+/**
+ * @brief Disable Gazell.
+ *
+ * When calling this function the Gazell Link Layer will begin disabling,
+ * and will be fully disabled when Gazell calls nrf_gzll_disabled().
+ * If there are any pending notifications, or if any new notifications are
+ * being added to the internal notification queue while Gazell is disabling,
+ * these will be sent to the application before Gazell is fully disabled.
+ *
+ * After Gazell has been fully disabled, no more notifications will be sent to
+ * the application.
+ */
+void nrf_gzll_disable(void);
+
+/** Check whether Gazell is enabled or disabled.
+ *
+ * @retval true If Gazell is enabled.
+ * @retval false If Gazell is disabled.
+ */
+bool nrf_gzll_is_enabled(void);
+
+/** @} */
+
+/******************************************************************************/
+/** @name Device mode callback functions
+ * @{ */
+/******************************************************************************/
+
+/**
+ * @brief ACK received callback (Device mode only).
+ *
+ * This callback is made when the Device receives an ACK (acknowledgement)
+ * packet.
+ * @sa nrf_gzll_ack_payload_received.
+ *
+ * @param pipe is the pipe on which an ACK packet was received.
+ * @param tx_info struct used to indicate whether a payload was received in the
+ * ack, as well as the number of TX attempts and channel switches required.
+ */
+void nrf_gzll_device_tx_success(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info);
+
+/**
+ * @brief Transmission failed callback (Device mode only).
+ *
+ * This callback is made when a packet does not receive an ACK after
+ * nrf_gzll_max_retries is reached. The packet is deleted by Gazell.
+ *
+ * @param pipe is the pipe on which the transmission failed.
+ * @param tx_info struct used to indicate whether a payload was received
+ * in the ack, as well as RSSI and the number of TX attempts and
+ * channel switches required.
+ */
+void nrf_gzll_device_tx_failed(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info);
+
+/** @} */
+
+/******************************************************************************/
+/** @name Host mode callback functions
+ * @{ */
+/******************************************************************************/
+
+/**
+ * @brief Data packet received callback (Host mode only).
+ *
+ * This callback is made when a Host receives a data packet from a Device.
+ *
+ * @param pipe is the pipe on which the data packet was received.
+ * @param rx_info struct used to indicate whether a payload was removed from the
+ * pipe's TX FIFO, as well as RSSI.
+ */
+void nrf_gzll_host_rx_data_ready(uint32_t pipe, nrf_gzll_host_rx_info_t rx_info);
+
+/** @} */
+
+/******************************************************************************/
+/** @name Callback functions for both Device and Host mode
+ * @{ */
+/******************************************************************************/
+
+/**
+ * @brief Disabled callback.
+ *
+ * This is called after Gazell enters the disabled state.
+ * There is no further CPU use by Gazell, the radio is disabled and the timer is
+ * powered down.
+ */
+void nrf_gzll_disabled(void);
+
+/**
+ * @brief Mode changed callbackl.
+ *
+ * This function is called after the Gazell mode has been changed.
+ * This function can only be called when Gazell is enabled.
+ */
+void nrf_gzll_mode_changed(void);
+
+/** @} */
+
+/******************************************************************************/
+/** @name Packet transmission and receiving functions
+ * @{ */
+/******************************************************************************/
+
+/**
+ * @brief Add a packet to the tail of the TX FIFO.
+ *
+ * In Device mode, the packet will be added.
+ * In Host mode, the payload will be piggybacked onto an ACK.
+ *
+ * @param pipe Pipe to which to add the payload. This value must be < NRF_GZLL_CONST_PIPE_COUNT.
+ * @param p_payload Pointer to the payload.
+ * @param length Number of bytes of the payload to transmit
+ * (0 to NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH).
+ *
+ * @retval true if the packet was successfully added to the TX FIFO.
+ * @retval false if unsuccessful, check nrf_gzll_error_code_t for more information.
+ */
+bool nrf_gzll_add_packet_to_tx_fifo(uint32_t pipe, uint8_t * p_payload, uint32_t length);
+
+/**
+ * @brief Fetch a packet from the head of the RX FIFO.
+ *
+ * @param pipe Pipe from which to fetch the payload. This value must be < NRF_GZLL_CONST_PIPE_COUNT.
+ * @param p_payload Pointer to copy the payload to.
+ * @param p_length Length must be at least as large as the the number of bytes
+ * in the received payload length.
+ *
+ * @retval true If the fetch was successful.
+ * @retval false If unsuccessful, check nrf_gzll_error_code_t for more information.
+ */
+bool nrf_gzll_fetch_packet_from_rx_fifo(uint32_t pipe, uint8_t * p_payload, uint32_t * p_length);
+
+/**
+ * @brief Get the number of packets in the TX FIFO on a specific pipe.
+ *
+ * @param pipe The pipe for which to check. This value must be < NRF_GZLL_CONST_PIPE_COUNT.
+ *
+ * @retval >=0 The number of packets in the TX FIFO for the pipe.
+ * @retval -1 If the pipe number is invalid.
+ */
+int32_t nrf_gzll_get_tx_fifo_packet_count(uint32_t pipe);
+
+/**
+ * @brief Get the number of packets in the RX FIFO on a specific pipe.
+ *
+ * @param pipe The pipe for which to check. This value must be < NRF_GZLL_CONST_PIPE_COUNT.
+ * @retval >=0 The number of packets in the RX FIFO for the pipe.
+ * @retval -1 If the pipe number is invalid.
+ */
+int32_t nrf_gzll_get_rx_fifo_packet_count(uint32_t pipe);
+
+/**
+ * @brief Get the total number of packets residing in all TX and RX FIFOs.
+ *
+ * Can be used to check against NRF_GZLL_CONST_MAX_TOTAL_PACKETS to
+ * determine if there is free space in the memory pool for more packets.
+ *
+ * @return The number of packets residing in all TX and RX FIFOs.
+ */
+uint32_t nrf_gzll_get_total_allocated_packet_count(void);
+
+/**
+ * @brief Check if adding a packet to a pipe's TX FIFO should be successful.
+ *
+ * Checks if there is another space in the pipe's TX and RX FIFOs
+ * as well as enough overall space in the packet pool.
+ *
+ * @param pipe The pip for which to check. This value must be < NRF_GZLL_CONST_PIPE_COUNT.
+ *
+ * @retval true If there is another space.
+ * @retval false If there is not enough space, or the pipe is invalid.
+ */
+bool nrf_gzll_ok_to_add_packet_to_tx_fifo(uint32_t pipe);
+
+/**
+ * @brief Flush the RX FIFO for a specific pipe.
+ *
+ * Delete all the packets and free the memory of the TX FIFO for a
+ * specific pipe.
+ *
+ * Note that it is not allowed to flush a TX FIFO when
+ * Gazell is enabled.
+ *
+ * @param pipe is the pipe for which to flush. This value must be < NRF_GZLL_CONST_PIPE_COUNT.
+ * @retval true if the pipe was flushed.
+ * @retval false if the pipe was not flushed.
+ */
+bool nrf_gzll_flush_tx_fifo(uint32_t pipe);
+
+/**
+ * @brief Flush the RX FIFO for a specific pipe.
+ *
+ * Delete all the packets and free the memory of the RX FIFO for a
+ * specific pipe.
+ *
+ * @param pipe is the pipe for which to flush. This value must be < NRF_GZLL_CONST_PIPE_COUNT.
+ * @retval true if the pipe was flushed.
+ * @retval false if the pipe was not flushed.
+ */
+bool nrf_gzll_flush_rx_fifo(uint32_t pipe);
+
+/**
+ * @brief Function for enabling transmission statistics.
+ *
+ * @param p_statistics Pointer to the statistics structure.
+ *
+ * @return True if channel statistics has been enabled, false otherwise.
+ */
+bool nrf_gzll_tx_statistics_enable(nrf_gzll_tx_statistics_t * p_statistics);
+
+/**
+ * @brief Function for disabling transmission statistics.
+ */
+void nrf_gzll_tx_statistics_disable(void);
+
+/**
+ * @brief Function for obtaining number of transmission timeouts for specific channel.
+ *
+ * @param[in] channel_index Channel index in channel table.
+ * @param[out] p_timeouts Pointer for the result.
+ *
+ * @return True in case of success, false otherwise.
+ */
+bool nrf_gzll_get_channel_timeouts(uint8_t channel_index, uint32_t *p_timeouts);
+
+/**
+ * @brief Function for clearing transmission statistic structure.
+ */
+void nrf_gzll_reset_tx_statistics(void);
+
+/** @} */
+
+/******************************************************************************/
+/** @name Configuration functions
+ *
+ * Configuration 'set' functions may only be called while Gazell is disabled. The
+ * new parameter comes into effect when Gazell is enabled again.
+ *
+ * Configuration 'get' functions may be called at any time.
+ *
+ * @{ */
+/******************************************************************************/
+
+/**
+ * @brief Function for registering callback to be called on the transmission timeout.
+ */
+void nrf_gzll_tx_timeout_callback_register(nrf_gzll_tx_timeout_callback callback);
+
+
+/**
+ * @brief Function for registering callback to be called on the packet CRC failure.
+ */
+void nrf_gzll_crc_failure_callback_register(nrf_gzll_crc_failure_callback callback);
+
+
+/**
+ * @brief Set the mode.
+ *
+ * @param mode The mode to be used.
+ * See nrf_gzll_mode_t for a list of valid modes.
+ *
+ * It is allowed to change mode when Gazell is enabled. If the mode is
+ * being changed while Gazell is enabled, the mode will not change right away.
+ * In this case the callback function nrf_gzll_mode_changed() will be called
+ * after the mdoe has changed.
+ *
+ * @retval true If the parameter was set.
+ */
+bool nrf_gzll_set_mode(nrf_gzll_mode_t mode);
+
+/**
+ * @brief Get function counterpart to nrf_gzll_set_mode().
+ *
+ * @return The current mode.
+ */
+nrf_gzll_mode_t nrf_gzll_get_mode(void);
+
+/**
+ * @brief Set the base address for pipe 0.
+ *
+ * The full on-air address for each pipe is composed of a multi-byte base address
+ * prepended to a prefix byte.
+ *
+ * For packets to be received correctly, the most significant byte of
+ * the base address should not be an alternating sequence of 0s and 1s i.e.
+ * it should not be 0x55 or 0xAA.
+ *
+ * @param base_address The 4 byte base address. All bytes are used.
+ *
+ * @note Due to the nRF52 Anomaly 107, pipe 0 address should not have
+ * both prefix and two LSB of base address set to 0.
+ *
+ * @retval true If the parameter was set.
+ * @return false If Gazell was enabled.
+ */
+bool nrf_gzll_set_base_address_0(uint32_t base_address);
+
+/**
+ * @brief Get function counterpart to nrf_gzll_set_base_address_0().
+ *
+ * @return Base address 0.
+ */
+uint32_t nrf_gzll_get_base_address_0(void);
+
+/**
+ * @brief Set the base address for pipes 1-7.
+ *
+ * Pipes 1 through 7 share base_address_1. @sa nrf_gzll_set_base_address_0.
+ *
+ * @param base_address The 4 byte base address.
+ *
+ * @retval true If the parameter was set.
+ * @retval false If Gazell was enabled.
+ */
+bool nrf_gzll_set_base_address_1(uint32_t base_address);
+
+/**
+ * @brief Get function counterpart to nrf_gzll_set_base_address_1().
+ *
+ * @return Base address 1.
+ */
+uint32_t nrf_gzll_get_base_address_1(void);
+
+/**
+ * @brief Set the address prefix byte for a specific pipe.
+ *
+ * Each pipe should have its own unique prefix byte.
+ *
+ * @param pipe The pipe that the address should apply to.
+ * This value must be < NRF_GZLL_CONST_PIPE_COUNT.
+ * @param address_prefix_byte The address prefix byte.
+ *
+ * @note Due to the Anomaly 107, pipe 0 address should not have
+ * both prefix and two LSB of base address set to 0.
+ *
+ * @retval true If the parameter was set.
+ * @retval false If Gazell was enabled, or if the pipe was invalid.
+ */
+bool nrf_gzll_set_address_prefix_byte(uint32_t pipe, uint8_t address_prefix_byte);
+
+/**
+ * @brief Get function counterpart to nrf_gzll_set_address_prefix_byte().
+ *
+ * @param pipe The pipe for which to get the address.
+ * This value must be < NRF_GZLL_CONST_PIPE_COUNT.
+ * @param p_out_address_prefix_byte The pointer in which to return the
+ * address prefix byte.
+ *
+ * @retval true If the parameter was returned.
+ * @retval false If Gazell was enabled, the pipe was invalid or
+ * out_address was a NULL pointer.
+ */
+bool nrf_gzll_get_address_prefix_byte(uint32_t pipe, uint8_t * p_out_address_prefix_byte);
+
+/**
+ * @brief Set which pipes shall listen for packets in Host mode.
+ *
+ * This value is a bitmap, and each bit corresponds to a given pipe number.
+ * Bit 0 set to "1" enables pipes 0, bit 1 set to "1" enables pipe 1
+ * and so forth.
+ * The maximum number of pipes is defined by NRF_GZLL_CONST_PIPE_COUNT.
+ *
+ * @param pipes A bitmap specifying which pipes to monitor.
+ *
+ * @retval true If the parameter was set.
+ * @retval false If Gazell was enabled.
+ */
+bool nrf_gzll_set_rx_pipes_enabled(uint32_t pipes);
+
+/**
+ * @brief Get function counterpart to nrf_gzll_set_rx_pipes_enabled().
+ *
+ * @return Bitmap holding the current enabled pipes.
+ */
+uint32_t nrf_gzll_get_rx_pipes_enabled(void);
+
+/**
+ * @brief Set the timeslot period.
+ *
+ * The length in microseconds of a Gazell link layer timeslot.
+ *
+ * The minimum value of the timeslot period is dependent of the
+ * radio data rate (@sa nrf_gzll_set_datarate()).
+ *
+ * - For NRF_GZLL_DATARATE_2MBIT the timeslot period must be >= 600 us.
+ * - For NRF_GZLL_DATARATE_1MBIT the timeslot period must be >= 900 us.
+ * - For NRF_GZLL_DATARATE_250KBIT the timeslot period must be >= 2700 us.
+ *
+ * @param period_us The timeslot period in microseconds.
+ *
+ * @retval true If the parameter was set.
+ * @retval false If Gazell was enabled.
+ */
+bool nrf_gzll_set_timeslot_period(uint32_t period_us);
+
+/**
+ * @brief Get function counterpart to nrf_gzll_get_timeslot_period().
+ *
+ * @return The current timeslot period.
+ */
+uint32_t nrf_gzll_get_timeslot_period(void);
+
+/**
+ * @brief Set the Device channel selection policy
+ *
+ * The policy determines the initial channel when starting a new packet.
+ * transmission.
+ *
+ * @param policy The channel selection policy.
+ *
+ * @arg NRF_GZLL_DEVICE_CHANNEL_SELECTION_POLICY_USE_SUCCESSFUL specifies
+ * that a new packet transmission always shall use the previous
+ * successful channel from the channel table. If Gazell is "in sync", Gazell
+ * will wait until this channel is being monitored by the Host before starting
+ * the transmission.
+ *
+ * @arg NRF_GZLL_DEVICE_CHANNEL_SELECTION_POLICY_USE_CURRENT specifies that
+ * Gazell shall transmit on the channel that is currently being monitored by the
+ * Host. This parameter is only used when Gazell is "in sync". When "out of" sync,
+ * Gazell will always start using the "previous successful" channel.
+ *
+ * @retval true If the parameter was set.
+ * @retval false If Gazell was enabled or the policy was invalid.
+ */
+bool nrf_gzll_set_device_channel_selection_policy(nrf_gzll_device_channel_selection_policy_t policy);
+
+/**
+ * @brief Get function counterpart to nrf_gzll_set_device_channel_selection_policy().
+ *
+ * @return the Device channel selection policy.
+ */
+nrf_gzll_device_channel_selection_policy_t nrf_gzll_get_device_channel_selection_policy(void);
+
+/**
+ * @brief Set the number of timeslots that Gazell shall
+ * reside on a single channel before switching to another channel.
+ *
+ * This parameter applies in Host mode and for a Device that is
+ * in the "in sync" state.
+ *
+ * Since the Device and Host can not be in perfect synchronization, a
+ * transmission should overlap to adjacent timeslots on the Host.
+ * Therefore this value should be at least 2.
+ *
+ * @sa nrf_gzll_set_timeslots_per_channel_when_device_out_of_sync
+ *
+ * @param timeslots The number of timeslots to reside on
+ * each channel before channel switch.
+ *
+ * @retval true If the parameter was set.
+ * @retval false If Gazell was enabled.
+ */
+bool nrf_gzll_set_timeslots_per_channel(uint32_t timeslots);
+
+/**
+ * @brief Get function counterpart to nrf_gzll_set_timeslots_per_channel().
+ *
+ * @return The current number of timeslots.
+ */
+uint32_t nrf_gzll_get_timeslots_per_channel(void);
+
+/**
+ * @brief Set the number of timeslots that a Gazell shall
+ * reside on a single channel before switching to another channel when
+ * in the "out of sync" state.
+ *
+ * This value should be set so that the Device transmits on one channel
+ * while the Host goes through a full channel rotation, i.e.,
+ * channel_table_size*timeslots_per_channel.
+ * This ensures that the channels on the Device and Host will coincide
+ * at some point.
+ * Further increasing the value has been observed to provide better performance
+ * in the presence of interferers.
+ *
+ * @param timeslots The number of timeslots to reside on
+ * each channel before channel switch.
+ *
+ * @retval true If the parameter was set.
+ * @retval false If Gazell was enabled.
+ */
+bool nrf_gzll_set_timeslots_per_channel_when_device_out_of_sync(uint32_t timeslots);
+
+/**
+ * @brief Get function counterpart to
+ * nrf_gzll_set_timeslots_per_channel_when_device_out_of_sync().
+ *
+ * @return The current number of timeslots.
+ */
+uint32_t nrf_gzll_get_timeslots_per_channel_when_device_out_of_sync(void);
+
+/**
+ * @brief Set the number of timeslots after a successful
+ * reception of a Device or Host packet that the Gazell Link Layer shall assume
+ * that the link is synchronized. A value of 0 implies that the
+ * link is always out of sync.
+ *
+ * @param lifetime The sync lifetime in number of timeslots.
+ *
+ * @retval true If the sync lifetime was set.
+ * @retval false If Gazell was enabled.
+ */
+bool nrf_gzll_set_sync_lifetime(uint32_t lifetime);
+
+/**
+ * @brief Get function counterpart to nrf_gzll_set_sync_lifetime().
+ *
+ * @return The sync lifetime measured in number of timeslots.
+ */
+uint32_t nrf_gzll_get_sync_lifetime(void);
+
+/**
+ * @brief Set the maximum number of TX attempts
+ * that can be used for a single packet.
+ *
+ * After the maximum number of attempts have been spent without
+ * receiving any ACK from the Host, the transmission will be terminated
+ * and the nrf_gzll_device_tx_failed() callback will be called. A zero
+ * value of the function parameter implies the infinite number of TX attempts.
+ *
+ * @param max_tx_attempts The maximum number of TX attempts.
+ */
+void nrf_gzll_set_max_tx_attempts(uint16_t max_tx_attempts);
+
+/**
+ * @brief Get function counterpart to nrf_gzll_set_max_tx_attempts().
+ *
+ * @return The current max Device TX attempts.
+ */
+uint16_t nrf_gzll_get_max_tx_attempts(void);
+
+/**
+ * @brief Set the table of Radio Frequency (RF) channels.
+ *
+ * The valid channels are in the range 0 <= channel <= 125, where the
+ * actual centre frequency is (2400 + channel) MHz.
+ * The maximum channel table size is defined by
+ * NRF_GZLL_CONST_MAX_CHANNEL_TABLE_SIZE.
+ *
+ * @param p_channel_table Pointer to the channel table.
+ * @param size The size of the channel table.
+ *
+ * @retval true If the channel table was set.
+ * @retval false If Gazell was enabled, or the channel_table pointer was NULL,
+ * or the size was invalid.
+ */
+bool nrf_gzll_set_channel_table(uint8_t * p_channel_table, uint32_t size);
+
+/**
+ * @brief Get the table of Radio Frequency (RF) channels.
+ *
+ * @param p_channel_table Pointer to copy the channel table to.
+ * @param p_size Pointer to copy the size of the channel table to.
+ * The value already at size must be at least the size
+ * of the channel table.
+ *
+ * @retval true If the channel table was copied to channel_table.
+ * @retval false If the channel_table pointer was NULL,
+ * or the size was not large enough.
+ */
+bool nrf_gzll_get_channel_table(uint8_t * p_channel_table, uint32_t * p_size);
+
+/**
+ * @brief Get the current channel table size.
+ *
+ * @return The current channel table size.
+ */
+uint32_t nrf_gzll_get_channel_table_size(void);
+
+/**
+ * @brief Set the radio TX power.
+ *
+ * @param tx_power TX power.
+ *
+ * @retval true If the parameter was set.
+ * @retval false If the TX power was invalid.
+*/
+bool nrf_gzll_set_tx_power(nrf_gzll_tx_power_t tx_power);
+
+/**
+ * @brief Get function counterpart to nrf_gzll_set_tx_power().
+ *
+ * @return The current TX power.
+ */
+nrf_gzll_tx_power_t nrf_gzll_get_tx_power(void);
+
+/**
+ * @brief Set the radio datarate.
+ *
+ * @param data_rate Datarate.
+ *
+ * @retval true If the parameter was set.
+ * @retval false If Gazell was enabled or the datarate was invalid.
+ */
+bool nrf_gzll_set_datarate(nrf_gzll_datarate_t data_rate);
+
+/**
+ * @brief Get function counterpart to nrf_gzll_set_datarate().
+ *
+ * @return The current datarate.
+ */
+nrf_gzll_datarate_t nrf_gzll_get_datarate(void);
+
+/**
+ * @brief Set whether start/stop of external oscillator (XOSC) shall be handled
+ * automatically inside Gazell or manually by the application.
+ *
+ * When controlling the XOSC manually from the application it is
+ * required that the XOSC is started before Gazell is enabled.
+ *
+ * When start/stop of the XOSC is handled automatically by Gazell,
+ * the XOSC will only be running when needed, that is when the radio
+ * is being used or when Gazell needs to maintain synchronization.
+ *
+ * It is required that the XOSC is started in order for the radio to be
+ * able to send or receive any packets.
+ *
+ * @param xosc_ctl setting for XOSC control.
+ *
+ * @retval true if the parameter was set.
+ * @retval false if Gazell was enabled or the xosc_ctl value was invalid.
+ */
+bool nrf_gzll_set_xosc_ctl(nrf_gzll_xosc_ctl_t xosc_ctl);
+
+/**
+ * Get function counterpart for nrf_gzll_set_xosc_ctl();
+ *
+ * @return The XOSC control setting.
+ */
+nrf_gzll_xosc_ctl_t nrf_gzll_get_xosc_ctl(void);
+
+/**
+ * @brief Set Gazell to disable automatically after a certain number of timeslot ticks.
+ *
+ * @param num_ticks Number of timeslot ticks.
+ *
+ */
+void nrf_gzll_set_auto_disable(uint32_t num_ticks);
+
+#if defined(NRF52_SERIES) || defined(__SDK_DOXYGEN__)
+/**
+ * @brief Set up external front end control.
+ *
+ * @param p_pa_lna_cfg Pointer to the configuration struct.
+ */
+bool nrf_gzll_set_pa_lna_cfg(nrf_gzll_pa_lna_cfg_t const * p_pa_lna_cfg);
+#endif
+
+/**
+ * @brief Get the number of timeslot ticks that have occurred since
+ * nrf_gzll_init() was called.
+ *
+ * @return Number of timeslot ticks.
+ *
+ */
+uint32_t nrf_gzll_get_tick_count(void);
+
+/**
+ * @brief Clear the internal timeslot tick count variable that is read
+ * by nrf_gzll_get_tick_count().
+ *
+ */
+void nrf_gzll_clear_tick_count(void);
+
+/** @} */
+
+/******************************************************************************/
+/** @name Error handling functions
+ * @{ */
+/******************************************************************************/
+
+/**
+ * @brief Gets the Gazell error code.
+ *
+ * @return The current error code.
+ */
+nrf_gzll_error_code_t nrf_gzll_get_error_code(void);
+
+
+/**
+ * @brief Reset the Gazell error code.
+ *
+ * The error code is reset to NRF_GZLL_ERROR_CODE_NO_ERRROR.
+ */
+void nrf_gzll_reset_error_code(void);
+
+/** @} */
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzll_constants.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzll_constants.h
new file mode 100644
index 0000000..80df7c1
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzll_constants.h
@@ -0,0 +1,188 @@
+/**
+ * Copyright (c) 2011 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/**
+ * @file
+ * @brief Gazell Link Layer constants and default values.
+ *
+ * NOTE! Changing values here has no effect. They are only provided as a reference.
+ */
+
+#ifndef NRF_GZLL_CONSTANTS_H__
+#define NRF_GZLL_CONSTANTS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * @addtogroup gzll_02_api
+ * @{
+ */
+
+
+/*****************************************************************************/
+/** @name Hardware resources used by Gazell */
+/*****************************************************************************/
+#define NRF_GZLL_HIGH_IRQ_PRIORITY 0 ///< Interrupt priority the Gazell timer and the radio
+#define NRF_GZLL_LOW_IRQ_PRIORITY 1 ///< Interrupt priority for Gazell callback functions.
+
+#ifndef USE_SD_HW_RESOURCES
+
+#define NRF_GZLL_SWI_IRQn SWI0_IRQn ///< Software interrupt # used for callback functions.
+#define NRF_GZLL_SWI_IRQ_HANDLER SWI0_IRQHandler ///< Software interrupt handler used for callback functions.
+#define NRF_GZLL_TIMER NRF_TIMER2 ///< Timer to be used as flywheel timer.
+#define NRF_GZLL_TIMER_IRQn TIMER2_IRQn ///< Interrupt # for the timer.
+#define NRF_GZLL_TIMER_IRQ_HANDLER TIMER2_IRQHandler ///< Interrupt handler for the timer.
+
+// In addition, Gazell uses the radio peripheral and radio interrupts.
+
+/*
+ * PPI configuration
+ */
+#define NRF_GZLL_PPI_EEP0 (NRF_PPI->CH0_EEP) ///< Gazell PPI event endpoint 0
+#define NRF_GZLL_PPI_TEP0 (NRF_PPI->CH0_TEP) ///< Gazell PPI task endpoint 0
+#define NRF_GZLL_PPI_EEP1 (NRF_PPI->CH1_EEP) ///< Gazell PPI event endpoint 1
+#define NRF_GZLL_PPI_TEP1 (NRF_PPI->CH1_TEP) ///< Gazell PPI task endpoint 1
+#define NRF_GZLL_PPI_EEP2 (NRF_PPI->CH2_EEP) ///< Gazell PPI event endpoint 2
+#define NRF_GZLL_PPI_TEP2 (NRF_PPI->CH2_TEP) ///< Gazell PPI task endpoint 2
+
+#define NRF_GZLL_PPI_CHEN_MSK_0_AND_1 (0x03) ///< Channel enable/disable mask for PPI endpoint 0 and 1.
+#define NRF_GZLL_PPI_CHEN_MSK_2 (0x04) ///< Channel enable/disable mask for PPI endpoint 2.
+
+#else
+
+#define NRF_GZLL_SWI_IRQn SWI1_IRQn ///< Software interrupt # used for callback functions.
+#define NRF_GZLL_SWI_IRQ_HANDLER SWI1_IRQHandler ///< Software interrupt handler used for callback functions.
+#define NRF_GZLL_TIMER NRF_TIMER0 ///< Timer to be used as flywheel timer.
+#define NRF_GZLL_TIMER_PERPOWER_Msk POWER_PERPOWER_TIMER0_Msk ///< PERPOWER mask for the timer.
+#define NRF_GZLL_TIMER_IRQn TIMER0_IRQn ///< Interrupt # for the timer.
+#define NRF_GZLL_TIMER_IRQ_HANDLER TIMER0_IRQHandler ///< Interrupt handler for the timer.
+
+// In addition, Gazell uses the radio peripheral and radio interrupts.
+
+/*
+ * PPI configuration
+ */
+#define NRF_GZLL_PPI_EEP0 (NRF_PPI->CH8_EEP) ///< Gazell PPI event endpoint 0
+#define NRF_GZLL_PPI_TEP0 (NRF_PPI->CH8_TEP) ///< Gazell PPI task endpoint 0
+#define NRF_GZLL_PPI_EEP1 (NRF_PPI->CH9_EEP) ///< Gazell PPI event endpoint 1
+#define NRF_GZLL_PPI_TEP1 (NRF_PPI->CH9_TEP) ///< Gazell PPI task endpoint 1
+#define NRF_GZLL_PPI_EEP2 (NRF_PPI->CH10_EEP) ///< Gazell PPI event endpoint 2
+#define NRF_GZLL_PPI_TEP2 (NRF_PPI->CH10_TEP) ///< Gazell PPI task endpoint 2
+
+#define NRF_GZLL_PPI_CHEN_MSK_0_AND_1 (0x300) ///< Channel enable/disable mask for PPI endpoint 0 and 1.
+#define NRF_GZLL_PPI_CHEN_MSK_2 (0x400) ///< Channel enable/disable mask for PPI endpoint 2.
+
+#endif
+/** @} */
+
+/*****************************************************************************/
+/** @name Constant pipe and FIFO configuration */
+/*****************************************************************************/
+#define NRF_GZLL_CONST_PIPE_COUNT 8 ///< Number of TX pipes (at least one for each Device-Host pairs).
+#define NRF_GZLL_CONST_FIFO_LENGTH 3 ///< Maximum number of packets allowed in a TX or RX FIFO.
+#define NRF_GZLL_CONST_MAX_TOTAL_PACKETS 6 ///< Maximum number of packets available for reservation at any one time.
+#define NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH 32 ///< Maximum allowed payload length in bytes.
+#define NRF_GZLL_CONST_CALLBACK_QUEUE_LENGTH 10 ///< Maximum number of notifications allowed in the callback queue.
+/** @} */
+
+/*****************************************************************************/
+/** @name Default radio configuration */
+/*****************************************************************************/
+#define NRF_GZLL_DEFAULT_TX_POWER NRF_GZLL_TX_POWER_0_DBM ///< Default TX power.
+#define NRF_GZLL_DEFAULT_DATARATE NRF_GZLL_DATARATE_2MBIT ///< Default data rate.
+
+#define NRF_GZLL_DEFAULT_CHANNEL_TABLE {4, 25, 42, 63, 77} ///< Default channel table.
+#define NRF_GZLL_DEFAULT_CHANNEL_TABLE_SIZE 5 ///< Default channel table size.
+#define NRF_GZLL_CONST_MAX_CHANNEL_TABLE_SIZE 16 ///< Maximum channel table size allowed by Gazell.
+/** @} */
+
+/*****************************************************************************/
+/** @name Default Address configuration */
+/*****************************************************************************/
+
+/*
+Corresponds to Legacy nRFgo SDK Gazell config:
+#define GZLL_DEFAULT_ADDRESS_PIPE0 {0x01, 0x04, 0x07, 0x0A, 0x0D}
+#define GZLL_DEFAULT_ADDRESS_PIPE1 {0x02, 0x05, 0x08, 0x0B, 0x0E}
+#define GZLL_DEFAULT_ADDRESS_PIPE2 3
+#define GZLL_DEFAULT_ADDRESS_PIPE3 4
+#define GZLL_DEFAULT_ADDRESS_PIPE4 5
+#define GZLL_DEFAULT_ADDRESS_PIPE5 6
+*/
+
+#define NRF_GZLL_DEFAULT_FULL_ADDRESS_PIPE0 {0x01, 0x04, 0x07, 0x0A, 0x0D} ///< Corresponding legacy Gazell pipe 0 address.
+#define NRF_GZLL_DEFAULT_BASE_ADDRESS_0 0x0D0A0704 ///< Default base address 0.
+#define NRF_GZLL_DEFAULT_BASE_ADDRESS_1 0x0E0B0805 ///< Default base address 1.
+#define NRF_GZLL_DEFAULT_PREFIX_BYTE_0 1 ///< Default prefix address pipe 0.
+#define NRF_GZLL_DEFAULT_PREFIX_BYTE_1 2 ///< Default prefix address pipe 1.
+#define NRF_GZLL_DEFAULT_PREFIX_BYTE_2 3 ///< Default prefix address pipe 2.
+#define NRF_GZLL_DEFAULT_PREFIX_BYTE_3 4 ///< Default prefix address pipe 3.
+#define NRF_GZLL_DEFAULT_PREFIX_BYTE_4 5 ///< Default prefix address pipe 4.
+#define NRF_GZLL_DEFAULT_PREFIX_BYTE_5 6 ///< Default prefix address pipe 5.
+#define NRF_GZLL_DEFAULT_PREFIX_BYTE_6 7 ///< Default prefix address pipe 6.
+#define NRF_GZLL_DEFAULT_PREFIX_BYTE_7 8 ///< Default prefix address pipe 7.
+#define NRF_GZLL_DEFAULT_BASE_ADDRESS_LENGTH NRF_GZLL_BASE_ADDRESS_LENGTH_4B ///< Default on-air base address length.
+#define NRF_GZLL_DEFAULT_RX_PIPES_ENABLED 0x000000FF ///< Enabled Rx pipes. See nrf_gzll_set_rx_pipes_enabled().
+/** @} */
+
+/*****************************************************************************/
+/** @name Default timeslot and synchronization configuration */
+/*****************************************************************************/
+#define NRF_GZLL_DEFAULT_TIMESLOT_PERIOD 600 ///< Default timeslot period.
+#define NRF_GZLL_DEFAULT_TIMESLOTS_PER_CHANNEL 2 ///< Timeslots use by the Host and by the Device when communication is in sync.
+#define NRF_GZLL_DEFAULT_DEVICE_CHANNEL_SELECTION_POLICY NRF_GZLL_DEVICE_CHANNEL_SELECTION_POLICY_USE_SUCCESSFUL ///< Default channel Gazell Device channel selection policy
+#define NRF_GZLL_DEFAULT_MAX_TX_ATTEMPTS 0 ///< Default maximum TX attempts for each packet. A value of zero implies the infinite number of TX attempts.
+#define NRF_GZLL_DEFAULT_XOSC_CTL NRF_GZLL_XOSC_CTL_AUTO ///< Deafult setting for controlling the XOSC
+#define NRF_GZLL_DEFAULT_TIMESLOTS_PER_CHANNEL_WHEN_DEVICE_OUT_OF_SYNC 15 ///< Timeslots use by the Device before communication is in sync.
+#define NRF_GZLL_DEFAULT_SYNC_LIFETIME (3 * NRF_GZLL_DEFAULT_CHANNEL_TABLE_SIZE * NRF_GZLL_DEFAULT_TIMESLOTS_PER_CHANNEL) ///< Number of timeslots to keep the timer running so that communication remains synchronized.
+/** @} */
+
+#define NRF_GZLL_PA_LNA_MAX_RAMP_UP_TIME 129 ///< Max external front end ramp up time [us].
+#define NRF_GZLL_PA_LNA_PPI_CHANNELS_NUM 4 ///< Number of PPI channels used for front end control.
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzll_error.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzll_error.h
new file mode 100644
index 0000000..6806a1b
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzll_error.h
@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/**
+ * @file
+ * @brief Gazell error API.
+ */
+
+#ifndef NRF_GZLL_ERROR_H__
+#define NRF_GZLL_ERROR_H__
+
+#include "sdk_errors.h"
+#include "nrf_gzll.h"
+#include "app_error.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GAZELLE_ERROR_CODE_CHECK(GZLL_RESULT) \
+ do \
+ { \
+ if ((GZLL_RESULT) == false) \
+ { \
+ nrf_gzll_error_code_t gzll_error_code = nrf_gzll_get_error_code(); \
+ ret_code_t error_code = gzll_error_code + NRF_ERROR_GAZELLE_ERR_BASE; \
+ APP_ERROR_HANDLER(error_code); \
+ } \
+ } while (0)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzll_resources.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzll_resources.h
new file mode 100644
index 0000000..f419b6a
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzll_resources.h
@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef NRF_GZLL_RESOURCES_H__
+#define NRF_GZLL_RESOURCES_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef GAZELL_ALTERNATIVE_RESOURCES
+ #define GZLL_PPI_CHANNELS_USED 0x00000007uL /**< PPI channels utilized by Gazell (not available to th spplication). */
+ #define GZLL_TIMERS_USED 0x00000004uL /**< Timers used by Gazell. */
+ #define GZLL_SWI_USED 0x00000001uL /**< Software interrupts used by Gazell */
+#else
+ #define GZLL_PPI_CHANNELS_USED 0x00000700uL /**< PPI channels utilized by Gazell (not available to th spplication). */
+ #define GZLL_TIMERS_USED 0x00000001uL /**< Timers used by Gazell. */
+ #define GZLL_SWI_USED 0x00000002uL /**< Software interrupts used by Gazell */
+#endif
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NRF_GZLL_RESOURCES_H__ */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp.c
new file mode 100644
index 0000000..07e0488
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp.c
@@ -0,0 +1,363 @@
+/**
+ * Copyright (c) 2009 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/**
+ * @file
+ * @brief Implementation of Gazell Pairing Library (gzp), Common functions.
+ * @defgroup gzp_source_common Gazell Pairing common functions implementation
+ * @{
+ * @ingroup gzp_04_source
+ */
+
+
+#include "nrf_gzp.h"
+#include "nrf_gzll.h"
+#include "nrf_ecb.h"
+#include <string.h>
+
+
+#define SOURCE_FILE NRF_SOURCE_FILE_GZP ///< File identifer for asserts.
+
+
+/******************************************************************************/
+/** @name Global variables
+ * @{ */
+/******************************************************************************/
+
+/**
+ * Constant holding base address part of the pairing address.
+ */
+static const uint8_t pairing_base_address[4] = { GZP_ADDRESS };
+
+/**
+ * Constant holding prefix byte of the pairing address.
+ */
+static const uint8_t pairing_address_prefix_byte = 0;
+
+/**
+ * Constant holding pre-defined "validation ID".
+ */
+static const uint8_t gzp_validation_id[GZP_VALIDATION_ID_LENGTH] = GZP_VALIDATION_ID;
+
+/**
+ * Constant holding pre-defined "secret key".
+ */
+static const uint8_t gzp_secret_key[16] = GZP_SECRET_KEY;
+
+/**
+ * Variable used for AES key selection
+ */
+static gzp_key_select_t gzp_key_select;
+
+
+/** @} */
+
+
+/******************************************************************************/
+/** @name Misc. external variables.
+ * @{ */
+/******************************************************************************/
+static uint8_t gzp_session_token[GZP_SESSION_TOKEN_LENGTH];
+static uint8_t gzp_dyn_key[GZP_DYN_KEY_LENGTH];
+
+/** @} */
+
+/******************************************************************************/
+/** @name Implementation common internal GZP functions
+ * @{ */
+/******************************************************************************/
+bool gzp_update_radio_params(const uint8_t* system_address)
+{
+ uint8_t i;
+ uint8_t channels[NRF_GZLL_CONST_MAX_CHANNEL_TABLE_SIZE];
+ uint32_t channel_table_size;
+ uint32_t pairing_base_address_32, system_address_32;
+ bool update_ok = true;
+ bool gzll_enabled_state;
+
+ gzll_enabled_state = nrf_gzll_is_enabled();
+
+ // Configure "global" pairing address
+ pairing_base_address_32 = (pairing_base_address[0]) +
+ ((uint32_t)pairing_base_address[1] << 8) +
+ ((uint32_t)pairing_base_address[2] << 16) +
+ ((uint32_t)pairing_base_address[3] << 24) ;
+ if (system_address != NULL)
+ {
+ system_address_32 = (system_address[0]) +
+ ((uint32_t)system_address[1] << 8) +
+ ((uint32_t)system_address[2] << 16) +
+ ((uint32_t)system_address[3] << 24) ;
+ }
+ else
+ {
+ return false;
+ }
+
+ nrf_gzp_disable_gzll();
+ update_ok = update_ok && nrf_gzll_set_base_address_0(pairing_base_address_32);
+ update_ok = update_ok && nrf_gzll_set_address_prefix_byte(GZP_PAIRING_PIPE, pairing_address_prefix_byte);
+ update_ok = update_ok && nrf_gzll_set_base_address_1(system_address_32);
+
+ // Configure address for pipe 1 - 5. Address byte set to equal pipe number.
+ for (i = 1; i < NRF_GZLL_CONST_PIPE_COUNT; i++)
+ {
+ update_ok = update_ok && nrf_gzll_set_address_prefix_byte(i,i);
+ }
+
+ channel_table_size = nrf_gzll_get_channel_table_size();
+ gzp_generate_channels(&channels[0], system_address, channel_table_size);
+
+ // Write generated channel subset to Gazell Link Layer
+ update_ok = update_ok && nrf_gzll_set_channel_table(&channels[0], channel_table_size);
+ if (gzll_enabled_state)
+ {
+ update_ok = update_ok && nrf_gzll_enable();
+ }
+ return update_ok;
+}
+
+void gzp_generate_channels(uint8_t* ch_dst, const uint8_t* system_address, uint8_t channel_tab_size)
+{
+ uint8_t binsize, spacing, i;
+
+ binsize = (GZP_CHANNEL_MAX - GZP_CHANNEL_MIN) / channel_tab_size;
+
+ ch_dst[0] = GZP_CHANNEL_LOW;
+ ch_dst[channel_tab_size - 1] = GZP_CHANNEL_HIGH;
+
+ if (system_address != NULL)
+ {
+ for (i = 1; i < (channel_tab_size - 1); i++)
+ {
+ ch_dst[i] = (binsize * i) + (system_address[i % 4] % binsize);
+ }
+ }
+
+ // If channels are too close, shift them to better positions
+ for (i = 1; i < channel_tab_size; i++)
+ {
+ spacing = (ch_dst[i] - ch_dst[i - 1]);
+ if (spacing < GZP_CHANNEL_SPACING_MIN)
+ {
+ ch_dst[i] += (GZP_CHANNEL_SPACING_MIN - spacing);
+ }
+ }
+}
+
+__INLINE void nrf_gzp_disable_gzll(void)
+{
+ if (nrf_gzll_is_enabled())
+ {
+ nrf_gzll_disable();
+ __WFI();
+ while (nrf_gzll_is_enabled())
+ {
+ }
+ }
+}
+
+#ifndef GZP_CRYPT_DISABLE
+
+void gzp_xor_cipher(uint8_t* dst, const uint8_t* src, const uint8_t* pad, uint8_t length)
+{
+ uint8_t i;
+
+ for (i = 0; i < length; i++)
+ {
+ *dst = *src ^ *pad;
+ dst++;
+ src++;
+ pad++;
+ }
+}
+
+bool gzp_validate_id(const uint8_t* id)
+{
+ return (memcmp(id, (void*)gzp_validation_id, GZP_VALIDATION_ID_LENGTH) == 0);
+}
+
+void gzp_add_validation_id(uint8_t* dst)
+{
+ memcpy(dst, (void const*)gzp_validation_id, GZP_VALIDATION_ID_LENGTH);
+}
+
+void gzp_crypt_set_session_token(const uint8_t * token)
+{
+ memcpy(gzp_session_token, (void const*)token, GZP_SESSION_TOKEN_LENGTH);
+}
+
+void gzp_crypt_set_dyn_key(const uint8_t* key)
+{
+ memcpy(gzp_dyn_key, (void const*)key, GZP_DYN_KEY_LENGTH);
+}
+
+void gzp_crypt_get_session_token(uint8_t * dst_token)
+{
+ memcpy(dst_token, (void const*)gzp_session_token, GZP_SESSION_TOKEN_LENGTH);
+}
+
+void gzp_crypt_get_dyn_key(uint8_t* dst_key)
+{
+ memcpy(dst_key, (void const*)gzp_dyn_key, GZP_DYN_KEY_LENGTH);
+}
+
+void gzp_crypt_select_key(gzp_key_select_t key_select)
+{
+ gzp_key_select = key_select;
+}
+
+void gzp_crypt(uint8_t* dst, const uint8_t* src, uint8_t length)
+{
+ uint8_t i;
+ uint8_t key[16];
+ uint8_t iv[16];
+
+ // Build AES key based on "gzp_key_select"
+
+ switch (gzp_key_select)
+ {
+ case GZP_ID_EXCHANGE:
+ memcpy(key, (void const*)gzp_secret_key, 16);
+ break;
+ case GZP_KEY_EXCHANGE:
+ memcpy(key, (void const*)gzp_secret_key, 16);
+ gzp_get_host_id(key);
+ break;
+ case GZP_DATA_EXCHANGE:
+ memcpy(key, (void const*)gzp_secret_key, 16);
+ memcpy(key, (void const*)gzp_dyn_key, GZP_DYN_KEY_LENGTH);
+ break;
+ default:
+ return;
+ }
+
+ // Build init vector from "gzp_session_token"
+ for (i = 0; i < 16; i++)
+ {
+ if (i < GZP_SESSION_TOKEN_LENGTH)
+ {
+ iv[i] = gzp_session_token[i];
+ }
+ else
+ {
+ iv[i] = 0;
+ }
+ }
+
+ // Set up hal_aes using new key and init vector
+ (void)nrf_ecb_init();
+ nrf_ecb_set_key(key);
+ //hal_aes_setup(false, ECB, key, NULL); // Note, here we skip the IV as we use ECB mode
+
+ // Encrypt IV using ECB mode
+ (void)nrf_ecb_crypt(iv, iv);
+
+ // Encrypt data by XOR'ing with AES output
+ gzp_xor_cipher(dst, src, iv, length);
+
+}
+
+void gzp_random_numbers_generate(uint8_t * dst, uint8_t n)
+{
+ uint8_t i;
+
+ NRF_RNG->EVENTS_VALRDY=0;
+ NRF_RNG->TASKS_START = 1;
+ for (i = 0; i < n; i++)
+ {
+ while (NRF_RNG->EVENTS_VALRDY==0)
+ {}
+ dst[i] = (uint8_t)NRF_RNG->VALUE;
+ NRF_RNG->EVENTS_VALRDY=0;
+ }
+ NRF_RNG->TASKS_STOP = 1;
+}
+
+
+/******************************************************************************/
+/** @name Implementation of nRF51 specific GZP functions
+ * @{ */
+/******************************************************************************/
+
+/**
+* @brief Function for setting the Primask variable. Only necessary if ARMCC
+* compiler skips __set_PRIMASK at high optimization levels.
+*
+* @param primask The primask value. 1 to disable interrupts, 0 otherwise.
+*/
+static void nrf_gzp_set_primask(uint32_t primask)
+{
+ #if defined(__CC_ARM)
+ //lint -save -e10 -e618 -e438 -e550 -e526 -e628 -e526
+ volatile register uint32_t __regPriMask __ASM("primask");
+ __regPriMask = (primask);
+ #else
+ __set_PRIMASK(primask);
+ #endif
+ //lint -restore
+}
+
+void nrf_gzp_flush_rx_fifo(uint32_t pipe)
+{
+ static uint8_t dummy_packet[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH];
+ uint32_t length;
+
+ nrf_gzp_set_primask(1);
+ while (nrf_gzll_get_rx_fifo_packet_count(pipe) >0)
+ {
+ length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH;
+ (void)nrf_gzll_fetch_packet_from_rx_fifo(pipe,dummy_packet,&length);
+ }
+ nrf_gzp_set_primask(0);
+}
+/** @} */
+
+
+
+/******************************************************************************/
+/** @name Implementation of debug functions
+ * @{ */
+/******************************************************************************/
+
+
+/** @} */
+
+/** @} */
+#endif
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp.h
new file mode 100644
index 0000000..336151f
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp.h
@@ -0,0 +1,665 @@
+/**
+ * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/**
+ * @file
+ * @brief Gazell Pairing API
+ */
+
+#ifndef __GZP_H
+#define __GZP_H
+
+#include "nrf.h"
+#include "nrf_gzp_config.h"
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+* @defgroup gzp_02_api Gazell Pairing
+* @{
+* @ingroup modules_02_gzp
+* @brief Gazell Pairing Application Programming Interface (API).
+*/
+
+
+/******************************************************************************/
+/** @name Pairing configuration defines
+ * @{ */
+/******************************************************************************/
+
+
+#define GZP_PAIRING_PIPE 0 ///< Pipe reserved for initial pairing communication.
+#define GZP_DATA_PIPE 1 ///< Pipe reserved for GZP encrypted data communication (one pipe only).
+#define GZP_TX_RX_TRANS_DELAY 10 ///< Time to wait between request and fetch packets in RX_PERIODS (2 timeslot periods)
+#define GZP_SYSTEM_ADDRESS_WIDTH 4 ///< Must equal Gazell base address length.
+
+
+#define GZP_VALIDATION_ID {0x32, 0x53, 0x66} ///< Validation ID. Required to be shared by Host and Device. Not a secret.
+#define GZP_VALIDATION_ID_LENGTH 3 ///< Validation ID length in bytes.
+#define GZP_HOST_ID_LENGTH 5 ///< Host ID length in bytes.
+#define GZP_SESSION_TOKEN_LENGTH GZP_HOST_ID_LENGTH ///< Session token length in bytes.
+#define GZP_DYN_KEY_LENGTH (16 - GZP_VALIDATION_ID_LENGTH) ///< Dynamic key length in bytes.
+
+#define GZP_HOST_RX_POWER_THRESHOLD -64 ///< RSSI threshold for when signal strength in RX packet power is high enough.
+
+/** @} */
+
+
+/******************************************************************************/
+/** @name Device -> Host packet definitions
+ * @{ */
+/******************************************************************************/
+
+#define GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH 1 ///< "Host address request" packet, payload length
+
+#define GZP_CMD_HOST_ADDRESS_FETCH_PAYLOAD_LENGTH 1 ///< "Host address fetch" packet, payload length
+
+#define GZP_CMD_HOST_ID_REQ_SESSION_TOKEN 1 ///< "Host ID request" packet, session token position
+#define GZP_CMD_HOST_ID_REQ_PAYLOAD_LENGTH (GZP_CMD_HOST_ID_REQ_SESSION_TOKEN + GZP_SESSION_TOKEN_LENGTH) ///< "Host ID request" payload length
+
+#if (GZP_CMD_HOST_ID_REQ_PAYLOAD_LENGTH > 17)
+#error GZP_SESSION_TOKEN_LENGTH too long.
+#endif
+
+
+#define GZP_CMD_HOST_ID_FETCH_VALIDATION_ID 1 ///< "Host ID fetch" packet
+#define GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH (GZP_CMD_HOST_ID_FETCH_VALIDATION_ID + GZP_VALIDATION_ID_LENGTH) ///< "Host ID fetch" payload length
+
+#if (GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH > 17)
+#error GZP_VALIDATION_ID_LENGTH set too long.
+#endif
+
+#define GZP_CMD_KEY_UPDATE_PREPARE_PAYLOAD_LENGTH 1 ///< "Key update prepare" payload length
+
+#define GZP_CMD_KEY_UPDATE_VALIDATION_ID 1 ///< "Key update" packet, validation ID position
+#define GZP_CMD_KEY_UPDATE_NEW_KEY (GZP_CMD_KEY_UPDATE_VALIDATION_ID + GZP_VALIDATION_ID_LENGTH) ///< "Key update" packet, new key position
+#define GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH (GZP_CMD_KEY_UPDATE_NEW_KEY + GZP_DYN_KEY_LENGTH) ///< "Key update" packet, payload length
+
+#if (GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH > 17)
+#error Sum (GZP_VALIDATION_ID_LENGTH + GZP_DYN_KEY_LENGTH) too high.
+#endif
+
+
+#define GZP_CMD_ENCRYPTED_USER_DATA_VALIDATION_ID 1 ///< "Encrypted user data" packet, validation ID position
+#define GZP_CMD_ENCRYPTED_USER_DATA_PAYLOAD ((GZP_CMD_ENCRYPTED_USER_DATA_VALIDATION_ID + GZP_VALIDATION_ID_LENGTH)) ///< "Encrypted user data" packet, user data position
+#define GZP_ENCRYPTED_USER_DATA_PACKET_OVERHEAD ( GZP_CMD_ENCRYPTED_USER_DATA_VALIDATION_ID + GZP_VALIDATION_ID_LENGTH) ///< "Encrypted user data" packet, packet overhead length
+#define GZP_ENCRYPTED_USER_DATA_MAX_LENGTH (17 - GZP_ENCRYPTED_USER_DATA_PACKET_OVERHEAD) ///< "Encrypted user data" packet, max payload length
+
+#if (GZP_MAX_FW_PAYLOAD_LENGTH < 17)
+ #error GZP_MAX_FW_PAYLOAD_LENGTH must be greater or equal to 17.
+#endif
+
+#define GZP_CMD_FETCH_RESP_PAYLOAD_LENGTH 1 ///< General "fetch response" packet, payload_length
+
+/** @} */
+
+
+/******************************************************************************/
+/** @name Host -> Device packet definitions
+ * @{ */
+/******************************************************************************/
+
+
+#define GZP_CMD_HOST_ADDRESS_RESP_ADDRESS 1 ///< "Host address fetch" response packet, address position
+#define GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH (GZP_CMD_HOST_ADDRESS_RESP_ADDRESS + GZP_SYSTEM_ADDRESS_WIDTH) ///< ///< "Host address fetch" response packet, payload length
+
+#if (GZP_MAX_ACK_PAYLOAD_LENGTH < GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH)
+ #error GZP_MAX_ACK_PAYLOAD_LENGTH must be greater or equal to GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH.
+#endif
+
+
+#define GZP_CMD_HOST_ID_FETCH_RESP_VALIDATION_ID 1 ///< "Host ID fetch" response packet, validation ID position
+#define GZP_CMD_HOST_ID_FETCH_RESP_STATUS (GZP_CMD_HOST_ID_FETCH_RESP_VALIDATION_ID + GZP_VALIDATION_ID_LENGTH) ///< "Host ID fetch" response packet, status position
+#define GZP_CMD_HOST_ID_FETCH_RESP_HOST_ID (GZP_CMD_HOST_ID_FETCH_RESP_STATUS + 1) ///< "Host ID fetch" response packet, Host ID position
+#define GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH (GZP_CMD_HOST_ID_FETCH_RESP_HOST_ID + GZP_HOST_ID_LENGTH) ///< "Host ID fetch" response packet, payload length
+
+#if (GZP_MAX_ACK_PAYLOAD_LENGTH < GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH)
+ #error GZP_MAX_ACK_PAYLOAD_LENGTH must be greater or equal to GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH.
+#endif
+
+
+#define GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN 1 ///< "Key update prepare" response packet, session token position
+#define GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH (GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN + GZP_SESSION_TOKEN_LENGTH) ///< "Key update prepare" response packet, payload length position
+
+#if (GZP_MAX_ACK_PAYLOAD_LENGTH < GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH)
+ #error GZP_MAX_ACK_PAYLOAD_LENGTH must be greater or equal to GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH.
+#endif
+
+
+#define GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN 1 ///< "Encrypted user data" response packet, session token position
+#define GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID (GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN + GZP_SESSION_TOKEN_LENGTH) ///< "Encrypted user data" response packet, validation ID position
+#define GZP_CMD_ENCRYPTED_USER_DATA_RESP_PAYLOAD_LENGTH (GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID + GZP_VALIDATION_ID_LENGTH) ///< "Encrypted user data" response packet, payload length position
+
+#if (GZP_MAX_ACK_PAYLOAD_LENGTH < GZP_CMD_ENCRYPTED_USER_DATA_RESP_PAYLOAD_LENGTH)
+ #error GZP_MAX_ACK_PAYLOAD_LENGTH must be greater or equal to GZP_CMD_ENCRYPTED_USER_DATA_RESP_PAYLOAD_LENGTH.
+#endif
+
+#if (GZP_VALIDATION_ID_LENGTH > GZP_HOST_ID_LENGTH)
+ #error GZP_HOST_ID_LENGTH should be greater or equal to GZP_VALIDATION_ID_LENGTH.
+#endif
+
+#if (GZP_SESSION_TOKEN_LENGTH != GZP_HOST_ID_LENGTH)
+ #error GZP_SESSION_TOKEN_LENGTH must equal GZP_HOST_ID_LENGTH.
+#endif
+
+#ifdef GZLL_CRYPT_ENABLE
+ #error Gazell encryption can not be enabled when using the Gazell pairing library. \
+ GZLL_CRYPT_ENABLE must be undefined.
+#endif
+
+/** @} */
+
+
+/******************************************************************************/
+/** @name Typedefs
+ * @{ */
+/******************************************************************************/
+
+
+/**
+ * @enum gzp_key_select_t
+ * @brief Enumerator used for selecting the key to be used for encryption.
+ */
+typedef enum
+{
+ GZP_ID_EXCHANGE, ///< "Secret key" only
+ GZP_KEY_EXCHANGE, ///< "Secret key" and "Host ID"
+ GZP_DATA_EXCHANGE ///< "Dynamic key" and "Host ID"
+} gzp_key_select_t;
+
+
+/**
+ * @enum gzp_cmd_t
+ * @brief Enumerator used in the first payload byte of each packet to
+ * indicate the packet type.
+ */
+typedef enum
+{
+ GZP_CMD_HOST_ADDRESS_REQ = 0, ///< Host address request
+ GZP_CMD_HOST_ADDRESS_FETCH, ///< Host address fetch
+ GZP_CMD_HOST_ID_REQ, ///< Host ID request
+ GZP_CMD_HOST_ID_FETCH, ///< Host ID fetch request
+ GZP_CMD_KEY_UPDATE_PREPARE, ///< Key update prepare
+ GZP_CMD_KEY_UPDATE, ///< Key update
+ GZP_CMD_ENCRYPTED_USER_DATA, ///< Encrypted user data
+ GZP_CMD_FETCH_RESP, ///< Fetch response
+ GZP_CMD_HOST_ADDRESS_RESP, ///< Host address response
+ GZP_CMD_HOST_ID_FETCH_RESP, ///< Host ID fetch response
+ GZP_CMD_KEY_UPDATE_PREPARE_RESP, ///< Key update prepare
+ GZP_CMD_ENCRYPTED_USER_DATA_RESP, ///< Encrypted user data response
+} gzp_cmd_t;
+
+
+/**
+ * @enum gzp_id_req_res_t
+ * @brief Enumerator used to identify the state of the current
+ * Host ID request.
+ */
+typedef enum
+{
+ GZP_ID_RESP_PENDING, ///< ID response pending
+ GZP_ID_RESP_GRANTED, ///< ID response granted
+ GZP_ID_RESP_REJECTED, ///< ID response rejected
+ GZP_ID_RESP_FAILED, ///< ID response failed
+ GZP_ID_RESP_NO_REQUEST ///< Default value. No ID request has yet been received.
+} gzp_id_req_res_t;
+
+
+/** @} */
+
+
+/******************************************************************************/
+/** @name Misc. function prototypes
+ * @{ */
+/******************************************************************************/
+
+/**
+ * Set the session token.
+ *
+ * @param token Pointer to the session token to set.
+ */
+void gzp_crypt_set_session_token(const uint8_t *token);
+
+
+/**
+ * Get the session token.
+ *
+ * @param dst_token Pointer to write the session token.
+ */
+void gzp_crypt_get_session_token(uint8_t *dst_token);
+
+
+/**
+ * Set the dynamic key.
+ *
+ * @param dyn_key Pointer to the dynamic key to set.
+ */
+void gzp_crypt_set_dyn_key(const uint8_t* dyn_key);
+
+
+/**
+ * Get the dynamic key.
+ *
+ * @param dst_key Pointer to write the dynamic key too.
+ */
+void gzp_crypt_get_dyn_key(uint8_t *dst_key);
+
+
+/**
+ * Set the Host ID.
+ *
+ * @param src Pointer to the Host ID to set.
+ */
+static void gzp_set_host_id(const uint8_t* src);
+
+
+/**
+ * Get the Host ID.
+ *
+ * @param dst Pointer to write the Host ID to.
+ */
+void gzp_get_host_id(uint8_t *dst);
+
+
+/**
+ * Selecting what key-set that should be used when encrypting data
+ * using gzp_crypt().
+ *
+ * @param key_select Key-set to use.
+ */
+void gzp_crypt_select_key(gzp_key_select_t key_select);
+
+
+/**
+ * Encypt / decrypt data.
+ *
+ * The current "session token" will be used as initialization vector (IV).
+ * The AES key to be used is selected by gzp_crypt_select_key().
+ * AES is a symmetric encryption scheme, this function can be used
+ * to perform both encryption and decryption.
+ *
+ * @param dst Destination to write encrypted data to. Should be 16 bytes long.
+ * @param src Source data to encrypt.
+ * @param length Length in bytes of src.
+ */
+void gzp_crypt(uint8_t* dst, const uint8_t* src, uint8_t length);
+
+
+/**
+ * Compare the *src_id with a pre-defined validation ID.
+ *
+ * @param src_id Pointer to the source validation ID to compare to.
+ *
+ * @retval true If *src_id equals the pre-defined ID.
+ * @retval false If *src_id does not equal the pre-defined ID.
+ */
+bool gzp_validate_id(const uint8_t *src_id);
+
+
+/**
+ * Add the pre-defined validation ID to dst_id.
+ * GZP_VALIDATION_ID_LENGTH bytes will be added.
+ *
+ * @param dst_id Pointer to add the GZP validation ID to.
+ */
+void gzp_add_validation_id(uint8_t *dst_id);
+
+
+/**
+ * Generate random bytes.
+ *
+ * @param dst Destination to write the random bytes to.
+ * @param n Number of bytes to generate.
+ */
+void gzp_random_numbers_generate(uint8_t *dst, uint8_t n);
+
+
+/**
+ * Update the channel table and the system address.
+ *
+ * The channel table is updated to pseudo-random set generated using the
+ * system address. The channel table still includes GZP_CHANNEL_MAX and
+ * GZP_CHANNEL_MIN.
+ * The system address is applied to base address 1 and therefore applies
+ * to pipes 1-7.
+ *
+ * @param system_address Pointer to the system_address to set.
+ *
+ * @retval true If theradio parameters were updated successfully.
+ * @retval false If there was an error updated the radio parameters.
+ */
+bool gzp_update_radio_params(const uint8_t *system_address);
+
+
+/**
+ * Generate a set of channels from a 4 byte address.
+ *
+ * @param ch_dst Destination to write the channel set to. The channel set
+ * includes GZP_CHANNEL_MAX and GZP_CHANNEL_MIN.
+ * @param address Four byte address to generate the channel set from.
+ * @param channel_set_size Size of the channel set to generate.
+ */
+void gzp_generate_channels(uint8_t *ch_dst, const uint8_t * address, uint8_t channel_set_size);
+
+
+/**
+ * Perform an XOR on two byte strings.
+ *
+ * @param dst Destination to write the result to. Should be of size length.
+ * @param src
+ * @param pad
+ * @param length Number of bytes to perform the XOR operation on.
+ */
+void gzp_xor_cipher(uint8_t* dst, const uint8_t* src, const uint8_t* pad, uint8_t length);
+
+
+/******************************************************************************/
+/** @name Common Device and Host functions
+ * @{ */
+/******************************************************************************/
+
+
+/**
+ * Initialization function. This function initializes the Gazell Pairing Library.
+
+ * This function must be called before any of the other Gazell Pairing Library functions are
+ * used and must be called @b after gzll_init() is called.
+ *
+ */
+void gzp_init(void);
+
+/**
+ * Function for erasing all pairing data.
+ */
+void gzp_erase_pairing_data(void);
+
+/**
+ * Disable Gazell and sleep while waiting for nrf_gzll_disabled callback.
+ */
+void nrf_gzp_disable_gzll(void);
+
+/**
+ Function for cancelling an ongoing (pending) "Host ID request".
+
+ After calling this function the "Host ID request" status will go to
+ "ID request Idle".
+*/
+void gzp_id_req_cancel(void);
+
+/**
+ * Flush the GZLL RX FIFO for a specific pipe while GZLL is disabled.
+ *
+ * @param pipe Pipe.
+ */
+void nrf_gzp_flush_rx_fifo(uint32_t pipe);
+
+/**
+@name Device functions
+*/
+
+/**
+ * Check whether current GZP packet transaction has completed.
+ *
+ * @retval true
+ * @retval false
+ */
+bool nrf_gzp_tx_complete(void);
+
+/**
+ * Check whether previous GZP packet transaction was successful.
+ *
+ * @retval true
+ * @retval false
+ */
+bool nrf_gzp_tx_success(void);
+
+/**
+ * Reset tx_complete status.
+ */
+void nrf_gzp_reset_tx_complete(void);
+
+/**
+ * Reset tx_success status.
+ */
+void nrf_gzp_reset_tx_success(void);
+
+/**
+* Function to check whether a Device has existing pairing data, implying that it is
+* paired to a Host.
+*
+* @retval -2 The pairing database is empty.
+* @retval -1 The device has a system address but no Host ID.
+* @retval >=0 The device has a system address and HostID at this index value in the database.
+*/
+int8_t gzp_get_pairing_status(void);
+
+/**
+ Function for sending a "system address" request to a Host.
+
+ When calling this function the Device will attempt acquiring the "system address" from
+ any Host within close proximity.
+
+ If a host is located within close proximity and pairing is enabled in the Host,
+ a "system address" will be sent in return to the Device.
+
+ The new "system address" will apply immediately in the Device, and the new "system address"
+ will be stored in non volatile (NV) memory.
+
+ Note. Using OTP devices limits the number of times a new "system address" can
+ be stored in NV memory.
+
+ @return
+
+ @retval true if new "system address" was received from a Host.
+ @retval false if no "system address" was received from a Host.
+*/
+bool gzp_address_req_send(void);
+
+/**
+ Function for sending a "Host ID request" to a Host.
+
+ The "Host ID" is needed to be able to send encrypted data using
+ gzp_crypt_data_send().
+
+ The request will be sent using the "system address" previously received using
+ gzp_address_req_send().
+
+ It is not required that the Host is within close proximity in order to acquire the
+ "Host ID".
+
+ The new "Host ID" will apply immediately for the Device, and the new "Host ID"
+ will be stored in non volatile (NV) memory.
+
+ Note. Using OTP devices limits the number of times a new "Host ID" can
+ be stored in NV memory.
+
+ @return
+
+ @retval GZP_ID_RESP_PENDING if a "Host ID request" has been sent to the Host, but the Host application has
+ not yet decided whether to Grant or Reject the "ID request".
+ @retval GZP_ID_RESP_GRANTED if the "Host ID" has been received from the Host. The received "Host ID" will be stored
+ in non volatile memory.
+ @retval GZP_ID_RESP_REJECTED if the Host application has rejected the "Host ID request".
+ @retval GZP_ID_RESP_FAILED if failing to send a request or receive a response from the Host.
+*/
+gzp_id_req_res_t gzp_id_req_send(void);
+
+/**
+ Function for sending encrypted user data to the Host.
+
+ Before any data can be sent the Device must acquire both the Host's
+ "system address" by using gzp_address_req_send() and the "Host ID" by using
+ gzp_id_req_send().
+
+ @param *src is a pointer to the data packet to be sent.
+ @param length is the length of the data packet to be sent.
+
+
+ @return
+ @retval true if the data was successfully transmitted and decrypted by the Host.
+ @retval false if data transmission failed or Host failed to decryption data correctly.
+*/
+bool gzp_crypt_data_send(const uint8_t *src, uint8_t length);
+
+
+/**
+@name Host functions
+*/
+
+/**
+ Function for enabling/disabling pairing in a host. When pairing is enabled the host will
+ be monitoring for "system address" and "Host ID" requests from Devices.
+
+ A "system address request" received from a Device will always be granted.
+ When a "host ID request" has been received, the Host application have to grant,
+ reject or cancel this by using one of the following functions:
+
+ - gzp_id_req_grant()
+ - gzp_id_req_reject()
+ - gzp_id_req_cancel()
+
+ @param enable
+ @arg true enables pairing.
+ @arg false disables pairing.
+*/
+void gzp_pairing_enable(bool enable);
+
+/**
+ * Execute the Gazell Pairing Library Host operation.
+ *
+ * This function must be called regularly by the Host application.
+ */
+void gzp_host_execute(void);
+
+/**
+ * Address exchanged check.
+ *
+ * @retval true If a "system address" was delivered to a requesting Device during the
+ * previous call to gzp_host_execute();
+ * @retval false Otherwise.
+*/
+bool gzp_address_exchanged(void);
+
+/**
+ Function for checking if a "Host ID request" has been received from a Device.
+
+ If a request has been received, the Pairing library will enter "ID request pending"
+ state.
+
+ The application is responsible for responding to this request by calling
+ one of the following functions:
+
+ - gzp_id_req_grant()
+ - gzp_id_req_reject()
+ - gzp_id_req_cancel()
+
+ @retval true if a "Host ID request" has been received (internal state is "ID request pending")
+ @retval false if no "Host ID request" has been received (internal state is "ID request idle")
+*/
+bool gzp_id_req_received(void);
+
+/**
+ Function for rejecting the previously received "Host ID request". This function should be called
+ only when a "Host ID request" has been received (internal state is "ID request pending").
+
+ The internal state of the Pairing library will remain "ID request pending" until the a "reject" message
+ has been successfully transmitted to the requesting Device. After this the internal state will
+ change to "ID request idle".
+*/
+void gzp_id_req_reject(void);
+
+/**
+ * Function for granting the previously received "Host ID request". This function should be called
+ only when a "Host ID request" has been received (internal state is "ID request pending").
+
+ The internal state of the Pairing library will remain "ID request pending" until the "Host ID" has
+ been successfully transmitted to the requesting Device. After this the internal state will
+ change to "ID request idle".
+*/
+void gzp_id_req_grant(void);
+
+
+/**
+ * Check if user data has been received.
+ *
+ * @retval true If encrypted user data has been received.
+ * @retval false Otherwise.
+*/
+bool gzp_crypt_user_data_received(void);
+
+/**
+ Function for reading encrypted user data.
+
+ Note that the read user data will be automatically decrypted. Only data
+ that was decrypted correctly will be presented.
+
+ @param dst* is a pointer to where the received data will be written.
+ @param length* is a pointer for returning the number of bytes received. Only 1 byte will
+ be writtem to length*.
+
+ @return
+ @retval true if data has been received and is written to dst*
+ @retval false if no data has been received.
+*/
+bool gzp_crypt_user_data_read(uint8_t* dst, uint8_t* length);
+
+
+/**
+ Function emulating behavior of gzll_rx_start() in legeacy nRF24xx Gaell
+ linbrary.
+
+ This functions sets Gazell in Host mode and starts reception (enable).
+*/
+void gzll_rx_start(void);
+
+
+/** @} */
+/** @} */
+/** @} */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp_device.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp_device.c
new file mode 100644
index 0000000..7ee4037
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp_device.c
@@ -0,0 +1,1146 @@
+/**
+ * Copyright (c) 2009 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/**
+ * @file
+ * @brief Implementation of Gazell Pairing Library (gzp), Device functions.
+ * @defgroup gzp_source_device Gazell Pairing Device implementation.
+ * @{
+ * @ingroup gzp_04_source
+ */
+
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "nrf_gzll.h"
+#include "nrf_gzp.h"
+#include "nrf_delay.h"
+#include "nrf_nvmc.h"
+
+#define SOURCE_FILE NRF_SOURCE_FILE_GZP_DEVICE ///< File identifer for asserts.
+
+/******************************************************************************/
+/** @name Misc. defines
+ * @{ */
+/******************************************************************************/
+
+#define GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS 0 ///< System address position.
+#define GZP_PARAMS_DB_ELEMENT_HOST_ID (GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS + GZP_SYSTEM_ADDRESS_WIDTH) ///< Host ID position
+#define GZP_PARAMS_DB_ELEMENT_SIZE (GZP_SYSTEM_ADDRESS_WIDTH + GZP_HOST_ID_LENGTH)///< Total size
+#define GZP_PARAMS_DB_MAX_ENTRIES 14 ///< Maximum allowed entries in the database.
+
+/** @} */
+
+/******************************************************************************/
+/** @name Derived parameters
+ * @{ */
+/******************************************************************************/
+
+//lint -esym(40, GZP_PARAMS_STORAGE_ADR) "Undeclare identifier"
+#define GZP_PARAMS_DB_ADR GZP_PARAMS_STORAGE_ADR ///<
+#define GZP_PARAMS_DB_SIZE (GZP_PARAMS_DB_MAX_ENTRIES * GZP_PARAMS_DB_ELEMENT_SIZE) ///<
+
+#define GZP_INDEX_DB_ADR (GZP_PARAMS_STORAGE_ADR + GZP_PARAMS_DB_SIZE) ///<
+#define GZP_INDEX_DB_SIZE (GZP_DEVICE_PARAMS_STORAGE_SIZE - GZP_PARAMS_DB_SIZE) ///<
+
+#if (GZP_DEVICE_PARAMS_STORAGE_SIZE < GZP_PARAMS_DB_SIZE)
+ #error GZP_DEVICE_PARAMS_STORAGE_SIZE must be greater or equal to GZP_PAIRING_PARAMS_DB_SIZE
+#elif (GZP_DEVICE_PARAMS_STORAGE_SIZE == GZP_PARAMS_DB_SIZE )
+ #warning GZP_DEVICE_PARAMS_STORAGE_SIZE to low to be able store any pairing parameters NV memory
+#endif
+/** @} */
+
+
+/******************************************************************************/
+/** @name Typedefs
+ * @{ */
+/******************************************************************************/
+
+
+/**
+ * Possible return values for the function gzp_tx_rx_transaction()
+ */
+typedef enum
+{
+ GZP_TX_RX_SUCCESS, ///< ACK received. Transaction successful.
+ GZP_TX_RX_FAILED_TO_SEND, ///<
+ GZP_TX_RX_NO_RESPONSE ///<
+} gzp_tx_rx_trans_result_t;
+/** @} */
+
+
+/******************************************************************************/
+/** @name Internal variables
+ * @{ */
+/******************************************************************************/
+
+static uint8_t gzp_system_address[GZP_SYSTEM_ADDRESS_WIDTH]; ///<
+static uint8_t gzp_host_id[GZP_HOST_ID_LENGTH]; ///<
+static uint8_t dyn_key[GZP_DYN_KEY_LENGTH];
+static bool gzp_id_req_pending = false;
+
+/** @} */
+
+
+/******************************************************************************/
+/** @name Internal (static) function prototypes
+ * @{ */
+/******************************************************************************/
+
+/**
+ * Function for sending an encrypted packet.
+ *
+ * The function waits for the transmission to complete.
+ *
+ * @param tx_packet Pointer to the packet to be sent.
+ * @param length Length of the packet to be sent.
+ * @param pipe Pipe on which the packet should be sent.
+ *
+ * @retval true If the transmission succeeded.
+ * @retval false If the transmission failed (timed out).
+ */
+static bool gzp_tx_packet(const uint8_t* tx_packet, uint8_t length, uint8_t pipe);
+
+/**
+ * Function sending the packet *tx_packet and a subsequent packet fetching the response
+ * to *tx_packet.
+ *
+ * @param tx_packet is a pointer to the packet to be sent.
+ * @param tx_length is the length of the packet to be sent.
+ * @param rx_dst is a pointer to where the received response packet should be stored.
+ * @param rx_length is a pointer to where the length of the received packet should be stored.
+ * @param pipe is the pipe on which the packet should be sent.
+ *
+ * @return result of the transaction.
+ */
+ static gzp_tx_rx_trans_result_t gzp_tx_rx_transaction(const uint8_t *tx_packet, uint8_t tx_length, uint8_t *rx_dst, uint32_t *rx_length, uint8_t pipe);
+
+/**
+ * Function for sending an encrypted packet. The function detects whether the correct
+ * key was used, and attempts to send a "key update" to the host if the wrong key was being
+ * used.
+
+ * @param tx_packet is a pointer to the packet to be sent.
+ * @param length is the length of the packet to be sent.
+
+ * @retval true if transmission succeeded and packet was decrypted correctly by host.
+ * @retval false if transmission failed or packet was not decrypted correctly by host.
+ */
+static bool gzp_crypt_tx_transaction(const uint8_t *tx_packet, uint8_t length);
+
+/**
+ * Function updateing the "dynamic key" and sending a "key update" to the host.
+ *
+ * @retval true if key update succeeded.
+ * @retval false if if key update failed.
+ */
+static bool gzp_key_update(void);
+
+/**
+ * Function for adding an element to "parameters data base" in non volatile (NV) memory. An element is
+ * GZP_PARAMS_ELEMENT_SYSTEM_ADDRESS bytes long, holding the "system address" and "host ID".
+ *
+ * The "parameters data base" can store up to GZP_DEVICE_PAIRING_PARAMS_DB_MAX_ENTRIES
+ * elements.
+ *
+ * @param src_element is a pointer to the element.
+ * @param index is a number between 0 and (GZP_PARAMS_DB_MAX_ENTRIES - 1)
+ * selecting the location in which the element will be stored.
+ */
+static void gzp_params_db_add(const uint8_t *src_element, uint8_t index);
+
+/**
+ * Function for reading an element from "parameters data base" in non volatile (NV) memory. An element is
+ * GZP_PARAMS_ELEMENT_SYSTEM_ADDRESS bytes long, holding the "system address" and "host ID".
+ *
+ * @param dst_element is a pointer where the read element should be stored.
+ * @param index is a number between 0 and (GZP_PARAMS_DB_MAX_ENTRIES - 1).
+ * selecting the location that should be read.
+ */
+static void gzp_params_db_read(uint8_t* dst_element, uint8_t index);
+
+/**
+ * Function for writing an index to the "index data base" in non volatile (NV) memory.
+ *
+ * @param index is the index to be written to the data base.
+ */
+static void gzp_index_db_add(uint8_t index);
+
+/**
+ * Function for reading the index previously written to the "index data base" in NV memory.
+ *
+ * @return
+ */
+static uint8_t gzp_index_db_read(void);
+
+/**
+ * Check "index data base" is full.
+ *
+ * @retval true
+ * @retval false
+ */
+static bool gzp_index_db_full(void);
+
+/**
+ * Function returning @b true if the "index data base" is empty.
+ *
+ * @retval true
+ * @retval false
+ */
+static bool gzp_index_db_empty(void);
+
+/**
+ * Function returning @b true if array contains only 1s (0xff).
+ *
+ * @param *src is a pointer to the array to be evaluated.
+ * @param length is the length of the array to be evaluated.
+ *
+ * @retval true
+ * @retval false
+ */
+static bool gzp_array_is_set(const uint8_t* src, uint8_t length);
+
+/**
+ * Function for storing the current "system address" and "host ID" in NV memory.
+ *
+ * @param store_all selects whether only "system address" or both "system address" and
+ * "host ID" should be stored.
+ * @arg true selects that both should be stored.
+ * @arg false selects that only "system address" should be stored.
+ *
+ * @retval true
+ * @retval false
+ */
+static bool gzp_params_store(bool store_all);
+
+/**
+ * Restore the "system address" and "host ID" from NV memory.
+ * @retval true
+ * @retval false
+ */
+static bool gzp_params_restore(void);
+
+/**
+ * Delay function. Will add a delay equal to GZLL_RX_PERIOD * rx_periods [us].
+ *
+ * @param rx_periods
+ */
+void gzp_delay_rx_periods(uint32_t rx_periods);
+
+/**
+ * Delay function. Will add a delay equal to GZLL_RX_PERIOD * rx_periods [us] using the
+ * gazell timer and not a delay loop.
+ *
+ * @param rx_periods
+ */
+void gzp_tick_sleep_rx_periods(uint32_t rx_periods);
+
+/*
+ * Print debug string. By default does nothing.
+ *
+ * If GZP_DEBUG is defined then the print string function is required to
+ * be implemented.
+ */
+void print_string(char* p_expr);
+
+/** @} */
+
+/******************************************************************************/
+/** @name Internal (static) variables
+ * @{ */
+/******************************************************************************/
+
+static nrf_gzll_device_tx_info_t latest_tx_info; ///< Information about the last TX attempt, e.g. RSSI of ACK.
+
+static volatile bool tx_complete; ///< Flag to indicate whether a GZLL TX attempt has completed.
+static bool tx_success; ///< Flag to indicate whether a GZLL TX attempt was successful.
+
+// Define Macro to make array initialization nicer
+#define REP4(X) X X X X
+
+#if defined(__ICCARM__)
+ #if GZP_PARAMS_DB_ADR == 0x1000
+ static const uint32_t database[GZP_DEVICE_PARAMS_STORAGE_SIZE/4] @ "gzp_dev_data"
+ #elif GZP_PARAMS_DB_ADR == 0x15000
+ static const uint32_t database[GZP_DEVICE_PARAMS_STORAGE_SIZE/4] @ "gzp_dev_data_sd"
+ #else
+ #error
+ #endif
+#else
+static const uint32_t database[GZP_DEVICE_PARAMS_STORAGE_SIZE / 4] __attribute__((at(GZP_PARAMS_DB_ADR)))
+#endif
+= {
+ #define STATIC_INIT_VALUE 0xFFFFFFFF
+ #define STATIC_INIT_COUNT (GZP_DEVICE_PARAMS_STORAGE_SIZE / 4)
+ #define INIT_1 STATIC_INIT_VALUE,
+ #define INIT_4 REP4(INIT_1)
+ #define INIT_16 REP4(INIT_4)
+ #define INIT_64 REP4(INIT_16)
+ #define INIT_256 REP4(INIT_64)
+ #define INIT_1024 REP4(INIT_256)
+
+ #if (STATIC_INIT_COUNT == 256)
+ INIT_256
+ #elif (STATIC_INIT_COUNT == 1024)
+ INIT_1024
+ #else
+ #error Gazell Pairing Library database not initialized properly!
+ #endif
+}; ///< Database for storing keys.
+
+
+/** @} */
+
+
+/******************************************************************************/
+// Implementation: Device-specific API functions
+/******************************************************************************/
+
+
+void gzp_init()
+{
+ gzp_id_req_pending = false;
+
+#ifndef GZP_NV_STORAGE_DISABLE
+ (void)gzp_params_restore();
+#endif
+
+ // Update radio parameters from gzp_system_address
+ (void)gzp_update_radio_params(gzp_system_address);
+}
+
+
+void gzp_erase_pairing_data(void)
+{
+ // Erase database flash page so that it can be later written to.
+ nrf_nvmc_page_erase((uint32_t)database);
+}
+
+bool gzp_address_req_send()
+{
+ //lint -save -e514 Unusual use of a Boolean expression (gzll_update_ok &= ...)
+ uint8_t i;
+ bool retval = false;
+ bool success;
+ uint8_t address_req[GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH];
+ uint8_t rx_payload[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH];
+ uint32_t rx_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH;
+ nrf_gzll_tx_power_t temp_power;
+ uint32_t temp_max_tx_attempts;
+ bool gzll_update_ok = true;
+
+
+ // Store parameters that are temporarily changed
+ temp_max_tx_attempts = nrf_gzll_get_max_tx_attempts();
+ temp_power = nrf_gzll_get_tx_power();
+
+ // Modify parameters
+ nrf_gzp_disable_gzll();
+ nrf_gzll_set_max_tx_attempts(GZP_REQ_TX_TIMEOUT);
+ gzll_update_ok &= nrf_gzll_set_tx_power(GZP_POWER);
+
+ // Flush RX FIFO
+ gzll_update_ok &= nrf_gzll_flush_rx_fifo(GZP_PAIRING_PIPE);
+ gzll_update_ok &= nrf_gzll_enable();
+ // Build "request" packet
+ address_req[0] = (uint8_t)GZP_CMD_HOST_ADDRESS_REQ;
+
+ // Send a number of packets in order to broadcast that devices not within
+ // close proximity must back off.
+ for (i = 0; i < GZP_MAX_BACKOFF_PACKETS; i++)
+ {
+ success = gzp_tx_packet(address_req, GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, GZP_PAIRING_PIPE);
+ if (success)
+ {
+ nrf_gzp_flush_rx_fifo(GZP_PAIRING_PIPE);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ gzp_delay_rx_periods(GZP_TX_ACK_WAIT_TIMEOUT);
+ // Send message for fetching pairing response from host.
+ address_req[0] = (uint8_t)GZP_CMD_HOST_ADDRESS_FETCH;
+
+ success = gzp_tx_packet(address_req, GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, GZP_PAIRING_PIPE);
+ if (success && latest_tx_info.payload_received_in_ack)
+ {
+ // If pairing response received
+ if (nrf_gzll_get_rx_fifo_packet_count(GZP_PAIRING_PIPE) > 0)
+ {
+ rx_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; //dummy placeholder
+ if (nrf_gzll_fetch_packet_from_rx_fifo(GZP_PAIRING_PIPE, rx_payload, &rx_payload_length))
+ {
+ if (rx_payload[0] == (uint8_t)GZP_CMD_HOST_ADDRESS_RESP)
+ {
+ memcpy(gzp_system_address, &rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH);
+ gzll_update_ok &= gzp_update_radio_params(&rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS]);
+ #ifndef GZP_NV_STORAGE_DISABLE
+ (void)gzp_params_store(false); // "False" indicates that only "system address" part of DB element will be stored
+ #endif
+ retval = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ gzp_delay_rx_periods(GZP_NOT_PROXIMITY_BACKOFF_RX_TIMEOUT - GZP_TX_ACK_WAIT_TIMEOUT);
+ }
+ gzp_delay_rx_periods(GZP_STEP1_RX_TIMEOUT);
+
+ // Clean-up and restore parameters temporarily modified
+ nrf_gzp_disable_gzll();
+ gzll_update_ok &= nrf_gzll_flush_rx_fifo(GZP_PAIRING_PIPE);
+ gzll_update_ok &= nrf_gzll_flush_tx_fifo(GZP_PAIRING_PIPE);
+ nrf_gzll_set_max_tx_attempts(temp_max_tx_attempts);
+ gzll_update_ok &= nrf_gzll_set_tx_power(temp_power);
+ gzll_update_ok &= nrf_gzll_enable();
+
+ if (!gzll_update_ok)
+ {
+ /*
+ The update of the Gazell parameters failed. Use nrf_gzll_get_error_code()
+ to investigate the cause.
+ */
+ }
+
+ return retval;
+ //lint -restore
+}
+
+#ifndef GZP_CRYPT_DISABLE
+
+gzp_id_req_res_t gzp_id_req_send()
+{
+ uint8_t tx_packet[GZP_CMD_HOST_ID_REQ_PAYLOAD_LENGTH];
+ uint8_t rx_packet[GZP_MAX_ACK_PAYLOAD_LENGTH];
+ gzp_tx_rx_trans_result_t trans_result;
+
+ // If no ID request is pending, send new "ID request"
+ if (!gzp_id_req_pending)
+ {
+ // Build "Host ID request packet"
+ tx_packet[0] = (uint8_t)GZP_CMD_HOST_ID_REQ;
+
+ // Generate new session token
+ gzp_random_numbers_generate(&tx_packet[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN], GZP_SESSION_TOKEN_LENGTH);
+
+ // Send "Host ID request"
+ if (gzp_tx_packet(tx_packet, GZP_CMD_HOST_ID_REQ_PAYLOAD_LENGTH, GZP_DATA_PIPE))
+ {
+ // Update session token if "Host ID request" was successfully transmitted
+ gzp_crypt_set_session_token(&tx_packet[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN]);
+ gzp_id_req_pending = true;
+
+ return GZP_ID_RESP_PENDING;
+ }
+ }
+ else // If "ID request is pending" send "fetch ID" packet
+ {
+ // Build "host ID fetch" packet
+ tx_packet[0] = (uint8_t)GZP_CMD_HOST_ID_FETCH;
+ gzp_add_validation_id(&tx_packet[GZP_CMD_HOST_ID_FETCH_VALIDATION_ID]);
+
+ // Encrypt "host ID fetch" packet
+ gzp_crypt_select_key(GZP_ID_EXCHANGE);
+ gzp_crypt(&tx_packet[1], &tx_packet[1], GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH - 1);
+
+ trans_result = gzp_tx_rx_transaction(tx_packet, GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH, rx_packet, NULL, GZP_DATA_PIPE);
+ // If packet was successfully sent AND a response packet was received
+ if (trans_result == GZP_TX_RX_SUCCESS)
+ {
+ // Validate response packet
+ if (rx_packet[0] == (uint8_t)GZP_CMD_HOST_ID_FETCH_RESP)
+ {
+ gzp_crypt(&rx_packet[1], &rx_packet[1], GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH - 1);
+ if (gzp_validate_id(&rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_VALIDATION_ID]))
+ {
+ switch (rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_STATUS])
+ {
+ case GZP_ID_RESP_PENDING:
+ break;
+ case GZP_ID_RESP_REJECTED:
+ gzp_id_req_pending = false;
+ break;
+ case GZP_ID_RESP_GRANTED:
+ gzp_set_host_id(&rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_HOST_ID]);
+ gzp_random_numbers_generate(dyn_key, GZP_DYN_KEY_LENGTH);
+ gzp_crypt_set_dyn_key(dyn_key);
+ #ifndef GZP_NV_STORAGE_DISABLE
+ (void)gzp_params_store(true);
+ #endif
+ gzp_id_req_pending = false;
+ break;
+ default:
+ break;
+ }
+
+ return (gzp_id_req_res_t)rx_packet[GZP_CMD_HOST_ID_FETCH_RESP_STATUS];
+ }
+ else
+ {
+ gzp_id_req_pending = false;
+ return GZP_ID_RESP_REJECTED;
+ }
+ }
+ }
+ }
+
+ gzp_id_req_pending = false;
+ return GZP_ID_RESP_FAILED;
+}
+
+void gzp_id_req_cancel()
+{
+ gzp_id_req_pending = false;
+}
+
+bool gzp_crypt_data_send(const uint8_t *src, uint8_t length)
+{
+ if (length <= GZP_ENCRYPTED_USER_DATA_MAX_LENGTH)
+ {
+ if (gzp_crypt_tx_transaction(src, length))
+ {
+ return true;
+ }
+ else
+ {
+ //print_string("GZP_CRYPT_TX failed\r\n");
+ // Attempt key update if user data transmission failed
+ // during normal operation (!gzp_id_req_pending)
+ if (!gzp_id_req_pending)
+ {
+ //print_string("KEY UPDATE\r\n");
+ if (gzp_key_update())
+ {
+ return gzp_crypt_tx_transaction(src, length);
+ }
+ }
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+}
+
+#endif
+/** @} */
+
+
+/******************************************************************************/
+// Implementation: Internal (static) functions
+/******************************************************************************/
+
+static bool gzp_tx_packet(const uint8_t* tx_packet, uint8_t length, uint8_t pipe)
+{
+ tx_complete = false;
+ tx_success = false;
+
+ if (nrf_gzll_add_packet_to_tx_fifo(pipe,(uint8_t *)tx_packet, length))
+ {
+ while (tx_complete == false)
+ {
+ __WFI();
+ }
+ return tx_success;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+static gzp_tx_rx_trans_result_t gzp_tx_rx_transaction(const uint8_t *tx_packet, uint8_t tx_length, uint8_t *rx_dst, uint32_t *rx_length, uint8_t pipe)
+{
+
+ gzp_tx_rx_trans_result_t retval;
+ uint8_t fetch_packet[GZP_CMD_FETCH_RESP_PAYLOAD_LENGTH];
+ bool tx_packet_success;
+ bool fetch_success;
+ uint32_t local_rx_length = GZP_MAX_ACK_PAYLOAD_LENGTH;
+ uint32_t temp_lifetime;
+
+ nrf_gzp_flush_rx_fifo(pipe);
+
+ retval = GZP_TX_RX_FAILED_TO_SEND;
+
+ (void)nrf_gzll_disable();
+ while (nrf_gzll_is_enabled())
+ {}
+ temp_lifetime = nrf_gzll_get_sync_lifetime();
+ (void)nrf_gzll_set_sync_lifetime(GZP_TX_RX_TRANS_DELAY * 3); // 3 = RXPERIOD * 2 + margin
+ (void)nrf_gzll_enable();
+
+ tx_packet_success = gzp_tx_packet(tx_packet, tx_length, pipe);
+
+ if (tx_packet_success)
+ {
+ retval = GZP_TX_RX_NO_RESPONSE;
+
+ nrf_gzp_flush_rx_fifo(pipe);
+
+ fetch_packet[0] = (uint8_t)GZP_CMD_FETCH_RESP;
+
+ gzp_tick_sleep_rx_periods(GZP_TX_RX_TRANS_DELAY);
+
+ tx_packet_success = gzp_tx_packet(fetch_packet, GZP_CMD_FETCH_RESP_PAYLOAD_LENGTH, pipe);
+
+ if (tx_packet_success)
+ {
+ if (nrf_gzll_get_rx_fifo_packet_count(pipe))
+ {
+ local_rx_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH;
+ fetch_success = nrf_gzll_fetch_packet_from_rx_fifo(pipe, rx_dst, &local_rx_length);
+ }
+ else
+ {
+ fetch_success = false;
+ }
+
+ if (fetch_success)
+ {
+ retval = GZP_TX_RX_SUCCESS;
+ }
+ else
+ {
+ //print_string("GZP_TX_FETCH_FAILED\r\n");
+ }
+ }
+ else
+ {
+ //print_string("GZP_TX_FETCH_NO_ACK\r\n");
+ }
+ }
+
+ (void)nrf_gzll_disable();
+ while (nrf_gzll_is_enabled())
+ {}
+ (void)nrf_gzll_set_sync_lifetime(temp_lifetime);
+ (void)nrf_gzll_enable();
+
+ return retval;
+}
+
+#ifndef GZP_CRYPT_DISABLE
+
+static bool gzp_crypt_tx_transaction(const uint8_t *src, uint8_t length)
+{
+ uint8_t tx_packet[GZP_MAX_FW_PAYLOAD_LENGTH];
+ uint8_t rx_packet[GZP_MAX_ACK_PAYLOAD_LENGTH];
+ uint8_t tx_packet_length;
+
+ gzp_tx_rx_trans_result_t result;
+
+ tx_packet_length = length + (uint8_t)GZP_ENCRYPTED_USER_DATA_PACKET_OVERHEAD;
+
+ // Assemble tx packet
+ tx_packet[0] = (uint8_t)GZP_CMD_ENCRYPTED_USER_DATA;
+ gzp_add_validation_id(&tx_packet[GZP_CMD_ENCRYPTED_USER_DATA_VALIDATION_ID]);
+ memcpy(&tx_packet[GZP_CMD_ENCRYPTED_USER_DATA_PAYLOAD], (uint8_t*)src, length);
+
+ // Encrypt tx packet
+ if (gzp_id_req_pending)
+ {
+ gzp_crypt_select_key(GZP_ID_EXCHANGE);
+ }
+ else
+ {
+ gzp_crypt_select_key(GZP_DATA_EXCHANGE);
+ }
+ gzp_crypt(&tx_packet[1], &tx_packet[1], tx_packet_length - 1);
+
+ // If packet was successfully sent AND a response packet was received
+ result = gzp_tx_rx_transaction(tx_packet, tx_packet_length, rx_packet, NULL, GZP_DATA_PIPE);
+ if (result == GZP_TX_RX_SUCCESS)
+ {
+ if (rx_packet[0] == (uint8_t)GZP_CMD_ENCRYPTED_USER_DATA_RESP)
+ {
+ gzp_crypt(&rx_packet[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID], &rx_packet[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID], GZP_VALIDATION_ID_LENGTH);
+
+ // Validate response in order to know whether packet was correctly decrypted by host
+ if (gzp_validate_id(&rx_packet[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID]))
+ {
+ // Update session token if normal operation (!gzp_id_req_pending)
+ if (!gzp_id_req_pending)
+ {
+ gzp_crypt_set_session_token(&rx_packet[GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN]);
+ }
+ return true;
+ }
+ else
+ {
+ //print_string("GZP_CRYPT_TX_TRANS: Validation ID bad\r\n");
+ return false;
+ }
+ }
+ else
+ {
+ //print_string("GZP_CRYPT_TX_TRANS: Bad CMD. \r\n");
+ return false;
+ }
+ }
+ else
+ {
+ //print_string("GZP_CRYPT_TX_TRANS: gzp_tx_rx_trans not SUCCESS\r\n");
+ return false;
+ }
+}
+
+static bool gzp_key_update(void)
+{
+ uint8_t tx_packet[GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH], rx_packet[GZP_MAX_ACK_PAYLOAD_LENGTH];
+
+ // Send "prepare packet" to get session token to be used for key update
+ tx_packet[0] = (uint8_t)GZP_CMD_KEY_UPDATE_PREPARE;
+
+ // If packet was successfully sent AND a response packet was received
+ if (gzp_tx_rx_transaction(tx_packet, GZP_CMD_KEY_UPDATE_PREPARE_PAYLOAD_LENGTH, rx_packet, NULL, GZP_DATA_PIPE) == GZP_TX_RX_SUCCESS)
+ {
+ if (rx_packet[0] == (uint8_t)GZP_CMD_KEY_UPDATE_PREPARE_RESP)
+ {
+ gzp_crypt_set_session_token(&rx_packet[GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN]);
+
+ // Build "key update" packet
+ tx_packet[0] = (uint8_t)GZP_CMD_KEY_UPDATE;
+ gzp_add_validation_id(&tx_packet[GZP_CMD_KEY_UPDATE_VALIDATION_ID]);
+ gzp_random_numbers_generate(&tx_packet[GZP_CMD_KEY_UPDATE_NEW_KEY], GZP_DYN_KEY_LENGTH);
+ gzp_crypt_set_dyn_key(&tx_packet[GZP_CMD_KEY_UPDATE_NEW_KEY]);
+
+ // Encrypt "key update packet"
+ gzp_crypt_select_key(GZP_KEY_EXCHANGE);
+ gzp_crypt(&tx_packet[1], &tx_packet[1], GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH - 1);
+
+ // Send "key update" packet
+ if (gzp_tx_packet(tx_packet, GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH, GZP_DATA_PIPE))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+#endif
+
+void gzp_set_host_id(const uint8_t * id)
+{
+ memcpy(gzp_host_id, id, GZP_HOST_ID_LENGTH);
+}
+
+void gzp_get_host_id(uint8_t * dst_id)
+{
+ memcpy(dst_id, gzp_host_id, GZP_HOST_ID_LENGTH);
+}
+
+static void gzp_params_db_add(const uint8_t* src_element, uint8_t index)
+{
+ nrf_nvmc_write_bytes((GZP_PARAMS_DB_ADR + (index * GZP_PARAMS_DB_ELEMENT_SIZE)), src_element, (uint32_t)GZP_PARAMS_DB_ELEMENT_SIZE);
+}
+
+
+static void gzp_params_db_read(uint8_t* dst_element, uint8_t index)
+{
+ memcpy(dst_element,(uint8_t*)(GZP_PARAMS_DB_ADR + (index * GZP_PARAMS_DB_ELEMENT_SIZE)), GZP_PARAMS_DB_ELEMENT_SIZE);
+}
+
+
+static void gzp_index_db_add(uint8_t val)
+{
+ int16_t i;
+ uint8_t temp_val;
+ uint32_t addr;
+
+ // Search for unwritten loacation in index DB
+ for (i = 0; i < GZP_INDEX_DB_SIZE; i++)
+ {
+ temp_val = *(uint8_t*)(GZP_INDEX_DB_ADR + i);
+
+ // Lower nibble
+ if (i != (GZP_INDEX_DB_SIZE - 1))
+ {
+ if ((temp_val & 0x0f) == 0x0f)
+ {
+ temp_val = (temp_val & 0xf0) | val;
+ break;
+ }
+ // Upper nibble
+ else if ((temp_val & 0xf0) == 0xf0)
+ {
+ temp_val = (temp_val & 0x0f) | (val << 4);
+ break;
+ }
+ }
+ else
+ {
+ temp_val = (GZP_PARAMS_DB_MAX_ENTRIES << 4) | val;
+ break;
+ }
+ }
+
+ // Write index DB
+ addr = (GZP_INDEX_DB_ADR + i);
+ nrf_nvmc_write_byte(addr, temp_val);
+}
+
+static uint8_t gzp_index_db_read()
+{
+ uint8_t retval;
+ int16_t i;
+
+ // Search for previously written location
+ for (i = (GZP_INDEX_DB_SIZE - 1); i >= 0; i--)
+ {
+ retval = *(uint8_t*)(GZP_INDEX_DB_ADR + i);
+
+ if (retval != 0xff)
+ {
+ break;
+ }
+ }
+
+ if (retval == 0xff)
+ {
+ retval = GZP_PARAMS_DB_MAX_ENTRIES; // index db empty
+ }
+ else if ((retval & 0xf0) != 0xf0)
+ {
+ retval >>= 4;
+ }
+ else
+ {
+ retval &= 0x0f;
+ }
+
+ return retval;
+}
+
+int8_t gzp_get_pairing_status(void)
+{
+ uint8_t db_byte;
+ int8_t db_index;
+ int16_t i;
+ uint8_t temp_element[GZP_PARAMS_DB_ELEMENT_SIZE];
+ uint8_t default_host_id[GZP_HOST_ID_LENGTH];
+
+ db_index = -2;
+
+ // Populate default Host ID with F's.
+ for (i=0; i< GZP_HOST_ID_LENGTH; i++)
+ {
+ default_host_id[i] = 0xFF;
+ }
+
+ // Search for previously written location
+ for (i = (GZP_INDEX_DB_SIZE - 1); i >= 0; i--)
+ {
+ db_byte = *(uint8_t*)(GZP_INDEX_DB_ADR + i);
+
+ // Check if idx has been written to
+ if (db_byte != 0xff)
+ {
+ // Convert 4-bit nibble to index
+ if ((db_byte & 0xf0) != 0xf0)
+ {
+ db_byte = (db_byte >> 4) & 0x0f;
+ }
+ else
+ {
+ db_byte = db_byte & 0x0f;
+ }
+
+ // Retrieve database entry
+ gzp_params_db_read(temp_element, db_byte);
+
+ // Check if database entry is all F's
+ if ( memcmp(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], default_host_id, GZP_HOST_ID_LENGTH) != 0)
+ {
+
+ db_index = db_byte;
+ }
+ else
+ {
+ db_index = -1;
+ }
+ break;
+ }
+ }
+
+ return db_index;
+}
+
+
+static bool gzp_index_db_full()
+{
+#if (GZP_INDEX_DB_SIZE != 0)
+ return ((*(uint8_t*)(GZP_INDEX_DB_ADR + (GZP_INDEX_DB_SIZE - 1)) != 0xff));
+#else
+ return true;
+#endif
+}
+
+//lint -save -e506 Constant value boolean
+static bool gzp_index_db_empty()
+{
+#if (GZP_INDEX_DB_SIZE != 0)
+ return ((GZP_INDEX_DB_SIZE == 0) || ((*(uint8_t*)(GZP_INDEX_DB_ADR)) == 0xff));
+#else
+ return true;
+#endif
+}
+//lint -restore
+
+static bool gzp_array_is_set(const uint8_t* src, uint8_t length)
+{
+ uint8_t i;
+
+ for (i = 0; i < length; i++)
+ {
+ if (*(src++) != 0xff)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool gzp_params_store(bool store_all)
+{
+ uint8_t i;
+ bool write_index_db = false;
+ bool write_param_db = false;
+ uint8_t new_db_index = 0;
+ uint8_t temp_element[GZP_PARAMS_DB_ELEMENT_SIZE];
+
+ // Search param DB to see if current setup exists
+ if (store_all)
+ {
+ // Search for: Current system address and host ID exists
+ for (i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
+ {
+ gzp_params_db_read(temp_element, i);
+
+ if (((memcmp(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH)) == 0) && ((memcmp(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], gzp_host_id, GZP_HOST_ID_LENGTH)) == 0))
+ {
+ write_index_db = true;
+ new_db_index = i;
+ break; // System address + host_id allready exists in database
+ }
+ }
+
+ // Search for: Current system address and cleared host ID
+ if (!write_index_db)
+ {
+ for (i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
+ {
+ gzp_params_db_read(temp_element, i);
+
+ if (((memcmp(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH)) == 0) && \
+ (gzp_array_is_set(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], GZP_HOST_ID_LENGTH)))
+ {
+ memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], gzp_host_id, GZP_HOST_ID_LENGTH);
+ new_db_index = i;
+ write_index_db = true;
+ write_param_db = true;
+ break;
+ }
+ }
+ }
+
+ // Search for: Cleared system address and cleared host ID
+ if (!write_index_db)
+ {
+ for (i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
+ {
+ gzp_params_db_read(temp_element, i);
+
+ if (gzp_array_is_set(temp_element, GZP_PARAMS_DB_ELEMENT_SIZE))
+ {
+ memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH);
+ memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], gzp_host_id, GZP_HOST_ID_LENGTH);
+ new_db_index = i;
+ write_index_db = true;
+ write_param_db = true;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Search for: System address + any host ID
+ for (i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
+ {
+ gzp_params_db_read(temp_element, i);
+
+ if ((memcmp(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH)) == 0)
+ {
+ //memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID], gzp_host_id, GZP_HOST_ID_LENGTH);
+ write_index_db = true;
+ new_db_index = i;
+ break;
+ }
+ }
+
+ // Search for: System address cleared
+ if (!write_index_db)
+ {
+ for (i = 0; i < GZP_PARAMS_DB_MAX_ENTRIES; i++)
+ {
+ gzp_params_db_read(temp_element, i);
+
+ if (gzp_array_is_set(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH))
+ {
+ memcpy(&temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], gzp_system_address, GZP_SYSTEM_ADDRESS_WIDTH);
+ write_index_db = true;
+ write_param_db = true;
+ new_db_index = i;
+ break;
+ }
+ }
+ }
+ }
+
+ if (write_param_db)
+ {
+ gzp_params_db_add(temp_element, new_db_index);
+ }
+
+ if (write_index_db)
+ {
+ if (!gzp_index_db_full() && (new_db_index != gzp_index_db_read()) && (new_db_index != GZP_PARAMS_DB_MAX_ENTRIES))
+ {
+ gzp_index_db_add(new_db_index);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool gzp_params_restore(void)
+{
+ uint8_t i;
+ uint8_t temp_element[GZP_PARAMS_DB_ELEMENT_SIZE];
+
+ if (!gzp_index_db_full() && !gzp_index_db_empty())
+ {
+ i = gzp_index_db_read();
+
+ if (i < GZP_PARAMS_DB_MAX_ENTRIES)
+ {
+ gzp_params_db_read(temp_element, i);
+ memcpy(gzp_system_address, &temp_element[GZP_PARAMS_DB_ELEMENT_SYSTEM_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH);
+ gzp_set_host_id(&temp_element[GZP_PARAMS_DB_ELEMENT_HOST_ID]);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void gzp_delay_rx_periods(uint32_t rx_periods)
+{
+ nrf_delay_us(rx_periods * 2 * nrf_gzll_get_timeslot_period());
+}
+
+void gzp_tick_sleep_rx_periods(uint32_t rx_periods)
+{
+ nrf_gzll_clear_tick_count();
+
+ while (nrf_gzll_get_tick_count() < 2 * rx_periods)
+ {
+ __WFI();
+ }
+}
+
+
+void nrf_gzll_device_tx_success(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info)
+{
+ latest_tx_info = tx_info;
+
+ tx_complete = true;
+ tx_success = true;
+}
+
+void nrf_gzll_device_tx_failed(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info)
+{
+ latest_tx_info = tx_info;
+
+ tx_complete = true;
+ tx_success = false;
+}
+
+bool nrf_gzp_tx_complete(void)
+{
+ return tx_complete;
+}
+
+bool nrf_gzp_tx_success(void)
+{
+ return tx_success;
+}
+
+void nrf_gzp_reset_tx_complete()
+{
+ tx_complete = false;
+}
+
+void nrf_gzp_reset_tx_success()
+{
+ tx_success = false;
+}
+
+void nrf_gzll_disabled(void)
+{
+}
+
+void nrf_gzll_host_rx_data_ready(uint32_t pipe, nrf_gzll_host_rx_info_t rx_info)
+{
+}
+
+/** @} */
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp_host.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp_host.c
new file mode 100644
index 0000000..6e331a9
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp_host.c
@@ -0,0 +1,821 @@
+/**
+ * Copyright (c) 2009 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/**
+ * @file
+ * @brief Implementation of Gazell Pairing Library (gzp), Host functions.
+ * @defgroup gzp_source_host Gazell Pairing Host implementation
+ * @{
+ * @ingroup gzp_04_source
+ */
+
+
+#include "nrf_gzp.h"
+#include "nrf_gzll.h"
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "nrf_assert.h"
+#include "nrf_ecb.h"
+#include "nrf_nvmc.h"
+
+
+//lint -esym(40, GZP_PARAMS_STORAGE_ADR) "Undeclared identifier"
+#define GZP_PARAMS_DB_ADR GZP_PARAMS_STORAGE_ADR // Address of the GZP parameters flash page.
+
+
+/******************************************************************************/
+/** @name Typedefs
+ * @{ */
+/******************************************************************************/
+
+/**
+ * Definition of internal states.
+ */
+typedef enum
+{
+ GZP_ID_REQ_IDLE, ///< No Host ID request received from Device.
+ GZP_ID_REQ_PENDING, ///< Host ID request received and waiting on application to grant/reject.
+ GZP_ID_REQ_PENDING_AND_GRANTED, ///< Host ID request received and granted by application.
+ GZP_ID_REQ_PENDING_AND_REJECTED, ///< Host ID request received and rejected by application.
+} gzp_id_req_stat_t;
+
+/** @} */
+
+
+/******************************************************************************/
+/** @name Internal (static) function prototypes
+ * @{ */
+/******************************************************************************/
+
+
+/**
+ * Function for incrementing internal session counter.
+ */
+static void gzp_session_counter_inc(void);
+
+
+/**
+ * Function for reading value of internal session counter.
+ * @param dst Current session counter.
+ */
+static void gzp_get_session_counter(uint8_t* dst);
+
+
+/**
+ * Function processing received "system address request" from Device.
+ *
+ * @param gzp_req Pointer to RX payload containing system address request.
+ */
+static void gzp_process_address_req(uint8_t* gzp_req);
+
+
+/**
+ * Function to process Host ID request from device.
+ *
+ * The Host shall retrieve the Host ID from NVM, or shall generate if
+ * it does not yet exist.
+ *
+ * @param rx_payload Pointer to rx_payload contaning Host ID request.
+ */
+static void gzp_process_id_req(uint8_t* rx_payload);
+
+/**
+ * Function to process Host ID fetch request from Device.
+ *
+ * The Device fetches the Host ID after the Host has generated/retrieved
+ * the Host ID.
+ *
+ * @param rx_payload Pointer to rx_payload contaning Host ID fetch request.
+ */
+static void gzp_process_id_fetch(uint8_t* rx_payload);
+
+
+/**
+ * Function to process Key Update Prepare packet.
+ *
+ * Device requests the Session Token to be used for the Key Update request.
+ */
+static void gzp_process_key_update_prepare(void);
+
+
+/**
+ * Function to process Key Update packet.
+ *
+ * Device requests a Key Update and sends a new Dynamic Key. The Dynamic Key is
+ * updated on the Host.
+ *
+ * @param rx_payload Pointer to rx_payload containing Key Update request.
+ */
+static void gzp_process_key_update(uint8_t* rx_payload);
+
+
+/**
+ * Function to process received Encrypted User packet.
+ *
+ * @param rx_payload Pointer to rx_payload containing the encrypted user data.
+ * @param length Length of encrypted user data.
+ */
+static void gzp_process_encrypted_user_data(uint8_t* rx_payload, uint8_t length);
+
+
+/**
+ * Function to preload the payload for the next ACK.
+ *
+ * @param src Pointer to source payload.
+ * @param length Length of source payload.
+ * @param pipe Pipe for the ACK payload.
+ */
+static void gzp_preload_ack(uint8_t* src, uint8_t length, uint8_t pipe);
+
+
+/**
+ * Function for reading the Chip ID from non-volatile memory.
+ *
+ * The chip ID is used for the system address.
+ *
+ * If the Chip ID is not yet created a random Chip ID is created and
+ * written to non-volatile memory. Note that the term chip ID is used as
+ * the factory programmed chip sequence number was used for the system
+ * address in nRF24LU ICs.
+ *
+ * @param dst Address to copy Host ID to.
+ * @param[in] n Number of bytes in the Host ID.
+ */
+void gzp_host_chip_id_read(uint8_t *dst, uint8_t n);
+
+
+/**
+ * Function to set the Host ID.
+ *
+ * Writes the Host ID to non-volatile memory.
+ * @param src Address of the Host ID to copy from.
+ */
+static void gzp_set_host_id(const uint8_t* src);
+
+
+/**
+ * Function to request disabling of Gazell and wait for it to be disabled.
+ *
+ * Emulates legacy gzll_goto_idle().
+ */
+static void gzll_goto_idle(void);
+
+
+/**
+ * Flush all TX FIFOs.
+ *
+ * Emulates legacy gzll_tx_fifo_flush().
+ */
+static void gzll_tx_fifo_flush(void);
+
+
+/**
+ * Flush all RX FIFOs.
+ *
+ * Emulates legacy gzll_rx_fifo_flush().
+ */
+static void gzll_rx_fifo_flush(void);
+
+
+/**
+ * Set a timeout for the reception of packets on the Gazell Host.
+ *
+ * Emulates legacy Gazell function: gzll_set_param(GZLL_PARAM_RX_TIMEOUT, x).
+ *
+ * @param timeout Timeout in number of legacy "RX periods"
+ * (1 RX period = 2 timeslot periods).
+ */
+static void gzll_set_rx_timeout(uint32_t timeout);
+
+/** @} */
+
+
+/******************************************************************************/
+/** @name Internal (static) variabls
+ * @{ */
+/******************************************************************************/
+
+static gzp_id_req_stat_t gzp_id_req_stat; ///< Current state of Host ID request.
+static bool gzp_pairing_enabled_f; ///< True if Host is paired with a device.
+static bool gzp_address_exchanged_f; ///< True if Host has exchanged a system address with a device and thus pairing has begun.
+
+static uint8_t gzp_session_counter[GZP_SESSION_TOKEN_LENGTH]; ///< Session counter used for key generation and update.
+
+static bool gzp_encrypted_user_data[GZP_ENCRYPTED_USER_DATA_MAX_LENGTH]; ///< Placeholder for encrypted data from Device.
+static uint8_t gzp_encrypted_user_data_length; ///< Length of gzp_encrypted_user_data. Zero implies no data received.
+
+static nrf_gzll_host_rx_info_t prev_gzp_rx_info = {0, 0}; ///< RSSI and status of ACK payload transmission of previous Gazell packet.
+
+// Define Macro to make array initialization nicer
+#define REP4(X) X X X X
+
+#if defined(__ICCARM__)
+ #if GZP_PARAMS_DB_ADR == 0x1000
+ static const uint32_t database[GZP_DEVICE_PARAMS_STORAGE_SIZE/4] @ "gzp_dev_data"
+ #elif GZP_PARAMS_DB_ADR == 0x15000
+ static const uint32_t database[GZP_DEVICE_PARAMS_STORAGE_SIZE/4] @ "gzp_dev_data_sd"
+ #else
+ #error
+ #endif
+#else
+static const uint32_t database[GZP_DEVICE_PARAMS_STORAGE_SIZE / 4] __attribute__((at(GZP_PARAMS_DB_ADR)))
+#endif
+= {
+ #define STATIC_INIT_VALUE 0xFFFFFFFF
+ #define STATIC_INIT_COUNT (GZP_DEVICE_PARAMS_STORAGE_SIZE / 4)
+ #define INIT_1 STATIC_INIT_VALUE,
+ #define INIT_4 REP4(INIT_1)
+ #define INIT_16 REP4(INIT_4)
+ #define INIT_64 REP4(INIT_16)
+ #define INIT_256 REP4(INIT_64)
+ #define INIT_1024 REP4(INIT_256)
+
+ #if (STATIC_INIT_COUNT == 256)
+ INIT_256
+ #elif (STATIC_INIT_COUNT == 1024)
+ INIT_1024
+ #else
+ #error Gazell Pairing Library database not initialized properly!
+ #endif
+}; ///< Database for storing keys.
+
+/** @} */
+
+
+/******************************************************************************/
+// Implementation: Host-specific API functions
+/******************************************************************************/
+
+void gzp_init()
+{
+ uint8_t system_address[GZP_SYSTEM_ADDRESS_WIDTH];
+
+ // Read "chip id", of which 4 bytes (GZP_SYSTEM_ADDRESS_WIDTH)
+ // are used as system address
+ gzp_host_chip_id_read(system_address, GZP_SYSTEM_ADDRESS_WIDTH);
+
+ // Set up radio parameters (addresses and channel subset) from system_address
+ (void)gzp_update_radio_params(system_address);
+
+ // Only "data pipe" enabled by default
+
+ (void)nrf_gzll_set_rx_pipes_enabled(nrf_gzll_get_rx_pipes_enabled() | (1 << GZP_DATA_PIPE));
+
+ gzp_pairing_enabled_f = false;
+ gzp_address_exchanged_f = false;
+ gzp_id_req_stat = GZP_ID_REQ_IDLE;
+ gzp_encrypted_user_data_length = 0;
+
+ // Infinite RX timeout
+ gzll_set_rx_timeout(0);
+}
+
+void gzp_pairing_enable(bool enable)
+{
+ if (gzp_pairing_enabled_f != enable)
+ {
+ gzll_goto_idle();
+
+ if (enable)
+ {
+ (void)nrf_gzll_set_rx_pipes_enabled(nrf_gzll_get_rx_pipes_enabled() | (1 << GZP_PAIRING_PIPE));
+ }
+ else
+ {
+ (void)nrf_gzll_set_rx_pipes_enabled(nrf_gzll_get_rx_pipes_enabled() & ~(1 << GZP_PAIRING_PIPE));
+
+ gzp_id_req_stat = GZP_ID_REQ_IDLE;
+ }
+
+ gzp_pairing_enabled_f = enable;
+
+ gzll_rx_start();
+ }
+}
+
+void gzp_host_execute()
+{
+ bool gzp_packet_received = false;
+ uint32_t payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH;
+ uint8_t rx_payload[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH];
+
+ gzp_address_exchanged_f = false;
+
+ if (nrf_gzll_get_rx_fifo_packet_count(GZP_PAIRING_PIPE) > 0)
+ {
+ gzp_packet_received = nrf_gzll_fetch_packet_from_rx_fifo(GZP_PAIRING_PIPE, rx_payload, &payload_length);
+ }
+
+ if (!gzp_packet_received && (gzp_encrypted_user_data_length == 0))
+ {
+ if (nrf_gzll_get_rx_fifo_packet_count(GZP_DATA_PIPE) > 0)
+ {
+ gzp_packet_received = nrf_gzll_fetch_packet_from_rx_fifo(GZP_DATA_PIPE, rx_payload, &payload_length);
+ }
+ }
+
+ if (gzp_packet_received)
+ {
+ //lint -save -esym(644,rx_payload) //may not have been initialized
+ switch (rx_payload[0])
+ {
+ case GZP_CMD_HOST_ADDRESS_REQ:
+ gzp_process_address_req(rx_payload);
+ break;
+
+ #ifndef GZP_CRYPT_DISABLE
+
+ case GZP_CMD_HOST_ID_REQ:
+ gzp_process_id_req(rx_payload);
+ break;
+ case GZP_CMD_HOST_ID_FETCH:
+ gzp_process_id_fetch(rx_payload);
+ break;
+ case GZP_CMD_KEY_UPDATE_PREPARE:
+ gzp_process_key_update_prepare();
+ break;
+ case GZP_CMD_KEY_UPDATE:
+ gzp_process_key_update(rx_payload);
+ break;
+ case GZP_CMD_ENCRYPTED_USER_DATA:
+ gzp_process_encrypted_user_data(rx_payload, payload_length);
+ break;
+
+ #endif
+
+ case GZP_CMD_FETCH_RESP:
+ default:
+ break;
+ }
+ }
+
+ // Restart reception if "not proximity backoff" period has elapsed
+ if (!nrf_gzll_is_enabled())
+ {
+ gzll_set_rx_timeout(0);
+
+ if (gzp_pairing_enabled_f)
+ {
+ (void)nrf_gzll_set_rx_pipes_enabled(nrf_gzll_get_rx_pipes_enabled() | (1 << GZP_PAIRING_PIPE));
+ }
+
+ gzll_rx_start();
+ }
+
+ #ifndef GZP_CRYPT_DISABLE
+ gzp_session_counter_inc();
+ #endif
+}
+
+void gzll_rx_start(void)
+{
+ if (nrf_gzll_get_mode() != NRF_GZLL_MODE_HOST)
+ {
+ gzll_goto_idle();
+ (void)nrf_gzll_set_mode(NRF_GZLL_MODE_HOST);
+ }
+
+ if (!nrf_gzll_is_enabled())
+ {
+ (void)nrf_gzll_enable();
+ }
+}
+
+bool gzp_id_req_received()
+{
+ return (gzp_id_req_stat != GZP_ID_REQ_IDLE);
+}
+
+void gzp_id_req_reject()
+{
+ if (gzp_id_req_received())
+ {
+ gzp_id_req_stat = GZP_ID_REQ_PENDING_AND_REJECTED;
+ }
+}
+
+void gzp_id_req_grant()
+{
+ if (gzp_id_req_received())
+ {
+ gzp_id_req_stat = GZP_ID_REQ_PENDING_AND_GRANTED;
+ }
+}
+
+void gzp_id_req_cancel()
+{
+ if (gzp_id_req_received())
+ {
+ gzp_id_req_stat = GZP_ID_REQ_IDLE;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Implementation: Static functions
+//-----------------------------------------------------------------------------
+
+static void gzp_process_address_req(uint8_t* gzp_req)
+{
+ uint8_t temp_rx_pipes;
+ uint8_t pairing_resp[GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH];
+ uint32_t rx_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH;
+
+ gzp_address_exchanged_f = false;
+
+ gzll_goto_idle();
+ ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
+
+ temp_rx_pipes = nrf_gzll_get_rx_pipes_enabled();
+ ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
+
+ // If requesting Device within close proximity
+ if (prev_gzp_rx_info.rssi >= GZP_HOST_RX_POWER_THRESHOLD)
+ {
+ (void)nrf_gzll_set_rx_pipes_enabled(0);
+ ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
+
+ gzll_set_rx_timeout(GZP_CLOSE_PROXIMITY_BACKOFF_RX_TIMEOUT);
+ ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
+
+ gzll_rx_fifo_flush();
+ ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
+
+ // Start "proximity" back off period
+ gzll_rx_start();
+ ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
+
+ while (nrf_gzll_is_enabled())
+ {}
+
+ // Build pairing response packet
+ pairing_resp[0] = (uint8_t)GZP_CMD_HOST_ADDRESS_RESP;
+ gzp_host_chip_id_read(&pairing_resp[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH);
+
+ (void)nrf_gzll_add_packet_to_tx_fifo(0, &pairing_resp[0], GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH);
+ ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
+ gzll_set_rx_timeout(GZP_STEP1_RX_TIMEOUT);
+
+ // Enable only pairing pipe when waiting for pairing request step 1
+ (void)nrf_gzll_set_rx_pipes_enabled((1 << GZP_PAIRING_PIPE));
+
+ gzll_rx_start();
+
+ while (nrf_gzll_is_enabled())
+ {
+ if (nrf_gzll_get_rx_fifo_packet_count(GZP_PAIRING_PIPE))
+ {
+ (void)nrf_gzll_fetch_packet_from_rx_fifo(GZP_PAIRING_PIPE, &gzp_req[0], &rx_payload_length);
+
+ // Validate step 1 of pairing request
+ if (gzp_req[0] == (uint8_t)GZP_CMD_HOST_ADDRESS_FETCH)
+ {
+ gzp_address_exchanged_f = true;
+ }
+ }
+ }
+
+ gzll_tx_fifo_flush();
+ gzll_rx_fifo_flush();
+
+ gzll_set_rx_timeout(0);
+
+ (void)nrf_gzll_set_rx_pipes_enabled(temp_rx_pipes);
+
+ // Return to normal operation
+ gzll_rx_start();
+ }
+ else
+ {
+ (void)nrf_gzll_set_rx_pipes_enabled(temp_rx_pipes & ~(1 << GZP_PAIRING_PIPE));
+
+ gzll_set_rx_timeout(GZP_NOT_PROXIMITY_BACKOFF_RX_TIMEOUT);
+
+ // Start "not proximity" backoff period
+ gzll_rx_start();
+ }
+}
+
+static void gzp_preload_ack(uint8_t* src, uint8_t length, uint8_t pipe)
+{
+ gzll_goto_idle();
+
+ gzll_tx_fifo_flush();
+
+ (void)nrf_gzll_add_packet_to_tx_fifo(pipe, src, length);
+
+ gzll_rx_start();
+}
+
+static void gzll_set_rx_timeout(uint32_t timeout)
+{
+ timeout *= 2; // * 2 as gzll_set_rx_timeout() takes RX_PERIODS as input, which equals 2 timeslots.
+ nrf_gzll_set_auto_disable(timeout);
+}
+
+bool gzp_address_exchanged()
+{
+ return gzp_address_exchanged_f;
+}
+
+#ifndef GZP_CRYPT_DISABLE
+
+bool gzp_crypt_user_data_received()
+{
+ return (gzp_encrypted_user_data_length > 0);
+}
+
+bool gzp_crypt_user_data_read(uint8_t* dst, uint8_t* length)
+{
+ if (gzp_encrypted_user_data_length > 0)
+ {
+ memcpy(dst, (void*)gzp_encrypted_user_data, gzp_encrypted_user_data_length);
+
+ if (length != NULL)
+ {
+ *length = gzp_encrypted_user_data_length;
+ }
+ gzp_encrypted_user_data_length = 0;
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+static void gzp_session_counter_inc()
+{
+ uint8_t i;
+
+ for (i = 0; i < GZP_SESSION_TOKEN_LENGTH; i++)
+ {
+ gzp_session_counter[i]++;
+ if (gzp_session_counter[i] != 0)
+ {
+ break;
+ }
+ }
+}
+
+static void gzp_get_session_counter(uint8_t* dst)
+{
+ memcpy(dst, (void*)gzp_session_counter, GZP_SESSION_TOKEN_LENGTH);
+}
+
+static void gzp_set_host_id(const uint8_t* src)
+{
+ if (*((uint8_t*)database) == 0xff)
+ {
+ nrf_nvmc_write_bytes(GZP_PARAMS_STORAGE_ADR + 1, src, GZP_HOST_ID_LENGTH);
+ nrf_nvmc_write_byte(GZP_PARAMS_STORAGE_ADR, 0x00);
+ }
+}
+
+void gzp_get_host_id(uint8_t *dst)
+{
+ memcpy(dst, (uint8_t*)GZP_PARAMS_STORAGE_ADR + 1, GZP_HOST_ID_LENGTH);
+}
+
+static void gzp_process_id_req(uint8_t* rx_payload)
+{
+ int i;
+ uint8_t temp_host_id[GZP_HOST_ID_LENGTH];
+
+ if (gzp_pairing_enabled_f)
+ {
+ if (!gzp_id_req_received())
+ {
+ gzp_crypt_set_session_token(&rx_payload[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN]);
+ gzp_id_req_stat = GZP_ID_REQ_PENDING;
+ }
+
+ gzp_get_host_id(temp_host_id);
+
+ // Added:
+ for (i = 0; i < GZP_HOST_ID_LENGTH; i++)
+ {
+ if (temp_host_id[i] != 0xFF)
+ {
+ break;
+ }
+ }
+
+ if (i == GZP_HOST_ID_LENGTH) // If host not generated yet
+ {
+ gzp_get_session_counter(temp_host_id);
+
+#if (GZP_HOST_ID_LENGTH > GZP_SESSION_TOKEN_LENGTH)
+ gzp_xor_cipher(temp_host_id, temp_host_id, &rx_payload[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN], GZP_SESSION_TOKEN_LENGTH);
+#else //(GZP_HOST_ID_LENGTH > GZP_SESSION_TOKEN_LENGTH)
+ gzp_xor_cipher(temp_host_id, temp_host_id, &rx_payload[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN], GZP_HOST_ID_LENGTH);
+#endif //(GZP_HOST_ID_LENGTH > GZP_SESSION_TOKEN_LENGTH)
+
+ gzp_set_host_id(temp_host_id);
+ }
+ }
+}
+
+static void gzp_process_id_fetch(uint8_t* rx_payload)
+{
+ uint8_t tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH];
+
+ if (gzp_id_req_received())
+ {
+ gzp_crypt_select_key(GZP_ID_EXCHANGE);
+ gzp_crypt(&rx_payload[1], &rx_payload[1], GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH - 1);
+ if (gzp_validate_id(&rx_payload[GZP_CMD_HOST_ID_FETCH_VALIDATION_ID]))
+ {
+ switch (gzp_id_req_stat)
+ {
+ case GZP_ID_REQ_PENDING_AND_GRANTED:
+ tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_STATUS] = (uint8_t)GZP_ID_RESP_GRANTED;
+ gzp_get_host_id(&tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_HOST_ID]);
+ gzp_id_req_stat = GZP_ID_REQ_IDLE;
+ break;
+ case GZP_ID_REQ_PENDING_AND_REJECTED:
+ tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_STATUS] = (uint8_t)GZP_ID_RESP_REJECTED;
+ gzp_id_req_stat = GZP_ID_REQ_IDLE;
+ break;
+ case GZP_ID_REQ_PENDING:
+ default:
+ tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_STATUS] = (uint8_t)GZP_ID_RESP_PENDING;
+ break;
+ }
+
+ tx_payload[0] = (uint8_t)GZP_CMD_HOST_ID_FETCH_RESP;
+ gzp_add_validation_id(&tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_VALIDATION_ID]);
+ gzp_crypt(&tx_payload[1], &tx_payload[1], GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH - 1);
+
+ ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
+ gzp_preload_ack(tx_payload, GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH, GZP_DATA_PIPE);
+ ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
+ }
+ }
+}
+
+static void gzp_process_key_update_prepare()
+{
+ uint8_t tx_payload[GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH];
+
+ tx_payload[0] = (uint8_t)GZP_CMD_KEY_UPDATE_PREPARE_RESP;
+
+ gzp_get_session_counter(&tx_payload[GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN]);
+
+ // Update session token if no ID request is pending
+ if (!gzp_id_req_received())
+ {
+ gzp_crypt_set_session_token(&tx_payload[GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN]);
+ }
+
+ gzp_preload_ack(tx_payload, GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH, GZP_DATA_PIPE);
+ ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
+}
+
+static void gzp_process_key_update(uint8_t* rx_payload)
+{
+ gzp_crypt_select_key(GZP_KEY_EXCHANGE);
+ gzp_crypt(&rx_payload[1], &rx_payload[1], GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH - 1);
+ if (gzp_validate_id(&rx_payload[GZP_CMD_KEY_UPDATE_VALIDATION_ID]))
+ {
+ gzp_crypt_set_dyn_key(&rx_payload[GZP_CMD_KEY_UPDATE_NEW_KEY]);
+ }
+}
+
+static void gzp_process_encrypted_user_data(uint8_t* rx_payload, uint8_t length)
+{
+ uint8_t tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_PAYLOAD_LENGTH];
+
+ if (gzp_id_req_received())
+ {
+ gzp_crypt_select_key(GZP_ID_EXCHANGE);
+ }
+ else
+ {
+ gzp_crypt_select_key(GZP_DATA_EXCHANGE);
+ }
+
+ gzp_crypt(&rx_payload[1], &rx_payload[1], length - 1);
+ if (gzp_validate_id(&rx_payload[GZP_CMD_ENCRYPTED_USER_DATA_VALIDATION_ID]))
+ {
+ gzp_encrypted_user_data_length = length - GZP_ENCRYPTED_USER_DATA_PACKET_OVERHEAD;
+ memcpy((void*)gzp_encrypted_user_data, &rx_payload[GZP_CMD_ENCRYPTED_USER_DATA_PAYLOAD], gzp_encrypted_user_data_length);
+ }
+
+ // Build response packet
+ tx_payload[0] = (uint8_t)GZP_CMD_ENCRYPTED_USER_DATA_RESP;
+ gzp_add_validation_id(&tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID]);
+ gzp_crypt(&tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID], &tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID], GZP_VALIDATION_ID_LENGTH);
+ gzp_get_session_counter(&tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN]);
+
+ // Update "session token" only if no ID request is pending
+ if (!gzp_id_req_received())
+ {
+ gzp_crypt_set_session_token(&tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN]);
+ }
+
+ ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
+ gzp_preload_ack(tx_payload, GZP_CMD_ENCRYPTED_USER_DATA_RESP_PAYLOAD_LENGTH, GZP_DATA_PIPE);
+ ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
+}
+
+//-----------------------------------------------------------------------------
+// Function added during LE1 -> nRF51 port
+//-----------------------------------------------------------------------------
+
+static void gzll_goto_idle()
+{
+ nrf_gzll_disable();
+ while (nrf_gzll_is_enabled())
+ {}
+}
+
+static void gzll_tx_fifo_flush(void)
+{
+ int i;
+
+ for (i = 0; i < NRF_GZLL_CONST_PIPE_COUNT; i++)
+ {
+ (void)nrf_gzll_flush_tx_fifo(i);
+ }
+}
+
+static void gzll_rx_fifo_flush(void)
+{
+ int i;
+
+ for (i = 0; i < NRF_GZLL_CONST_PIPE_COUNT; i++)
+ {
+ (void)nrf_gzll_flush_rx_fifo(i);
+ }
+}
+
+
+/******************************************************************************/
+// Implementation: Gazell callback functions
+/******************************************************************************/
+
+void nrf_gzll_device_tx_failed(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info)
+{
+}
+
+
+void nrf_gzll_device_tx_success(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info)
+{
+}
+
+
+void nrf_gzll_disabled(void)
+{
+}
+
+
+void nrf_gzll_host_rx_data_ready(uint32_t pipe, nrf_gzll_host_rx_info_t rx_info)
+{
+ if (pipe == GZP_PAIRING_PIPE)
+ {
+ prev_gzp_rx_info = rx_info;
+ }
+}
+
+/** @} */
+/** @} */
+
+#endif
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp_host_nrf5x.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp_host_nrf5x.c
new file mode 100644
index 0000000..b78c34c
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/proprietary_rf/gzll/nrf_gzp_host_nrf5x.c
@@ -0,0 +1,74 @@
+/**
+ * Copyright (c) 2009 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include "nrf_gzp.h"
+#include "nrf_nvmc.h"
+
+/**
+ * @file
+ * @brief Implementation of Gazell Pairing Library (gzp), nRF5x specific Host functions.
+ * @defgroup gzp_source_host_nrf5x Gazell Pairing Host nRF5x specific implementation
+ * @{
+ * @ingroup gzp_04_source
+ */
+
+
+void gzp_host_chip_id_read(uint8_t *dst, uint8_t n)
+{
+ uint8_t i;
+ uint8_t random_number;
+
+ if ( *((uint8_t*)(GZP_PARAMS_STORAGE_ADR + GZP_HOST_ID_LENGTH + 1)) == 0xff)
+ {
+ nrf_nvmc_write_byte((GZP_PARAMS_STORAGE_ADR + GZP_HOST_ID_LENGTH + 1) , 0x00);
+
+ for (i = 0; i < n; i++)
+ {
+ gzp_random_numbers_generate(&random_number, 1);
+ nrf_nvmc_write_byte((GZP_PARAMS_STORAGE_ADR + GZP_HOST_ID_LENGTH + 2 + i) , random_number);
+ }
+ }
+
+ for (i = 0; i < n; i++)
+ {
+ *(dst++) = *((uint8_t*)(GZP_PARAMS_STORAGE_ADR + GZP_HOST_ID_LENGTH + 2 + i));
+ }
+}
+
+/** @} */