1 /* ----------------------------------------------------------------------
2  * Project:      CMSIS DSP Library
3  * Title:        arm_cfft_radix2_q31.c
4  * Description:  Radix-2 Decimation in Frequency CFFT & CIFFT Fixed 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_q31(
32         q31_t * pSrc,
33         uint32_t fftLen,
34   const q31_t * pCoef,
35         uint16_t twidCoefModifier);
36 
37 void arm_radix2_butterfly_inverse_q31(
38         q31_t * pSrc,
39         uint32_t fftLen,
40   const q31_t * pCoef,
41         uint16_t twidCoefModifier);
42 
43 void arm_bitreversal_q31(
44         q31_t * pSrc,
45         uint32_t fftLen,
46         uint16_t bitRevFactor,
47   const uint16_t * pBitRevTab);
48 
49 
50 /**
51   @addtogroup ComplexFFTDeprecated
52   @{
53  */
54 
55 /**
56   @brief         Processing function for the fixed-point CFFT/CIFFT.
57   @deprecated    Do not use this function. It has been superseded by \ref arm_cfft_q31 and will be removed in the future.
58   @param[in]     S    points to an instance of the fixed-point CFFT/CIFFT structure
59   @param[in,out] pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place
60  */
61 
arm_cfft_radix2_q31(const arm_cfft_radix2_instance_q31 * S,q31_t * pSrc)62 void arm_cfft_radix2_q31(
63   const arm_cfft_radix2_instance_q31 * S,
64         q31_t * pSrc)
65 {
66 
67    if (S->ifftFlag == 1U)
68    {
69       arm_radix2_butterfly_inverse_q31(pSrc, S->fftLen,
70       S->pTwiddle, S->twidCoefModifier);
71    }
72    else
73    {
74       arm_radix2_butterfly_q31(pSrc, S->fftLen,
75       S->pTwiddle, S->twidCoefModifier);
76    }
77 
78    arm_bitreversal_q31(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable);
79 }
80 
81 /**
82   @} end of ComplexFFTDeprecated group
83  */
84 
arm_radix2_butterfly_q31(q31_t * pSrc,uint32_t fftLen,const q31_t * pCoef,uint16_t twidCoefModifier)85 void arm_radix2_butterfly_q31(
86         q31_t * pSrc,
87         uint32_t fftLen,
88   const q31_t * pCoef,
89         uint16_t twidCoefModifier)
90 {
91 
92    unsigned i, j, k, l, m;
93    unsigned n1, n2, ia;
94    q31_t xt, yt, cosVal, sinVal;
95    q31_t p0, p1;
96 
97    //N = fftLen;
98    n2 = fftLen;
99 
100    n1 = n2;
101    n2 = n2 >> 1;
102    ia = 0;
103 
104    // loop for groups
105    for (i = 0; i < n2; i++)
106    {
107       cosVal = pCoef[ia * 2];
108       sinVal = pCoef[(ia * 2) + 1];
109       ia = ia + twidCoefModifier;
110 
111       l = i + n2;
112       xt = (pSrc[2 * i] >> 1U) - (pSrc[2 * l] >> 1U);
113       pSrc[2 * i] = ((pSrc[2 * i] >> 1U) + (pSrc[2 * l] >> 1U)) >> 1U;
114 
115       yt = (pSrc[2 * i + 1] >> 1U) - (pSrc[2 * l + 1] >> 1U);
116       pSrc[2 * i + 1] =
117         ((pSrc[2 * l + 1] >> 1U) + (pSrc[2 * i + 1] >> 1U)) >> 1U;
118 
119       mult_32x32_keep32_R(p0, xt, cosVal);
120       mult_32x32_keep32_R(p1, yt, cosVal);
121       multAcc_32x32_keep32_R(p0, yt, sinVal);
122       multSub_32x32_keep32_R(p1, xt, sinVal);
123 
124       pSrc[2U * l] = p0;
125       pSrc[2U * l + 1U] = p1;
126 
127    }                             // groups loop end
128 
129    twidCoefModifier <<= 1U;
130 
131    // loop for stage
132    for (k = fftLen / 2; k > 2; k = k >> 1)
133    {
134       n1 = n2;
135       n2 = n2 >> 1;
136       ia = 0;
137 
138       // loop for groups
139       for (j = 0; j < n2; j++)
140       {
141          cosVal = pCoef[ia * 2];
142          sinVal = pCoef[(ia * 2) + 1];
143          ia = ia + twidCoefModifier;
144 
145          // loop for butterfly
146          i = j;
147          m = fftLen / n1;
148          do
149          {
150             l = i + n2;
151             xt = pSrc[2 * i] - pSrc[2 * l];
152             pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1U;
153 
154             yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
155             pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1U;
156 
157             mult_32x32_keep32_R(p0, xt, cosVal);
158             mult_32x32_keep32_R(p1, yt, cosVal);
159             multAcc_32x32_keep32_R(p0, yt, sinVal);
160             multSub_32x32_keep32_R(p1, xt, sinVal);
161 
162             pSrc[2U * l] = p0;
163             pSrc[2U * l + 1U] = p1;
164             i += n1;
165             m--;
166          } while ( m > 0);                   // butterfly loop end
167 
168       }                           // groups loop end
169 
170       twidCoefModifier <<= 1U;
171    }                             // stages loop end
172 
173    n1 = n2;
174    n2 = n2 >> 1;
175    ia = 0;
176 
177    cosVal = pCoef[ia * 2];
178    sinVal = pCoef[(ia * 2) + 1];
179    ia = ia + twidCoefModifier;
180 
181    // loop for butterfly
182    for (i = 0; i < fftLen; i += n1)
183    {
184       l = i + n2;
185       xt = pSrc[2 * i] - pSrc[2 * l];
186       pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
187 
188       yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
189       pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
190 
191       pSrc[2U * l] = xt;
192 
193       pSrc[2U * l + 1U] = yt;
194 
195       i += n1;
196       l = i + n2;
197 
198       xt = pSrc[2 * i] - pSrc[2 * l];
199       pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
200 
201       yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
202       pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
203 
204       pSrc[2U * l] = xt;
205 
206       pSrc[2U * l + 1U] = yt;
207 
208    }                             // butterfly loop end
209 
210 }
211 
212 
arm_radix2_butterfly_inverse_q31(q31_t * pSrc,uint32_t fftLen,const q31_t * pCoef,uint16_t twidCoefModifier)213 void arm_radix2_butterfly_inverse_q31(
214         q31_t * pSrc,
215         uint32_t fftLen,
216   const q31_t * pCoef,
217         uint16_t twidCoefModifier)
218 {
219 
220    unsigned i, j, k, l;
221    unsigned n1, n2, ia;
222    q31_t xt, yt, cosVal, sinVal;
223    q31_t p0, p1;
224 
225    //N = fftLen;
226    n2 = fftLen;
227 
228    n1 = n2;
229    n2 = n2 >> 1;
230    ia = 0;
231 
232    // loop for groups
233    for (i = 0; i < n2; i++)
234    {
235       cosVal = pCoef[ia * 2];
236       sinVal = pCoef[(ia * 2) + 1];
237       ia = ia + twidCoefModifier;
238 
239       l = i + n2;
240       xt = (pSrc[2 * i] >> 1U) - (pSrc[2 * l] >> 1U);
241       pSrc[2 * i] = ((pSrc[2 * i] >> 1U) + (pSrc[2 * l] >> 1U)) >> 1U;
242 
243       yt = (pSrc[2 * i + 1] >> 1U) - (pSrc[2 * l + 1] >> 1U);
244       pSrc[2 * i + 1] =
245         ((pSrc[2 * l + 1] >> 1U) + (pSrc[2 * i + 1] >> 1U)) >> 1U;
246 
247       mult_32x32_keep32_R(p0, xt, cosVal);
248       mult_32x32_keep32_R(p1, yt, cosVal);
249       multSub_32x32_keep32_R(p0, yt, sinVal);
250       multAcc_32x32_keep32_R(p1, xt, sinVal);
251 
252       pSrc[2U * l] = p0;
253       pSrc[2U * l + 1U] = p1;
254    }                             // groups loop end
255 
256    twidCoefModifier = twidCoefModifier << 1U;
257 
258    // loop for stage
259    for (k = fftLen / 2; k > 2; k = k >> 1)
260    {
261       n1 = n2;
262       n2 = n2 >> 1;
263       ia = 0;
264 
265       // loop for groups
266       for (j = 0; j < n2; j++)
267       {
268          cosVal = pCoef[ia * 2];
269          sinVal = pCoef[(ia * 2) + 1];
270          ia = ia + twidCoefModifier;
271 
272          // loop for butterfly
273          for (i = j; i < fftLen; i += n1)
274          {
275             l = i + n2;
276             xt = pSrc[2 * i] - pSrc[2 * l];
277             pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]) >> 1U;
278 
279             yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
280             pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]) >> 1U;
281 
282             mult_32x32_keep32_R(p0, xt, cosVal);
283             mult_32x32_keep32_R(p1, yt, cosVal);
284             multSub_32x32_keep32_R(p0, yt, sinVal);
285             multAcc_32x32_keep32_R(p1, xt, sinVal);
286 
287             pSrc[2U * l] = p0;
288             pSrc[2U * l + 1U] = p1;
289          }                         // butterfly loop end
290 
291       }                           // groups loop end
292 
293       twidCoefModifier = twidCoefModifier << 1U;
294    }                             // stages loop end
295 
296    n1 = n2;
297    n2 = n2 >> 1;
298    ia = 0;
299 
300    cosVal = pCoef[ia * 2];
301    sinVal = pCoef[(ia * 2) + 1];
302    ia = ia + twidCoefModifier;
303 
304    // loop for butterfly
305    for (i = 0; i < fftLen; i += n1)
306    {
307       l = i + n2;
308       xt = pSrc[2 * i] - pSrc[2 * l];
309       pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
310 
311       yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
312       pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
313 
314       pSrc[2U * l] = xt;
315 
316       pSrc[2U * l + 1U] = yt;
317 
318       i += n1;
319       l = i + n2;
320 
321       xt = pSrc[2 * i] - pSrc[2 * l];
322       pSrc[2 * i] = (pSrc[2 * i] + pSrc[2 * l]);
323 
324       yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
325       pSrc[2 * i + 1] = (pSrc[2 * l + 1] + pSrc[2 * i + 1]);
326 
327       pSrc[2U * l] = xt;
328 
329       pSrc[2U * l + 1U] = yt;
330 
331    }                             // butterfly loop end
332 
333 }
334