1 /*
2 * Copyright (c) 2017-2020 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stddef.h>
8 #include <string.h>
9
10 #include <zephyr/toolchain.h>
11
12 #include <soc.h>
13
14 #include "hal/cpu.h"
15 #include "hal/cntr.h"
16 #include "hal/ccm.h"
17 #include "hal/radio.h"
18 #include "hal/radio_df.h"
19
20 #include "util/memq.h"
21 #include "util/util.h"
22 #include "util/dbuf.h"
23
24 #include "pdu_df.h"
25 #include "pdu_vendor.h"
26 #include "pdu.h"
27
28 #include "lll.h"
29 #include "lll_clock.h"
30 #include "lll_internal.h"
31
32 #if defined(CONFIG_BT_CTLR_DF)
33 #include "lll_df_types.h"
34 #include "lll_df.h"
35 #endif /* CONFIG_BT_CTLR_DF */
36
37 #include "ll_test.h"
38
39 #if defined(CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT)
40 #include "ull_df_types.h"
41 #include "ull_df_internal.h"
42 #endif /* CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT */
43
44 #include <zephyr/bluetooth/hci_types.h>
45
46 #include "hal/debug.h"
47
48 #define CNTR_MIN_DELTA 3
49
50 /* Helper definitions for repeated payload sequence */
51 #define PAYLOAD_11110000 0x0f
52 #define PAYLOAD_10101010 0x55
53 #define PAYLOAD_11111111 0xff
54 #define PAYLOAD_00000000 0x00
55 #define PAYLOAD_00001111 0xf0
56 #define PAYLOAD_01010101 0xaa
57
58 static const uint32_t test_sync_word = 0x71764129;
59 static uint8_t test_phy;
60 static uint8_t test_phy_flags;
61
62 #if defined(CONFIG_BT_CTLR_DF_CTE_RX)
63 static uint8_t test_cte_type;
64 #endif /* CONFIG_BT_CTLR_DF_CTE_RX */
65
66 #if defined(CONFIG_BT_CTLR_DF_CTE_TX) || defined(CONFIG_BT_CTLR_DF_CTE_RX)
67 static uint8_t test_cte_len;
68 #endif /* CONFIG_BT_CTLR_DF_CTE_TX || CONFIG_BT_CTLR_DF_CTE_RX */
69
70 #if defined(CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT)
71 static uint8_t test_chan;
72 static uint8_t test_slot_duration;
73 #endif /* CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT */
74
75 static uint32_t tx_tifs;
76 static uint16_t test_num_rx;
77 static bool started;
78
79 /* NOTE: The PRBS9 sequence used as packet payload.
80 * The bytes in the sequence are in the right order, but the bits of each byte
81 * in the array are reverse from that found by running the PRBS9 algorithm. This
82 * is done to transmit MSbit first on air.
83 */
84
85 static const uint8_t prbs9[] = {
86 0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B,
87 0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23,
88 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B,
89 0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA,
90 0x0C, 0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A,
91 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE,
92 0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E,
93 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87,
94 0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5,
95 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11,
96 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D,
97 0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65,
98 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D,
99 0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F,
100 0x15, 0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF,
101 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3,
102 0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2,
103 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88,
104 0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E,
105 0x14, 0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32,
106 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6,
107 0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF,
108 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7,
109 0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1,
110 0x3F, 0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1,
111 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44,
112 0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27,
113 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99,
114 0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3,
115 0x3C, 0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57,
116 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB,
117 0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7};
118
119 /* TODO: fill correct prbs15 */
120 static const uint8_t prbs15[255] = { 0x00, };
121
122 static uint8_t tx_req;
123 static uint8_t volatile tx_ack;
124
125 #if defined(CONFIG_BT_CTLR_DF_CTE_RX)
126 static bool check_rx_cte(bool cte_ready);
127 #endif /* CONFIG_BT_CTLR_DF_CTE_RX */
128
129 #if defined(CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT)
create_iq_report(bool crc_ok)130 static int create_iq_report(bool crc_ok)
131 {
132 struct node_rx_iq_report *iq_report;
133 struct node_rx_ftr *ftr;
134 uint8_t sample_cnt;
135 uint8_t cte_info;
136 uint8_t ant;
137
138 sample_cnt = radio_df_iq_samples_amount_get();
139
140 /* If there are no samples available, the CTEInfo was
141 * not detected and sampling was not started.
142 */
143 if (!sample_cnt) {
144 return -EINVAL;
145 }
146
147 cte_info = radio_df_cte_status_get();
148 ant = radio_df_pdu_antenna_switch_pattern_get();
149 iq_report = ull_df_iq_report_alloc();
150 if (!iq_report) {
151 return -ENOBUFS;
152 }
153
154 iq_report->rx.hdr.type = NODE_RX_TYPE_DTM_IQ_SAMPLE_REPORT;
155 iq_report->sample_count = sample_cnt;
156 iq_report->packet_status = ((crc_ok) ? BT_HCI_LE_CTE_CRC_OK :
157 BT_HCI_LE_CTE_CRC_ERR_CTE_BASED_TIME);
158 iq_report->rssi_ant_id = ant;
159 iq_report->cte_info = *(struct pdu_cte_info *)&cte_info;
160 iq_report->local_slot_durations = test_slot_duration;
161 iq_report->chan_idx = test_chan;
162
163 ftr = &iq_report->rx.rx_ftr;
164 ftr->param = NULL;
165 ftr->rssi = BT_HCI_LE_RSSI_NOT_AVAILABLE;
166
167 ull_rx_put(iq_report->rx.hdr.link, iq_report);
168
169 return 0;
170 }
171 #endif /* CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT */
172
isr_tx(void * param)173 static void isr_tx(void *param)
174 {
175 /* Clear radio status and events */
176 radio_status_reset();
177 radio_tmr_status_reset();
178
179 #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
180 radio_gpio_pa_lna_disable();
181 #endif /* HAL_RADIO_GPIO_HAVE_PA_PIN */
182
183 /* Exit if radio disabled */
184 if (((tx_req - tx_ack) & 0x01) == 0U) {
185 tx_ack = tx_req;
186
187 return;
188 }
189
190 /* Setup next Tx */
191 radio_tmr_tifs_set(tx_tifs);
192 radio_switch_complete_and_b2b_tx(test_phy, test_phy_flags, test_phy, test_phy_flags);
193
194 radio_tmr_end_capture();
195
196 #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
197 radio_gpio_pa_setup();
198 radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() +
199 tx_tifs -
200 radio_tx_ready_delay_get(test_phy, test_phy_flags) -
201 HAL_RADIO_GPIO_PA_OFFSET);
202 #endif /* HAL_RADIO_GPIO_HAVE_PA_PIN */
203 }
204
isr_rx(void * param)205 static void isr_rx(void *param)
206 {
207 uint8_t crc_ok = 0U;
208 uint8_t trx_done;
209
210 #if defined(CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT)
211 struct node_rx_iq_report *node_rx;
212 #endif /* CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT */
213
214 #if defined(CONFIG_BT_CTLR_DF_CTE_RX)
215 bool cte_ready;
216 bool cte_ok = 0;
217 #endif /* CONFIG_BT_CTLR_DF_CTE_RX */
218
219 /* Read radio status and events */
220 trx_done = radio_is_done();
221 if (trx_done) {
222 crc_ok = radio_crc_is_valid();
223 #if defined(CONFIG_BT_CTLR_DF_CTE_RX)
224 cte_ready = radio_df_cte_ready();
225 #endif /* CONFIG_BT_CTLR_DF_CTE_RX */
226 }
227
228 /* Clear radio status and events */
229 radio_status_reset();
230 radio_tmr_status_reset();
231
232 /* Exit if radio disabled */
233 if (!trx_done) {
234 return;
235 }
236
237 #if defined(CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT)
238 if (test_cte_len > 0) {
239 /* Get free iq report node for next Rx operation. */
240 node_rx = ull_df_iq_report_alloc_peek(1);
241 LL_ASSERT(node_rx);
242
243 radio_df_iq_data_packet_set(node_rx->pdu, IQ_SAMPLE_TOTAL_CNT);
244 }
245 #endif /* CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT */
246
247 /* Setup next Rx */
248 radio_tmr_tifs_set(EVENT_IFS_US);
249 radio_switch_complete_and_b2b_rx(test_phy, test_phy_flags, test_phy, test_phy_flags);
250
251 /* Count Rx-ed packets */
252 if (crc_ok) {
253
254 #if defined(CONFIG_BT_CTLR_DF_CTE_RX)
255 if (test_cte_len > 0) {
256 cte_ok = check_rx_cte(cte_ready);
257 if (cte_ok) {
258 test_num_rx++;
259 }
260 } else
261 #endif /* CONFIG_BT_CTLR_DF_CTE_RX */
262
263 {
264 test_num_rx++;
265 }
266 }
267
268 #if defined(CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT)
269 if (cte_ok) {
270 int err;
271
272 err = create_iq_report(crc_ok);
273 if (!err) {
274 ull_rx_sched();
275 }
276 }
277 #endif
278 }
279
tx_power_check(int8_t tx_power)280 static uint8_t tx_power_check(int8_t tx_power)
281 {
282 if ((tx_power != BT_HCI_TX_TEST_POWER_MIN_SET) &&
283 (tx_power != BT_HCI_TX_TEST_POWER_MAX_SET) &&
284 ((tx_power < BT_HCI_TX_TEST_POWER_MIN) || (tx_power > BT_HCI_TX_TEST_POWER_MAX))) {
285 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
286 }
287
288 return BT_HCI_ERR_SUCCESS;
289 }
290
tx_power_set(int8_t tx_power)291 static uint8_t tx_power_set(int8_t tx_power)
292 {
293 uint8_t err;
294
295 err = tx_power_check(tx_power);
296 if (err) {
297 return err;
298 }
299
300 if (tx_power == BT_HCI_TX_TEST_POWER_MAX_SET) {
301 tx_power = radio_tx_power_max_get();
302 } else if (tx_power == BT_HCI_TX_TEST_POWER_MIN_SET) {
303 tx_power = radio_tx_power_min_get();
304 } else {
305 tx_power = radio_tx_power_floor(tx_power);
306 }
307
308 radio_tx_power_set(tx_power);
309
310 return err;
311 }
312
313 #if defined(CONFIG_BT_CTLR_DF_CTE_TX)
cte_tx_parameters_check(uint8_t cte_len,uint8_t cte_type,uint8_t switch_pattern_len)314 static uint8_t cte_tx_parameters_check(uint8_t cte_len, uint8_t cte_type,
315 uint8_t switch_pattern_len)
316 {
317 if ((cte_type > BT_HCI_LE_AOD_CTE_2US) ||
318 (cte_len < BT_HCI_LE_CTE_LEN_MIN) ||
319 (cte_len > BT_HCI_LE_CTE_LEN_MAX)) {
320 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
321 }
322
323 if (cte_type != BT_HCI_LE_AOA_CTE) {
324 if ((switch_pattern_len < BT_HCI_LE_SWITCH_PATTERN_LEN_MIN) ||
325 (switch_pattern_len > BT_HCI_LE_SWITCH_PATTERN_LEN_MAX)) {
326 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
327 }
328 }
329
330 if ((cte_type == BT_HCI_LE_AOD_CTE_1US) &&
331 !IS_ENABLED(CONFIG_BT_CTLR_DF_ANT_SWITCH_1US)) {
332 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
333 }
334
335 return BT_HCI_ERR_SUCCESS;
336 }
337
cte_tx_init(uint8_t cte_len,uint8_t cte_type,uint8_t switch_pattern_len,const uint8_t * ant_id)338 static uint8_t cte_tx_init(uint8_t cte_len, uint8_t cte_type, uint8_t switch_pattern_len,
339 const uint8_t *ant_id)
340 {
341 uint8_t err;
342
343 err = cte_tx_parameters_check(cte_len, cte_type, switch_pattern_len);
344 if (err) {
345 return err;
346 }
347
348 if (cte_type == BT_HCI_LE_AOA_CTE) {
349 radio_df_mode_set_aoa();
350 radio_df_cte_tx_aoa_set(cte_len);
351 } else {
352 #if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX)
353 radio_df_mode_set_aod();
354
355 if (cte_type == BT_HCI_LE_AOD_CTE_1US) {
356 radio_df_cte_tx_aod_2us_set(cte_len);
357 } else {
358 radio_df_cte_tx_aod_4us_set(cte_len);
359 }
360
361 radio_df_ant_switching_pin_sel_cfg();
362 radio_df_ant_switch_pattern_clear();
363 radio_df_ant_switch_pattern_set(ant_id, switch_pattern_len);
364 #else
365 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
366 #endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_TX */
367 }
368
369 return err;
370 }
371 #endif /* CONFIG_BT_CTLR_DF_CTE_TX */
372
373 #if defined(CONFIG_BT_CTLR_DF_CTE_RX)
cte_rx_parameters_check(uint8_t expected_cte_len,uint8_t expected_cte_type,uint8_t slot_duration,uint8_t switch_pattern_len)374 static uint8_t cte_rx_parameters_check(uint8_t expected_cte_len, uint8_t expected_cte_type,
375 uint8_t slot_duration, uint8_t switch_pattern_len)
376 {
377 if ((expected_cte_type > BT_HCI_LE_AOD_CTE_2US) ||
378 (expected_cte_len < BT_HCI_LE_CTE_LEN_MIN) ||
379 (expected_cte_len > BT_HCI_LE_CTE_LEN_MAX)) {
380 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
381 }
382
383 if (expected_cte_type == BT_HCI_LE_AOA_CTE) {
384 if ((switch_pattern_len < BT_HCI_LE_SWITCH_PATTERN_LEN_MIN) ||
385 (switch_pattern_len > BT_HCI_LE_SWITCH_PATTERN_LEN_MAX)) {
386 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
387 }
388
389 if ((slot_duration == 0) ||
390 (slot_duration > BT_HCI_LE_ANTENNA_SWITCHING_SLOT_2US)) {
391 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
392 }
393 }
394
395 if ((slot_duration == BT_HCI_LE_ANTENNA_SWITCHING_SLOT_1US) &&
396 (!IS_ENABLED(CONFIG_BT_CTLR_DF_CTE_RX_SAMPLE_1US))) {
397 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
398 }
399
400 return BT_HCI_ERR_SUCCESS;
401 }
402
cte_rx_init(uint8_t expected_cte_len,uint8_t expected_cte_type,uint8_t slot_duration,uint8_t switch_pattern_len,const uint8_t * ant_ids,uint8_t phy)403 static uint8_t cte_rx_init(uint8_t expected_cte_len, uint8_t expected_cte_type,
404 uint8_t slot_duration, uint8_t switch_pattern_len,
405 const uint8_t *ant_ids, uint8_t phy)
406 {
407 uint8_t err;
408 uint8_t cte_phy = (phy == BT_HCI_LE_RX_PHY_1M) ? PHY_1M : PHY_2M;
409
410 err = cte_rx_parameters_check(expected_cte_len, expected_cte_type,
411 slot_duration, switch_pattern_len);
412 if (err) {
413 return err;
414 }
415
416 if (slot_duration == BT_HCI_LE_ANTENNA_SWITCHING_SLOT_1US) {
417 #if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_1US)
418 radio_df_cte_rx_2us_switching(true, cte_phy);
419 #else
420 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
421 #endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_1US */
422 } else {
423 radio_df_cte_rx_4us_switching(true, cte_phy);
424 }
425
426 #if defined(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX)
427 radio_df_ant_switching_pin_sel_cfg();
428 radio_df_ant_switch_pattern_clear();
429 radio_df_ant_switch_pattern_set(ant_ids, switch_pattern_len);
430 #else
431 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
432 #endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_RX */
433
434 #if defined(CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT)
435 struct node_rx_iq_report *node_rx;
436
437 node_rx = ull_df_iq_report_alloc_peek(1);
438 LL_ASSERT(node_rx);
439
440 radio_df_iq_data_packet_set(node_rx->pdu, IQ_SAMPLE_TOTAL_CNT);
441 #else
442 radio_df_iq_data_packet_set(NULL, 0);
443 #endif
444
445 return err;
446 }
447
check_rx_cte(bool cte_ready)448 static bool check_rx_cte(bool cte_ready)
449 {
450 uint8_t cte_status;
451 struct pdu_cte_info *cte_info;
452
453 cte_status = radio_df_cte_status_get();
454 cte_info = (struct pdu_cte_info *)&cte_status;
455
456 if ((cte_info->type != test_cte_type) || (cte_info->time != test_cte_len)) {
457 return false;
458 }
459
460 return true;
461 }
462 #endif /* CONFIG_BT_CTLR_DF_CTE_RX */
463
calculate_tifs(uint8_t len)464 static uint32_t calculate_tifs(uint8_t len)
465 {
466 uint32_t interval;
467 uint32_t transmit_time;
468
469 #if defined(CONFIG_BT_CTLR_DF_CTE_TX)
470 /* Include additional byte for the CTEInfo field and CTE length in microseconds. */
471 transmit_time = PDU_US((test_cte_len > 0) ? (len + 1) : len, 0, test_phy, test_phy_flags) +
472 CTE_LEN_US(test_cte_len);
473 #else
474 transmit_time = PDU_US(len, 0, test_phy, test_phy_flags);
475 #endif /* CONFIG_BT_CTLR_DF_CTE_TX */
476
477 /* Ble Core Specification Vol 6 Part F 4.1.6
478 * LE Test packet interval: I(L) = ceil((L + 249) / 625) * 625 us
479 * where L is an LE Test packet length in microseconds unit.
480 */
481 interval = DIV_ROUND_UP((transmit_time + 249), SCAN_INT_UNIT_US) * SCAN_INT_UNIT_US;
482
483 return interval - transmit_time;
484 }
485
init(uint8_t chan,uint8_t phy,int8_t tx_power,bool cte,void (* isr)(void *))486 static uint8_t init(uint8_t chan, uint8_t phy, int8_t tx_power,
487 bool cte, void (*isr)(void *))
488 {
489 int err;
490 uint8_t ret;
491
492 if (started) {
493 return BT_HCI_ERR_CMD_DISALLOWED;
494 }
495
496 /* start coarse timer */
497 cntr_start();
498
499 /* Setup resources required by Radio */
500 err = lll_hfclock_on_wait();
501 LL_ASSERT(err >= 0);
502
503 /* Reset Radio h/w */
504 radio_reset();
505 radio_isr_set(isr, NULL);
506
507 #if defined(CONFIG_BT_CTLR_DF)
508 /* Reset Radio DF */
509 radio_df_reset();
510 #endif
511
512 /* Store value needed in Tx/Rx ISR */
513 if (phy < BT_HCI_LE_TX_PHY_CODED_S2) {
514 test_phy = BIT(phy - 1);
515 test_phy_flags = 1U;
516 } else {
517 test_phy = BIT(2);
518 test_phy_flags = 0U;
519 }
520
521 /* Setup Radio in Tx/Rx */
522 /* NOTE: No whitening in test mode. */
523 radio_phy_set(test_phy, test_phy_flags);
524
525 ret = tx_power_set(tx_power);
526
527 radio_freq_chan_set((chan << 1) + 2);
528 radio_aa_set((uint8_t *)&test_sync_word);
529 radio_crc_configure(0x65b, PDU_AC_CRC_IV);
530 radio_pkt_configure(RADIO_PKT_CONF_LENGTH_8BIT, PDU_DTM_PAYLOAD_SIZE_MAX,
531 RADIO_PKT_CONF_PHY(test_phy) |
532 RADIO_PKT_CONF_PDU_TYPE(IS_ENABLED(CONFIG_BT_CTLR_DF_CTE_TX) ?
533 RADIO_PKT_CONF_PDU_TYPE_DC :
534 RADIO_PKT_CONF_PDU_TYPE_AC) |
535 RADIO_PKT_CONF_CTE(cte ? RADIO_PKT_CONF_CTE_ENABLED :
536 RADIO_PKT_CONF_CTE_DISABLED));
537
538 return ret;
539 }
540
payload_set(uint8_t type,uint8_t len,uint8_t cte_len,uint8_t cte_type)541 static void payload_set(uint8_t type, uint8_t len, uint8_t cte_len, uint8_t cte_type)
542 {
543 struct pdu_dtm *pdu = radio_pkt_scratch_get();
544
545 pdu->type = type;
546 pdu->len = len;
547
548 #if defined(CONFIG_BT_CTLR_DF_CTE_TX)
549 pdu->cp = cte_len ? 1U : 0U;
550 pdu->octet3.cte_info.time = cte_len;
551 pdu->octet3.cte_info.type = cte_type;
552 #else
553 ARG_UNUSED(cte_len);
554 ARG_UNUSED(cte_type);
555 #endif /* CONFIG_BT_CTLR_DF_CTE_TX */
556
557 switch (type) {
558 case BT_HCI_TEST_PKT_PAYLOAD_PRBS9:
559 (void)memcpy(pdu->payload, prbs9, len);
560 break;
561
562 case BT_HCI_TEST_PKT_PAYLOAD_11110000:
563 (void)memset(pdu->payload, PAYLOAD_11110000, len);
564 break;
565
566 case BT_HCI_TEST_PKT_PAYLOAD_10101010:
567 (void)memset(pdu->payload, PAYLOAD_10101010, len);
568 break;
569
570 case BT_HCI_TEST_PKT_PAYLOAD_PRBS15:
571 (void)memcpy(pdu->payload, prbs15, len);
572 break;
573
574 case BT_HCI_TEST_PKT_PAYLOAD_11111111:
575 (void)memset(pdu->payload, PAYLOAD_11111111, len);
576 break;
577
578 case BT_HCI_TEST_PKT_PAYLOAD_00000000:
579 (void)memset(pdu->payload, PAYLOAD_00000000, len);
580 break;
581
582 case BT_HCI_TEST_PKT_PAYLOAD_00001111:
583 (void)memset(pdu->payload, PAYLOAD_00001111, len);
584 break;
585
586 case BT_HCI_TEST_PKT_PAYLOAD_01010101:
587 (void)memset(pdu->payload, PAYLOAD_01010101, len);
588 break;
589 }
590
591 radio_pkt_tx_set(pdu);
592 }
593
ll_test_tx(uint8_t chan,uint8_t len,uint8_t type,uint8_t phy,uint8_t cte_len,uint8_t cte_type,uint8_t switch_pattern_len,const uint8_t * ant_id,int8_t tx_power)594 uint8_t ll_test_tx(uint8_t chan, uint8_t len, uint8_t type, uint8_t phy,
595 uint8_t cte_len, uint8_t cte_type, uint8_t switch_pattern_len,
596 const uint8_t *ant_id, int8_t tx_power)
597 {
598 uint32_t start_us;
599 uint8_t err;
600 const bool cte_request = (cte_len > 0) ? true : false;
601
602 if ((type > BT_HCI_TEST_PKT_PAYLOAD_01010101) || !phy ||
603 (phy > BT_HCI_LE_TX_PHY_CODED_S2)) {
604 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
605 }
606
607 err = init(chan, phy, tx_power, cte_request, isr_tx);
608 if (err) {
609 return err;
610 }
611
612 /* Configure Constant Tone Extension */
613 if (cte_request) {
614 #if defined(CONFIG_BT_CTLR_DF_CTE_TX)
615 if (phy > BT_HCI_LE_TX_PHY_2M) {
616 return BT_HCI_ERR_CMD_DISALLOWED;
617 }
618
619 err = cte_tx_init(cte_len, cte_type, switch_pattern_len, ant_id);
620 if (err) {
621 return err;
622 }
623 #else
624 return BT_HCI_ERR_CMD_DISALLOWED;
625 #endif /* CONFIG_BT_CTLR_DF_CTE_TX */
626 }
627
628 tx_req++;
629
630 payload_set(type, len, cte_len, cte_type);
631
632 #if defined(CONFIG_BT_CTLR_DF_CTE_TX)
633 /* Store CTE parameters needed in Tx ISR */
634 test_cte_len = cte_len;
635 #endif /* CONFIG_BT_CTLR_DF_CTE_TX */
636
637 tx_tifs = calculate_tifs(len);
638
639 radio_tmr_tifs_set(tx_tifs);
640 radio_switch_complete_and_b2b_tx(test_phy, test_phy_flags, test_phy, test_phy_flags);
641
642 start_us = radio_tmr_start(1, cntr_cnt_get() + CNTR_MIN_DELTA, 0);
643 radio_tmr_end_capture();
644
645 #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
646 radio_gpio_pa_setup();
647 radio_gpio_pa_lna_enable(start_us +
648 radio_tx_ready_delay_get(test_phy,
649 test_phy_flags) -
650 HAL_RADIO_GPIO_PA_OFFSET);
651 #else /* !HAL_RADIO_GPIO_HAVE_PA_PIN */
652 ARG_UNUSED(start_us);
653 #endif /* !HAL_RADIO_GPIO_HAVE_PA_PIN */
654
655 started = true;
656
657 return BT_HCI_ERR_SUCCESS;
658 }
659
ll_test_rx(uint8_t chan,uint8_t phy,uint8_t mod_idx,uint8_t expected_cte_len,uint8_t expected_cte_type,uint8_t slot_duration,uint8_t switch_pattern_len,const uint8_t * ant_ids)660 uint8_t ll_test_rx(uint8_t chan, uint8_t phy, uint8_t mod_idx, uint8_t expected_cte_len,
661 uint8_t expected_cte_type, uint8_t slot_duration, uint8_t switch_pattern_len,
662 const uint8_t *ant_ids)
663 {
664 uint8_t err;
665 const bool cte_expected = (expected_cte_len > 0) ? true : false;
666
667 if (!phy || (phy > BT_HCI_LE_RX_PHY_CODED)) {
668 return BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL;
669 }
670
671 err = init(chan, phy, BT_HCI_TX_TEST_POWER_MAX_SET, cte_expected, isr_rx);
672 if (err) {
673 return err;
674 }
675
676 if (cte_expected) {
677 #if defined(CONFIG_BT_CTLR_DF_CTE_RX)
678 if (phy == BT_HCI_LE_RX_PHY_CODED) {
679 return BT_HCI_ERR_CMD_DISALLOWED;
680 }
681
682 err = cte_rx_init(expected_cte_len, expected_cte_type, slot_duration,
683 switch_pattern_len, ant_ids, phy);
684 if (err) {
685 return err;
686 }
687 #else
688 return BT_HCI_ERR_CMD_DISALLOWED;
689 #endif /* CONFIG_BT_CTLR_DF_CTE_RX */
690 }
691
692 #if defined(CONFIG_BT_CTLR_DF_CTE_RX)
693 /* Store CTE parameters needed in Rx ISR */
694 test_cte_type = expected_cte_type;
695 test_cte_len = expected_cte_len;
696 #endif /* CONFIG_BT_CTLR_DF_CTE_RX */
697
698 #if defined(CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT)
699 test_chan = chan;
700 test_slot_duration = slot_duration;
701 #endif /* CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT */
702
703 radio_pkt_rx_set(radio_pkt_scratch_get());
704 radio_tmr_tifs_set(EVENT_IFS_US);
705 radio_switch_complete_and_b2b_rx(test_phy, test_phy_flags, test_phy, test_phy_flags);
706 radio_tmr_start(0, cntr_cnt_get() + CNTR_MIN_DELTA, 0);
707
708 #if defined(HAL_RADIO_GPIO_HAVE_LNA_PIN)
709 radio_gpio_lna_on();
710 #endif /* !HAL_RADIO_GPIO_HAVE_LNA_PIN */
711
712 started = true;
713
714 return BT_HCI_ERR_SUCCESS;
715 }
716
ll_test_end(uint16_t * num_rx)717 uint8_t ll_test_end(uint16_t *num_rx)
718 {
719 int err;
720 uint8_t ack;
721
722 if (!started) {
723 return BT_HCI_ERR_CMD_DISALLOWED;
724 }
725
726 /* Return packets Rx-ed/Completed */
727 *num_rx = test_num_rx;
728 test_num_rx = 0U;
729
730 /* Disable Radio, if in Rx test */
731 ack = tx_ack;
732 if (tx_req == ack) {
733 radio_disable();
734 } else {
735 /* Wait for Tx to complete */
736 tx_req = ack + 2;
737 while (tx_req != tx_ack) {
738 cpu_sleep();
739 }
740 }
741
742 /* Stop packet timer */
743 radio_tmr_stop();
744
745 /* Release resources acquired for Radio */
746 err = lll_hfclock_off();
747 LL_ASSERT(err >= 0);
748
749 /* Stop coarse timer */
750 cntr_stop();
751
752 #if defined(HAL_RADIO_GPIO_HAVE_LNA_PIN)
753 radio_gpio_lna_off();
754 #endif /* !HAL_RADIO_GPIO_HAVE_LNA_PIN */
755
756 started = false;
757
758 return BT_HCI_ERR_SUCCESS;
759 }
760