Skip to content

Commit 2b648c9

Browse files
eriksandgrennordicjm
authored andcommitted
bluetooth: cs_de: Refactor calculate_dist_ifft
This commit splits `calculate_dist_ifft` into smaller functions and adds documentation with the intention of making the code easier to understand. Signed-off-by: Erik Sandgren <[email protected]>
1 parent 8aac9df commit 2b648c9

File tree

1 file changed

+61
-19
lines changed

1 file changed

+61
-19
lines changed

subsys/bluetooth/cs_de/cs_de.c

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -161,40 +161,61 @@ static int32_t calculate_left_null_compensation_of_peak(int32_t peak_index,
161161
return compensated_peak_index;
162162
}
163163

164-
165-
static void calculate_dist_ifft(float *dist, float iq_tones_comb[2 * CONFIG_BT_CS_DE_NFFT_SIZE])
164+
static void calculate_ifft_mag(float iq_tones_comb[2 * CONFIG_BT_CS_DE_NFFT_SIZE])
166165
{
166+
/* This function calculates the magnitude of the IFFT of the input IQ values.
167+
* Note that the result is written back to the input array.
168+
* Also note that the input array is a complex array of size CONFIG_BT_CS_DE_NFFT_SIZE
169+
* Odd indexes contain the real part and even indexes contain the imaginary part.
170+
*
171+
* To find the IFFT this the function uses FFT functions provided by the CMSIS-DSP library.
172+
* To calculate the IFFT using FFT the following steps can be used:
173+
* 1. Complex conjugate the input.
174+
* 2. Perform the FFT.
175+
* 3. Complex conjugate the output.
176+
* Since we are interested in the magnitude of the IFFT, we can skip step 3.
177+
* and directly calculate the magnitude of the output of step 2.
178+
*/
167179

168180
/* Complex conjugate the input. */
169181
for (uint32_t i = 0; i < NUM_CHANNELS; i++) {
170182
iq_tones_comb[i * 2 + 1] = -iq_tones_comb[i * 2 + 1];
171183
}
172184

173-
#if CONFIG_BT_CS_DE_NFFT_SIZE == 512
174-
arm_cfft_f32(&arm_cfft_sR_f32_len512, iq_tones_comb, 0, 1);
175-
#elif CONFIG_BT_CS_DE_NFFT_SIZE == 1024
176-
arm_cfft_f32(&arm_cfft_sR_f32_len1024, iq_tones_comb, 0, 1);
177-
#elif CONFIG_BT_CS_DE_NFFT_SIZE == 2048
178-
arm_cfft_f32(&arm_cfft_sR_f32_len2048, iq_tones_comb, 0, 1);
179-
#else
180-
#error
181-
#endif
182-
183-
/* Compute the magnitude of iq_tones_comb[0:2*CONFIG_BT_CS_DE_NFFT_SIZE - 1], store output
184-
* in iq_tones_comb[0:CONFIG_BT_CS_DE_NFFT_SIZE - 1]
185+
/* Perform the FFT. */
186+
#if CONFIG_BT_CS_DE_NFFT_SIZE == 512
187+
arm_cfft_f32(&arm_cfft_sR_f32_len512, iq_tones_comb, 0, 1);
188+
#elif CONFIG_BT_CS_DE_NFFT_SIZE == 1024
189+
arm_cfft_f32(&arm_cfft_sR_f32_len1024, iq_tones_comb, 0, 1);
190+
#elif CONFIG_BT_CS_DE_NFFT_SIZE == 2048
191+
arm_cfft_f32(&arm_cfft_sR_f32_len2048, iq_tones_comb, 0, 1);
192+
#else
193+
#error
194+
#endif
195+
196+
/* Compute the magnitude of complex values in
197+
* iq_tones_comb[0:2*CONFIG_BT_CS_DE_NFFT_SIZE - 1]
198+
* and scale by 1/CONFIG_BT_CS_DE_NFFT_SIZE.
199+
* Store output in iq_tones_comb[0:CONFIG_BT_CS_DE_NFFT_SIZE - 1]
185200
*/
186201
for (uint32_t n = 0; n < CONFIG_BT_CS_DE_NFFT_SIZE; n++) {
187202
float realIn = iq_tones_comb[2 * n] / CONFIG_BT_CS_DE_NFFT_SIZE;
188203
float imagIn = iq_tones_comb[(2 * n) + 1] / CONFIG_BT_CS_DE_NFFT_SIZE;
189204

190205
arm_sqrt_f32((realIn * realIn) + (imagIn * imagIn), &iq_tones_comb[n]);
191206
}
207+
}
192208

193-
/* The iq_tones_comb array now contains the ifft_mag in the indices
194-
* [0:CONFIG_BT_CS_DE_NFFT_SIZE-1]
209+
static uint32_t find_ifft_peak_index(float ifft_mag[2 * CONFIG_BT_CS_DE_NFFT_SIZE])
210+
{
211+
/* This function tries to find the peak index of the input IFFT magnitude.
212+
*
213+
* The function uses the following approach:
214+
* 1. Find the index of the strongest peak,
215+
* corresponding to the maximum value in the IFFT magnitude.
216+
* 2. Search for strong peaks closer than the max peak.
217+
* 3. When applicable: Compensate peak based on left null location.
195218
*/
196-
float *ifft_mag = iq_tones_comb;
197-
198219
uint32_t ifft_mag_max_index;
199220
float ifft_mag_max;
200221

@@ -230,7 +251,28 @@ static void calculate_dist_ifft(float *dist, float iq_tones_comb[2 * CONFIG_BT_C
230251
calculate_left_null_compensation_of_peak(shortest_path_idx, ifft_mag);
231252
}
232253

233-
*dist = calculate_ifft_peak_index_to_distance(compensated_peak_index, ifft_mag);
254+
return compensated_peak_index;
255+
}
256+
257+
static void calculate_dist_ifft(float *dist, float iq_tones_comb[2 * CONFIG_BT_CS_DE_NFFT_SIZE])
258+
{
259+
/* This function calculates a distance estimate
260+
* based on the IFFT magnitude of the input IQ values.
261+
*
262+
* To do this the function uses the following steps:
263+
* 1. Calculate the IFFT magnitude of the input IQ values.
264+
* 2. Find index of the peak in the IFFT magnitude which is believed
265+
* to correspond to the path with the shortest propagattion time.
266+
* 3. Convert the peak index to a distance estimate.
267+
*/
268+
calculate_ifft_mag(iq_tones_comb);
269+
270+
/* The input IQ values are overwritten with the IFFT magnitude. */
271+
float *ifft_mag = iq_tones_comb;
272+
273+
uint32_t ifft_peak_index = find_ifft_peak_index(ifft_mag);
274+
275+
*dist = calculate_ifft_peak_index_to_distance(ifft_peak_index, ifft_mag);
234276
}
235277

236278
static void calculate_dist_rtt(cs_de_report_t *p_report)

0 commit comments

Comments
 (0)