@@ -24,10 +24,66 @@ 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
+ uint8_t antenna_path_lut_n_ap_2 [2 ][3 ] =
35
+ {
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
+ uint8_t antenna_path_lut_n_ap_3 [6 ][4 ] =
43
+ {
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
+ uint8_t antenna_path_lut_n_ap_4 [24 ][5 ] =
55
+ {
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
85
uint8_t antenna_permutation ;
86
+ uint8_t antenna_path ;
31
87
struct bt_le_cs_iq_sample local_iq_sample ;
32
88
struct bt_le_cs_iq_sample peer_iq_sample ;
33
89
};
@@ -48,6 +104,20 @@ struct processing_context {
48
104
enum bt_conn_le_cs_role role ;
49
105
};
50
106
107
+ static uint8_t get_antenna_path (uint8_t n_ap , uint8_t antenna_path_permutation , uint8_t i )
108
+ {
109
+ if (n_ap == 2 ) {
110
+ return antenna_path_lut_n_ap_2 [antenna_path_permutation ][i ];
111
+ }
112
+ if (n_ap == 3 ) {
113
+ return antenna_path_lut_n_ap_3 [antenna_path_permutation ][i ];
114
+ }
115
+ if (n_ap == 4 ) {
116
+ return antenna_path_lut_n_ap_4 [antenna_path_permutation ][i ];
117
+ }
118
+ return 0 ;
119
+ }
120
+
51
121
static void calc_complex_product (int32_t z_a_real , int32_t z_a_imag , int32_t z_b_real ,
52
122
int32_t z_b_imag , int32_t * z_out_real , int32_t * z_out_imag )
53
123
{
@@ -107,7 +177,7 @@ static void bubblesort_2(float *array1, float *array2, uint16_t len)
107
177
}
108
178
}
109
179
110
- static float estimate_distance_using_phase_slope (struct iq_sample_and_channel * data , uint8_t len )
180
+ static float estimate_distance_using_phase_slope (struct iq_sample_and_channel * data , uint8_t len , uint8_t ant_path , uint8_t * samples_cnt )
111
181
{
112
182
int32_t combined_i ;
113
183
int32_t combined_q ;
@@ -116,14 +186,15 @@ static float estimate_distance_using_phase_slope(struct iq_sample_and_channel *d
116
186
static float frequencies [MAX_NUM_IQ_SAMPLES ];
117
187
118
188
for (uint8_t i = 0 ; i < len ; i ++ ) {
119
- if (!data [i ].failed ) {
189
+ if (!data [i ].failed && data [ i ]. antenna_path == ant_path ) {
120
190
calc_complex_product (data [i ].local_iq_sample .i , data [i ].local_iq_sample .q ,
121
191
data [i ].peer_iq_sample .i , data [i ].peer_iq_sample .q ,
122
192
& combined_i , & combined_q );
123
193
124
194
theta [num_angles ] = atan2 (1.0 * combined_q , 1.0 * combined_i );
125
195
frequencies [num_angles ] = 1.0 * CS_FREQUENCY_MHZ (data [i ].channel );
126
196
num_angles ++ ;
197
+ * samples_cnt += 1 ;
127
198
}
128
199
}
129
200
@@ -195,6 +266,8 @@ static void process_tone_info_data(struct processing_context *context,
195
266
iq_sample_channel_data [context -> iq_sample_channel_data_index ].channel = channel ;
196
267
iq_sample_channel_data [context -> iq_sample_channel_data_index ].antenna_permutation =
197
268
antenna_permutation_index ;
269
+ iq_sample_channel_data [context -> iq_sample_channel_data_index ].antenna_path =
270
+ get_antenna_path (context -> n_ap , antenna_permutation_index , i );
198
271
iq_sample_channel_data [context -> iq_sample_channel_data_index ].local_iq_sample =
199
272
bt_le_cs_parse_pct (local_tone_info [i ].phase_correction_term );
200
273
iq_sample_channel_data [context -> iq_sample_channel_data_index ].peer_iq_sample =
@@ -290,6 +363,7 @@ static bool process_step_data(struct bt_le_cs_subevent_step *local_step,
290
363
void estimate_distance (struct net_buf_simple * local_steps , struct net_buf_simple * peer_steps ,
291
364
uint8_t n_ap , enum bt_conn_le_cs_role role )
292
365
{
366
+ bool distance_measurement_failed = true;
293
367
struct processing_context context = {
294
368
.rtt_timing_data_index = 0 ,
295
369
.iq_sample_channel_data_index = 0 ,
@@ -303,24 +377,30 @@ void estimate_distance(struct net_buf_simple *local_steps, struct net_buf_simple
303
377
bt_ras_rreq_rd_subevent_data_parse (peer_steps , local_steps , context .role , NULL ,
304
378
process_step_data , & context );
305
379
306
- float phase_slope_based_distance = estimate_distance_using_phase_slope (
307
- iq_sample_channel_data , context .iq_sample_channel_data_index );
380
+ LOG_INF ("Estimated distance to reflector:" );
308
381
309
382
float rtt_based_distance =
310
383
estimate_distance_using_time_of_flight (context .rtt_timing_data_index );
311
384
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
385
if (rtt_based_distance != 0.0f ) {
319
386
LOG_INF ("- Round-Trip Timing method: %f meters (derived from %d samples)" ,
320
387
(double )rtt_based_distance , context .rtt_timing_data_index );
388
+ distance_measurement_failed = false;
389
+ }
390
+ for (int i = 0 ; i < n_ap ; i ++ ) {
391
+ uint8_t samples_cnt = 0 ;
392
+ float phase_slope_based_distance = estimate_distance_using_phase_slope (
393
+ iq_sample_channel_data , context .iq_sample_channel_data_index , i , & samples_cnt );
394
+
395
+ if (phase_slope_based_distance != 0.0f ) {
396
+ LOG_INF ("- Phase-Based Ranging method: %f meters (derived on antenna path %d from %d samples)" ,
397
+ (double )phase_slope_based_distance ,
398
+ i ,
399
+ samples_cnt );
400
+ distance_measurement_failed = false;
401
+ }
321
402
}
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 );
403
+ if (distance_measurement_failed ) {
404
+ LOG_INF ("- A reliable distance estimate could not be computed." );
325
405
}
326
406
}
0 commit comments