1 /* ----------------------------------------------------------------------
2 * Project: CMSIS DSP Library
3 * Title: arm_cfft_radix2_f16.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_f16.h"
30
31 #if defined(ARM_FLOAT16_SUPPORTED)
32
33 void arm_radix2_butterfly_f16(
34 float16_t * pSrc,
35 uint32_t fftLen,
36 const float16_t * pCoef,
37 uint16_t twidCoefModifier);
38
39 void arm_radix2_butterfly_inverse_f16(
40 float16_t * pSrc,
41 uint32_t fftLen,
42 const float16_t * pCoef,
43 uint16_t twidCoefModifier,
44 float16_t onebyfftLen);
45
46 extern void arm_bitreversal_f16(
47 float16_t * pSrc,
48 uint16_t fftSize,
49 uint16_t bitRevFactor,
50 const uint16_t * pBitRevTab);
51
52 /**
53 @ingroup groupTransforms
54 */
55
56 /**
57 @addtogroup ComplexFFT
58 @{
59 */
60
61 /**
62 @brief Radix-2 CFFT/CIFFT.
63 @deprecated Do not use this function. It has been superseded by \ref arm_cfft_f16 and will be removed in the future
64 @param[in] S points to an instance of the floating-point Radix-2 CFFT/CIFFT structure
65 @param[in,out] pSrc points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place
66 @return none
67 */
68
arm_cfft_radix2_f16(const arm_cfft_radix2_instance_f16 * S,float16_t * pSrc)69 void arm_cfft_radix2_f16(
70 const arm_cfft_radix2_instance_f16 * S,
71 float16_t * pSrc)
72 {
73
74 if (S->ifftFlag == 1U)
75 {
76 /* Complex IFFT radix-2 */
77 arm_radix2_butterfly_inverse_f16(pSrc, S->fftLen, S->pTwiddle,
78 S->twidCoefModifier, S->onebyfftLen);
79 }
80 else
81 {
82 /* Complex FFT radix-2 */
83 arm_radix2_butterfly_f16(pSrc, S->fftLen, S->pTwiddle,
84 S->twidCoefModifier);
85 }
86
87 if (S->bitReverseFlag == 1U)
88 {
89 /* Bit Reversal */
90 arm_bitreversal_f16(pSrc, S->fftLen, S->bitRevFactor, S->pBitRevTable);
91 }
92
93 }
94
95
96 /**
97 @} end of ComplexFFT group
98 */
99
100
101
102 /* ----------------------------------------------------------------------
103 ** Internal helper function used by the FFTs
104 ** ------------------------------------------------------------------- */
105
106 /*
107 * @brief Core function for the floating-point CFFT butterfly process.
108 * @param[in, out] *pSrc points to the in-place buffer of floating-point data type.
109 * @param[in] fftLen length of the FFT.
110 * @param[in] *pCoef points to the twiddle coefficient buffer.
111 * @param[in] twidCoefModifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
112 * @return none.
113 */
114
arm_radix2_butterfly_f16(float16_t * pSrc,uint32_t fftLen,const float16_t * pCoef,uint16_t twidCoefModifier)115 void arm_radix2_butterfly_f16(
116 float16_t * pSrc,
117 uint32_t fftLen,
118 const float16_t * pCoef,
119 uint16_t twidCoefModifier)
120 {
121
122 uint32_t i, j, k, l;
123 uint32_t n1, n2, ia;
124 float16_t xt, yt, cosVal, sinVal;
125 float16_t p0, p1, p2, p3;
126 float16_t a0, a1;
127
128 #if defined (ARM_MATH_DSP)
129
130 /* Initializations for the first stage */
131 n2 = fftLen >> 1;
132 ia = 0;
133 i = 0;
134
135 // loop for groups
136 for (k = n2; k > 0; k--)
137 {
138 cosVal = pCoef[ia * 2];
139 sinVal = pCoef[(ia * 2) + 1];
140
141 /* Twiddle coefficients index modifier */
142 ia += twidCoefModifier;
143
144 /* index calculation for the input as, */
145 /* pSrc[i + 0], pSrc[i + fftLen/1] */
146 l = i + n2;
147
148 /* Butterfly implementation */
149 a0 = pSrc[2 * i] + pSrc[2 * l];
150 xt = pSrc[2 * i] - pSrc[2 * l];
151
152 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
153 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
154
155 p0 = xt * cosVal;
156 p1 = yt * sinVal;
157 p2 = yt * cosVal;
158 p3 = xt * sinVal;
159
160 pSrc[2 * i] = a0;
161 pSrc[2 * i + 1] = a1;
162
163 pSrc[2 * l] = p0 + p1;
164 pSrc[2 * l + 1] = p2 - p3;
165
166 i++;
167 } // groups loop end
168
169 twidCoefModifier <<= 1U;
170
171 // loop for stage
172 for (k = n2; k > 2; k = k >> 1)
173 {
174 n1 = n2;
175 n2 = n2 >> 1;
176 ia = 0;
177
178 // loop for groups
179 j = 0;
180 do
181 {
182 cosVal = pCoef[ia * 2];
183 sinVal = pCoef[(ia * 2) + 1];
184 ia += twidCoefModifier;
185
186 // loop for butterfly
187 i = j;
188 do
189 {
190 l = i + n2;
191 a0 = pSrc[2 * i] + pSrc[2 * l];
192 xt = pSrc[2 * i] - pSrc[2 * l];
193
194 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
195 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
196
197 p0 = xt * cosVal;
198 p1 = yt * sinVal;
199 p2 = yt * cosVal;
200 p3 = xt * sinVal;
201
202 pSrc[2 * i] = a0;
203 pSrc[2 * i + 1] = a1;
204
205 pSrc[2 * l] = p0 + p1;
206 pSrc[2 * l + 1] = p2 - p3;
207
208 i += n1;
209 } while ( i < fftLen ); // butterfly loop end
210 j++;
211 } while ( j < n2); // groups loop end
212 twidCoefModifier <<= 1U;
213 } // stages loop end
214
215 // loop for butterfly
216 for (i = 0; i < fftLen; i += 2)
217 {
218 a0 = pSrc[2 * i] + pSrc[2 * i + 2];
219 xt = pSrc[2 * i] - pSrc[2 * i + 2];
220
221 yt = pSrc[2 * i + 1] - pSrc[2 * i + 3];
222 a1 = pSrc[2 * i + 3] + pSrc[2 * i + 1];
223
224 pSrc[2 * i] = a0;
225 pSrc[2 * i + 1] = a1;
226 pSrc[2 * i + 2] = xt;
227 pSrc[2 * i + 3] = yt;
228 } // groups loop end
229
230 #else
231
232 n2 = fftLen;
233
234 // loop for stage
235 for (k = fftLen; k > 1; k = k >> 1)
236 {
237 n1 = n2;
238 n2 = n2 >> 1;
239 ia = 0;
240
241 // loop for groups
242 j = 0;
243 do
244 {
245 cosVal = pCoef[ia * 2];
246 sinVal = pCoef[(ia * 2) + 1];
247 ia += twidCoefModifier;
248
249 // loop for butterfly
250 i = j;
251 do
252 {
253 l = i + n2;
254 a0 = pSrc[2 * i] + pSrc[2 * l];
255 xt = pSrc[2 * i] - pSrc[2 * l];
256
257 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
258 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
259
260 p0 = xt * cosVal;
261 p1 = yt * sinVal;
262 p2 = yt * cosVal;
263 p3 = xt * sinVal;
264
265 pSrc[2 * i] = a0;
266 pSrc[2 * i + 1] = a1;
267
268 pSrc[2 * l] = p0 + p1;
269 pSrc[2 * l + 1] = p2 - p3;
270
271 i += n1;
272 } while (i < fftLen);
273 j++;
274 } while (j < n2);
275 twidCoefModifier <<= 1U;
276 }
277
278 #endif // #if defined (ARM_MATH_DSP)
279
280 }
281
282
arm_radix2_butterfly_inverse_f16(float16_t * pSrc,uint32_t fftLen,const float16_t * pCoef,uint16_t twidCoefModifier,float16_t onebyfftLen)283 void arm_radix2_butterfly_inverse_f16(
284 float16_t * pSrc,
285 uint32_t fftLen,
286 const float16_t * pCoef,
287 uint16_t twidCoefModifier,
288 float16_t onebyfftLen)
289 {
290
291 uint32_t i, j, k, l;
292 uint32_t n1, n2, ia;
293 float16_t xt, yt, cosVal, sinVal;
294 float16_t p0, p1, p2, p3;
295 float16_t a0, a1;
296
297 #if defined (ARM_MATH_DSP)
298
299 n2 = fftLen >> 1;
300 ia = 0;
301
302 // loop for groups
303 for (i = 0; i < n2; i++)
304 {
305 cosVal = pCoef[ia * 2];
306 sinVal = pCoef[(ia * 2) + 1];
307 ia += twidCoefModifier;
308
309 l = i + n2;
310 a0 = pSrc[2 * i] + pSrc[2 * l];
311 xt = pSrc[2 * i] - pSrc[2 * l];
312
313 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
314 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
315
316 p0 = xt * cosVal;
317 p1 = yt * sinVal;
318 p2 = yt * cosVal;
319 p3 = xt * sinVal;
320
321 pSrc[2 * i] = a0;
322 pSrc[2 * i + 1] = a1;
323
324 pSrc[2 * l] = p0 - p1;
325 pSrc[2 * l + 1] = p2 + p3;
326 } // groups loop end
327
328 twidCoefModifier <<= 1U;
329
330 // loop for stage
331 for (k = fftLen / 2; k > 2; k = k >> 1)
332 {
333 n1 = n2;
334 n2 = n2 >> 1;
335 ia = 0;
336
337 // loop for groups
338 j = 0;
339 do
340 {
341 cosVal = pCoef[ia * 2];
342 sinVal = pCoef[(ia * 2) + 1];
343 ia += twidCoefModifier;
344
345 // loop for butterfly
346 i = j;
347 do
348 {
349 l = i + n2;
350 a0 = pSrc[2 * i] + pSrc[2 * l];
351 xt = pSrc[2 * i] - pSrc[2 * l];
352
353 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
354 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
355
356 p0 = xt * cosVal;
357 p1 = yt * sinVal;
358 p2 = yt * cosVal;
359 p3 = xt * sinVal;
360
361 pSrc[2 * i] = a0;
362 pSrc[2 * i + 1] = a1;
363
364 pSrc[2 * l] = p0 - p1;
365 pSrc[2 * l + 1] = p2 + p3;
366
367 i += n1;
368 } while ( i < fftLen ); // butterfly loop end
369 j++;
370 } while (j < n2); // groups loop end
371
372 twidCoefModifier <<= 1U;
373 } // stages loop end
374
375 // loop for butterfly
376 for (i = 0; i < fftLen; i += 2)
377 {
378 a0 = pSrc[2 * i] + pSrc[2 * i + 2];
379 xt = pSrc[2 * i] - pSrc[2 * i + 2];
380
381 a1 = pSrc[2 * i + 3] + pSrc[2 * i + 1];
382 yt = pSrc[2 * i + 1] - pSrc[2 * i + 3];
383
384 p0 = a0 * onebyfftLen;
385 p2 = xt * onebyfftLen;
386 p1 = a1 * onebyfftLen;
387 p3 = yt * onebyfftLen;
388
389 pSrc[2 * i] = p0;
390 pSrc[2 * i + 1] = p1;
391 pSrc[2 * i + 2] = p2;
392 pSrc[2 * i + 3] = p3;
393 } // butterfly loop end
394
395 #else
396
397 n2 = fftLen;
398
399 // loop for stage
400 for (k = fftLen; k > 2; k = k >> 1)
401 {
402 n1 = n2;
403 n2 = n2 >> 1;
404 ia = 0;
405
406 // loop for groups
407 j = 0;
408 do
409 {
410 cosVal = pCoef[ia * 2];
411 sinVal = pCoef[(ia * 2) + 1];
412 ia = ia + twidCoefModifier;
413
414 // loop for butterfly
415 i = j;
416 do
417 {
418 l = i + n2;
419 a0 = pSrc[2 * i] + pSrc[2 * l];
420 xt = pSrc[2 * i] - pSrc[2 * l];
421
422 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
423 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
424
425 p0 = xt * cosVal;
426 p1 = yt * sinVal;
427 p2 = yt * cosVal;
428 p3 = xt * sinVal;
429
430 pSrc[2 * i] = a0;
431 pSrc[2 * i + 1] = a1;
432
433 pSrc[2 * l] = p0 - p1;
434 pSrc[2 * l + 1] = p2 + p3;
435
436 i += n1;
437 } while ( i < fftLen ); // butterfly loop end
438 j++;
439 } while ( j < n2 ); // groups loop end
440
441 twidCoefModifier = twidCoefModifier << 1U;
442 } // stages loop end
443
444 n1 = n2;
445 n2 = n2 >> 1;
446
447 // loop for butterfly
448 for (i = 0; i < fftLen; i += n1)
449 {
450 l = i + n2;
451
452 a0 = pSrc[2 * i] + pSrc[2 * l];
453 xt = pSrc[2 * i] - pSrc[2 * l];
454
455 a1 = pSrc[2 * l + 1] + pSrc[2 * i + 1];
456 yt = pSrc[2 * i + 1] - pSrc[2 * l + 1];
457
458 p0 = a0 * onebyfftLen;
459 p2 = xt * onebyfftLen;
460 p1 = a1 * onebyfftLen;
461 p3 = yt * onebyfftLen;
462
463 pSrc[2 * i] = p0;
464 pSrc[2U * l] = p2;
465
466 pSrc[2 * i + 1] = p1;
467 pSrc[2U * l + 1U] = p3;
468 } // butterfly loop end
469
470 #endif // #if defined (ARM_MATH_DSP)
471
472 }
473
474
475 #endif /* #if defined(ARM_FLOAT16_SUPPORTED) */