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
52 /**
53 @addtogroup ComplexFFTDeprecated
54 @{
55 */
56
57 /**
58 @brief Radix-2 CFFT/CIFFT.
59 @deprecated Do not use this function. It has been superseded by \ref arm_cfft_f32 and will be removed in the future
60 @param[in] S points to an instance of the floating-point Radix-2 CFFT/CIFFT structure
61 @param[in,out] pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place
62 @return none
63 */
64
arm_cfft_radix2_f32(const arm_cfft_radix2_instance_f32 * S,float32_t * pSrc)65 void arm_cfft_radix2_f32(
66 const arm_cfft_radix2_instance_f32 * S,
67 float32_t * pSrc)
68 {
69
70 if (S->ifftFlag == 1U)
71 {
72 /* Complex IFFT radix-2 */
73 arm_radix2_butterfly_inverse_f32(pSrc, S->fftLen, S->pTwiddle,
74 S->twidCoefModifier, S->onebyfftLen);
75 }
76 else
77 {
78 /* Complex FFT radix-2 */
79 arm_radix2_butterfly_f32(pSrc, S->fftLen, S->pTwiddle,
80 S->twidCoefModifier);
81 }
82
83 if (S->bitReverseFlag == 1U)
84 {
85 /* Bit Reversal */
86 arm_bitreversal_f32(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable);
87 }
88
89 }
90
91
92 /**
93 @} end of ComplexFFTDeprecated group
94 */
95
96
97
98 /* ----------------------------------------------------------------------
99 ** Internal helper function used by the FFTs
100 ** ------------------------------------------------------------------- */
101
102 /**
103 brief Core function for the floating-point CFFT butterfly process.
104 param[in,out] pSrc points to in-place buffer of floating-point data type
105 param[in] fftLen length of the FFT
106 param[in] pCoef points to twiddle coefficient buffer
107 param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table
108 return none
109 */
110
arm_radix2_butterfly_f32(float32_t * pSrc,uint32_t fftLen,const float32_t * pCoef,uint16_t twidCoefModifier)111 void arm_radix2_butterfly_f32(
112 float32_t * pSrc,
113 uint32_t fftLen,
114 const float32_t * pCoef,
115 uint16_t twidCoefModifier)
116 {
117
118 uint32_t i, j, k, l;
119 uint32_t n1, n2, ia;
120 float32_t xt, yt, cosVal, sinVal;
121 float32_t p0, p1, p2, p3;
122 float32_t a0, a1;
123
124 #if defined (ARM_MATH_DSP)
125
126 /* Initializations for the first stage */
127 n2 = fftLen >> 1;
128 ia = 0;
129 i = 0;
130
131 // loop for groups
132 for (k = n2; k > 0; k--)
133 {
134 cosVal = pCoef[ia * 2];
135 sinVal = pCoef[(ia * 2) + 1];
136
137 /* Twiddle coefficients index modifier */
138 ia += twidCoefModifier;
139
140 /* index calculation for the input as, */
141 /* pSrc[i + 0], pSrc[i + fftLen/1] */
142 l = i + n2;
143
144 /* Butterfly implementation */
145 a0 = pSrc[2 * i] + pSrc[2 * l];
146 xt = pSrc[2 * i] - pSrc[2 * l];
147
148 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
149 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
150
151 p0 = xt * cosVal;
152 p1 = yt * sinVal;
153 p2 = yt * cosVal;
154 p3 = xt * sinVal;
155
156 pSrc[2 * i] = a0;
157 pSrc[2 * i + 1] = a1;
158
159 pSrc[2 * l] = p0 + p1;
160 pSrc[2 * l + 1] = p2 - p3;
161
162 i++;
163 } // groups loop end
164
165 twidCoefModifier <<= 1U;
166
167 // loop for stage
168 for (k = n2; k > 2; k = k >> 1)
169 {
170 n1 = n2;
171 n2 = n2 >> 1;
172 ia = 0;
173
174 // loop for groups
175 j = 0;
176 do
177 {
178 cosVal = pCoef[ia * 2];
179 sinVal = pCoef[(ia * 2) + 1];
180 ia += twidCoefModifier;
181
182 // loop for butterfly
183 i = j;
184 do
185 {
186 l = i + n2;
187 a0 = pSrc[2 * i] + pSrc[2 * l];
188 xt = pSrc[2 * i] - pSrc[2 * l];
189
190 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
191 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
192
193 p0 = xt * cosVal;
194 p1 = yt * sinVal;
195 p2 = yt * cosVal;
196 p3 = xt * sinVal;
197
198 pSrc[2 * i] = a0;
199 pSrc[2 * i + 1] = a1;
200
201 pSrc[2 * l] = p0 + p1;
202 pSrc[2 * l + 1] = p2 - p3;
203
204 i += n1;
205 } while ( i < fftLen ); // butterfly loop end
206 j++;
207 } while ( j < n2); // groups loop end
208 twidCoefModifier <<= 1U;
209 } // stages loop end
210
211 // loop for butterfly
212 for (i = 0; i < fftLen; i += 2)
213 {
214 a0 = pSrc[2 * i] + pSrc[2 * i + 2];
215 xt = pSrc[2 * i] - pSrc[2 * i + 2];
216
217 yt = pSrc[2 * i + 1] - pSrc[2 * i + 3];
218 a1 = pSrc[2 * i + 3] + pSrc[2 * i + 1];
219
220 pSrc[2 * i] = a0;
221 pSrc[2 * i + 1] = a1;
222 pSrc[2 * i + 2] = xt;
223 pSrc[2 * i + 3] = yt;
224 } // groups loop end
225
226 #else /* #if defined (ARM_MATH_DSP) */
227
228 n2 = fftLen;
229
230 // loop for stage
231 for (k = fftLen; k > 1; k = k >> 1)
232 {
233 n1 = n2;
234 n2 = n2 >> 1;
235 ia = 0;
236
237 // loop for groups
238 j = 0;
239 do
240 {
241 cosVal = pCoef[ia * 2];
242 sinVal = pCoef[(ia * 2) + 1];
243 ia += twidCoefModifier;
244
245 // loop for butterfly
246 i = j;
247 do
248 {
249 l = i + n2;
250 a0 = pSrc[2 * i] + pSrc[2 * l];
251 xt = pSrc[2 * i] - pSrc[2 * l];
252
253 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
254 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
255
256 p0 = xt * cosVal;
257 p1 = yt * sinVal;
258 p2 = yt * cosVal;
259 p3 = xt * sinVal;
260
261 pSrc[2 * i] = a0;
262 pSrc[2 * i + 1] = a1;
263
264 pSrc[2 * l] = p0 + p1;
265 pSrc[2 * l + 1] = p2 - p3;
266
267 i += n1;
268 } while (i < fftLen);
269 j++;
270 } while (j < n2);
271 twidCoefModifier <<= 1U;
272 }
273
274 #endif /* #if defined (ARM_MATH_DSP) */
275
276 }
277
278
arm_radix2_butterfly_inverse_f32(float32_t * pSrc,uint32_t fftLen,const float32_t * pCoef,uint16_t twidCoefModifier,float32_t onebyfftLen)279 void arm_radix2_butterfly_inverse_f32(
280 float32_t * pSrc,
281 uint32_t fftLen,
282 const float32_t * pCoef,
283 uint16_t twidCoefModifier,
284 float32_t onebyfftLen)
285 {
286
287 uint32_t i, j, k, l;
288 uint32_t n1, n2, ia;
289 float32_t xt, yt, cosVal, sinVal;
290 float32_t p0, p1, p2, p3;
291 float32_t a0, a1;
292
293 #if defined (ARM_MATH_DSP)
294
295 n2 = fftLen >> 1;
296 ia = 0;
297
298 // loop for groups
299 for (i = 0; i < n2; i++)
300 {
301 cosVal = pCoef[ia * 2];
302 sinVal = pCoef[(ia * 2) + 1];
303 ia += twidCoefModifier;
304
305 l = i + n2;
306 a0 = pSrc[2 * i] + pSrc[2 * l];
307 xt = pSrc[2 * i] - pSrc[2 * l];
308
309 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
310 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
311
312 p0 = xt * cosVal;
313 p1 = yt * sinVal;
314 p2 = yt * cosVal;
315 p3 = xt * sinVal;
316
317 pSrc[2 * i] = a0;
318 pSrc[2 * i + 1] = a1;
319
320 pSrc[2 * l] = p0 - p1;
321 pSrc[2 * l + 1] = p2 + p3;
322 } // groups loop end
323
324 twidCoefModifier <<= 1U;
325
326 // loop for stage
327 for (k = fftLen / 2; k > 2; k = k >> 1)
328 {
329 n1 = n2;
330 n2 = n2 >> 1;
331 ia = 0;
332
333 // loop for groups
334 j = 0;
335 do
336 {
337 cosVal = pCoef[ia * 2];
338 sinVal = pCoef[(ia * 2) + 1];
339 ia += twidCoefModifier;
340
341 // loop for butterfly
342 i = j;
343 do
344 {
345 l = i + n2;
346 a0 = pSrc[2 * i] + pSrc[2 * l];
347 xt = pSrc[2 * i] - pSrc[2 * l];
348
349 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
350 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
351
352 p0 = xt * cosVal;
353 p1 = yt * sinVal;
354 p2 = yt * cosVal;
355 p3 = xt * sinVal;
356
357 pSrc[2 * i] = a0;
358 pSrc[2 * i + 1] = a1;
359
360 pSrc[2 * l] = p0 - p1;
361 pSrc[2 * l + 1] = p2 + p3;
362
363 i += n1;
364 } while ( i < fftLen ); // butterfly loop end
365 j++;
366 } while (j < n2); // groups loop end
367
368 twidCoefModifier <<= 1U;
369 } // stages loop end
370
371 // loop for butterfly
372 for (i = 0; i < fftLen; i += 2)
373 {
374 a0 = pSrc[2 * i] + pSrc[2 * i + 2];
375 xt = pSrc[2 * i] - pSrc[2 * i + 2];
376
377 a1 = pSrc[2 * i + 3] + pSrc[2 * i + 1];
378 yt = pSrc[2 * i + 1] - pSrc[2 * i + 3];
379
380 p0 = a0 * onebyfftLen;
381 p2 = xt * onebyfftLen;
382 p1 = a1 * onebyfftLen;
383 p3 = yt * onebyfftLen;
384
385 pSrc[2 * i] = p0;
386 pSrc[2 * i + 1] = p1;
387 pSrc[2 * i + 2] = p2;
388 pSrc[2 * i + 3] = p3;
389 } // butterfly loop end
390
391 #else /* #if defined (ARM_MATH_DSP) */
392
393 n2 = fftLen;
394
395 // loop for stage
396 for (k = fftLen; k > 2; k = k >> 1)
397 {
398 n1 = n2;
399 n2 = n2 >> 1;
400 ia = 0;
401
402 // loop for groups
403 j = 0;
404 do
405 {
406 cosVal = pCoef[ia * 2];
407 sinVal = pCoef[(ia * 2) + 1];
408 ia = ia + twidCoefModifier;
409
410 // loop for butterfly
411 i = j;
412 do
413 {
414 l = i + n2;
415 a0 = pSrc[2 * i] + pSrc[2 * l];
416 xt = pSrc[2 * i] - pSrc[2 * l];
417
418 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
419 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
420
421 p0 = xt * cosVal;
422 p1 = yt * sinVal;
423 p2 = yt * cosVal;
424 p3 = xt * sinVal;
425
426 pSrc[2 * i] = a0;
427 pSrc[2 * i + 1] = a1;
428
429 pSrc[2 * l] = p0 - p1;
430 pSrc[2 * l + 1] = p2 + p3;
431
432 i += n1;
433 } while ( i < fftLen ); // butterfly loop end
434 j++;
435 } while ( j < n2 ); // groups loop end
436
437 twidCoefModifier = twidCoefModifier << 1U;
438 } // stages loop end
439
440 n1 = n2;
441 n2 = n2 >> 1;
442
443 // loop for butterfly
444 for (i = 0; i < fftLen; i += n1)
445 {
446 l = i + n2;
447
448 a0 = pSrc[2 * i] + pSrc[2 * l];
449 xt = pSrc[2 * i] - pSrc[2 * l];
450
451 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
452 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
453
454 p0 = a0 * onebyfftLen;
455 p2 = xt * onebyfftLen;
456 p1 = a1 * onebyfftLen;
457 p3 = yt * onebyfftLen;
458
459 pSrc[2 * i] = p0;
460 pSrc[2 * l] = p2;
461
462 pSrc[2 * i + 1] = p1;
463 pSrc[2 * l + 1] = p3;
464 } // butterfly loop end
465
466 #endif /* #if defined (ARM_MATH_DSP) */
467
468 }
469