This is a standalone DTM firmware for Nordic mKit-based hardware. It uses the serial port to receive DTM commands (e.g. through nRF Go Studio). By default the ports are set to USBTX and USBRX, but can be re-configured in main.cpp.

Dependencies:   BLE_API mbed nRF51822

Committer:
pvaibhav
Date:
Wed Jan 14 12:36:59 2015 +0000
Revision:
0:a2cffc867df4
Initial commit of working DTM mode via serial port

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pvaibhav 0:a2cffc867df4 1 /* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
pvaibhav 0:a2cffc867df4 2 *
pvaibhav 0:a2cffc867df4 3 * The information contained herein is property of Nordic Semiconductor ASA.
pvaibhav 0:a2cffc867df4 4 * Terms and conditions of usage are described in detail in NORDIC
pvaibhav 0:a2cffc867df4 5 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
pvaibhav 0:a2cffc867df4 6 *
pvaibhav 0:a2cffc867df4 7 * Licensees are granted free, non-transferable use of the information. NO
pvaibhav 0:a2cffc867df4 8 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
pvaibhav 0:a2cffc867df4 9 * the file.
pvaibhav 0:a2cffc867df4 10 *
pvaibhav 0:a2cffc867df4 11 */
pvaibhav 0:a2cffc867df4 12
pvaibhav 0:a2cffc867df4 13 #include "mbed.h"
pvaibhav 0:a2cffc867df4 14 #include <stdint.h>
pvaibhav 0:a2cffc867df4 15 #include <stdbool.h>
pvaibhav 0:a2cffc867df4 16 #include "nrf51.h"
pvaibhav 0:a2cffc867df4 17 #include "nrf51_bitfields.h"
pvaibhav 0:a2cffc867df4 18 #include "ble_dtm.h"
pvaibhav 0:a2cffc867df4 19 #include "nrf_gpio.h"
pvaibhav 0:a2cffc867df4 20
pvaibhav 0:a2cffc867df4 21 // Configuration parameters.
pvaibhav 0:a2cffc867df4 22 #define BITRATE UART_BAUDRATE_BAUDRATE_Baud19200 /**< Serial bitrate on the UART */
pvaibhav 0:a2cffc867df4 23 #define TX_PIN_NUMBER USBTX /**< Use proper value for your hardware */
pvaibhav 0:a2cffc867df4 24 #define RX_PIN_NUMBER USBRX /**< Use proper value for your hardware */
pvaibhav 0:a2cffc867df4 25 #define MAX_ITERATIONS_NEEDED_FOR_NEXT_BYTE 21
pvaibhav 0:a2cffc867df4 26 /**@brief Function for UART initialization.
pvaibhav 0:a2cffc867df4 27 */
pvaibhav 0:a2cffc867df4 28 static void uart_init(void)
pvaibhav 0:a2cffc867df4 29 {
pvaibhav 0:a2cffc867df4 30 // Configure UART0 pins.
pvaibhav 0:a2cffc867df4 31 nrf_gpio_cfg_output(TX_PIN_NUMBER);
pvaibhav 0:a2cffc867df4 32 nrf_gpio_cfg_input(RX_PIN_NUMBER, NRF_GPIO_PIN_NOPULL);
pvaibhav 0:a2cffc867df4 33
pvaibhav 0:a2cffc867df4 34 NRF_UART0->PSELTXD = TX_PIN_NUMBER;
pvaibhav 0:a2cffc867df4 35 NRF_UART0->PSELRXD = RX_PIN_NUMBER;
pvaibhav 0:a2cffc867df4 36 NRF_UART0->BAUDRATE = BITRATE;
pvaibhav 0:a2cffc867df4 37
pvaibhav 0:a2cffc867df4 38 // Clean out possible events from earlier operations
pvaibhav 0:a2cffc867df4 39 NRF_UART0->EVENTS_RXDRDY = 0;
pvaibhav 0:a2cffc867df4 40 NRF_UART0->EVENTS_TXDRDY = 0;
pvaibhav 0:a2cffc867df4 41 NRF_UART0->EVENTS_ERROR = 0;
pvaibhav 0:a2cffc867df4 42
pvaibhav 0:a2cffc867df4 43 // Activate UART.
pvaibhav 0:a2cffc867df4 44 NRF_UART0->ENABLE = UART_ENABLE_ENABLE_Enabled;
pvaibhav 0:a2cffc867df4 45 NRF_UART0->INTENSET = 0;
pvaibhav 0:a2cffc867df4 46 NRF_UART0->TASKS_STARTTX = 1;
pvaibhav 0:a2cffc867df4 47 NRF_UART0->TASKS_STARTRX = 1;
pvaibhav 0:a2cffc867df4 48 }
pvaibhav 0:a2cffc867df4 49
pvaibhav 0:a2cffc867df4 50
pvaibhav 0:a2cffc867df4 51 /**@brief Function for splitting UART command bit fields into separate command parameters for the DTM library.
pvaibhav 0:a2cffc867df4 52 *
pvaibhav 0:a2cffc867df4 53 * @param[in] command The packed UART command.
pvaibhav 0:a2cffc867df4 54 * @return result status from dtmlib.
pvaibhav 0:a2cffc867df4 55 */
pvaibhav 0:a2cffc867df4 56 static uint32_t dtm_cmd_put(uint16_t command)
pvaibhav 0:a2cffc867df4 57 {
pvaibhav 0:a2cffc867df4 58 dtm_cmd_t command_code = (command >> 14) & 0x03;
pvaibhav 0:a2cffc867df4 59 dtm_freq_t freq = (command >> 8) & 0x3F;
pvaibhav 0:a2cffc867df4 60 uint32_t length = (command >> 2) & 0x3F;
pvaibhav 0:a2cffc867df4 61 dtm_pkt_type_t payload = command & 0x03;
pvaibhav 0:a2cffc867df4 62
pvaibhav 0:a2cffc867df4 63 // Check for Vendor Specific payload.
pvaibhav 0:a2cffc867df4 64 if (payload == 0x03) {
pvaibhav 0:a2cffc867df4 65 /* Note that in a HCI adaption layer, as well as in the DTM PDU format,
pvaibhav 0:a2cffc867df4 66 the value 0x03 is a distinct bit pattern (PRBS15). Even though BLE does not
pvaibhav 0:a2cffc867df4 67 support PRBS15, this implementation re-maps 0x03 to DTM_PKT_VENDORSPECIFIC,
pvaibhav 0:a2cffc867df4 68 to avoid the risk of confusion, should the code be extended to greater coverage.
pvaibhav 0:a2cffc867df4 69 */
pvaibhav 0:a2cffc867df4 70 payload = DTM_PKT_VENDORSPECIFIC;
pvaibhav 0:a2cffc867df4 71 }
pvaibhav 0:a2cffc867df4 72 return dtm_cmd(command_code, freq, length, payload);
pvaibhav 0:a2cffc867df4 73 }
pvaibhav 0:a2cffc867df4 74
pvaibhav 0:a2cffc867df4 75 /**@brief Function for application main entry.
pvaibhav 0:a2cffc867df4 76 *
pvaibhav 0:a2cffc867df4 77 * @details This function serves as an adaptation layer between a 2-wire UART interface and the
pvaibhav 0:a2cffc867df4 78 * dtmlib. After initialization, DTM commands submitted through the UART are forwarded to
pvaibhav 0:a2cffc867df4 79 * dtmlib and events (i.e. results from the command) is reported back through the UART.
pvaibhav 0:a2cffc867df4 80 */
pvaibhav 0:a2cffc867df4 81 int main(void)
pvaibhav 0:a2cffc867df4 82 {
pvaibhav 0:a2cffc867df4 83 uint32_t current_time;
pvaibhav 0:a2cffc867df4 84 uint32_t dtm_error_code;
pvaibhav 0:a2cffc867df4 85 uint32_t msb_time = 0; // Time when MSB of the DTM command was read. Used to catch stray bytes from "misbehaving" testers.
pvaibhav 0:a2cffc867df4 86 bool is_msb_read = false; // True when MSB of the DTM command has been read and the application is waiting for LSB.
pvaibhav 0:a2cffc867df4 87 uint16_t dtm_cmd_from_uart = 0; // Packed command containing command_code:freqency:length:payload in 2:6:6:2 bits.
pvaibhav 0:a2cffc867df4 88 uint8_t rx_byte; // Last byte read from UART.
pvaibhav 0:a2cffc867df4 89 dtm_event_t result; // Result of a DTM operation.
pvaibhav 0:a2cffc867df4 90
pvaibhav 0:a2cffc867df4 91 uart_init();
pvaibhav 0:a2cffc867df4 92
pvaibhav 0:a2cffc867df4 93 // Turn default LED on to indicate power
pvaibhav 0:a2cffc867df4 94 nrf_gpio_cfg_output(LED1);
pvaibhav 0:a2cffc867df4 95 nrf_gpio_pin_set(LED1);
pvaibhav 0:a2cffc867df4 96
pvaibhav 0:a2cffc867df4 97 dtm_error_code = dtm_init();
pvaibhav 0:a2cffc867df4 98 if (dtm_error_code != DTM_SUCCESS) {
pvaibhav 0:a2cffc867df4 99 // If DTM cannot be correctly initialized, then we just return.
pvaibhav 0:a2cffc867df4 100 return -1;
pvaibhav 0:a2cffc867df4 101 }
pvaibhav 0:a2cffc867df4 102
pvaibhav 0:a2cffc867df4 103 for (;;) {
pvaibhav 0:a2cffc867df4 104 // Will return every timeout, 625 us.
pvaibhav 0:a2cffc867df4 105 current_time = dtm_wait();
pvaibhav 0:a2cffc867df4 106
pvaibhav 0:a2cffc867df4 107 if (NRF_UART0->EVENTS_RXDRDY == 0) {
pvaibhav 0:a2cffc867df4 108 // Nothing read from the UART.
pvaibhav 0:a2cffc867df4 109 continue;
pvaibhav 0:a2cffc867df4 110 }
pvaibhav 0:a2cffc867df4 111 NRF_UART0->EVENTS_RXDRDY = 0;
pvaibhav 0:a2cffc867df4 112 rx_byte = (uint8_t)NRF_UART0->RXD;
pvaibhav 0:a2cffc867df4 113
pvaibhav 0:a2cffc867df4 114 if (!is_msb_read) {
pvaibhav 0:a2cffc867df4 115 // This is first byte of two-byte command.
pvaibhav 0:a2cffc867df4 116 is_msb_read = true;
pvaibhav 0:a2cffc867df4 117 dtm_cmd_from_uart = ((dtm_cmd_t)rx_byte) << 8;
pvaibhav 0:a2cffc867df4 118 msb_time = current_time;
pvaibhav 0:a2cffc867df4 119
pvaibhav 0:a2cffc867df4 120 // Go back and wait for 2nd byte of command word.
pvaibhav 0:a2cffc867df4 121 continue;
pvaibhav 0:a2cffc867df4 122 }
pvaibhav 0:a2cffc867df4 123
pvaibhav 0:a2cffc867df4 124 // This is the second byte read; combine it with the first and process command
pvaibhav 0:a2cffc867df4 125 if (current_time > (msb_time + MAX_ITERATIONS_NEEDED_FOR_NEXT_BYTE)) {
pvaibhav 0:a2cffc867df4 126 // More than ~5mS after msb: Drop old byte, take the new byte as MSB.
pvaibhav 0:a2cffc867df4 127 // The variable is_msb_read will remains true.
pvaibhav 0:a2cffc867df4 128 // Go back and wait for 2nd byte of the command word.
pvaibhav 0:a2cffc867df4 129 dtm_cmd_from_uart = ((dtm_cmd_t)rx_byte) << 8;
pvaibhav 0:a2cffc867df4 130 msb_time = current_time;
pvaibhav 0:a2cffc867df4 131 continue;
pvaibhav 0:a2cffc867df4 132 }
pvaibhav 0:a2cffc867df4 133
pvaibhav 0:a2cffc867df4 134 // 2-byte UART command received.
pvaibhav 0:a2cffc867df4 135 is_msb_read = false;
pvaibhav 0:a2cffc867df4 136 dtm_cmd_from_uart |= (dtm_cmd_t)rx_byte;
pvaibhav 0:a2cffc867df4 137
pvaibhav 0:a2cffc867df4 138 if (dtm_cmd_put(dtm_cmd_from_uart) != DTM_SUCCESS) {
pvaibhav 0:a2cffc867df4 139 // Extended error handling may be put here.
pvaibhav 0:a2cffc867df4 140 // Default behavior is to return the event on the UART (see below);
pvaibhav 0:a2cffc867df4 141 // the event report will reflect any lack of success.
pvaibhav 0:a2cffc867df4 142 }
pvaibhav 0:a2cffc867df4 143
pvaibhav 0:a2cffc867df4 144 // Retrieve result of the operation. This implementation will busy-loop
pvaibhav 0:a2cffc867df4 145 // for the duration of the byte transmissions on the UART.
pvaibhav 0:a2cffc867df4 146 if (dtm_event_get(&result)) {
pvaibhav 0:a2cffc867df4 147 // Report command status on the UART.
pvaibhav 0:a2cffc867df4 148 // Transmit MSB of the result.
pvaibhav 0:a2cffc867df4 149 NRF_UART0->TXD = (result >> 8) & 0xFF;
pvaibhav 0:a2cffc867df4 150 // Wait until MSB is sent.
pvaibhav 0:a2cffc867df4 151 while (NRF_UART0->EVENTS_TXDRDY != 1) {
pvaibhav 0:a2cffc867df4 152 // Do nothing.
pvaibhav 0:a2cffc867df4 153 }
pvaibhav 0:a2cffc867df4 154 NRF_UART0->EVENTS_TXDRDY = 0;
pvaibhav 0:a2cffc867df4 155
pvaibhav 0:a2cffc867df4 156 // Transmit LSB of the result.
pvaibhav 0:a2cffc867df4 157 NRF_UART0->TXD = result & 0xFF;
pvaibhav 0:a2cffc867df4 158 // Wait until LSB is sent.
pvaibhav 0:a2cffc867df4 159 while (NRF_UART0->EVENTS_TXDRDY != 1) {
pvaibhav 0:a2cffc867df4 160 // Do nothing.
pvaibhav 0:a2cffc867df4 161 }
pvaibhav 0:a2cffc867df4 162 NRF_UART0->EVENTS_TXDRDY = 0;
pvaibhav 0:a2cffc867df4 163 }
pvaibhav 0:a2cffc867df4 164 }
pvaibhav 0:a2cffc867df4 165 }
pvaibhav 0:a2cffc867df4 166
pvaibhav 0:a2cffc867df4 167 /// @}