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