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