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