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