aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2018-08-23 17:08:59 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2018-08-23 17:12:21 +0200
commit3061ecca3d0fdfb87dabbf5f63c9e06c2a30f53a (patch)
treeab49cc16ed0b853452c5c2ed2d3042416d628986 /thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm
downloadiot-sensors-3061ecca3d0fdfb87dabbf5f63c9e06c2a30f53a.tar.gz
iot-sensors-3061ecca3d0fdfb87dabbf5f63c9e06c2a30f53a.tar.bz2
iot-sensors-3061ecca3d0fdfb87dabbf5f63c9e06c2a30f53a.tar.xz
iot-sensors-3061ecca3d0fdfb87dabbf5f63c9e06c2a30f53a.zip
o Initial import.HEADmaster
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm.c957
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm.h237
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm_hw.h103
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm_hw_nrf51.c120
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm_hw_nrf52.c128
5 files changed, 1545 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm.c
new file mode 100644
index 0000000..f73c030
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm.c
@@ -0,0 +1,957 @@
+/**
+ * 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.
+ *
+ */
+#include "sdk_common.h"
+#if NRF_MODULE_ENABLED(BLE_DTM)
+#include "ble_dtm.h"
+#include "ble_dtm_hw.h"
+#include <stdbool.h>
+#include <string.h>
+#include "nrf.h"
+
+#define DTM_HEADER_OFFSET 0 /**< Index where the header of the pdu is located. */
+#define DTM_HEADER_SIZE 2 /**< Size of PDU header. */
+#define DTM_PAYLOAD_MAX_SIZE 255 /**< Maximum payload size allowed during dtm execution. */
+#define DTM_LENGTH_OFFSET (DTM_HEADER_OFFSET + 1) /**< Index where the length of the payload is encoded. */
+#define DTM_PDU_MAX_MEMORY_SIZE (DTM_HEADER_SIZE + DTM_PAYLOAD_MAX_SIZE) /**< Maximum PDU size allowed during dtm execution. */
+#define DTM_ON_AIR_OVERHEAD_SIZE 10 /**< Size of the packet on air without the payload (preamble + sync word + type + RFU + length + CRC). */
+
+#define RX_MODE true /**< Constant defining RX mode for radio during dtm test. */
+#define TX_MODE false /**< Constant defining TX mode for radio during dtm test. */
+
+#define PHYS_CH_MAX 39 /**< Maximum number of valid channels in BLE. */
+
+// Values that for now are "constants" - they could be configured by a function setting them,
+// but most of these are set by the BLE DTM standard, so changing them is not relevant.
+#define RFPHY_TEST_0X0F_REF_PATTERN 0x0f /**< RF-PHY test packet patterns, for the repeated octet packets. */
+#define RFPHY_TEST_0X55_REF_PATTERN 0x55 /**< RF-PHY test packet patterns, for the repeated octet packets. */
+#define RFPHY_TEST_0XFF_REF_PATTERN 0xFF /**< RF-PHY test packet patterns, for the repeated octet packets. */
+
+#define PRBS9_CONTENT {0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B, \
+ 0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23, \
+ 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, \
+ 0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA, \
+ 0x0C, 0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A, \
+ 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE, \
+ 0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E, \
+ 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, \
+ 0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5, \
+ 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11, \
+ 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D, \
+ 0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65, \
+ 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, \
+ 0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F, \
+ 0x15, 0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF, \
+ 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3, \
+ 0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2, \
+ 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, \
+ 0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E, \
+ 0x14, 0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32, \
+ 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6, \
+ 0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF, \
+ 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, \
+ 0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1, \
+ 0x3F, 0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1, \
+ 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44, \
+ 0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27, \
+ 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, \
+ 0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3, \
+ 0x3C, 0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57, \
+ 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB, \
+ 0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7} /**< The PRBS9 sequence used as packet payload.
+ The bytes in the sequence is in the right order, but the bits of each byte in the array is reverse.
+ of that found by running the PRBS9 algorithm. This is because of the endianess of the nRF5 radio. */
+
+/**@brief Structure holding the PDU used for transmitting/receiving a PDU.
+ */
+typedef struct
+{
+ uint8_t content[DTM_HEADER_SIZE + DTM_PAYLOAD_MAX_SIZE]; /**< PDU packet content. */
+} pdu_type_t;
+
+/**@brief States used for the DTM test implementation.
+ */
+typedef enum
+{
+ STATE_UNINITIALIZED, /**< The DTM is uninitialized. */
+ STATE_IDLE, /**< State when system has just initialized, or current test has completed. */
+ STATE_TRANSMITTER_TEST, /**< State used when a DTM Transmission test is running. */
+ STATE_CARRIER_TEST, /**< State used when a DTM Carrier test is running (Vendor specific test). */
+ STATE_RECEIVER_TEST /**< State used when a DTM Receive test is running. */
+} state_t;
+
+
+// Internal variables set as side effects of commands or events.
+static state_t m_state = STATE_UNINITIALIZED; /**< Current machine state. */
+static uint16_t m_rx_pkt_count; /**< Number of valid packets received. */
+static pdu_type_t m_pdu; /**< PDU to be sent. */
+static uint16_t m_event; /**< current command status - initially "ok", may be set if error detected, or to packet count. */
+static bool m_new_event; /**< Command has been processed - number of not yet reported event bytes. */
+static uint32_t m_packet_length; /**< Payload length of transmitted PDU, bits 2:7 of 16-bit dtm command. */
+static dtm_pkt_type_t m_packet_type; /**< Bits 0..1 of 16-bit transmit command, or 0xFFFFFFFF. */
+static dtm_freq_t m_phys_ch; /**< 0..39 physical channel number (base 2402 MHz, Interval 2 MHz), bits 8:13 of 16-bit dtm command. */
+static uint32_t m_current_time = 0; /**< Counter for interrupts from timer to ensure that the 2 bytes forming a DTM command are received within the time window. */
+
+// Nordic specific configuration values (not defined by BLE standard).
+// Definition of initial values found in ble_dtm.h
+static int32_t m_tx_power = DEFAULT_TX_POWER; /**< TX power for transmission test, default to maximum value (+4 dBm). */
+static NRF_TIMER_Type * mp_timer = DEFAULT_TIMER; /**< Timer to be used. */
+static IRQn_Type m_timer_irq = DEFAULT_TIMER_IRQn; /**< which interrupt line to clear on every timeout */
+
+static uint8_t const m_prbs_content[] = PRBS9_CONTENT; /**< Pseudo-random bit sequence defined by the BLE standard. */
+static uint8_t m_packetHeaderLFlen = 8; /**< Length of length field in packet Header (in bits). */
+static uint8_t m_packetHeaderS0len = 1; /**< Length of S0 field in packet Header (in bytes). */
+static uint8_t m_packetHeaderS1len = 0; /**< Length of S1 field in packet Header (in bits). */
+static uint8_t m_packetHeaderPlen = RADIO_PCNF0_PLEN_8bit; /**< Length of the preamble. */
+
+static uint8_t m_crcConfSkipAddr = 1; /**< Leave packet address field out of CRC calculation. */
+static uint8_t m_static_length = 0; /**< Number of bytes sent in addition to the var.length payload. */
+static uint32_t m_balen = 3; /**< Base address length in bytes. */
+static uint32_t m_endian = RADIO_PCNF1_ENDIAN_Little; /**< On air endianess of packet, this applies to the S0, LENGTH, S1 and the PAYLOAD fields. */
+static uint32_t m_whitening = RADIO_PCNF1_WHITEEN_Disabled; /**< Whitening disabled. */
+static uint8_t m_crcLength = RADIO_CRCCNF_LEN_Three; /**< CRC Length (in bytes). */
+static uint32_t m_address = 0x71764129; /**< Address. */
+static uint32_t m_crc_poly = 0x0000065B; /**< CRC polynomial. */
+static uint32_t m_crc_init = 0x00555555; /**< Initial value for CRC calculation. */
+static uint8_t m_radio_mode = RADIO_MODE_MODE_Ble_1Mbit; /**< nRF51 specific radio mode value. */
+static uint32_t m_txIntervaluS = 2500; /**< Time between start of Tx packets (in uS). */
+
+
+/**@brief Function for verifying that a received PDU has the expected structure and content.
+ */
+static bool check_pdu(void)
+{
+ uint8_t k; // Byte pointer for running through PDU payload
+ uint8_t pattern; // Repeating octet value in payload
+ dtm_pkt_type_t pdu_packet_type; // Note: PDU packet type is a 4-bit field in HCI, but 2 bits in BLE DTM
+ uint32_t length = 0;
+
+ pdu_packet_type = (dtm_pkt_type_t)(m_pdu.content[DTM_HEADER_OFFSET] & 0x0F);
+ length = m_pdu.content[DTM_LENGTH_OFFSET];
+
+ // Check that the length is valid.
+ if (length > DTM_PAYLOAD_MAX_SIZE)
+ {
+ return false;
+ }
+
+ // If the 1Mbit or 2Mbit radio mode is active, check that one of the three valid uncoded DTM packet types are selected.
+ if ((m_radio_mode == RADIO_MODE_MODE_Ble_1Mbit || m_radio_mode == RADIO_MODE_MODE_Ble_2Mbit) && (pdu_packet_type > (dtm_pkt_type_t)DTM_PKT_0X55))
+ {
+ return false;
+ }
+
+#ifdef NRF52840_XXAA
+ // If a long range radio mode is active, check that one of the four valid coded DTM packet types are selected.
+ if ((m_radio_mode == RADIO_MODE_MODE_Ble_LR500Kbit || m_radio_mode == RADIO_MODE_MODE_Ble_LR125Kbit) && (pdu_packet_type > (dtm_pkt_type_t)DTM_PKT_0XFF))
+ {
+ return false;
+ }
+#endif
+
+ if (pdu_packet_type == DTM_PKT_PRBS9)
+ {
+ // Payload does not consist of one repeated octet; must compare ir with entire block into
+ return (memcmp(m_pdu.content + DTM_HEADER_SIZE, m_prbs_content, length) == 0);
+ }
+
+ if (pdu_packet_type == DTM_PKT_0X0F)
+ {
+ pattern = RFPHY_TEST_0X0F_REF_PATTERN;
+ }
+ else if (pdu_packet_type == DTM_PKT_0X55)
+ {
+ pattern = RFPHY_TEST_0X55_REF_PATTERN;
+ }
+ else if (pdu_packet_type == DTM_PKT_0XFF)
+ {
+ pattern = RFPHY_TEST_0XFF_REF_PATTERN;
+ }
+ else
+ {
+ // No valid packet type set.
+ return false;
+ }
+
+ for (k = 0; k < length; k++)
+ {
+ // Check repeated pattern filling the PDU payload
+ if (m_pdu.content[k + 2] != pattern)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+/**@brief Function for turning off the radio after a test.
+ * Also called after test done, to be ready for next test.
+ */
+static void radio_reset(void)
+{
+ NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Msk | PPI_CHENCLR_CH1_Msk;
+
+ NRF_RADIO->SHORTS = 0;
+ NRF_RADIO->EVENTS_DISABLED = 0;
+ NRF_RADIO->TASKS_DISABLE = 1;
+
+ while (NRF_RADIO->EVENTS_DISABLED == 0)
+ {
+ // Do nothing
+ }
+
+ NRF_RADIO->EVENTS_DISABLED = 0;
+ NRF_RADIO->TASKS_RXEN = 0;
+ NRF_RADIO->TASKS_TXEN = 0;
+
+ m_rx_pkt_count = 0;
+}
+
+
+/**@brief Function for initializing the radio for DTM.
+ */
+static uint32_t radio_init(void)
+{
+ if (dtm_radio_validate(m_tx_power, m_radio_mode) != DTM_SUCCESS)
+ {
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+ return DTM_ERROR_ILLEGAL_CONFIGURATION;
+ }
+
+ // Turn off radio before configuring it
+ radio_reset();
+
+ NRF_RADIO->TXPOWER = m_tx_power;
+ NRF_RADIO->MODE = m_radio_mode << RADIO_MODE_MODE_Pos;
+
+ // Set the access address, address0/prefix0 used for both Rx and Tx address
+ NRF_RADIO->PREFIX0 &= ~RADIO_PREFIX0_AP0_Msk;
+ NRF_RADIO->PREFIX0 |= (m_address >> 24) & RADIO_PREFIX0_AP0_Msk;
+ NRF_RADIO->BASE0 = m_address << 8;
+ NRF_RADIO->RXADDRESSES = RADIO_RXADDRESSES_ADDR0_Enabled << RADIO_RXADDRESSES_ADDR0_Pos;
+ NRF_RADIO->TXADDRESS = (0x00 << RADIO_TXADDRESS_TXADDRESS_Pos) & RADIO_TXADDRESS_TXADDRESS_Msk;
+
+ // Configure CRC calculation
+ NRF_RADIO->CRCCNF = (m_crcConfSkipAddr << RADIO_CRCCNF_SKIP_ADDR_Pos) |
+ (m_crcLength << RADIO_CRCCNF_LEN_Pos);
+
+ if (m_radio_mode == RADIO_MODE_MODE_Ble_1Mbit || m_radio_mode == RADIO_MODE_MODE_Ble_2Mbit)
+ {
+ // Non-coded PHY
+ NRF_RADIO->PCNF0 = (m_packetHeaderS1len << RADIO_PCNF0_S1LEN_Pos) |
+ (m_packetHeaderS0len << RADIO_PCNF0_S0LEN_Pos) |
+ (m_packetHeaderLFlen << RADIO_PCNF0_LFLEN_Pos) |
+ (m_packetHeaderPlen << RADIO_PCNF0_PLEN_Pos);
+ }
+#ifdef NRF52840_XXAA
+ else
+ {
+ // Coded PHY (Long range)
+ NRF_RADIO->PCNF0 = (m_packetHeaderS1len << RADIO_PCNF0_S1LEN_Pos) |
+ (m_packetHeaderS0len << RADIO_PCNF0_S0LEN_Pos) |
+ (m_packetHeaderLFlen << RADIO_PCNF0_LFLEN_Pos) |
+ (3 << RADIO_PCNF0_TERMLEN_Pos) |
+ (2 << RADIO_PCNF0_CILEN_Pos) |
+ (m_packetHeaderPlen << RADIO_PCNF0_PLEN_Pos);
+ }
+#endif
+
+ NRF_RADIO->PCNF1 = (m_whitening << RADIO_PCNF1_WHITEEN_Pos) |
+ (m_endian << RADIO_PCNF1_ENDIAN_Pos) |
+ (m_balen << RADIO_PCNF1_BALEN_Pos) |
+ (m_static_length << RADIO_PCNF1_STATLEN_Pos) |
+ (DTM_PAYLOAD_MAX_SIZE << RADIO_PCNF1_MAXLEN_Pos);
+
+ return DTM_SUCCESS;
+}
+
+
+/**@brief Function for preparing the radio. At start of each test: Turn off RF, clear interrupt flags of RF, initialize the radio
+ * at given RF channel.
+ *
+ *@param[in] rx boolean indicating if radio should be prepared in rx mode (true) or tx mode.
+ */
+static void radio_prepare(bool rx)
+{
+ dtm_turn_off_test();
+ NRF_RADIO->CRCPOLY = m_crc_poly;
+ NRF_RADIO->CRCINIT = m_crc_init;
+ NRF_RADIO->FREQUENCY = (m_phys_ch << 1) + 2; // Actual frequency (MHz): 2400 + register value
+ NRF_RADIO->PACKETPTR = (uint32_t)&m_pdu; // Setting packet pointer will start the radio
+ NRF_RADIO->EVENTS_READY = 0;
+ NRF_RADIO->SHORTS = (1 << RADIO_SHORTS_READY_START_Pos) | // Shortcut between READY event and START task
+ (1 << RADIO_SHORTS_END_DISABLE_Pos); // Shortcut between END event and DISABLE task
+
+ if (rx)
+ {
+ NRF_RADIO->EVENTS_END = 0;
+ NRF_RADIO->TASKS_RXEN = 1; // shorts will start radio in RX mode when it is ready
+ }
+ else // tx
+ {
+ NRF_RADIO->TXPOWER = m_tx_power;
+ }
+}
+
+
+/**@brief Function for terminating the ongoing test (if any) and closing down the radio.
+ */
+static void dtm_test_done(void)
+{
+ dtm_turn_off_test();
+ NRF_PPI->CHENCLR = 0x01;
+ NRF_PPI->CH[0].EEP = 0; // Break connection from timer to radio to stop transmit loop
+ NRF_PPI->CH[0].TEP = 0;
+
+ radio_reset();
+ m_state = STATE_IDLE;
+}
+
+
+/**@brief Function for configuring the timer for 625us cycle time.
+ */
+static uint32_t timer_init(void)
+{
+ // Use 16MHz from external crystal
+ // This could be customized for RC/Xtal, or even to use a 32 kHz crystal
+ NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
+ NRF_CLOCK->TASKS_HFCLKSTART = 1;
+
+ while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
+ {
+ // Do nothing while waiting for the clock to start
+ }
+
+ mp_timer->TASKS_STOP = 1; // Stop timer, if it was running
+ mp_timer->TASKS_CLEAR = 1;
+ mp_timer->MODE = TIMER_MODE_MODE_Timer; // Timer mode (not counter)
+ mp_timer->EVENTS_COMPARE[0] = 0; // clean up possible old events
+ mp_timer->EVENTS_COMPARE[1] = 0;
+ mp_timer->EVENTS_COMPARE[2] = 0;
+ mp_timer->EVENTS_COMPARE[3] = 0;
+
+ // Timer is polled, but enable the compare0 interrupt in order to wakeup from CPU sleep
+ mp_timer->INTENSET = TIMER_INTENSET_COMPARE0_Msk;
+ mp_timer->SHORTS = 1 << TIMER_SHORTS_COMPARE0_CLEAR_Pos; // Clear the count every time timer reaches the CCREG0 count
+ mp_timer->PRESCALER = 4; // Input clock is 16MHz, timer clock = 2 ^ prescale -> interval 1us
+ mp_timer->CC[0] = m_txIntervaluS; // 625uS with 1MHz clock to the timer
+ mp_timer->CC[1] = UART_POLL_CYCLE; // Depends on the baud rate of the UART. Default baud rate of 19200 will result in a 260uS time with 1MHz clock to the timer
+ mp_timer->TASKS_START = 1; // Start the timer - it will be running continuously
+ m_current_time = 0;
+ return DTM_SUCCESS;
+}
+
+
+/**@brief Function for handling vendor specific commands.
+ * Used when packet type is set to Vendor specific.
+ * The length field is used for encoding vendor specific command.
+ * The frequency field is used for encoding vendor specific options to the command.
+ *
+ * @param[in] vendor_cmd Vendor specific command to be executed.
+ * @param[in] vendor_option Vendor specific option to the vendor command.
+ *
+ * @return DTM_SUCCESS or one of the DTM_ERROR_ values
+ */
+static uint32_t dtm_vendor_specific_pkt(uint32_t vendor_cmd, dtm_freq_t vendor_option)
+{
+ switch (vendor_cmd)
+ {
+ // nRFgo Studio uses CARRIER_TEST_STUDIO to indicate a continuous carrier without
+ // a modulated signal.
+ case CARRIER_TEST:
+ case CARRIER_TEST_STUDIO:
+ // Not a packet type, but used to indicate that a continuous carrier signal
+ // should be transmitted by the radio.
+ radio_prepare(TX_MODE);
+
+ dtm_constant_carrier();
+
+ // Shortcut between READY event and START task
+ NRF_RADIO->SHORTS = 1 << RADIO_SHORTS_READY_START_Pos;
+
+ // Shortcut will start radio in Tx mode when it is ready
+ NRF_RADIO->TASKS_TXEN = 1;
+ m_state = STATE_CARRIER_TEST;
+ break;
+
+ case SET_TX_POWER:
+ if (!dtm_set_txpower(vendor_option))
+ {
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+ return DTM_ERROR_ILLEGAL_CONFIGURATION;
+ }
+ break;
+
+ case SELECT_TIMER:
+ if (!dtm_set_timer(vendor_option))
+ {
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+ return DTM_ERROR_ILLEGAL_CONFIGURATION;
+ }
+ break;
+ }
+ // Event code is unchanged, successful
+ return DTM_SUCCESS;
+}
+
+
+static uint32_t dtm_packet_interval_calculate(uint32_t test_payload_length, uint32_t mode)
+{
+ uint32_t test_packet_length = 0; // [us] NOTE: bits are us at 1Mbit
+ uint32_t packet_interval = 0; // us
+ uint32_t overhead_bits = 0; // bits
+
+ /* packet overhead
+ * see BLE [Vol 6, Part F] page 213
+ * 4.1 LE TEST PACKET FORMAT */
+ if (mode == RADIO_MODE_MODE_Ble_2Mbit)
+ {
+ // 16 preamble
+ // 32 sync word
+ // 8 PDU header, actually packetHeaderS0len * 8
+ // 8 PDU length, actually packetHeaderLFlen
+ // 24 CRC
+ overhead_bits = 88; // 11 bytes
+ }
+ else if (mode == RADIO_MODE_MODE_Ble_1Mbit)
+ {
+ // 8 preamble
+ // 32 sync word
+ // 8 PDU header, actually packetHeaderS0len * 8
+ // 8 PDU length, actually packetHeaderLFlen
+ // 24 CRC
+ overhead_bits = 80; // 10 bytes
+ }
+#ifdef NRF52840_XXAA
+ else if (mode == RADIO_MODE_MODE_Ble_LR125Kbit)
+ {
+ // 80 preamble
+ // 32 * 8 sync word coding=8
+ // 2 * 8 Coding indicator, coding=8
+ // 3 * 8 TERM1 coding=8
+ // 8 * 8 PDU header, actually packetHeaderS0len * 8 coding=8
+ // 8 * 8 PDU length, actually packetHeaderLFlen coding=8
+ // 24 * 8 CRC coding=8
+ // 3 * 8 TERM2 coding=8
+ overhead_bits = 720; // 90 bytes
+ }
+ else if (mode == RADIO_MODE_MODE_Ble_LR500Kbit)
+ {
+ // 80 preamble
+ // 32 * 8 sync word coding=8
+ // 2 * 8 Coding indicator, coding=8
+ // 3 * 8 TERM 1 coding=8
+ // 8 * 2 PDU header, actually packetHeaderS0len * 8 coding=2
+ // 8 * 2 PDU length, actually packetHeaderLFlen coding=2
+ // 24 * 2 CRC coding=2
+ // 3 * 2 TERM2 coding=2
+ // NOTE: this makes us clock out 46 bits for CI + TERM1 + TERM2
+ // assumption the radio will handle this
+ overhead_bits = 462; // 57.75 bytes
+ }
+#endif
+ /* add PDU payload test_payload length */
+ test_packet_length = (test_payload_length * 8); // in bits
+#ifdef NRF52840_XXAA
+ // account for the encoding of PDU
+ if (mode == RADIO_MODE_MODE_Ble_LR125Kbit)
+ {
+ test_packet_length *= 8; // 1 to 8 encoding
+ }
+ if (mode == RADIO_MODE_MODE_Ble_LR500Kbit)
+ {
+ test_packet_length *= 2; // 1 to 2 encoding
+ }
+#endif
+ // add overhead calculated above
+ test_packet_length += overhead_bits;
+ // we remember this bits are us in 1Mbit
+ if (mode == RADIO_MODE_MODE_Ble_2Mbit)
+ {
+ test_packet_length /= 2; // double speed
+ }
+
+ /*
+ * packet_interval = ceil((test_packet_length+249)/625)*625
+ * NOTE: To avoid floating point an equivalent calculation is used.
+ */
+ uint32_t i = 0;
+ uint32_t timeout = 0;
+ do
+ {
+ i++;
+ timeout = i * 625;
+ } while (test_packet_length + 249 > timeout);
+ packet_interval = i * 625;
+
+ return packet_interval;
+}
+
+
+uint32_t dtm_init(void)
+{
+ if ((timer_init() != DTM_SUCCESS) || (radio_init() != DTM_SUCCESS))
+ {
+ return DTM_ERROR_ILLEGAL_CONFIGURATION;
+ }
+ m_new_event = false;
+ m_state = STATE_IDLE;
+ m_packet_length = 0;
+
+ // Enable wake-up on event
+ SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
+
+ return DTM_SUCCESS;
+}
+
+
+uint32_t dtm_wait(void)
+{
+ // Enable wake-up on event
+ SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
+
+ for (;;)
+ {
+ // Event may be the reception of a packet -
+ // handle radio first, to give it highest priority:
+ if (NRF_RADIO->EVENTS_END != 0)
+ {
+ NRF_RADIO->EVENTS_END = 0;
+ NVIC_ClearPendingIRQ(RADIO_IRQn);
+
+ if (m_state == STATE_RECEIVER_TEST)
+ {
+ NRF_RADIO->TASKS_RXEN = 1;
+ if ((NRF_RADIO->CRCSTATUS == 1) && check_pdu())
+ {
+ // Count the number of successfully received packets
+ m_rx_pkt_count++;
+ }
+ // Note that failing packets are simply ignored (CRC or contents error).
+
+ // Zero fill all pdu fields to avoid stray data
+ memset(&m_pdu, 0, DTM_PDU_MAX_MEMORY_SIZE);
+ }
+ // If no RECEIVER_TEST is running, ignore incoming packets (but do clear IRQ!)
+ }
+
+ // Check for timeouts:
+ if (mp_timer->EVENTS_COMPARE[0] != 0)
+ {
+ mp_timer->EVENTS_COMPARE[0] = 0;
+ }
+ else if (mp_timer->EVENTS_COMPARE[1] != 0)
+ {
+ // Reset timeout event flag for next iteration.
+ mp_timer->EVENTS_COMPARE[1] = 0;
+ NVIC_ClearPendingIRQ(m_timer_irq);
+ return ++m_current_time;
+ }
+
+ // Other events: No processing
+ }
+}
+
+uint32_t dtm_cmd(dtm_cmd_t cmd, dtm_freq_t freq, uint32_t length, dtm_pkt_type_t payload)
+{
+ // Save specified packet in static variable for tx/rx functions to use.
+ // Note that BLE conformance testers always use full length packets.
+ m_packet_length = (m_packet_length & 0xC0) | ((uint8_t)length & 0x3F);
+ m_packet_type = payload;
+ m_phys_ch = freq;
+
+ // If 1 Mbit or 2 Mbit radio mode is in use check for Vendor Specific payload.
+ if ((m_radio_mode == RADIO_MODE_MODE_Ble_1Mbit || m_radio_mode == RADIO_MODE_MODE_Ble_2Mbit) && payload == DTM_PKT_VENDORSPECIFIC)
+ {
+ /* Note that in a HCI adaption layer, as well as in the DTM PDU format,
+ the value 0x03 is a distinct bit pattern (PRBS15). Even though BLE does not
+ support PRBS15, this implementation re-maps 0x03 to DTM_PKT_VENDORSPECIFIC,
+ to avoid the risk of confusion, should the code be extended to greater coverage.
+ */
+ m_packet_type = DTM_PKT_TYPE_VENDORSPECIFIC;
+ }
+
+ // Clean out any non-retrieved event that might linger from an earlier test
+ m_new_event = true;
+
+ // Set default event; any error will set it to LE_TEST_STATUS_EVENT_ERROR
+ m_event = LE_TEST_STATUS_EVENT_SUCCESS;
+
+ if (m_state == STATE_UNINITIALIZED)
+ {
+ // Application has not explicitly initialized DTM,
+ return DTM_ERROR_UNINITIALIZED;
+ }
+
+ if (cmd == LE_TEST_SETUP)
+ {
+ // Note that timer will continue running after a reset
+ dtm_test_done();
+ if (freq == LE_TEST_SETUP_RESET)
+ {
+ if (length != 0x00)
+ {
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+ return DTM_ERROR_ILLEGAL_CONFIGURATION;
+ }
+ // Reset the packet length upper bits.
+ m_packet_length = 0;
+
+ // Reset the selected PHY to 1Mbit
+ m_radio_mode = RADIO_MODE_MODE_Ble_1Mbit;
+ m_packetHeaderPlen = RADIO_PCNF0_PLEN_8bit;
+
+#ifdef NRF52840_XXAA
+ // Workaround for Errata ID 164
+ *(volatile uint32_t *)0x4000173C &= ~0x80000000;
+
+ // Workaround for Errata ID 191
+ *(volatile uint32_t *) 0x40001740 = ((*((volatile uint32_t *) 0x40001740)) & 0x7FFFFFFF);
+#endif
+ }
+ else if (freq == LE_TEST_SETUP_SET_UPPER)
+ {
+ if (length > 0x03)
+ {
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+ return DTM_ERROR_ILLEGAL_CONFIGURATION;
+ }
+ m_packet_length = length << 6;
+ }
+ else if (freq == LE_TEST_SETUP_SET_PHY)
+ {
+ switch (length)
+ {
+ case LE_PHY_1M:
+ m_radio_mode = RADIO_MODE_MODE_Ble_1Mbit;
+ m_packetHeaderPlen = RADIO_PCNF0_PLEN_8bit;
+
+#ifdef NRF52840_XXAA
+ // Workaround for Errata ID 164
+ *(volatile uint32_t *)0x4000173C &= ~0x80000000;
+
+ // Workaround for Errata ID 191
+ *(volatile uint32_t *) 0x40001740 = ((*((volatile uint32_t *) 0x40001740)) & 0x7FFFFFFF);
+#endif
+
+ return radio_init();
+
+ case LE_PHY_2M:
+ m_radio_mode = RADIO_MODE_MODE_Ble_2Mbit;
+ m_packetHeaderPlen = RADIO_PCNF0_PLEN_16bit;
+
+#ifdef NRF52840_XXAA
+ // Workaround for Errata ID 164
+ *(volatile uint32_t *)0x4000173C &= ~0x80000000;
+
+ // Workaround for Errata ID 191
+ *(volatile uint32_t *) 0x40001740 = ((*((volatile uint32_t *) 0x40001740)) & 0x7FFFFFFF);
+#endif
+
+ return radio_init();
+
+ case LE_PHY_LE_CODED_S8:
+#ifdef NRF52840_XXAA
+ m_radio_mode = RADIO_MODE_MODE_Ble_LR125Kbit;
+ m_packetHeaderPlen = RADIO_PCNF0_PLEN_LongRange;
+
+ // Workaround for Errata ID 164
+ *(volatile uint32_t *)0x4000173C |= 0x80000000;
+ *(volatile uint32_t *)0x4000173C = ((*(volatile uint32_t *)0x4000173C & 0xFFFFFF00) | 0x5C);
+
+ // Workaround for Errata ID 191
+ *(volatile uint32_t *) 0x40001740 = ((*((volatile uint32_t *) 0x40001740)) & 0x7FFF00FF) | 0x80000000 | (((uint32_t)(196)) << 8);
+
+ return radio_init();
+#else
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+ return DTM_ERROR_ILLEGAL_CONFIGURATION;
+#endif // NRF52840_XXAA
+ case LE_PHY_LE_CODED_S2:
+#ifdef NRF52840_XXAA
+ m_radio_mode = RADIO_MODE_MODE_Ble_LR500Kbit;
+ m_packetHeaderPlen = RADIO_PCNF0_PLEN_LongRange;
+
+ // Workaround for Errata ID 164
+ *(volatile uint32_t *)0x4000173C |= 0x80000000;
+ *(volatile uint32_t *)0x4000173C = ((*(volatile uint32_t *)0x4000173C & 0xFFFFFF00) | 0x5C);
+
+ // Workaround for Errata ID 191
+ *(volatile uint32_t *) 0x40001740 = ((*((volatile uint32_t *) 0x40001740)) & 0x7FFF00FF) | 0x80000000 | (((uint32_t)(196)) << 8);
+
+ return radio_init();
+#else
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+ return DTM_ERROR_ILLEGAL_CONFIGURATION;
+#endif
+ default:
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+ return DTM_ERROR_ILLEGAL_CONFIGURATION;
+ }
+ }
+ else if(freq == LE_TEST_SETUP_SELECT_MODULATION)
+ {
+ if (length > 0x01)
+ {
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+ return DTM_ERROR_ILLEGAL_CONFIGURATION;
+ }
+ // Only standard modulation is supported.
+ }
+ else if (freq == LE_TEST_SETUP_READ_SUPPORTED)
+ {
+ if (length != 0x00)
+ {
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+ return DTM_ERROR_ILLEGAL_CONFIGURATION;
+ }
+ // 0XXXXXXXXXXX0110 indicate that 2Mbit and DLE is supported and stable modulation is not supported (No nRF5 device supports this).
+ m_event = 0x0006;
+ }
+ else if (freq == LE_TEST_SETUP_READ_MAX)
+ {
+ // Read max supported value.
+ switch (length)
+ {
+ case 0x00:
+ // Read supportedMaxTxOctets
+ m_event = 0x01FE;
+ break;
+
+ case 0x01:
+ // Read supportedMaxTxTime
+ m_event = 0x4290;
+ break;
+
+ case 0x02:
+ // Read supportedMaxRxOctets
+ m_event = 0x01FE;
+ break;
+
+ case 0x03:
+ // Read supportedMaxRxTime
+ m_event = 0x4290;
+ break;
+
+ default:
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+ return DTM_ERROR_ILLEGAL_CONFIGURATION;
+ }
+ }
+ else
+ {
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+ return DTM_ERROR_ILLEGAL_CONFIGURATION;
+ }
+ return DTM_SUCCESS;
+ }
+
+ if (cmd == LE_TEST_END)
+ {
+ if (m_state == STATE_IDLE)
+ {
+ // Sequencing error - only rx or tx test may be ended!
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+ return DTM_ERROR_INVALID_STATE;
+ }
+ m_event = LE_PACKET_REPORTING_EVENT | m_rx_pkt_count;
+ dtm_test_done();
+ return DTM_SUCCESS;
+ }
+
+ if (m_state != STATE_IDLE)
+ {
+ // Sequencing error - only TEST_END/RESET are legal while test is running
+ // Note: State is unchanged; ongoing test not affected
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+ return DTM_ERROR_INVALID_STATE;
+ }
+
+ // Check for illegal values of m_phys_ch. Skip the check if the packet is vendor spesific.
+ if (payload != DTM_PKT_VENDORSPECIFIC && m_phys_ch > PHYS_CH_MAX)
+ {
+ // Parameter error
+ // Note: State is unchanged; ongoing test not affected
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+
+ return DTM_ERROR_ILLEGAL_CHANNEL;
+ }
+
+ m_rx_pkt_count = 0;
+
+ if (cmd == LE_RECEIVER_TEST)
+ {
+ // Zero fill all pdu fields to avoid stray data from earlier test run
+ memset(&m_pdu, 0, DTM_PDU_MAX_MEMORY_SIZE);
+ radio_prepare(RX_MODE); // Reinitialize "everything"; RF interrupts OFF
+ m_state = STATE_RECEIVER_TEST;
+ return DTM_SUCCESS;
+ }
+
+ if (cmd == LE_TRANSMITTER_TEST)
+ {
+ // Check for illegal values of m_packet_length. Skip the check if the packet is vendor spesific.
+ if (m_packet_type != DTM_PKT_TYPE_VENDORSPECIFIC && m_packet_length > DTM_PAYLOAD_MAX_SIZE)
+ {
+ // Parameter error
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+ return DTM_ERROR_ILLEGAL_LENGTH;
+ }
+
+
+ m_pdu.content[DTM_LENGTH_OFFSET] = m_packet_length;
+ // Note that PDU uses 4 bits even though BLE DTM uses only 2 (the HCI SDU uses all 4)
+ switch (m_packet_type)
+ {
+ case DTM_PKT_PRBS9:
+ m_pdu.content[DTM_HEADER_OFFSET] = DTM_PDU_TYPE_PRBS9;
+ // Non-repeated, must copy entire pattern to PDU
+ memcpy(m_pdu.content + DTM_HEADER_SIZE, m_prbs_content, m_packet_length);
+ break;
+
+ case DTM_PKT_0X0F:
+ m_pdu.content[DTM_HEADER_OFFSET] = DTM_PDU_TYPE_0X0F;
+ // Bit pattern 00001111 repeated
+ memset(m_pdu.content + DTM_HEADER_SIZE, RFPHY_TEST_0X0F_REF_PATTERN, m_packet_length);
+ break;
+
+ case DTM_PKT_0X55:
+ m_pdu.content[DTM_HEADER_OFFSET] = DTM_PDU_TYPE_0X55;
+ // Bit pattern 01010101 repeated
+ memset(m_pdu.content + DTM_HEADER_SIZE, RFPHY_TEST_0X55_REF_PATTERN, m_packet_length);
+ break;
+
+ case DTM_PKT_0XFF:
+ m_pdu.content[DTM_HEADER_OFFSET] = DTM_PDU_TYPE_0XFF;
+ // Bit pattern 11111111 repeated. Only available in coded PHY (Long range).
+ memset(m_pdu.content + DTM_HEADER_SIZE, RFPHY_TEST_0XFF_REF_PATTERN, m_packet_length);
+ break;
+
+ case DTM_PKT_TYPE_VENDORSPECIFIC:
+ // The length field is for indicating the vendor specific command to execute.
+ // The frequency field is used for vendor specific options to the command.
+ return dtm_vendor_specific_pkt(length, freq);
+
+ default:
+ // Parameter error
+ m_event = LE_TEST_STATUS_EVENT_ERROR;
+ return DTM_ERROR_ILLEGAL_CONFIGURATION;
+ }
+
+ // Initialize CRC value, set channel:
+ radio_prepare(TX_MODE);
+
+ // Set the timer to the correct period. The delay between each packet is described in the
+ // Bluetooth Core Spsification version 4.2 Vol. 6 Part F Section 4.1.6.
+ mp_timer->CC[0] = dtm_packet_interval_calculate(m_packet_length, m_radio_mode);
+
+ // Configure PPI so that timer will activate radio every 625 us
+ NRF_PPI->CH[0].EEP = (uint32_t)&mp_timer->EVENTS_COMPARE[0];
+ NRF_PPI->CH[0].TEP = (uint32_t)&NRF_RADIO->TASKS_TXEN;
+ NRF_PPI->CHENSET = 0x01;
+ m_state = STATE_TRANSMITTER_TEST;
+ }
+ return DTM_SUCCESS;
+}
+
+
+bool dtm_event_get(dtm_event_t *p_dtm_event)
+{
+ bool was_new = m_new_event;
+ // mark the current event as retrieved
+ m_new_event = false;
+ *p_dtm_event = m_event;
+ // return value indicates whether this value was already retrieved.
+ return was_new;
+}
+
+
+// =================================================================================================
+// Configuration functions (only for parameters not definitely determined by the BLE DTM standard).
+// These functions return true if successful, false if value could not be set
+
+
+/**@brief Function for configuring the output power for transmitter test.
+ This function may be called directly, or through dtm_cmd() specifying
+ DTM_PKT_VENDORSPECIFIC as payload, SET_TX_POWER as length, and the dBm value as frequency.
+ */
+bool dtm_set_txpower(uint32_t new_tx_power)
+{
+ // radio->TXPOWER register is 32 bits, low octet a signed value, upper 24 bits zeroed
+ int8_t new_power8 = (int8_t)(new_tx_power & 0xFF);
+
+ // The two most significant bits are not sent in the 6 bit field of the DTM command.
+ // These two bits are 1's if and only if the tx_power is a negative number.
+ // All valid negative values have the fourth most significant bit as 1.
+ // All valid positive values have the fourth most significant bit as 0.
+ // By checking this bit, the two most significant bits can be determined.
+ new_power8 = (new_power8 & 0x30) != 0 ? (new_power8 | 0xC0) : new_power8;
+
+ if (m_state > STATE_IDLE)
+ {
+ // radio must be idle to change the tx power
+ return false;
+ }
+
+ m_tx_power = new_power8;
+
+ return true;
+}
+
+
+/**@brief Function for selecting a timer resource.
+ * This function may be called directly, or through dtm_cmd() specifying
+ * DTM_PKT_VENDORSPECIFIC as payload, SELECT_TIMER as length, and the timer as freq
+ *
+ * @param[in] new_timer Timer id for the timer to use: 0, 1, or 2.
+ *
+ * @return true if the timer was successfully changed, false otherwise.
+ */
+bool dtm_set_timer(uint32_t new_timer)
+{
+ if (m_state > STATE_IDLE)
+ {
+ return false;
+ }
+ return dtm_hw_set_timer(&mp_timer, &m_timer_irq, new_timer);
+}
+
+/// @}
+#endif // NRF_MODULE_ENABLED(BLE_DTM)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm.h
new file mode 100644
index 0000000..61f92c5
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm.h
@@ -0,0 +1,237 @@
+/**
+ * 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
+ *
+ * @defgroup ble_dtm DTM - Direct Test Mode
+ * @{
+ * @ingroup ble_sdk_lib
+ * @brief Module for testing RF/PHY using DTM commands.
+ */
+
+#ifndef BLE_DTM_H__
+#define BLE_DTM_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "nrf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**@brief Configuration parameters. */
+#define DTM_BITRATE UARTE_BAUDRATE_BAUDRATE_Baud19200 /**< Serial bitrate on the UART */
+#define DEFAULT_TX_POWER RADIO_TXPOWER_TXPOWER_0dBm /**< Default Transmission power using in the DTM module. */
+#define DEFAULT_TIMER NRF_TIMER0 /**< Default timer used for timing. */
+#define DEFAULT_TIMER_IRQn TIMER0_IRQn /**< IRQ used for timer. NOTE: MUST correspond to DEFAULT_TIMER. */
+
+/**@brief BLE DTM command codes. */
+typedef uint32_t dtm_cmd_t; /**< DTM command type. */
+
+#define LE_TEST_SETUP 0 /**< DTM command: Set PHY or modulation, configure upper two bits of length,
+ request matrix of supported features or request max values of parameters. */
+#define LE_RECEIVER_TEST 1 /**< DTM command: Start receive test. */
+#define LE_TRANSMITTER_TEST 2 /**< DTM command: Start transmission test. */
+#define LE_TEST_END 3 /**< DTM command: End test and send packet report. */
+
+#define LE_TEST_SETUP_RESET 0 /**< DTM command parameter: Stop TX/RX, reset the packet length upper bits and set the PHY to 1Mbit. */
+#define LE_TEST_SETUP_SET_UPPER 1 /**< DTM command parameter: Set the upper two bits of the length field. */
+#define LE_TEST_SETUP_SET_PHY 2 /**< DTM command parameter: Select the PHY to be used for packets. */
+#define LE_TEST_SETUP_SELECT_MODULATION 3 /**< DTM command parameter: Select standard or stable modulation index. Stable modulation index is not supported. */
+#define LE_TEST_SETUP_READ_SUPPORTED 4 /**< DTM command parameter: Read the supported test case features. */
+#define LE_TEST_SETUP_READ_MAX 5 /**< DTM command parameter: Read the max supported time and length for packets. */
+
+#define LE_PHY_1M 1 /**< DTM command parameter: Set PHY for future packets to use 1MBit PHY. */
+#define LE_PHY_2M 2 /**< DTM command parameter: Set PHY for future packets to use 2MBit PHY. */
+#define LE_PHY_LE_CODED_S8 3 /**< DTM command parameter: Set PHY for future packets to use coded PHY with S=8. */
+#define LE_PHY_LE_CODED_S2 4 /**< DTM command parameter: Set PHY for future packets to use coded PHY with S=2 */
+
+// Configuration options used as parameter 2
+// when cmd == LE_TRANSMITTER_TEST and payload == DTM_PKT_VENDORSPECIFIC
+// Configuration value, if any, is supplied in parameter 3
+
+#define CARRIER_TEST 0 /**< Length=0 indicates a constant, unmodulated carrier until LE_TEST_END or LE_RESET */
+#define CARRIER_TEST_STUDIO 1 /**< nRFgo Studio uses value 1 in length field, to indicate a constant, unmodulated carrier until LE_TEST_END or LE_RESET */
+#define SET_TX_POWER 2 /**< Set transmission power, value -40..+4 dBm in steps of 4 */
+#define SELECT_TIMER 3 /**< Select on of the 16 MHz timers 0, 1 or 2 */
+
+#define LE_PACKET_REPORTING_EVENT 0x8000 /**< DTM Packet reporting event, returned by the device to the tester. */
+#define LE_TEST_STATUS_EVENT_SUCCESS 0x0000 /**< DTM Status event, indicating success. */
+#define LE_TEST_STATUS_EVENT_ERROR 0x0001 /**< DTM Status event, indicating an error. */
+
+#define DTM_PKT_PRBS9 0x00 /**< Bit pattern PRBS9. */
+#define DTM_PKT_0X0F 0x01 /**< Bit pattern 11110000 (LSB is the leftmost bit). */
+#define DTM_PKT_0X55 0x02 /**< Bit pattern 10101010 (LSB is the leftmost bit). */
+#define DTM_PKT_0XFF 0x03 /**< Bit pattern 11111111 (Used only for coded PHY). */
+#define DTM_PKT_VENDORSPECIFIC 0x03 /**< Vendor specific PKT field value. Nordic: Continuous carrier test, or configuration. */
+#define DTM_PKT_TYPE_VENDORSPECIFIC 0xFF /**< Vendor specific packet type for internal use. */
+
+// The pdu payload type for each bit pattern. Identical to the PKT value except pattern 0xFF which is 0x04.
+#define DTM_PDU_TYPE_PRBS9 0x00 /**< PDU payload type for bit pattern PRBS9. */
+#define DTM_PDU_TYPE_0X0F 0x01 /**< PDU payload type for bit pattern 11110000 (LSB is the leftmost bit). */
+#define DTM_PDU_TYPE_0X55 0x02 /**< PDU payload type for bit pattern 10101010 (LSB is the leftmost bit). */
+#define DTM_PDU_TYPE_0XFF 0x04 /**< PDU payload type for bit pattern 11111111 (Used only for coded PHY). */
+
+/**@brief Return codes from dtm_cmd(). */
+#define DTM_SUCCESS 0x00 /**< Indicate that the DTM function completed with success. */
+#define DTM_ERROR_ILLEGAL_CHANNEL 0x01 /**< Physical channel number must be in the range 0..39. */
+#define DTM_ERROR_INVALID_STATE 0x02 /**< Sequencing error: Command is not valid now. */
+#define DTM_ERROR_ILLEGAL_LENGTH 0x03 /**< Payload size must be in the range 0..37. */
+#define DTM_ERROR_ILLEGAL_CONFIGURATION 0x04 /**< Parameter out of range (legal range is function dependent). */
+#define DTM_ERROR_UNINITIALIZED 0x05 /**< DTM module has not been initialized by the application. */
+
+/**@details The UART poll cycle in micro seconds.
+ * A baud rate of e.g. 19200 bits / second, and 8 data bits, 1 start/stop bit, no flow control,
+ * give the time to transmit a byte: 10 bits * 1/19200 = approx: 520 us.
+ * To ensure no loss of bytes, the UART should be polled every 260 us.
+ */
+#if DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud9600
+#define UART_POLL_CYCLE ((uint32_t)(10*1e6/9600/2))
+#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud14400
+#define UART_POLL_CYCLE ((uint32_t)(10*1e6/14400/2))
+#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud19200
+#define UART_POLL_CYCLE ((uint32_t)(10*1e6/19200/2))
+#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud28800
+#define UART_POLL_CYCLE ((uint32_t)(10*1e6/28800/2))
+#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud38400
+#define UART_POLL_CYCLE ((uint32_t)(10*1e6/38400/2))
+#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud57600
+#define UART_POLL_CYCLE ((uint32_t)(10*1e6/57600/2))
+#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud76800
+#define UART_POLL_CYCLE ((uint32_t)(10*1e6/768000/2))
+#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud115200
+#define UART_POLL_CYCLE ((uint32_t)(10*1e6/115200/2))
+#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud230400
+#define UART_POLL_CYCLE ((uint32_t)(10*1e6/230400/2))
+#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud250000
+#define UART_POLL_CYCLE ((uint32_t)(10*1e6/250000/2))
+#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud460800
+#define UART_POLL_CYCLE ((uint32_t)(10*1e6/460800/2))
+#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud921600
+#define UART_POLL_CYCLE ((uint32_t)(10*1e6/921600/2))
+#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud1M
+#define UART_POLL_CYCLE ((uint32_t)(10*1e6/1e6/2))
+#else
+// It is possible to find values that work for other baud rates, but the formula above is not
+// guaranteed to work for all values. Suitable values may have to be found by trial and error.
+#error "Unsupported baud rate set."
+#endif
+
+// Note: DTM_PKT_VENDORSPECIFIC, is not a packet type
+#define PACKET_TYPE_MAX DTM_PKT_0XFF /**< Highest value allowed as DTM Packet type. */
+
+/** @brief BLE DTM event type. */
+typedef uint32_t dtm_event_t; /**< Type for handling DTM event. */
+
+/** @brief BLE DTM frequency type. */
+typedef uint32_t dtm_freq_t; /**< Physical channel, valid range: 0..39. */
+
+/**@brief BLE DTM packet types. */
+typedef uint32_t dtm_pkt_type_t; /**< Type for holding the requested DTM payload type.*/
+
+
+/**@brief Function for initializing or re-initializing DTM module
+ *
+ * @return DTM_SUCCESS on successful initialization of the DTM module.
+*/
+uint32_t dtm_init(void);
+
+
+/**@brief Function for giving control to dtmlib for handling timer and radio events.
+ * Will return to caller at 625us intervals or whenever another event than radio occurs
+ * (such as UART input). Function will put MCU to sleep between events.
+ *
+ * @return Time counter, incremented every 625 us.
+ */
+uint32_t dtm_wait(void);
+
+
+/**@brief Function for calling when a complete command has been prepared by the Tester.
+ *
+ * @param[in] cmd One of the DTM_CMD values (bits 14:15 in the 16-bit UART format).
+ * @param[in] freq Phys. channel no - actual frequency = (2402 + freq * 2) MHz (bits 8:13 in
+ * the 16-bit UART format).
+ * @param[in] length Payload length, 0..37 (bits 2:7 in the 16-bit UART format).
+ * @param[in] payload One of the DTM_PKT values (bits 0:1 in the 16-bit UART format).
+ *
+ * @return DTM_SUCCESS or one of the DTM_ERROR_ values
+ */
+uint32_t dtm_cmd(dtm_cmd_t cmd, dtm_freq_t freq, uint32_t length, dtm_pkt_type_t payload);
+
+
+/**@brief Function for reading the result of a DTM command
+ *
+ * @param[out] p_dtm_event Pointer to buffer for 16 bit event code according to DTM standard.
+ *
+ * @return true: new event, false: no event since last call, this event has been read earlier
+ */
+bool dtm_event_get(dtm_event_t * p_dtm_event);
+
+
+/**@brief Function for configuring the timer to use.
+ *
+ * @note Must be called when no DTM test is running.
+ *
+ * @param[in] new_timer Index (0..2) of timer to be used by the DTM library
+ *
+ * @return true: success, new timer was selected, false: parameter error
+ */
+bool dtm_set_timer(uint32_t new_timer);
+
+
+/**@brief Function for configuring the transmit power.
+ *
+ * @note Must be called when no DTM test is running.
+ *
+ * @param[in] new_tx_power New output level, +4..-40, in steps of 4.
+ *
+ * @return true: tx power setting changed, false: parameter error
+ */
+bool dtm_set_txpower(uint32_t new_tx_power);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // BLE_DTM_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm_hw.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm_hw.h
new file mode 100644
index 0000000..944cf33
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm_hw.h
@@ -0,0 +1,103 @@
+/**
+ * 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
+ *
+ * @defgroup ble_dtm_hw Direct Test Mode HW
+ * @{
+ * @ingroup ble_sdk_lib
+ * @brief Module contains hardware related function for testing RF/PHY using DTM commands.
+ */
+
+#ifndef BLE_DTM_HW_H__
+#define BLE_DTM_HW_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "nrf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**@brief Function for selecting a timer resource.
+ * This function may be called directly, or through dtm_cmd() specifying
+ * DTM_PKT_VENDORSPECIFIC as payload, SELECT_TIMER as length, and the timer as freq
+ *
+ * @param[out] mp_timer Pointer to timer instance used in dtm source file.
+ * @param[out] m_timer_irq Pointer to timer interrupt related to mp_timer.
+ * @param[in] new_timer Timer id for the timer to use.
+ *
+ * @retval true if the timer was successfully changed.
+ * @retval false if the error occurs.
+ */
+
+bool dtm_hw_set_timer(NRF_TIMER_Type ** mp_timer, IRQn_Type * m_timer_irq, uint32_t new_timer);
+
+
+/**@brief Function for turning off radio test.
+ * This function is platform depending. For now only nRF51 requieres this special function.
+ */
+void dtm_turn_off_test(void);
+
+
+/**@brief Function for setting constant carrier in radio settings.
+ * This function is used to handle vendor specific command testing continous carrier without
+ * a modulated signal.
+ */
+void dtm_constant_carrier(void);
+
+
+/**@brief Function for validating tx power and radio move settings.
+ * @param[in] m_tx_power TX power for transmission test.
+ * @param[in] m_radio_mode Radio mode value.
+ *
+ * @retval DTM_SUCCESS if input parameters values are correct.
+ * @retval DTM_ERROR_ILLEGAL_CONFIGURATION if input parameters values are not correct.
+ */
+uint32_t dtm_radio_validate(int32_t m_tx_power, uint8_t m_radio_mode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // BLE_DTM_HW_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm_hw_nrf51.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm_hw_nrf51.c
new file mode 100644
index 0000000..1e6acca
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm_hw_nrf51.c
@@ -0,0 +1,120 @@
+/**
+ * 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 "ble_dtm_hw.h"
+#include "ble_dtm.h"
+#include <stdbool.h>
+#include <string.h>
+#include "nrf.h"
+
+
+void dtm_turn_off_test()
+{
+ NRF_RADIO->TEST = 0;
+}
+
+
+void dtm_constant_carrier()
+{
+ NRF_RADIO->TEST = (RADIO_TEST_PLL_LOCK_Enabled << RADIO_TEST_PLL_LOCK_Pos) |
+ (RADIO_TEST_CONST_CARRIER_Enabled << RADIO_TEST_CONST_CARRIER_Pos);
+}
+
+
+uint32_t dtm_radio_validate(int32_t m_tx_power, uint8_t m_radio_mode)
+{
+ // Handle BLE Radio tuning parameters from production for DTM if required.
+ // Only needed for DTM without SoftDevice, as the SoftDevice normally handles this.
+ // PCN-083.
+ if ( ((NRF_FICR->OVERRIDEEN) & FICR_OVERRIDEEN_BLE_1MBIT_Msk) == FICR_OVERRIDEEN_BLE_1MBIT_Override)
+ {
+ NRF_RADIO->OVERRIDE0 = NRF_FICR->BLE_1MBIT[0];
+ NRF_RADIO->OVERRIDE1 = NRF_FICR->BLE_1MBIT[1];
+ NRF_RADIO->OVERRIDE2 = NRF_FICR->BLE_1MBIT[2];
+ NRF_RADIO->OVERRIDE3 = NRF_FICR->BLE_1MBIT[3];
+ NRF_RADIO->OVERRIDE4 = NRF_FICR->BLE_1MBIT[4];
+ }
+
+ // Initializing code below is quite generic - for BLE, the values are fixed, and expressions
+ // are constant. Non-constant values are essentially set in radio_prepare().
+ if (!(m_tx_power == RADIO_TXPOWER_TXPOWER_0dBm ||
+ m_tx_power == RADIO_TXPOWER_TXPOWER_Pos4dBm ||
+ m_tx_power == RADIO_TXPOWER_TXPOWER_Neg30dBm ||
+ m_tx_power == RADIO_TXPOWER_TXPOWER_Neg20dBm ||
+ m_tx_power == RADIO_TXPOWER_TXPOWER_Neg16dBm ||
+ m_tx_power == RADIO_TXPOWER_TXPOWER_Neg12dBm ||
+ m_tx_power == RADIO_TXPOWER_TXPOWER_Neg8dBm ||
+ m_tx_power == RADIO_TXPOWER_TXPOWER_Neg4dBm
+ ) ||
+ (m_radio_mode > RADIO_MODE_MODE_Ble_1Mbit) // Values 0 - 2: Proprietary mode, 3 (last valid): BLE
+ )
+ {
+ return DTM_ERROR_ILLEGAL_CONFIGURATION;
+ }
+
+ return DTM_SUCCESS;
+}
+
+
+bool dtm_hw_set_timer(NRF_TIMER_Type ** mp_timer, IRQn_Type * m_timer_irq, uint32_t new_timer)
+{
+ if (new_timer == 0)
+ {
+ *mp_timer = NRF_TIMER0;
+ *m_timer_irq = TIMER0_IRQn;
+ }
+ else if (new_timer == 1)
+ {
+ *mp_timer = NRF_TIMER1;
+ *m_timer_irq = TIMER1_IRQn;
+ }
+ else if (new_timer == 2)
+ {
+ *mp_timer = NRF_TIMER2;
+ *m_timer_irq = TIMER2_IRQn;
+ }
+ else
+ {
+ // Parameter error: Only TIMER 0, 1, 2 provided by nRF51
+ return false;
+ }
+ // New timer has been selected:
+ return true;
+}
+
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm_hw_nrf52.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm_hw_nrf52.c
new file mode 100644
index 0000000..4dcfa96
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_dtm/ble_dtm_hw_nrf52.c
@@ -0,0 +1,128 @@
+/**
+ * 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 "ble_dtm_hw.h"
+#include "ble_dtm.h"
+#include <stdbool.h>
+#include <string.h>
+#include "nrf.h"
+
+
+void dtm_turn_off_test()
+{
+}
+
+
+void dtm_constant_carrier()
+{
+NRF_RADIO->MODECNF0 = (RADIO_MODECNF0_RU_Default << RADIO_MODECNF0_RU_Pos) |
+ (RADIO_MODECNF0_DTX_Center << RADIO_MODECNF0_DTX_Pos);
+}
+
+
+uint32_t dtm_radio_validate(int32_t m_tx_power, uint8_t m_radio_mode)
+{
+ // Initializing code below is quite generic - for BLE, the values are fixed, and expressions
+ // are constant. Non-constant values are essentially set in radio_prepare().
+ if (!(m_tx_power == RADIO_TXPOWER_TXPOWER_0dBm ||
+ m_tx_power == RADIO_TXPOWER_TXPOWER_Pos4dBm ||
+ m_tx_power == RADIO_TXPOWER_TXPOWER_Neg30dBm ||
+ m_tx_power == RADIO_TXPOWER_TXPOWER_Neg20dBm ||
+ m_tx_power == RADIO_TXPOWER_TXPOWER_Neg16dBm ||
+ m_tx_power == RADIO_TXPOWER_TXPOWER_Neg12dBm ||
+ m_tx_power == RADIO_TXPOWER_TXPOWER_Neg8dBm ||
+ m_tx_power == RADIO_TXPOWER_TXPOWER_Neg4dBm ||
+ m_tx_power == RADIO_TXPOWER_TXPOWER_Pos3dBm ||
+ m_tx_power == RADIO_TXPOWER_TXPOWER_Neg40dBm
+ ) ||
+
+ !(
+#ifdef NRF52840_XXAA
+ m_radio_mode == RADIO_MODE_MODE_Ble_LR125Kbit ||
+ m_radio_mode == RADIO_MODE_MODE_Ble_LR500Kbit ||
+#endif //NRF52840_XXAA
+ m_radio_mode == RADIO_MODE_MODE_Ble_1Mbit ||
+ m_radio_mode == RADIO_MODE_MODE_Ble_2Mbit
+ )
+ )
+ {
+ return DTM_ERROR_ILLEGAL_CONFIGURATION;
+ }
+
+ return DTM_SUCCESS;
+}
+
+
+bool dtm_hw_set_timer(NRF_TIMER_Type ** mp_timer, IRQn_Type * m_timer_irq, uint32_t new_timer)
+{
+ if (new_timer == 0)
+ {
+ *mp_timer = NRF_TIMER0;
+ *m_timer_irq = TIMER0_IRQn;
+ }
+ else if (new_timer == 1)
+ {
+ *mp_timer = NRF_TIMER1;
+ *m_timer_irq = TIMER1_IRQn;
+ }
+ else if (new_timer == 2)
+ {
+ *mp_timer = NRF_TIMER2;
+ *m_timer_irq = TIMER2_IRQn;
+ }
+#ifndef NRF52810_XXAA
+ else if (new_timer == 3)
+ {
+ *mp_timer = NRF_TIMER3;
+ *m_timer_irq = TIMER3_IRQn;
+ }
+ else if (new_timer == 4)
+ {
+ *mp_timer = NRF_TIMER4;
+ *m_timer_irq = TIMER4_IRQn;
+ }
+#endif //NRF52810_XXAA
+ else
+ {
+ // Parameter error: Only TIMER 0, 1, 2, 3 and 4 provided by nRF52
+ return false;
+ }
+ // New timer has been selected:
+ return true;
+}