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