1 /* ----------------------------------------------------------------------
2 * Project: CMSIS DSP Library
3 * Title: arm_cfft_radix2_f32.c
4 * Description: Radix-2 Decimation in Frequency CFFT & CIFFT Floating point processing function
5 *
6 * $Date: 23 April 2021
7 * $Revision: V1.9.0
8 *
9 * Target Processor: Cortex-M and Cortex-A cores
10 * -------------------------------------------------------------------- */
11 /*
12 * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
13 *
14 * SPDX-License-Identifier: Apache-2.0
15 *
16 * Licensed under the Apache License, Version 2.0 (the License); you may
17 * not use this file except in compliance with the License.
18 * You may obtain a copy of the License at
19 *
20 * www.apache.org/licenses/LICENSE-2.0
21 *
22 * Unless required by applicable law or agreed to in writing, software
23 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
24 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 * See the License for the specific language governing permissions and
26 * limitations under the License.
27 */
28
29 #include "dsp/transform_functions.h"
30
31 void arm_radix2_butterfly_f32(
32 float32_t * pSrc,
33 uint32_t fftLen,
34 const float32_t * pCoef,
35 uint16_t twidCoefModifier);
36
37 void arm_radix2_butterfly_inverse_f32(
38 float32_t * pSrc,
39 uint32_t fftLen,
40 const float32_t * pCoef,
41 uint16_t twidCoefModifier,
42 float32_t onebyfftLen);
43
44 extern void arm_bitreversal_f32(
45 float32_t * pSrc,
46 uint16_t fftSize,
47 uint16_t bitRevFactor,
48 const uint16_t * pBitRevTab);
49
50 /**
51 @ingroup groupTransforms
52 */
53
54 /**
55 @addtogroup ComplexFFT
56 @{
57 */
58
59 /**
60 @brief Radix-2 CFFT/CIFFT.
61 @deprecated Do not use this function. It has been superseded by \ref arm_cfft_f32 and will be removed in the future
62 @param[in] S points to an instance of the floating-point Radix-2 CFFT/CIFFT structure
63 @param[in,out] pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place
64 @return none
65 */
66
arm_cfft_radix2_f32(const arm_cfft_radix2_instance_f32 * S,float32_t * pSrc)67 void arm_cfft_radix2_f32(
68 const arm_cfft_radix2_instance_f32 * S,
69 float32_t * pSrc)
70 {
71
72 if (S->ifftFlag == 1U)
73 {
74 /* Complex IFFT radix-2 */
75 arm_radix2_butterfly_inverse_f32(pSrc, S->fftLen, S->pTwiddle,
76 S->twidCoefModifier, S->onebyfftLen);
77 }
78 else
79 {
80 /* Complex FFT radix-2 */
81 arm_radix2_butterfly_f32(pSrc, S->fftLen, S->pTwiddle,
82 S->twidCoefModifier);
83 }
84
85 if (S->bitReverseFlag == 1U)
86 {
87 /* Bit Reversal */
88 arm_bitreversal_f32(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable);
89 }
90
91 }
92
93
94 /**
95 @} end of ComplexFFT group
96 */
97
98
99
100 /* ----------------------------------------------------------------------
101 ** Internal helper function used by the FFTs
102 ** ------------------------------------------------------------------- */
103
104 /**
105 brief Core function for the floating-point CFFT butterfly process.
106 param[in,out] pSrc points to in-place buffer of floating-point data type
107 param[in] fftLen length of the FFT
108 param[in] pCoef points to twiddle coefficient buffer
109 param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table
110 return none
111 */
112
arm_radix2_butterfly_f32(float32_t * pSrc,uint32_t fftLen,const float32_t * pCoef,uint16_t twidCoefModifier)113 void arm_radix2_butterfly_f32(
114 float32_t * pSrc,
115 uint32_t fftLen,
116 const float32_t * pCoef,
117 uint16_t twidCoefModifier)
118 {
119
120 uint32_t i, j, k, l;
121 uint32_t n1, n2, ia;
122 float32_t xt, yt, cosVal, sinVal;
123 float32_t p0, p1, p2, p3;
124 float32_t a0, a1;
125
126 #if defined (ARM_MATH_DSP)
127
128 /* Initializations for the first stage */
129 n2 = fftLen >> 1;
130 ia = 0;
131 i = 0;
132
133 // loop for groups
134 for (k = n2; k > 0; k--)
135 {
136 cosVal = pCoef[ia * 2];
137 sinVal = pCoef[(ia * 2) + 1];
138
139 /* Twiddle coefficients index modifier */
140 ia += twidCoefModifier;
141
142 /* index calculation for the input as, */
143 /* pSrc[i + 0], pSrc[i + fftLen/1] */
144 l = i + n2;
145
146 /* Butterfly implementation */
147 a0 = pSrc[2 * i] + pSrc[2 * l];
148 xt = pSrc[2 * i] - pSrc[2 * l];
149
150 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
151 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
152
153 p0 = xt * cosVal;
154 p1 = yt * sinVal;
155 p2 = yt * cosVal;
156 p3 = xt * sinVal;
157
158 pSrc[2 * i] = a0;
159 pSrc[2 * i + 1] = a1;
160
161 pSrc[2 * l] = p0 + p1;
162 pSrc[2 * l + 1] = p2 - p3;
163
164 i++;
165 } // groups loop end
166
167 twidCoefModifier <<= 1U;
168
169 // loop for stage
170 for (k = n2; k > 2; k = k >> 1)
171 {
172 n1 = n2;
173 n2 = n2 >> 1;
174 ia = 0;
175
176 // loop for groups
177 j = 0;
178 do
179 {
180 cosVal = pCoef[ia * 2];
181 sinVal = pCoef[(ia * 2) + 1];
182 ia += twidCoefModifier;
183
184 // loop for butterfly
185 i = j;
186 do
187 {
188 l = i + n2;
189 a0 = pSrc[2 * i] + pSrc[2 * l];
190 xt = pSrc[2 * i] - pSrc[2 * l];
191
192 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
193 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
194
195 p0 = xt * cosVal;
196 p1 = yt * sinVal;
197 p2 = yt * cosVal;
198 p3 = xt * sinVal;
199
200 pSrc[2 * i] = a0;
201 pSrc[2 * i + 1] = a1;
202
203 pSrc[2 * l] = p0 + p1;
204 pSrc[2 * l + 1] = p2 - p3;
205
206 i += n1;
207 } while ( i < fftLen ); // butterfly loop end
208 j++;
209 } while ( j < n2); // groups loop end
210 twidCoefModifier <<= 1U;
211 } // stages loop end
212
213 // loop for butterfly
214 for (i = 0; i < fftLen; i += 2)
215 {
216 a0 = pSrc[2 * i] + pSrc[2 * i + 2];
217 xt = pSrc[2 * i] - pSrc[2 * i + 2];
218
219 yt = pSrc[2 * i + 1] - pSrc[2 * i + 3];
220 a1 = pSrc[2 * i + 3] + pSrc[2 * i + 1];
221
222 pSrc[2 * i] = a0;
223 pSrc[2 * i + 1] = a1;
224 pSrc[2 * i + 2] = xt;
225 pSrc[2 * i + 3] = yt;
226 } // groups loop end
227
228 #else /* #if defined (ARM_MATH_DSP) */
229
230 n2 = fftLen;
231
232 // loop for stage
233 for (k = fftLen; k > 1; k = k >> 1)
234 {
235 n1 = n2;
236 n2 = n2 >> 1;
237 ia = 0;
238
239 // loop for groups
240 j = 0;
241 do
242 {
243 cosVal = pCoef[ia * 2];
244 sinVal = pCoef[(ia * 2) + 1];
245 ia += twidCoefModifier;
246
247 // loop for butterfly
248 i = j;
249 do
250 {
251 l = i + n2;
252 a0 = pSrc[2 * i] + pSrc[2 * l];
253 xt = pSrc[2 * i] - pSrc[2 * l];
254
255 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
256 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
257
258 p0 = xt * cosVal;
259 p1 = yt * sinVal;
260 p2 = yt * cosVal;
261 p3 = xt * sinVal;
262
263 pSrc[2 * i] = a0;
264 pSrc[2 * i + 1] = a1;
265
266 pSrc[2 * l] = p0 + p1;
267 pSrc[2 * l + 1] = p2 - p3;
268
269 i += n1;
270 } while (i < fftLen);
271 j++;
272 } while (j < n2);
273 twidCoefModifier <<= 1U;
274 }
275
276 #endif /* #if defined (ARM_MATH_DSP) */
277
278 }
279
280
arm_radix2_butterfly_inverse_f32(float32_t * pSrc,uint32_t fftLen,const float32_t * pCoef,uint16_t twidCoefModifier,float32_t onebyfftLen)281 void arm_radix2_butterfly_inverse_f32(
282 float32_t * pSrc,
283 uint32_t fftLen,
284 const float32_t * pCoef,
285 uint16_t twidCoefModifier,
286 float32_t onebyfftLen)
287 {
288
289 uint32_t i, j, k, l;
290 uint32_t n1, n2, ia;
291 float32_t xt, yt, cosVal, sinVal;
292 float32_t p0, p1, p2, p3;
293 float32_t a0, a1;
294
295 #if defined (ARM_MATH_DSP)
296
297 n2 = fftLen >> 1;
298 ia = 0;
299
300 // loop for groups
301 for (i = 0; i < n2; i++)
302 {
303 cosVal = pCoef[ia * 2];
304 sinVal = pCoef[(ia * 2) + 1];
305 ia += twidCoefModifier;
306
307 l = i + n2;
308 a0 = pSrc[2 * i] + pSrc[2 * l];
309 xt = pSrc[2 * i] - pSrc[2 * l];
310
311 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
312 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
313
314 p0 = xt * cosVal;
315 p1 = yt * sinVal;
316 p2 = yt * cosVal;
317 p3 = xt * sinVal;
318
319 pSrc[2 * i] = a0;
320 pSrc[2 * i + 1] = a1;
321
322 pSrc[2 * l] = p0 - p1;
323 pSrc[2 * l + 1] = p2 + p3;
324 } // groups loop end
325
326 twidCoefModifier <<= 1U;
327
328 // loop for stage
329 for (k = fftLen / 2; k > 2; k = k >> 1)
330 {
331 n1 = n2;
332 n2 = n2 >> 1;
333 ia = 0;
334
335 // loop for groups
336 j = 0;
337 do
338 {
339 cosVal = pCoef[ia * 2];
340 sinVal = pCoef[(ia * 2) + 1];
341 ia += twidCoefModifier;
342
343 // loop for butterfly
344 i = j;
345 do
346 {
347 l = i + n2;
348 a0 = pSrc[2 * i] + pSrc[2 * l];
349 xt = pSrc[2 * i] - pSrc[2 * l];
350
351 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
352 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
353
354 p0 = xt * cosVal;
355 p1 = yt * sinVal;
356 p2 = yt * cosVal;
357 p3 = xt * sinVal;
358
359 pSrc[2 * i] = a0;
360 pSrc[2 * i + 1] = a1;
361
362 pSrc[2 * l] = p0 - p1;
363 pSrc[2 * l + 1] = p2 + p3;
364
365 i += n1;
366 } while ( i < fftLen ); // butterfly loop end
367 j++;
368 } while (j < n2); // groups loop end
369
370 twidCoefModifier <<= 1U;
371 } // stages loop end
372
373 // loop for butterfly
374 for (i = 0; i < fftLen; i += 2)
375 {
376 a0 = pSrc[2 * i] + pSrc[2 * i + 2];
377 xt = pSrc[2 * i] - pSrc[2 * i + 2];
378
379 a1 = pSrc[2 * i + 3] + pSrc[2 * i + 1];
380 yt = pSrc[2 * i + 1] - pSrc[2 * i + 3];
381
382 p0 = a0 * onebyfftLen;
383 p2 = xt * onebyfftLen;
384 p1 = a1 * onebyfftLen;
385 p3 = yt * onebyfftLen;
386
387 pSrc[2 * i] = p0;
388 pSrc[2 * i + 1] = p1;
389 pSrc[2 * i + 2] = p2;
390 pSrc[2 * i + 3] = p3;
391 } // butterfly loop end
392
393 #else /* #if defined (ARM_MATH_DSP) */
394
395 n2 = fftLen;
396
397 // loop for stage
398 for (k = fftLen; k > 2; k = k >> 1)
399 {
400 n1 = n2;
401 n2 = n2 >> 1;
402 ia = 0;
403
404 // loop for groups
405 j = 0;
406 do
407 {
408 cosVal = pCoef[ia * 2];
409 sinVal = pCoef[(ia * 2) + 1];
410 ia = ia + twidCoefModifier;
411
412 // loop for butterfly
413 i = j;
414 do
415 {
416 l = i + n2;
417 a0 = pSrc[2 * i] + pSrc[2 * l];
418 xt = pSrc[2 * i] - pSrc[2 * l];
419
420 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
421 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
422
423 p0 = xt * cosVal;
424 p1 = yt * sinVal;
425 p2 = yt * cosVal;
426 p3 = xt * sinVal;
427
428 pSrc[2 * i] = a0;
429 pSrc[2 * i + 1] = a1;
430
431 pSrc[2 * l] = p0 - p1;
432 pSrc[2 * l + 1] = p2 + p3;
433
434 i += n1;
435 } while ( i < fftLen ); // butterfly loop end
436 j++;
437 } while ( j < n2 ); // groups loop end
438
439 twidCoefModifier = twidCoefModifier << 1U;
440 } // stages loop end
441
442 n1 = n2;
443 n2 = n2 >> 1;
444
445 // loop for butterfly
446 for (i = 0; i < fftLen; i += n1)
447 {
448 l = i + n2;
449
450 a0 = pSrc[2 * i] + pSrc[2 * l];
451 xt = pSrc[2 * i] - pSrc[2 * l];
452
453 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
454 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
455
456 p0 = a0 * onebyfftLen;
457 p2 = xt * onebyfftLen;
458 p1 = a1 * onebyfftLen;
459 p3 = yt * onebyfftLen;
460
461 pSrc[2 * i] = p0;
462 pSrc[2 * l] = p2;
463
464 pSrc[2 * i + 1] = p1;
465 pSrc[2 * l + 1] = p3;
466 } // butterfly loop end
467
468 #endif /* #if defined (ARM_MATH_DSP) */
469
470 }
471