xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/controller/src/ble_ll_dtm.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1*042d53a7SEvalZero /*
2*042d53a7SEvalZero  * Licensed to the Apache Software Foundation (ASF) under one
3*042d53a7SEvalZero  * or more contributor license agreements.  See the NOTICE file
4*042d53a7SEvalZero  * distributed with this work for additional information
5*042d53a7SEvalZero  * regarding copyright ownership.  The ASF licenses this file
6*042d53a7SEvalZero  * to you under the Apache License, Version 2.0 (the
7*042d53a7SEvalZero  * "License"); you may not use this file except in compliance
8*042d53a7SEvalZero  * with the License.  You may obtain a copy of the License at
9*042d53a7SEvalZero  *
10*042d53a7SEvalZero  *  http://www.apache.org/licenses/LICENSE-2.0
11*042d53a7SEvalZero  *
12*042d53a7SEvalZero  * Unless required by applicable law or agreed to in writing,
13*042d53a7SEvalZero  * software distributed under the License is distributed on an
14*042d53a7SEvalZero  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15*042d53a7SEvalZero  * KIND, either express or implied.  See the License for the
16*042d53a7SEvalZero  * specific language governing permissions and limitations
17*042d53a7SEvalZero  * under the License.
18*042d53a7SEvalZero  */
19*042d53a7SEvalZero 
20*042d53a7SEvalZero #include "syscfg/syscfg.h"
21*042d53a7SEvalZero #include "sysinit/sysinit.h"
22*042d53a7SEvalZero 
23*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
24*042d53a7SEvalZero 
25*042d53a7SEvalZero #include <assert.h>
26*042d53a7SEvalZero #include "os/os.h"
27*042d53a7SEvalZero #include "stats/stats.h"
28*042d53a7SEvalZero #include "controller/ble_ll.h"
29*042d53a7SEvalZero #include "controller/ble_phy.h"
30*042d53a7SEvalZero #include "controller/ble_ll_sched.h"
31*042d53a7SEvalZero #include "controller/ble_ll_xcvr.h"
32*042d53a7SEvalZero #include "ble_ll_dtm_priv.h"
33*042d53a7SEvalZero 
34*042d53a7SEvalZero STATS_SECT_START(ble_ll_dtm_stats)
35*042d53a7SEvalZero     STATS_SECT_ENTRY(rx_count)
36*042d53a7SEvalZero     STATS_SECT_ENTRY(tx_failed)
37*042d53a7SEvalZero     STATS_SECT_ENTRY(rx_failed)
38*042d53a7SEvalZero STATS_SECT_END
39*042d53a7SEvalZero STATS_SECT_DECL(ble_ll_dtm_stats) ble_ll_dtm_stats;
40*042d53a7SEvalZero 
41*042d53a7SEvalZero STATS_NAME_START(ble_ll_dtm_stats)
42*042d53a7SEvalZero     STATS_NAME(ble_ll_dtm_stats, rx_count)
43*042d53a7SEvalZero     STATS_NAME(ble_ll_dtm_stats, tx_failed)
44*042d53a7SEvalZero     STATS_NAME(ble_ll_dtm_stats, rx_failed)
45*042d53a7SEvalZero STATS_NAME_END(ble_phy_stats)
46*042d53a7SEvalZero 
47*042d53a7SEvalZero struct dtm_ctx {
48*042d53a7SEvalZero     uint8_t payload_packet;
49*042d53a7SEvalZero     uint8_t itvl_rem_usec;
50*042d53a7SEvalZero     uint16_t num_of_packets;
51*042d53a7SEvalZero     uint32_t itvl_ticks;
52*042d53a7SEvalZero     int active;
53*042d53a7SEvalZero     uint8_t rf_channel;
54*042d53a7SEvalZero     uint8_t phy_mode;
55*042d53a7SEvalZero     struct os_mbuf *om;
56*042d53a7SEvalZero     struct ble_npl_event evt;
57*042d53a7SEvalZero     struct ble_ll_sched_item sch;
58*042d53a7SEvalZero };
59*042d53a7SEvalZero 
60*042d53a7SEvalZero static struct dtm_ctx g_ble_ll_dtm_ctx;
61*042d53a7SEvalZero 
62*042d53a7SEvalZero static const uint8_t g_ble_ll_dtm_prbs9_data[] =
63*042d53a7SEvalZero {
64*042d53a7SEvalZero     0xff, 0xc1, 0xfb, 0xe8, 0x4c, 0x90, 0x72, 0x8b,
65*042d53a7SEvalZero     0xe7, 0xb3, 0x51, 0x89, 0x63, 0xab, 0x23, 0x23,
66*042d53a7SEvalZero     0x02, 0x84, 0x18, 0x72, 0xaa, 0x61, 0x2f, 0x3b,
67*042d53a7SEvalZero     0x51, 0xa8, 0xe5, 0x37, 0x49, 0xfb, 0xc9, 0xca,
68*042d53a7SEvalZero     0x0c, 0x18, 0x53, 0x2c, 0xfd, 0x45, 0xe3, 0x9a,
69*042d53a7SEvalZero     0xe6, 0xf1, 0x5d, 0xb0, 0xb6, 0x1b, 0xb4, 0xbe,
70*042d53a7SEvalZero     0x2a, 0x50, 0xea, 0xe9, 0x0e, 0x9c, 0x4b, 0x5e,
71*042d53a7SEvalZero     0x57, 0x24, 0xcc, 0xa1, 0xb7, 0x59, 0xb8, 0x87,
72*042d53a7SEvalZero     0xff, 0xe0, 0x7d, 0x74, 0x26, 0x48, 0xb9, 0xc5,
73*042d53a7SEvalZero     0xf3, 0xd9, 0xa8, 0xc4, 0xb1, 0xd5, 0x91, 0x11,
74*042d53a7SEvalZero     0x01, 0x42, 0x0c, 0x39, 0xd5, 0xb0, 0x97, 0x9d,
75*042d53a7SEvalZero     0x28, 0xd4, 0xf2, 0x9b, 0xa4, 0xfd, 0x64, 0x65,
76*042d53a7SEvalZero     0x06, 0x8c, 0x29, 0x96, 0xfe, 0xa2, 0x71, 0x4d,
77*042d53a7SEvalZero     0xf3, 0xf8, 0x2e, 0x58, 0xdb, 0x0d, 0x5a, 0x5f,
78*042d53a7SEvalZero     0x15, 0x28, 0xf5, 0x74, 0x07, 0xce, 0x25, 0xaf,
79*042d53a7SEvalZero     0x2b, 0x12, 0xe6, 0xd0, 0xdb, 0x2c, 0xdc, 0xc3,
80*042d53a7SEvalZero     0x7f, 0xf0, 0x3e, 0x3a, 0x13, 0xa4, 0xdc, 0xe2,
81*042d53a7SEvalZero     0xf9, 0x6c, 0x54, 0xe2, 0xd8, 0xea, 0xc8, 0x88,
82*042d53a7SEvalZero     0x00, 0x21, 0x86, 0x9c, 0x6a, 0xd8, 0xcb, 0x4e,
83*042d53a7SEvalZero     0x14, 0x6a, 0xf9, 0x4d, 0xd2, 0x7e, 0xb2, 0x32,
84*042d53a7SEvalZero     0x03, 0xc6, 0x14, 0x4b, 0x7f, 0xd1, 0xb8, 0xa6,
85*042d53a7SEvalZero     0x79, 0x7c, 0x17, 0xac, 0xed, 0x06, 0xad, 0xaf,
86*042d53a7SEvalZero     0x0a, 0x94, 0x7a, 0xba, 0x03, 0xe7, 0x92, 0xd7,
87*042d53a7SEvalZero     0x15, 0x09, 0x73, 0xe8, 0x6d, 0x16, 0xee, 0xe1,
88*042d53a7SEvalZero     0x3f, 0x78, 0x1f, 0x9d, 0x09, 0x52, 0x6e, 0xf1,
89*042d53a7SEvalZero     0x7c, 0x36, 0x2a, 0x71, 0x6c, 0x75, 0x64, 0x44,
90*042d53a7SEvalZero     0x80, 0x10, 0x43, 0x4e, 0x35, 0xec, 0x65, 0x27,
91*042d53a7SEvalZero     0x0a, 0xb5, 0xfc, 0x26, 0x69, 0x3f, 0x59, 0x99,
92*042d53a7SEvalZero     0x01, 0x63, 0x8a, 0xa5, 0xbf, 0x68, 0x5c, 0xd3,
93*042d53a7SEvalZero     0x3c, 0xbe, 0x0b, 0xd6, 0x76, 0x83, 0xd6, 0x57,
94*042d53a7SEvalZero     0x05, 0x4a, 0x3d, 0xdd, 0x81, 0x73, 0xc9, 0xeb,
95*042d53a7SEvalZero     0x8a, 0x84, 0x39, 0xf4, 0x36, 0x0b, 0xf7
96*042d53a7SEvalZero };
97*042d53a7SEvalZero 
98*042d53a7SEvalZero static const uint8_t g_ble_ll_dtm_prbs15_data[] =
99*042d53a7SEvalZero {
100*042d53a7SEvalZero     0xff, 0x7f, 0xf0, 0x3e, 0x3a, 0x13, 0xa4, 0xdc,
101*042d53a7SEvalZero     0xe2, 0xf9, 0x6c, 0x54, 0xe2, 0xd8, 0xea, 0xc8,
102*042d53a7SEvalZero     0x88, 0x00, 0x21, 0x86, 0x9c, 0x6a, 0xd8, 0xcb,
103*042d53a7SEvalZero     0x4e, 0x14, 0x6a, 0xf9, 0x4d, 0xd2, 0x7e, 0xb2,
104*042d53a7SEvalZero     0x32, 0x03, 0xc6, 0x14, 0x4b, 0x7f, 0xd1, 0xb8,
105*042d53a7SEvalZero     0xa6, 0x79, 0x7c, 0x17, 0xac, 0xed, 0x06, 0xad,
106*042d53a7SEvalZero     0xaf, 0x0a, 0x94, 0x7a, 0xba, 0x03, 0xe7, 0x92,
107*042d53a7SEvalZero     0xd7, 0x15, 0x09, 0x73, 0xe8, 0x6d, 0x16, 0xee,
108*042d53a7SEvalZero     0xe1, 0x3f, 0x78, 0x1f, 0x9d, 0x09, 0x52, 0x6e,
109*042d53a7SEvalZero     0xf1, 0x7c, 0x36, 0x2a, 0x71, 0x6c, 0x75, 0x64,
110*042d53a7SEvalZero     0x44, 0x80, 0x10, 0x43, 0x4e, 0x35, 0xec, 0x65,
111*042d53a7SEvalZero     0x27, 0x0a, 0xb5, 0xfc, 0x26, 0x69, 0x3f, 0x59,
112*042d53a7SEvalZero     0x99, 0x01, 0x63, 0x8a, 0xa5, 0xbf, 0x68, 0x5c,
113*042d53a7SEvalZero     0xd3, 0x3c, 0xbe, 0x0b, 0xd6, 0x76, 0x83, 0xd6,
114*042d53a7SEvalZero     0x57, 0x05, 0x4a, 0x3d, 0xdd, 0x81, 0x73, 0xc9,
115*042d53a7SEvalZero     0xeb, 0x8a, 0x84, 0x39, 0xf4, 0x36, 0x0b, 0xf7,
116*042d53a7SEvalZero     0xf0, 0x1f, 0xbc, 0x8f, 0xce, 0x04, 0x29, 0xb7,
117*042d53a7SEvalZero     0x78, 0x3e, 0x1b, 0x95, 0x38, 0xb6, 0x3a, 0x32,
118*042d53a7SEvalZero     0x22, 0x40, 0x88, 0x21, 0xa7, 0x1a, 0xf6, 0xb2,
119*042d53a7SEvalZero     0x13, 0x85, 0x5a, 0x7e, 0x93, 0xb4, 0x9f, 0xac,
120*042d53a7SEvalZero     0xcc, 0x80, 0x31, 0xc5, 0xd2, 0x5f, 0x34, 0xae,
121*042d53a7SEvalZero     0x69, 0x1e, 0xdf, 0x05, 0x6b, 0xbb, 0x41, 0xeb,
122*042d53a7SEvalZero     0xab, 0x02, 0xa5, 0x9e, 0xee, 0xc0, 0xb9, 0xe4,
123*042d53a7SEvalZero     0x75, 0x45, 0xc2, 0x1c, 0x7a, 0x9b, 0x85, 0x7b,
124*042d53a7SEvalZero     0xf8, 0x0f, 0xde, 0x47, 0x67, 0x82, 0x94, 0x5b,
125*042d53a7SEvalZero     0x3c, 0x9f, 0x8d, 0x4a, 0x1c, 0x5b, 0x1d, 0x19,
126*042d53a7SEvalZero     0x11, 0x20, 0xc4, 0x90, 0x53, 0x0d, 0x7b, 0xd9,
127*042d53a7SEvalZero     0x89, 0x42, 0x2d, 0xbf, 0x49, 0xda, 0x4f, 0x56,
128*042d53a7SEvalZero     0x66, 0xc0, 0x98, 0x62, 0xe9, 0x2f, 0x1a, 0xd7,
129*042d53a7SEvalZero     0x34, 0x8f, 0xef, 0x82, 0xb5, 0xdd, 0xa0, 0xf5,
130*042d53a7SEvalZero     0x55, 0x81, 0x52, 0x4f, 0x77, 0xe0, 0x5c, 0xf2,
131*042d53a7SEvalZero     0xba, 0x22, 0x61, 0x0e, 0xbd, 0xcd, 0xc2
132*042d53a7SEvalZero };
133*042d53a7SEvalZero 
134*042d53a7SEvalZero static const uint8_t channel_rf_to_index[] = {
135*042d53a7SEvalZero         37,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 38, 11 ,12, 13, 14, 15,
136*042d53a7SEvalZero         16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
137*042d53a7SEvalZero         34, 35, 36, 39
138*042d53a7SEvalZero };
139*042d53a7SEvalZero 
140*042d53a7SEvalZero #define BLE_DTM_SYNC_WORD          (0x71764129)
141*042d53a7SEvalZero #define BLE_DTM_CRC                (0x555555)
142*042d53a7SEvalZero 
143*042d53a7SEvalZero static void
ble_ll_dtm_set_next(struct dtm_ctx * ctx)144*042d53a7SEvalZero ble_ll_dtm_set_next(struct dtm_ctx *ctx)
145*042d53a7SEvalZero {
146*042d53a7SEvalZero     struct ble_ll_sched_item *sch = &ctx->sch;
147*042d53a7SEvalZero 
148*042d53a7SEvalZero     sch->start_time += ctx->itvl_ticks;
149*042d53a7SEvalZero     sch->remainder += ctx->itvl_rem_usec;
150*042d53a7SEvalZero     if (sch->remainder > 30) {
151*042d53a7SEvalZero        sch->start_time++;
152*042d53a7SEvalZero        sch->remainder -= 30;
153*042d53a7SEvalZero     }
154*042d53a7SEvalZero 
155*042d53a7SEvalZero     sch->start_time -= g_ble_ll_sched_offset_ticks;
156*042d53a7SEvalZero }
157*042d53a7SEvalZero 
158*042d53a7SEvalZero static void
ble_ll_dtm_ev_tx_resched_cb(struct ble_npl_event * evt)159*042d53a7SEvalZero ble_ll_dtm_ev_tx_resched_cb(struct ble_npl_event *evt) {
160*042d53a7SEvalZero     /* It is called in LL context */
161*042d53a7SEvalZero     struct dtm_ctx *ctx = ble_npl_event_get_arg(evt);
162*042d53a7SEvalZero     int rc;
163*042d53a7SEvalZero     os_sr_t sr;
164*042d53a7SEvalZero 
165*042d53a7SEvalZero     OS_ENTER_CRITICAL(sr);
166*042d53a7SEvalZero     if (!ctx->active || !ctx->om) {
167*042d53a7SEvalZero         OS_EXIT_CRITICAL(sr);
168*042d53a7SEvalZero         return;
169*042d53a7SEvalZero     }
170*042d53a7SEvalZero     OS_EXIT_CRITICAL(sr);
171*042d53a7SEvalZero 
172*042d53a7SEvalZero     ble_ll_dtm_set_next(ctx);
173*042d53a7SEvalZero     rc = ble_ll_sched_dtm(&ctx->sch);
174*042d53a7SEvalZero     BLE_LL_ASSERT(rc == 0);
175*042d53a7SEvalZero }
176*042d53a7SEvalZero 
177*042d53a7SEvalZero static int ble_ll_dtm_rx_start(void);
178*042d53a7SEvalZero 
179*042d53a7SEvalZero static void
ble_ll_dtm_ev_rx_restart_cb(struct ble_npl_event * evt)180*042d53a7SEvalZero ble_ll_dtm_ev_rx_restart_cb(struct ble_npl_event *evt) {
181*042d53a7SEvalZero     if (ble_ll_dtm_rx_start() != 0) {
182*042d53a7SEvalZero         ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt);
183*042d53a7SEvalZero         STATS_INC(ble_ll_dtm_stats, rx_failed);
184*042d53a7SEvalZero     }
185*042d53a7SEvalZero }
186*042d53a7SEvalZero 
187*042d53a7SEvalZero static void
ble_ll_dtm_tx_done(void * arg)188*042d53a7SEvalZero ble_ll_dtm_tx_done(void *arg)
189*042d53a7SEvalZero {
190*042d53a7SEvalZero     struct dtm_ctx *ctx;
191*042d53a7SEvalZero 
192*042d53a7SEvalZero     ctx = arg;
193*042d53a7SEvalZero     if (!ctx->active) {
194*042d53a7SEvalZero         return;
195*042d53a7SEvalZero     }
196*042d53a7SEvalZero 
197*042d53a7SEvalZero     /* Reschedule event in LL context */
198*042d53a7SEvalZero     ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &ctx->evt);
199*042d53a7SEvalZero 
200*042d53a7SEvalZero     ble_ll_state_set(BLE_LL_STATE_STANDBY);
201*042d53a7SEvalZero }
202*042d53a7SEvalZero 
203*042d53a7SEvalZero static int
ble_ll_dtm_tx_sched_cb(struct ble_ll_sched_item * sch)204*042d53a7SEvalZero ble_ll_dtm_tx_sched_cb(struct ble_ll_sched_item *sch)
205*042d53a7SEvalZero {
206*042d53a7SEvalZero     struct dtm_ctx *ctx = sch->cb_arg;
207*042d53a7SEvalZero     int rc;
208*042d53a7SEvalZero 
209*042d53a7SEvalZero     if (!ctx->active) {
210*042d53a7SEvalZero         return BLE_LL_SCHED_STATE_DONE;
211*042d53a7SEvalZero     }
212*042d53a7SEvalZero 
213*042d53a7SEvalZero     rc = ble_phy_setchan(channel_rf_to_index[ctx->rf_channel],
214*042d53a7SEvalZero                                             BLE_DTM_SYNC_WORD, BLE_DTM_CRC);
215*042d53a7SEvalZero     if (rc != 0) {
216*042d53a7SEvalZero         BLE_LL_ASSERT(0);
217*042d53a7SEvalZero         return BLE_LL_SCHED_STATE_DONE;
218*042d53a7SEvalZero     }
219*042d53a7SEvalZero 
220*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY))
221*042d53a7SEvalZero     ble_phy_mode_set(ctx->phy_mode, ctx->phy_mode);
222*042d53a7SEvalZero #endif
223*042d53a7SEvalZero     ble_phy_set_txend_cb(ble_ll_dtm_tx_done, ctx);
224*042d53a7SEvalZero     ble_phy_txpwr_set(0);
225*042d53a7SEvalZero 
226*042d53a7SEvalZero     sch->start_time += g_ble_ll_sched_offset_ticks;
227*042d53a7SEvalZero 
228*042d53a7SEvalZero     rc = ble_phy_tx_set_start_time(sch->start_time, sch->remainder);
229*042d53a7SEvalZero     if (rc) {
230*042d53a7SEvalZero         goto resched;
231*042d53a7SEvalZero     }
232*042d53a7SEvalZero 
233*042d53a7SEvalZero     rc = ble_phy_tx(ble_ll_tx_mbuf_pducb, ctx->om, BLE_PHY_TRANSITION_NONE);
234*042d53a7SEvalZero     if (rc) {
235*042d53a7SEvalZero         goto resched;
236*042d53a7SEvalZero     }
237*042d53a7SEvalZero 
238*042d53a7SEvalZero     ble_ll_state_set(BLE_LL_STATE_DTM);
239*042d53a7SEvalZero 
240*042d53a7SEvalZero     return BLE_LL_SCHED_STATE_DONE;
241*042d53a7SEvalZero 
242*042d53a7SEvalZero resched:
243*042d53a7SEvalZero     /* Reschedule from LL task if late for this PDU */
244*042d53a7SEvalZero     ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &ctx->evt);
245*042d53a7SEvalZero 
246*042d53a7SEvalZero     STATS_INC(ble_ll_dtm_stats, tx_failed);
247*042d53a7SEvalZero 
248*042d53a7SEvalZero     return BLE_LL_SCHED_STATE_DONE;
249*042d53a7SEvalZero }
250*042d53a7SEvalZero 
251*042d53a7SEvalZero static void
ble_ll_dtm_calculate_itvl(struct dtm_ctx * ctx,uint8_t len,int phy_mode)252*042d53a7SEvalZero ble_ll_dtm_calculate_itvl(struct dtm_ctx *ctx, uint8_t len, int phy_mode)
253*042d53a7SEvalZero {
254*042d53a7SEvalZero     uint32_t l;
255*042d53a7SEvalZero     uint32_t itvl_usec;
256*042d53a7SEvalZero     uint32_t itvl_ticks;
257*042d53a7SEvalZero 
258*042d53a7SEvalZero     /* Calculate interval as per spec Bluetooth 5.0 Vol 6. Part F, 4.1.6 */
259*042d53a7SEvalZero     l = ble_ll_pdu_tx_time_get(len + BLE_LL_PDU_HDR_LEN, phy_mode);
260*042d53a7SEvalZero     itvl_usec = ((l + 249 + 624) / 625) * 625;
261*042d53a7SEvalZero 
262*042d53a7SEvalZero     itvl_ticks = os_cputime_usecs_to_ticks(itvl_usec);
263*042d53a7SEvalZero     ctx->itvl_rem_usec = (itvl_usec - os_cputime_ticks_to_usecs(itvl_ticks));
264*042d53a7SEvalZero     if (ctx->itvl_rem_usec == 31) {
265*042d53a7SEvalZero         ctx->itvl_rem_usec = 0;
266*042d53a7SEvalZero         ++itvl_ticks;
267*042d53a7SEvalZero     }
268*042d53a7SEvalZero     ctx->itvl_ticks = itvl_ticks;
269*042d53a7SEvalZero }
270*042d53a7SEvalZero 
271*042d53a7SEvalZero static int
ble_ll_dtm_tx_create_ctx(uint8_t packet_payload,uint8_t len,uint8_t rf_channel,uint8_t phy_mode)272*042d53a7SEvalZero ble_ll_dtm_tx_create_ctx(uint8_t packet_payload, uint8_t len,
273*042d53a7SEvalZero                          uint8_t rf_channel, uint8_t phy_mode)
274*042d53a7SEvalZero {
275*042d53a7SEvalZero     int rc = 0;
276*042d53a7SEvalZero     uint8_t byte_pattern;
277*042d53a7SEvalZero     struct ble_mbuf_hdr *ble_hdr;
278*042d53a7SEvalZero     struct os_mbuf *m;
279*042d53a7SEvalZero     struct ble_ll_sched_item *sch = &g_ble_ll_dtm_ctx.sch;
280*042d53a7SEvalZero 
281*042d53a7SEvalZero     /* MSYS is big enough to get continues memory */
282*042d53a7SEvalZero     m = os_msys_get_pkthdr(len, sizeof(struct ble_mbuf_hdr));
283*042d53a7SEvalZero     g_ble_ll_dtm_ctx.om = m;
284*042d53a7SEvalZero     BLE_LL_ASSERT(g_ble_ll_dtm_ctx.om);
285*042d53a7SEvalZero 
286*042d53a7SEvalZero     g_ble_ll_dtm_ctx.phy_mode = phy_mode;
287*042d53a7SEvalZero     g_ble_ll_dtm_ctx.rf_channel = rf_channel;
288*042d53a7SEvalZero 
289*042d53a7SEvalZero     /* Set BLE transmit header */
290*042d53a7SEvalZero     ble_hdr = BLE_MBUF_HDR_PTR(m);
291*042d53a7SEvalZero     ble_hdr->txinfo.flags = 0;
292*042d53a7SEvalZero     ble_hdr->txinfo.offset = 0;
293*042d53a7SEvalZero     ble_hdr->txinfo.pyld_len = len;
294*042d53a7SEvalZero     ble_hdr->txinfo.hdr_byte = packet_payload;
295*042d53a7SEvalZero 
296*042d53a7SEvalZero     switch(packet_payload) {
297*042d53a7SEvalZero     case 0x00:
298*042d53a7SEvalZero         if (os_mbuf_copyinto(m, 0, &g_ble_ll_dtm_prbs9_data, len)) {
299*042d53a7SEvalZero             return 1;
300*042d53a7SEvalZero         }
301*042d53a7SEvalZero         goto schedule;
302*042d53a7SEvalZero     case 0x01:
303*042d53a7SEvalZero         byte_pattern = 0x0F;
304*042d53a7SEvalZero         break;
305*042d53a7SEvalZero     case 0x02:
306*042d53a7SEvalZero         byte_pattern = 0x55;
307*042d53a7SEvalZero         break;
308*042d53a7SEvalZero     case 0x03:
309*042d53a7SEvalZero         if (os_mbuf_copyinto(m, 0, &g_ble_ll_dtm_prbs15_data, len)) {
310*042d53a7SEvalZero             return 1;
311*042d53a7SEvalZero         }
312*042d53a7SEvalZero         goto schedule;
313*042d53a7SEvalZero     case 0x04:
314*042d53a7SEvalZero         byte_pattern = 0xFF;
315*042d53a7SEvalZero         break;
316*042d53a7SEvalZero     case 0x05:
317*042d53a7SEvalZero         byte_pattern = 0x00;
318*042d53a7SEvalZero         break;
319*042d53a7SEvalZero     case 0x06:
320*042d53a7SEvalZero         byte_pattern = 0xF0;
321*042d53a7SEvalZero         break;
322*042d53a7SEvalZero     case 0x07:
323*042d53a7SEvalZero         byte_pattern = 0xAA;
324*042d53a7SEvalZero         break;
325*042d53a7SEvalZero     default:
326*042d53a7SEvalZero         return 1;
327*042d53a7SEvalZero     }
328*042d53a7SEvalZero 
329*042d53a7SEvalZero     for (rc = 0; rc < len; rc++) {
330*042d53a7SEvalZero         if (os_mbuf_copyinto(m, rc, &byte_pattern, 1)) {
331*042d53a7SEvalZero             return 1;
332*042d53a7SEvalZero         }
333*042d53a7SEvalZero     }
334*042d53a7SEvalZero 
335*042d53a7SEvalZero schedule:
336*042d53a7SEvalZero 
337*042d53a7SEvalZero     sch->sched_cb = ble_ll_dtm_tx_sched_cb;
338*042d53a7SEvalZero     sch->cb_arg = &g_ble_ll_dtm_ctx;
339*042d53a7SEvalZero     sch->sched_type = BLE_LL_SCHED_TYPE_DTM;
340*042d53a7SEvalZero     sch->start_time =  os_cputime_get32() +
341*042d53a7SEvalZero                                        os_cputime_usecs_to_ticks(5000);
342*042d53a7SEvalZero 
343*042d53a7SEvalZero     /* Prepare os_event */
344*042d53a7SEvalZero     ble_npl_event_init(&g_ble_ll_dtm_ctx.evt, ble_ll_dtm_ev_tx_resched_cb,
345*042d53a7SEvalZero                        &g_ble_ll_dtm_ctx);
346*042d53a7SEvalZero 
347*042d53a7SEvalZero     ble_ll_dtm_calculate_itvl(&g_ble_ll_dtm_ctx, len, phy_mode);
348*042d53a7SEvalZero 
349*042d53a7SEvalZero     /* Set some start point for TX packets */
350*042d53a7SEvalZero     rc = ble_ll_sched_dtm(sch);
351*042d53a7SEvalZero     BLE_LL_ASSERT(rc == 0);
352*042d53a7SEvalZero 
353*042d53a7SEvalZero     ble_phy_enable_dtm();
354*042d53a7SEvalZero 
355*042d53a7SEvalZero     g_ble_ll_dtm_ctx.active = 1;
356*042d53a7SEvalZero     return 0;
357*042d53a7SEvalZero }
358*042d53a7SEvalZero 
359*042d53a7SEvalZero static int
ble_ll_dtm_rx_start(void)360*042d53a7SEvalZero ble_ll_dtm_rx_start(void)
361*042d53a7SEvalZero {
362*042d53a7SEvalZero     os_sr_t sr;
363*042d53a7SEvalZero     int rc;
364*042d53a7SEvalZero 
365*042d53a7SEvalZero     rc = ble_phy_setchan(channel_rf_to_index[g_ble_ll_dtm_ctx.rf_channel],
366*042d53a7SEvalZero                          BLE_DTM_SYNC_WORD, BLE_DTM_CRC);
367*042d53a7SEvalZero     if (rc) {
368*042d53a7SEvalZero         return rc;
369*042d53a7SEvalZero     }
370*042d53a7SEvalZero 
371*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY))
372*042d53a7SEvalZero     ble_phy_mode_set(g_ble_ll_dtm_ctx.phy_mode, g_ble_ll_dtm_ctx.phy_mode);
373*042d53a7SEvalZero #endif
374*042d53a7SEvalZero 
375*042d53a7SEvalZero     OS_ENTER_CRITICAL(sr);
376*042d53a7SEvalZero     rc = ble_phy_rx_set_start_time(os_cputime_get32() +
377*042d53a7SEvalZero                                    g_ble_ll_sched_offset_ticks, 0);
378*042d53a7SEvalZero     OS_EXIT_CRITICAL(sr);
379*042d53a7SEvalZero     if (rc && rc != BLE_PHY_ERR_RX_LATE) {
380*042d53a7SEvalZero         return rc;
381*042d53a7SEvalZero     }
382*042d53a7SEvalZero 
383*042d53a7SEvalZero     ble_ll_state_set(BLE_LL_STATE_DTM);
384*042d53a7SEvalZero 
385*042d53a7SEvalZero #ifdef BLE_XCVR_RFCLK
386*042d53a7SEvalZero     if (ble_ll_xcvr_rfclk_state() == BLE_RFCLK_STATE_OFF) {
387*042d53a7SEvalZero         ble_ll_xcvr_rfclk_start_now(os_cputime_get32());
388*042d53a7SEvalZero     }
389*042d53a7SEvalZero #endif
390*042d53a7SEvalZero 
391*042d53a7SEvalZero     return 0;
392*042d53a7SEvalZero }
393*042d53a7SEvalZero 
394*042d53a7SEvalZero static int
ble_ll_dtm_rx_create_ctx(uint8_t rf_channel,uint8_t phy_mode)395*042d53a7SEvalZero ble_ll_dtm_rx_create_ctx(uint8_t rf_channel, uint8_t phy_mode)
396*042d53a7SEvalZero {
397*042d53a7SEvalZero     g_ble_ll_dtm_ctx.phy_mode = phy_mode;
398*042d53a7SEvalZero     g_ble_ll_dtm_ctx.rf_channel = rf_channel;
399*042d53a7SEvalZero     g_ble_ll_dtm_ctx.active = 1;
400*042d53a7SEvalZero 
401*042d53a7SEvalZero     STATS_CLEAR(ble_ll_dtm_stats, rx_count);
402*042d53a7SEvalZero 
403*042d53a7SEvalZero     ble_npl_event_init(&g_ble_ll_dtm_ctx.evt, ble_ll_dtm_ev_rx_restart_cb,
404*042d53a7SEvalZero                        NULL);
405*042d53a7SEvalZero 
406*042d53a7SEvalZero     if (ble_ll_dtm_rx_start() != 0) {
407*042d53a7SEvalZero         return 1;
408*042d53a7SEvalZero     }
409*042d53a7SEvalZero 
410*042d53a7SEvalZero     ble_phy_enable_dtm();
411*042d53a7SEvalZero 
412*042d53a7SEvalZero     return 0;
413*042d53a7SEvalZero }
414*042d53a7SEvalZero 
415*042d53a7SEvalZero static void
ble_ll_dtm_ctx_free(struct dtm_ctx * ctx)416*042d53a7SEvalZero ble_ll_dtm_ctx_free(struct dtm_ctx * ctx)
417*042d53a7SEvalZero {
418*042d53a7SEvalZero     os_sr_t sr;
419*042d53a7SEvalZero 
420*042d53a7SEvalZero     OS_ENTER_CRITICAL(sr);
421*042d53a7SEvalZero     if (!ctx->active) {
422*042d53a7SEvalZero         OS_EXIT_CRITICAL(sr);
423*042d53a7SEvalZero         return;
424*042d53a7SEvalZero     }
425*042d53a7SEvalZero     OS_EXIT_CRITICAL(sr);
426*042d53a7SEvalZero 
427*042d53a7SEvalZero     ble_ll_sched_rmv_elem(&ctx->sch);
428*042d53a7SEvalZero 
429*042d53a7SEvalZero     ble_phy_disable();
430*042d53a7SEvalZero     ble_phy_disable_dtm();
431*042d53a7SEvalZero     ble_ll_state_set(BLE_LL_STATE_STANDBY);
432*042d53a7SEvalZero #ifdef BLE_XCVR_RFCLK
433*042d53a7SEvalZero     ble_ll_xcvr_rfclk_stop();
434*042d53a7SEvalZero #endif
435*042d53a7SEvalZero 
436*042d53a7SEvalZero     os_mbuf_free_chain(ctx->om);
437*042d53a7SEvalZero     memset(ctx, 0, sizeof(*ctx));
438*042d53a7SEvalZero }
439*042d53a7SEvalZero 
440*042d53a7SEvalZero int
ble_ll_dtm_tx_test(uint8_t * cmdbuf,bool enhanced)441*042d53a7SEvalZero ble_ll_dtm_tx_test(uint8_t *cmdbuf, bool enhanced)
442*042d53a7SEvalZero {
443*042d53a7SEvalZero     uint8_t tx_chan = cmdbuf[0];
444*042d53a7SEvalZero     uint8_t len = cmdbuf[1];
445*042d53a7SEvalZero     uint8_t packet_payload = cmdbuf[2];
446*042d53a7SEvalZero     uint8_t phy_mode = BLE_PHY_MODE_1M;
447*042d53a7SEvalZero 
448*042d53a7SEvalZero     if (g_ble_ll_dtm_ctx.active) {
449*042d53a7SEvalZero         return BLE_ERR_CTLR_BUSY;
450*042d53a7SEvalZero     }
451*042d53a7SEvalZero 
452*042d53a7SEvalZero     if (enhanced) {
453*042d53a7SEvalZero         switch (cmdbuf[3]) {
454*042d53a7SEvalZero         case BLE_HCI_LE_PHY_1M:
455*042d53a7SEvalZero             phy_mode = BLE_PHY_MODE_1M;
456*042d53a7SEvalZero             break;
457*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
458*042d53a7SEvalZero         case BLE_HCI_LE_PHY_2M:
459*042d53a7SEvalZero             phy_mode = BLE_PHY_MODE_2M;
460*042d53a7SEvalZero             break;
461*042d53a7SEvalZero #endif
462*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
463*042d53a7SEvalZero         case BLE_HCI_LE_PHY_CODED_S8:
464*042d53a7SEvalZero             phy_mode = BLE_PHY_MODE_CODED_125KBPS;
465*042d53a7SEvalZero             break;
466*042d53a7SEvalZero         case BLE_HCI_LE_PHY_CODED_S2:
467*042d53a7SEvalZero             phy_mode = BLE_PHY_MODE_CODED_500KBPS;
468*042d53a7SEvalZero             break;
469*042d53a7SEvalZero #endif
470*042d53a7SEvalZero         default:
471*042d53a7SEvalZero             return BLE_ERR_INV_HCI_CMD_PARMS;
472*042d53a7SEvalZero         }
473*042d53a7SEvalZero     }
474*042d53a7SEvalZero 
475*042d53a7SEvalZero     if (tx_chan > 0x27 || packet_payload > 0x07) {
476*042d53a7SEvalZero         return BLE_ERR_INV_HCI_CMD_PARMS;
477*042d53a7SEvalZero     }
478*042d53a7SEvalZero 
479*042d53a7SEvalZero     if (ble_ll_dtm_tx_create_ctx(packet_payload, len, tx_chan, phy_mode)) {
480*042d53a7SEvalZero         return BLE_ERR_UNSPECIFIED;
481*042d53a7SEvalZero     }
482*042d53a7SEvalZero 
483*042d53a7SEvalZero     return BLE_ERR_SUCCESS;
484*042d53a7SEvalZero }
485*042d53a7SEvalZero 
ble_ll_dtm_rx_test(uint8_t * cmdbuf,bool enhanced)486*042d53a7SEvalZero int ble_ll_dtm_rx_test(uint8_t *cmdbuf, bool enhanced)
487*042d53a7SEvalZero {
488*042d53a7SEvalZero     uint8_t rx_chan = cmdbuf[0];
489*042d53a7SEvalZero     uint8_t phy_mode = BLE_PHY_MODE_1M;
490*042d53a7SEvalZero 
491*042d53a7SEvalZero     if (g_ble_ll_dtm_ctx.active) {
492*042d53a7SEvalZero         return BLE_ERR_CTLR_BUSY;
493*042d53a7SEvalZero     }
494*042d53a7SEvalZero 
495*042d53a7SEvalZero     /*XXX What to do with modulation cmdbuf[2]? */
496*042d53a7SEvalZero 
497*042d53a7SEvalZero     if (enhanced) {
498*042d53a7SEvalZero         switch (cmdbuf[1]) {
499*042d53a7SEvalZero         case BLE_HCI_LE_PHY_1M:
500*042d53a7SEvalZero             phy_mode = BLE_PHY_MODE_1M;
501*042d53a7SEvalZero             break;
502*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
503*042d53a7SEvalZero         case BLE_HCI_LE_PHY_2M:
504*042d53a7SEvalZero             phy_mode = BLE_PHY_MODE_2M;
505*042d53a7SEvalZero             break;
506*042d53a7SEvalZero #endif
507*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
508*042d53a7SEvalZero         case BLE_HCI_LE_PHY_CODED:
509*042d53a7SEvalZero             phy_mode = BLE_PHY_MODE_CODED_500KBPS;
510*042d53a7SEvalZero             break;
511*042d53a7SEvalZero #endif
512*042d53a7SEvalZero         default:
513*042d53a7SEvalZero             return BLE_ERR_INV_HCI_CMD_PARMS;
514*042d53a7SEvalZero         }
515*042d53a7SEvalZero     }
516*042d53a7SEvalZero 
517*042d53a7SEvalZero     if (rx_chan > 0x27) {
518*042d53a7SEvalZero         return BLE_ERR_INV_HCI_CMD_PARMS;
519*042d53a7SEvalZero     }
520*042d53a7SEvalZero 
521*042d53a7SEvalZero     if (ble_ll_dtm_rx_create_ctx(rx_chan, phy_mode)) {
522*042d53a7SEvalZero         return BLE_ERR_UNSPECIFIED;
523*042d53a7SEvalZero     }
524*042d53a7SEvalZero 
525*042d53a7SEvalZero     return BLE_ERR_SUCCESS;
526*042d53a7SEvalZero }
527*042d53a7SEvalZero 
ble_ll_dtm_end_test(uint8_t * rsp,uint8_t * rsplen)528*042d53a7SEvalZero int ble_ll_dtm_end_test(uint8_t *rsp, uint8_t *rsplen)
529*042d53a7SEvalZero {
530*042d53a7SEvalZero     put_le16(rsp, g_ble_ll_dtm_ctx. num_of_packets);
531*042d53a7SEvalZero     *rsplen = 2;
532*042d53a7SEvalZero 
533*042d53a7SEvalZero     ble_ll_dtm_ctx_free(&g_ble_ll_dtm_ctx);
534*042d53a7SEvalZero     return BLE_ERR_SUCCESS;
535*042d53a7SEvalZero }
536*042d53a7SEvalZero 
ble_ll_dtm_rx_isr_start(struct ble_mbuf_hdr * rxhdr,uint32_t aa)537*042d53a7SEvalZero int ble_ll_dtm_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa)
538*042d53a7SEvalZero {
539*042d53a7SEvalZero     return 0;
540*042d53a7SEvalZero }
541*042d53a7SEvalZero 
542*042d53a7SEvalZero void
ble_ll_dtm_rx_pkt_in(struct os_mbuf * rxpdu,struct ble_mbuf_hdr * hdr)543*042d53a7SEvalZero ble_ll_dtm_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
544*042d53a7SEvalZero {
545*042d53a7SEvalZero     if (BLE_MBUF_HDR_CRC_OK(hdr)) {
546*042d53a7SEvalZero         /* XXX Compare data. */
547*042d53a7SEvalZero         g_ble_ll_dtm_ctx.num_of_packets++;
548*042d53a7SEvalZero         STATS_INC(ble_ll_dtm_stats, rx_count);
549*042d53a7SEvalZero     }
550*042d53a7SEvalZero 
551*042d53a7SEvalZero     if (ble_ll_dtm_rx_start() != 0) {
552*042d53a7SEvalZero         ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt);
553*042d53a7SEvalZero         STATS_INC(ble_ll_dtm_stats, rx_failed);
554*042d53a7SEvalZero     }
555*042d53a7SEvalZero }
556*042d53a7SEvalZero 
557*042d53a7SEvalZero int
ble_ll_dtm_rx_isr_end(uint8_t * rxbuf,struct ble_mbuf_hdr * rxhdr)558*042d53a7SEvalZero ble_ll_dtm_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
559*042d53a7SEvalZero {
560*042d53a7SEvalZero     struct os_mbuf *rxpdu;
561*042d53a7SEvalZero 
562*042d53a7SEvalZero     if (!g_ble_ll_dtm_ctx.active) {
563*042d53a7SEvalZero         return -1;
564*042d53a7SEvalZero     }
565*042d53a7SEvalZero 
566*042d53a7SEvalZero     rxpdu = ble_ll_rxpdu_alloc(rxbuf[1] + BLE_LL_PDU_HDR_LEN);
567*042d53a7SEvalZero 
568*042d53a7SEvalZero     /* Copy the received pdu and hand it up */
569*042d53a7SEvalZero     if (rxpdu) {
570*042d53a7SEvalZero         ble_phy_rxpdu_copy(rxbuf, rxpdu);
571*042d53a7SEvalZero         ble_ll_rx_pdu_in(rxpdu);
572*042d53a7SEvalZero     }
573*042d53a7SEvalZero 
574*042d53a7SEvalZero     return 0;
575*042d53a7SEvalZero }
576*042d53a7SEvalZero 
577*042d53a7SEvalZero void
ble_ll_dtm_wfr_timer_exp(void)578*042d53a7SEvalZero ble_ll_dtm_wfr_timer_exp(void)
579*042d53a7SEvalZero {
580*042d53a7SEvalZero     /* Should not be needed */
581*042d53a7SEvalZero     BLE_LL_ASSERT(0);
582*042d53a7SEvalZero }
583*042d53a7SEvalZero 
584*042d53a7SEvalZero 
585*042d53a7SEvalZero void
ble_ll_dtm_reset(void)586*042d53a7SEvalZero ble_ll_dtm_reset(void)
587*042d53a7SEvalZero {
588*042d53a7SEvalZero     ble_ll_dtm_ctx_free(&g_ble_ll_dtm_ctx);
589*042d53a7SEvalZero }
590*042d53a7SEvalZero 
591*042d53a7SEvalZero void
ble_ll_dtm_init(void)592*042d53a7SEvalZero ble_ll_dtm_init(void)
593*042d53a7SEvalZero {
594*042d53a7SEvalZero     int rc;
595*042d53a7SEvalZero 
596*042d53a7SEvalZero     rc = stats_init_and_reg(STATS_HDR(ble_ll_dtm_stats),
597*042d53a7SEvalZero                             STATS_SIZE_INIT_PARMS(ble_ll_dtm_stats, STATS_SIZE_32),
598*042d53a7SEvalZero                             STATS_NAME_INIT_PARMS(ble_ll_dtm_stats),
599*042d53a7SEvalZero                             "ble_ll_dtm");
600*042d53a7SEvalZero     SYSINIT_PANIC_ASSERT(rc == 0);
601*042d53a7SEvalZero }
602*042d53a7SEvalZero #endif
603