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
main.cpp
- Committer:
- pvaibhav
- Date:
- 2015-01-14
- Revision:
- 0:a2cffc867df4
File content as of revision 0:a2cffc867df4:
/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved. * * The information contained herein is property of Nordic Semiconductor ASA. * Terms and conditions of usage are described in detail in NORDIC * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. * * Licensees are granted free, non-transferable use of the information. NO * WARRANTY of ANY KIND is provided. This heading must NOT be removed from * the file. * */ #include "mbed.h" #include <stdint.h> #include <stdbool.h> #include "nrf51.h" #include "nrf51_bitfields.h" #include "ble_dtm.h" #include "nrf_gpio.h" // Configuration parameters. #define BITRATE UART_BAUDRATE_BAUDRATE_Baud19200 /**< Serial bitrate on the UART */ #define TX_PIN_NUMBER USBTX /**< Use proper value for your hardware */ #define RX_PIN_NUMBER USBRX /**< Use proper value for your hardware */ #define MAX_ITERATIONS_NEEDED_FOR_NEXT_BYTE 21 /**@brief Function for UART initialization. */ static void uart_init(void) { // Configure UART0 pins. nrf_gpio_cfg_output(TX_PIN_NUMBER); nrf_gpio_cfg_input(RX_PIN_NUMBER, NRF_GPIO_PIN_NOPULL); NRF_UART0->PSELTXD = TX_PIN_NUMBER; NRF_UART0->PSELRXD = RX_PIN_NUMBER; NRF_UART0->BAUDRATE = BITRATE; // Clean out possible events from earlier operations NRF_UART0->EVENTS_RXDRDY = 0; NRF_UART0->EVENTS_TXDRDY = 0; NRF_UART0->EVENTS_ERROR = 0; // Activate UART. NRF_UART0->ENABLE = UART_ENABLE_ENABLE_Enabled; NRF_UART0->INTENSET = 0; NRF_UART0->TASKS_STARTTX = 1; NRF_UART0->TASKS_STARTRX = 1; } /**@brief Function for splitting UART command bit fields into separate command parameters for the DTM library. * * @param[in] command The packed UART command. * @return result status from dtmlib. */ static uint32_t dtm_cmd_put(uint16_t command) { dtm_cmd_t command_code = (command >> 14) & 0x03; dtm_freq_t freq = (command >> 8) & 0x3F; uint32_t length = (command >> 2) & 0x3F; dtm_pkt_type_t payload = command & 0x03; // Check for Vendor Specific payload. if (payload == 0x03) { /* 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. */ payload = DTM_PKT_VENDORSPECIFIC; } return dtm_cmd(command_code, freq, length, payload); } /**@brief Function for application main entry. * * @details This function serves as an adaptation layer between a 2-wire UART interface and the * dtmlib. After initialization, DTM commands submitted through the UART are forwarded to * dtmlib and events (i.e. results from the command) is reported back through the UART. */ int main(void) { uint32_t current_time; uint32_t dtm_error_code; uint32_t msb_time = 0; // Time when MSB of the DTM command was read. Used to catch stray bytes from "misbehaving" testers. bool is_msb_read = false; // True when MSB of the DTM command has been read and the application is waiting for LSB. uint16_t dtm_cmd_from_uart = 0; // Packed command containing command_code:freqency:length:payload in 2:6:6:2 bits. uint8_t rx_byte; // Last byte read from UART. dtm_event_t result; // Result of a DTM operation. uart_init(); // Turn default LED on to indicate power nrf_gpio_cfg_output(LED1); nrf_gpio_pin_set(LED1); dtm_error_code = dtm_init(); if (dtm_error_code != DTM_SUCCESS) { // If DTM cannot be correctly initialized, then we just return. return -1; } for (;;) { // Will return every timeout, 625 us. current_time = dtm_wait(); if (NRF_UART0->EVENTS_RXDRDY == 0) { // Nothing read from the UART. continue; } NRF_UART0->EVENTS_RXDRDY = 0; rx_byte = (uint8_t)NRF_UART0->RXD; if (!is_msb_read) { // This is first byte of two-byte command. is_msb_read = true; dtm_cmd_from_uart = ((dtm_cmd_t)rx_byte) << 8; msb_time = current_time; // Go back and wait for 2nd byte of command word. continue; } // This is the second byte read; combine it with the first and process command if (current_time > (msb_time + MAX_ITERATIONS_NEEDED_FOR_NEXT_BYTE)) { // More than ~5mS after msb: Drop old byte, take the new byte as MSB. // The variable is_msb_read will remains true. // Go back and wait for 2nd byte of the command word. dtm_cmd_from_uart = ((dtm_cmd_t)rx_byte) << 8; msb_time = current_time; continue; } // 2-byte UART command received. is_msb_read = false; dtm_cmd_from_uart |= (dtm_cmd_t)rx_byte; if (dtm_cmd_put(dtm_cmd_from_uart) != DTM_SUCCESS) { // Extended error handling may be put here. // Default behavior is to return the event on the UART (see below); // the event report will reflect any lack of success. } // Retrieve result of the operation. This implementation will busy-loop // for the duration of the byte transmissions on the UART. if (dtm_event_get(&result)) { // Report command status on the UART. // Transmit MSB of the result. NRF_UART0->TXD = (result >> 8) & 0xFF; // Wait until MSB is sent. while (NRF_UART0->EVENTS_TXDRDY != 1) { // Do nothing. } NRF_UART0->EVENTS_TXDRDY = 0; // Transmit LSB of the result. NRF_UART0->TXD = result & 0xFF; // Wait until LSB is sent. while (NRF_UART0->EVENTS_TXDRDY != 1) { // Do nothing. } NRF_UART0->EVENTS_TXDRDY = 0; } } } /// @}