main.c 7.0 KB

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