@@ -24,10 +24,65 @@ LOG_MODULE_DECLARE(app_main, LOG_LEVEL_INF);
24
24
#define MAX_NUM_RTT_SAMPLES 256
25
25
#define MAX_NUM_IQ_SAMPLES 256 * CONFIG_BT_RAS_MAX_ANTENNA_PATHS
26
26
27
+ #define A1 (0)
28
+ #define A2 (1)
29
+ #define A3 (2)
30
+ #define A4 (3)
31
+
32
+ /* Bluetooth Core Specification 6.0, Table 4.13, Antenna Path Permutation for N_AP=2.
33
+ * The last element corresponds to extension slot
34
+ */
35
+ static uint8_t antenna_path_lut_n_ap_2 [2 ][3 ] = {
36
+ {A1 , A2 , A2 },
37
+ {A2 , A1 , A1 },
38
+ };
39
+
40
+ /* Bluetooth Core Specification 6.0, Table 4.14, Antenna Path Permutation for N_AP=3.
41
+ * The last element corresponds to extension slot
42
+ */
43
+ static uint8_t antenna_path_lut_n_ap_3 [6 ][4 ] = {
44
+ {A1 , A2 , A3 , A3 },
45
+ {A2 , A1 , A3 , A3 },
46
+ {A1 , A3 , A2 , A2 },
47
+ {A3 , A1 , A2 , A2 },
48
+ {A3 , A2 , A1 , A1 },
49
+ {A2 , A3 , A1 , A1 },
50
+ };
51
+
52
+ /* Bluetooth Core Specification 6.0, Table 4.15, Antenna Path Permutation for N_AP=4.
53
+ * The last element corresponds to extension slot
54
+ */
55
+ static uint8_t antenna_path_lut_n_ap_4 [24 ][5 ] = {
56
+ {A1 , A2 , A3 , A4 , A4 },
57
+ {A2 , A1 , A3 , A4 , A4 },
58
+ {A1 , A3 , A2 , A4 , A4 },
59
+ {A3 , A1 , A2 , A4 , A4 },
60
+ {A3 , A2 , A1 , A4 , A4 },
61
+ {A2 , A3 , A1 , A4 , A4 },
62
+ {A1 , A2 , A4 , A3 , A3 },
63
+ {A2 , A1 , A4 , A3 , A3 },
64
+ {A1 , A4 , A2 , A3 , A3 },
65
+ {A4 , A1 , A2 , A3 , A3 },
66
+ {A4 , A2 , A1 , A3 , A3 },
67
+ {A2 , A4 , A1 , A3 , A3 },
68
+ {A1 , A4 , A3 , A2 , A2 },
69
+ {A4 , A1 , A3 , A2 , A2 },
70
+ {A1 , A3 , A4 , A2 , A2 },
71
+ {A3 , A1 , A4 , A2 , A2 },
72
+ {A3 , A4 , A1 , A2 , A2 },
73
+ {A4 , A3 , A1 , A2 , A2 },
74
+ {A4 , A2 , A3 , A1 , A1 },
75
+ {A2 , A4 , A3 , A1 , A1 },
76
+ {A4 , A3 , A2 , A1 , A1 },
77
+ {A3 , A4 , A2 , A1 , A1 },
78
+ {A3 , A2 , A4 , A1 , A1 },
79
+ {A2 , A3 , A4 , A1 , A1 },
80
+ };
81
+
27
82
struct iq_sample_and_channel {
28
83
bool failed ;
29
84
uint8_t channel ;
30
- uint8_t antenna_permutation ;
85
+ uint8_t antenna_path ;
31
86
struct bt_le_cs_iq_sample local_iq_sample ;
32
87
struct bt_le_cs_iq_sample peer_iq_sample ;
33
88
};
@@ -48,6 +103,22 @@ struct processing_context {
48
103
enum bt_conn_le_cs_role role ;
49
104
};
50
105
106
+ static uint8_t get_antenna_path (uint8_t n_ap ,
107
+ uint8_t antenna_path_permutation_index ,
108
+ uint8_t antenna_index )
109
+ {
110
+ if (n_ap == 2 ) {
111
+ return antenna_path_lut_n_ap_2 [antenna_path_permutation_index ][antenna_index ];
112
+ }
113
+ if (n_ap == 3 ) {
114
+ return antenna_path_lut_n_ap_3 [antenna_path_permutation_index ][antenna_index ];
115
+ }
116
+ if (n_ap == 4 ) {
117
+ return antenna_path_lut_n_ap_4 [antenna_path_permutation_index ][antenna_index ];
118
+ }
119
+ return 0 ;
120
+ }
121
+
51
122
static void calc_complex_product (int32_t z_a_real , int32_t z_a_imag , int32_t z_b_real ,
52
123
int32_t z_b_imag , int32_t * z_out_real , int32_t * z_out_imag )
53
124
{
@@ -107,7 +178,10 @@ static void bubblesort_2(float *array1, float *array2, uint16_t len)
107
178
}
108
179
}
109
180
110
- static float estimate_distance_using_phase_slope (struct iq_sample_and_channel * data , uint8_t len )
181
+ static float estimate_distance_using_phase_slope (struct iq_sample_and_channel * data ,
182
+ uint8_t len ,
183
+ uint8_t ant_path ,
184
+ uint8_t * samples_cnt )
111
185
{
112
186
int32_t combined_i ;
113
187
int32_t combined_q ;
@@ -116,14 +190,15 @@ static float estimate_distance_using_phase_slope(struct iq_sample_and_channel *d
116
190
static float frequencies [MAX_NUM_IQ_SAMPLES ];
117
191
118
192
for (uint8_t i = 0 ; i < len ; i ++ ) {
119
- if (!data [i ].failed ) {
193
+ if (!data [i ].failed && data [ i ]. antenna_path == ant_path ) {
120
194
calc_complex_product (data [i ].local_iq_sample .i , data [i ].local_iq_sample .q ,
121
195
data [i ].peer_iq_sample .i , data [i ].peer_iq_sample .q ,
122
196
& combined_i , & combined_q );
123
197
124
198
theta [num_angles ] = atan2 (1.0 * combined_q , 1.0 * combined_i );
125
199
frequencies [num_angles ] = 1.0 * CS_FREQUENCY_MHZ (data [i ].channel );
126
200
num_angles ++ ;
201
+ * samples_cnt += 1 ;
127
202
}
128
203
}
129
204
@@ -193,8 +268,8 @@ static void process_tone_info_data(struct processing_context *context,
193
268
}
194
269
195
270
iq_sample_channel_data [context -> iq_sample_channel_data_index ].channel = channel ;
196
- iq_sample_channel_data [context -> iq_sample_channel_data_index ].antenna_permutation =
197
- antenna_permutation_index ;
271
+ iq_sample_channel_data [context -> iq_sample_channel_data_index ].antenna_path =
272
+ get_antenna_path ( context -> n_ap , antenna_permutation_index , i ) ;
198
273
iq_sample_channel_data [context -> iq_sample_channel_data_index ].local_iq_sample =
199
274
bt_le_cs_parse_pct (local_tone_info [i ].phase_correction_term );
200
275
iq_sample_channel_data [context -> iq_sample_channel_data_index ].peer_iq_sample =
@@ -290,6 +365,7 @@ static bool process_step_data(struct bt_le_cs_subevent_step *local_step,
290
365
void estimate_distance (struct net_buf_simple * local_steps , struct net_buf_simple * peer_steps ,
291
366
uint8_t n_ap , enum bt_conn_le_cs_role role )
292
367
{
368
+ bool distance_measurement_failed = true;
293
369
struct processing_context context = {
294
370
.rtt_timing_data_index = 0 ,
295
371
.iq_sample_channel_data_index = 0 ,
@@ -303,24 +379,34 @@ void estimate_distance(struct net_buf_simple *local_steps, struct net_buf_simple
303
379
bt_ras_rreq_rd_subevent_data_parse (peer_steps , local_steps , context .role , NULL ,
304
380
process_step_data , & context );
305
381
306
- float phase_slope_based_distance = estimate_distance_using_phase_slope (
307
- iq_sample_channel_data , context .iq_sample_channel_data_index );
382
+ LOG_INF ("Estimated distance to reflector:" );
308
383
309
384
float rtt_based_distance =
310
385
estimate_distance_using_time_of_flight (context .rtt_timing_data_index );
311
386
312
- if (rtt_based_distance == 0.0f && phase_slope_based_distance == 0.0f ) {
313
- LOG_INF ("A reliable distance estimate could not be computed." );
314
- } else {
315
- LOG_INF ("Estimated distance to reflector:" );
316
- }
317
-
318
387
if (rtt_based_distance != 0.0f ) {
319
388
LOG_INF ("- Round-Trip Timing method: %f meters (derived from %d samples)" ,
320
389
(double )rtt_based_distance , context .rtt_timing_data_index );
390
+ distance_measurement_failed = false;
391
+ }
392
+ for (int i = 0 ; i < n_ap ; i ++ ) {
393
+ uint8_t samples_cnt = 0 ;
394
+ float phase_slope_based_distance = estimate_distance_using_phase_slope (
395
+ iq_sample_channel_data ,
396
+ context .iq_sample_channel_data_index ,
397
+ i ,
398
+ & samples_cnt );
399
+
400
+ if (phase_slope_based_distance != 0.0f ) {
401
+ LOG_INF ("- Phase-Based Ranging method: %f meters "
402
+ "(derived on antenna path %d from %d samples)" ,
403
+ (double )phase_slope_based_distance ,
404
+ i ,
405
+ samples_cnt );
406
+ distance_measurement_failed = false;
407
+ }
321
408
}
322
- if (phase_slope_based_distance != 0.0f ) {
323
- LOG_INF ("- Phase-Based Ranging method: %f meters (derived from %d samples)" ,
324
- (double )phase_slope_based_distance , context .iq_sample_channel_data_index );
409
+ if (distance_measurement_failed ) {
410
+ LOG_INF ("- A reliable distance estimate could not be computed." );
325
411
}
326
412
}
0 commit comments