CMSIS DSP library
Dependents: performance_timer Surfboard_ gps2rtty Capstone ... more
arm_cfft_f32.c
00001 /* ---------------------------------------------------------------------- 00002 * Copyright (C) 2010-2014 ARM Limited. All rights reserved. 00003 * 00004 * $Date: 19. March 2015 00005 * $Revision: V.1.4.5 00006 * 00007 * Project: CMSIS DSP Library 00008 * Title: arm_cfft_f32.c 00009 * 00010 * Description: Combined Radix Decimation in Frequency CFFT Floating point processing function 00011 * 00012 * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0 00013 * 00014 * Redistribution and use in source and binary forms, with or without 00015 * modification, are permitted provided that the following conditions 00016 * are met: 00017 * - Redistributions of source code must retain the above copyright 00018 * notice, this list of conditions and the following disclaimer. 00019 * - Redistributions in binary form must reproduce the above copyright 00020 * notice, this list of conditions and the following disclaimer in 00021 * the documentation and/or other materials provided with the 00022 * distribution. 00023 * - Neither the name of ARM LIMITED nor the names of its contributors 00024 * may be used to endorse or promote products derived from this 00025 * software without specific prior written permission. 00026 * 00027 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00028 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00029 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00030 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00031 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00032 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00033 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00034 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00035 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00036 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00037 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00038 * POSSIBILITY OF SUCH DAMAGE. 00039 * -------------------------------------------------------------------- */ 00040 00041 #include "arm_math.h" 00042 #include "arm_common_tables.h" 00043 00044 extern void arm_radix8_butterfly_f32( 00045 float32_t * pSrc, 00046 uint16_t fftLen, 00047 const float32_t * pCoef, 00048 uint16_t twidCoefModifier); 00049 00050 extern void arm_bitreversal_32( 00051 uint32_t * pSrc, 00052 const uint16_t bitRevLen, 00053 const uint16_t * pBitRevTable); 00054 00055 /** 00056 * @ingroup groupTransforms 00057 */ 00058 00059 /** 00060 * @defgroup ComplexFFT Complex FFT Functions 00061 * 00062 * \par 00063 * The Fast Fourier Transform (FFT) is an efficient algorithm for computing the 00064 * Discrete Fourier Transform (DFT). The FFT can be orders of magnitude faster 00065 * than the DFT, especially for long lengths. 00066 * The algorithms described in this section 00067 * operate on complex data. A separate set of functions is devoted to handling 00068 * of real sequences. 00069 * \par 00070 * There are separate algorithms for handling floating-point, Q15, and Q31 data 00071 * types. The algorithms available for each data type are described next. 00072 * \par 00073 * The FFT functions operate in-place. That is, the array holding the input data 00074 * will also be used to hold the corresponding result. The input data is complex 00075 * and contains <code>2*fftLen</code> interleaved values as shown below. 00076 * <pre> {real[0], imag[0], real[1], imag[1],..} </pre> 00077 * The FFT result will be contained in the same array and the frequency domain 00078 * values will have the same interleaving. 00079 * 00080 * \par Floating-point 00081 * The floating-point complex FFT uses a mixed-radix algorithm. Multiple radix-8 00082 * stages are performed along with a single radix-2 or radix-4 stage, as needed. 00083 * The algorithm supports lengths of [16, 32, 64, ..., 4096] and each length uses 00084 * a different twiddle factor table. 00085 * \par 00086 * The function uses the standard FFT definition and output values may grow by a 00087 * factor of <code>fftLen</code> when computing the forward transform. The 00088 * inverse transform includes a scale of <code>1/fftLen</code> as part of the 00089 * calculation and this matches the textbook definition of the inverse FFT. 00090 * \par 00091 * Pre-initialized data structures containing twiddle factors and bit reversal 00092 * tables are provided and defined in <code>arm_const_structs.h</code>. Include 00093 * this header in your function and then pass one of the constant structures as 00094 * an argument to arm_cfft_f32. For example: 00095 * \par 00096 * <code>arm_cfft_f32(arm_cfft_sR_f32_len64, pSrc, 1, 1)</code> 00097 * \par 00098 * computes a 64-point inverse complex FFT including bit reversal. 00099 * The data structures are treated as constant data and not modified during the 00100 * calculation. The same data structure can be reused for multiple transforms 00101 * including mixing forward and inverse transforms. 00102 * \par 00103 * Earlier releases of the library provided separate radix-2 and radix-4 00104 * algorithms that operated on floating-point data. These functions are still 00105 * provided but are deprecated. The older functions are slower and less general 00106 * than the new functions. 00107 * \par 00108 * An example of initialization of the constants for the arm_cfft_f32 function follows: 00109 * \code 00110 * const static arm_cfft_instance_f32 *S; 00111 * ... 00112 * switch (length) { 00113 * case 16: 00114 * S = &arm_cfft_sR_f32_len16; 00115 * break; 00116 * case 32: 00117 * S = &arm_cfft_sR_f32_len32; 00118 * break; 00119 * case 64: 00120 * S = &arm_cfft_sR_f32_len64; 00121 * break; 00122 * case 128: 00123 * S = &arm_cfft_sR_f32_len128; 00124 * break; 00125 * case 256: 00126 * S = &arm_cfft_sR_f32_len256; 00127 * break; 00128 * case 512: 00129 * S = &arm_cfft_sR_f32_len512; 00130 * break; 00131 * case 1024: 00132 * S = &arm_cfft_sR_f32_len1024; 00133 * break; 00134 * case 2048: 00135 * S = &arm_cfft_sR_f32_len2048; 00136 * break; 00137 * case 4096: 00138 * S = &arm_cfft_sR_f32_len4096; 00139 * break; 00140 * } 00141 * \endcode 00142 * \par Q15 and Q31 00143 * The floating-point complex FFT uses a mixed-radix algorithm. Multiple radix-4 00144 * stages are performed along with a single radix-2 stage, as needed. 00145 * The algorithm supports lengths of [16, 32, 64, ..., 4096] and each length uses 00146 * a different twiddle factor table. 00147 * \par 00148 * The function uses the standard FFT definition and output values may grow by a 00149 * factor of <code>fftLen</code> when computing the forward transform. The 00150 * inverse transform includes a scale of <code>1/fftLen</code> as part of the 00151 * calculation and this matches the textbook definition of the inverse FFT. 00152 * \par 00153 * Pre-initialized data structures containing twiddle factors and bit reversal 00154 * tables are provided and defined in <code>arm_const_structs.h</code>. Include 00155 * this header in your function and then pass one of the constant structures as 00156 * an argument to arm_cfft_q31. For example: 00157 * \par 00158 * <code>arm_cfft_q31(arm_cfft_sR_q31_len64, pSrc, 1, 1)</code> 00159 * \par 00160 * computes a 64-point inverse complex FFT including bit reversal. 00161 * The data structures are treated as constant data and not modified during the 00162 * calculation. The same data structure can be reused for multiple transforms 00163 * including mixing forward and inverse transforms. 00164 * \par 00165 * Earlier releases of the library provided separate radix-2 and radix-4 00166 * algorithms that operated on floating-point data. These functions are still 00167 * provided but are deprecated. The older functions are slower and less general 00168 * than the new functions. 00169 * \par 00170 * An example of initialization of the constants for the arm_cfft_q31 function follows: 00171 * \code 00172 * const static arm_cfft_instance_q31 *S; 00173 * ... 00174 * switch (length) { 00175 * case 16: 00176 * S = &arm_cfft_sR_q31_len16; 00177 * break; 00178 * case 32: 00179 * S = &arm_cfft_sR_q31_len32; 00180 * break; 00181 * case 64: 00182 * S = &arm_cfft_sR_q31_len64; 00183 * break; 00184 * case 128: 00185 * S = &arm_cfft_sR_q31_len128; 00186 * break; 00187 * case 256: 00188 * S = &arm_cfft_sR_q31_len256; 00189 * break; 00190 * case 512: 00191 * S = &arm_cfft_sR_q31_len512; 00192 * break; 00193 * case 1024: 00194 * S = &arm_cfft_sR_q31_len1024; 00195 * break; 00196 * case 2048: 00197 * S = &arm_cfft_sR_q31_len2048; 00198 * break; 00199 * case 4096: 00200 * S = &arm_cfft_sR_q31_len4096; 00201 * break; 00202 * } 00203 * \endcode 00204 * 00205 */ 00206 00207 void arm_cfft_radix8by2_f32( arm_cfft_instance_f32 * S, float32_t * p1) 00208 { 00209 uint32_t L = S->fftLen; 00210 float32_t * pCol1, * pCol2, * pMid1, * pMid2; 00211 float32_t * p2 = p1 + L; 00212 const float32_t * tw = (float32_t *) S->pTwiddle; 00213 float32_t t1[4], t2[4], t3[4], t4[4], twR, twI; 00214 float32_t m0, m1, m2, m3; 00215 uint32_t l; 00216 00217 pCol1 = p1; 00218 pCol2 = p2; 00219 00220 // Define new length 00221 L >>= 1; 00222 // Initialize mid pointers 00223 pMid1 = p1 + L; 00224 pMid2 = p2 + L; 00225 00226 // do two dot Fourier transform 00227 for ( l = L >> 2; l > 0; l-- ) 00228 { 00229 t1[0] = p1[0]; 00230 t1[1] = p1[1]; 00231 t1[2] = p1[2]; 00232 t1[3] = p1[3]; 00233 00234 t2[0] = p2[0]; 00235 t2[1] = p2[1]; 00236 t2[2] = p2[2]; 00237 t2[3] = p2[3]; 00238 00239 t3[0] = pMid1[0]; 00240 t3[1] = pMid1[1]; 00241 t3[2] = pMid1[2]; 00242 t3[3] = pMid1[3]; 00243 00244 t4[0] = pMid2[0]; 00245 t4[1] = pMid2[1]; 00246 t4[2] = pMid2[2]; 00247 t4[3] = pMid2[3]; 00248 00249 *p1++ = t1[0] + t2[0]; 00250 *p1++ = t1[1] + t2[1]; 00251 *p1++ = t1[2] + t2[2]; 00252 *p1++ = t1[3] + t2[3]; // col 1 00253 00254 t2[0] = t1[0] - t2[0]; 00255 t2[1] = t1[1] - t2[1]; 00256 t2[2] = t1[2] - t2[2]; 00257 t2[3] = t1[3] - t2[3]; // for col 2 00258 00259 *pMid1++ = t3[0] + t4[0]; 00260 *pMid1++ = t3[1] + t4[1]; 00261 *pMid1++ = t3[2] + t4[2]; 00262 *pMid1++ = t3[3] + t4[3]; // col 1 00263 00264 t4[0] = t4[0] - t3[0]; 00265 t4[1] = t4[1] - t3[1]; 00266 t4[2] = t4[2] - t3[2]; 00267 t4[3] = t4[3] - t3[3]; // for col 2 00268 00269 twR = *tw++; 00270 twI = *tw++; 00271 00272 // multiply by twiddle factors 00273 m0 = t2[0] * twR; 00274 m1 = t2[1] * twI; 00275 m2 = t2[1] * twR; 00276 m3 = t2[0] * twI; 00277 00278 // R = R * Tr - I * Ti 00279 *p2++ = m0 + m1; 00280 // I = I * Tr + R * Ti 00281 *p2++ = m2 - m3; 00282 00283 // use vertical symmetry 00284 // 0.9988 - 0.0491i <==> -0.0491 - 0.9988i 00285 m0 = t4[0] * twI; 00286 m1 = t4[1] * twR; 00287 m2 = t4[1] * twI; 00288 m3 = t4[0] * twR; 00289 00290 *pMid2++ = m0 - m1; 00291 *pMid2++ = m2 + m3; 00292 00293 twR = *tw++; 00294 twI = *tw++; 00295 00296 m0 = t2[2] * twR; 00297 m1 = t2[3] * twI; 00298 m2 = t2[3] * twR; 00299 m3 = t2[2] * twI; 00300 00301 *p2++ = m0 + m1; 00302 *p2++ = m2 - m3; 00303 00304 m0 = t4[2] * twI; 00305 m1 = t4[3] * twR; 00306 m2 = t4[3] * twI; 00307 m3 = t4[2] * twR; 00308 00309 *pMid2++ = m0 - m1; 00310 *pMid2++ = m2 + m3; 00311 } 00312 00313 // first col 00314 arm_radix8_butterfly_f32( pCol1, L, (float32_t *) S->pTwiddle, 2u); 00315 // second col 00316 arm_radix8_butterfly_f32( pCol2, L, (float32_t *) S->pTwiddle, 2u); 00317 } 00318 00319 void arm_cfft_radix8by4_f32( arm_cfft_instance_f32 * S, float32_t * p1) 00320 { 00321 uint32_t L = S->fftLen >> 1; 00322 float32_t * pCol1, *pCol2, *pCol3, *pCol4, *pEnd1, *pEnd2, *pEnd3, *pEnd4; 00323 const float32_t *tw2, *tw3, *tw4; 00324 float32_t * p2 = p1 + L; 00325 float32_t * p3 = p2 + L; 00326 float32_t * p4 = p3 + L; 00327 float32_t t2[4], t3[4], t4[4], twR, twI; 00328 float32_t p1ap3_0, p1sp3_0, p1ap3_1, p1sp3_1; 00329 float32_t m0, m1, m2, m3; 00330 uint32_t l, twMod2, twMod3, twMod4; 00331 00332 pCol1 = p1; // points to real values by default 00333 pCol2 = p2; 00334 pCol3 = p3; 00335 pCol4 = p4; 00336 pEnd1 = p2 - 1; // points to imaginary values by default 00337 pEnd2 = p3 - 1; 00338 pEnd3 = p4 - 1; 00339 pEnd4 = pEnd3 + L; 00340 00341 tw2 = tw3 = tw4 = (float32_t *) S->pTwiddle; 00342 00343 L >>= 1; 00344 00345 // do four dot Fourier transform 00346 00347 twMod2 = 2; 00348 twMod3 = 4; 00349 twMod4 = 6; 00350 00351 // TOP 00352 p1ap3_0 = p1[0] + p3[0]; 00353 p1sp3_0 = p1[0] - p3[0]; 00354 p1ap3_1 = p1[1] + p3[1]; 00355 p1sp3_1 = p1[1] - p3[1]; 00356 00357 // col 2 00358 t2[0] = p1sp3_0 + p2[1] - p4[1]; 00359 t2[1] = p1sp3_1 - p2[0] + p4[0]; 00360 // col 3 00361 t3[0] = p1ap3_0 - p2[0] - p4[0]; 00362 t3[1] = p1ap3_1 - p2[1] - p4[1]; 00363 // col 4 00364 t4[0] = p1sp3_0 - p2[1] + p4[1]; 00365 t4[1] = p1sp3_1 + p2[0] - p4[0]; 00366 // col 1 00367 *p1++ = p1ap3_0 + p2[0] + p4[0]; 00368 *p1++ = p1ap3_1 + p2[1] + p4[1]; 00369 00370 // Twiddle factors are ones 00371 *p2++ = t2[0]; 00372 *p2++ = t2[1]; 00373 *p3++ = t3[0]; 00374 *p3++ = t3[1]; 00375 *p4++ = t4[0]; 00376 *p4++ = t4[1]; 00377 00378 tw2 += twMod2; 00379 tw3 += twMod3; 00380 tw4 += twMod4; 00381 00382 for (l = (L - 2) >> 1; l > 0; l-- ) 00383 { 00384 // TOP 00385 p1ap3_0 = p1[0] + p3[0]; 00386 p1sp3_0 = p1[0] - p3[0]; 00387 p1ap3_1 = p1[1] + p3[1]; 00388 p1sp3_1 = p1[1] - p3[1]; 00389 // col 2 00390 t2[0] = p1sp3_0 + p2[1] - p4[1]; 00391 t2[1] = p1sp3_1 - p2[0] + p4[0]; 00392 // col 3 00393 t3[0] = p1ap3_0 - p2[0] - p4[0]; 00394 t3[1] = p1ap3_1 - p2[1] - p4[1]; 00395 // col 4 00396 t4[0] = p1sp3_0 - p2[1] + p4[1]; 00397 t4[1] = p1sp3_1 + p2[0] - p4[0]; 00398 // col 1 - top 00399 *p1++ = p1ap3_0 + p2[0] + p4[0]; 00400 *p1++ = p1ap3_1 + p2[1] + p4[1]; 00401 00402 // BOTTOM 00403 p1ap3_1 = pEnd1[-1] + pEnd3[-1]; 00404 p1sp3_1 = pEnd1[-1] - pEnd3[-1]; 00405 p1ap3_0 = pEnd1[0] + pEnd3[0]; 00406 p1sp3_0 = pEnd1[0] - pEnd3[0]; 00407 // col 2 00408 t2[2] = pEnd2[0] - pEnd4[0] + p1sp3_1; 00409 t2[3] = pEnd1[0] - pEnd3[0] - pEnd2[-1] + pEnd4[-1]; 00410 // col 3 00411 t3[2] = p1ap3_1 - pEnd2[-1] - pEnd4[-1]; 00412 t3[3] = p1ap3_0 - pEnd2[0] - pEnd4[0]; 00413 // col 4 00414 t4[2] = pEnd2[0] - pEnd4[0] - p1sp3_1; 00415 t4[3] = pEnd4[-1] - pEnd2[-1] - p1sp3_0; 00416 // col 1 - Bottom 00417 *pEnd1-- = p1ap3_0 + pEnd2[0] + pEnd4[0]; 00418 *pEnd1-- = p1ap3_1 + pEnd2[-1] + pEnd4[-1]; 00419 00420 // COL 2 00421 // read twiddle factors 00422 twR = *tw2++; 00423 twI = *tw2++; 00424 // multiply by twiddle factors 00425 // let Z1 = a + i(b), Z2 = c + i(d) 00426 // => Z1 * Z2 = (a*c - b*d) + i(b*c + a*d) 00427 00428 // Top 00429 m0 = t2[0] * twR; 00430 m1 = t2[1] * twI; 00431 m2 = t2[1] * twR; 00432 m3 = t2[0] * twI; 00433 00434 *p2++ = m0 + m1; 00435 *p2++ = m2 - m3; 00436 // use vertical symmetry col 2 00437 // 0.9997 - 0.0245i <==> 0.0245 - 0.9997i 00438 // Bottom 00439 m0 = t2[3] * twI; 00440 m1 = t2[2] * twR; 00441 m2 = t2[2] * twI; 00442 m3 = t2[3] * twR; 00443 00444 *pEnd2-- = m0 - m1; 00445 *pEnd2-- = m2 + m3; 00446 00447 // COL 3 00448 twR = tw3[0]; 00449 twI = tw3[1]; 00450 tw3 += twMod3; 00451 // Top 00452 m0 = t3[0] * twR; 00453 m1 = t3[1] * twI; 00454 m2 = t3[1] * twR; 00455 m3 = t3[0] * twI; 00456 00457 *p3++ = m0 + m1; 00458 *p3++ = m2 - m3; 00459 // use vertical symmetry col 3 00460 // 0.9988 - 0.0491i <==> -0.9988 - 0.0491i 00461 // Bottom 00462 m0 = -t3[3] * twR; 00463 m1 = t3[2] * twI; 00464 m2 = t3[2] * twR; 00465 m3 = t3[3] * twI; 00466 00467 *pEnd3-- = m0 - m1; 00468 *pEnd3-- = m3 - m2; 00469 00470 // COL 4 00471 twR = tw4[0]; 00472 twI = tw4[1]; 00473 tw4 += twMod4; 00474 // Top 00475 m0 = t4[0] * twR; 00476 m1 = t4[1] * twI; 00477 m2 = t4[1] * twR; 00478 m3 = t4[0] * twI; 00479 00480 *p4++ = m0 + m1; 00481 *p4++ = m2 - m3; 00482 // use vertical symmetry col 4 00483 // 0.9973 - 0.0736i <==> -0.0736 + 0.9973i 00484 // Bottom 00485 m0 = t4[3] * twI; 00486 m1 = t4[2] * twR; 00487 m2 = t4[2] * twI; 00488 m3 = t4[3] * twR; 00489 00490 *pEnd4-- = m0 - m1; 00491 *pEnd4-- = m2 + m3; 00492 } 00493 00494 //MIDDLE 00495 // Twiddle factors are 00496 // 1.0000 0.7071-0.7071i -1.0000i -0.7071-0.7071i 00497 p1ap3_0 = p1[0] + p3[0]; 00498 p1sp3_0 = p1[0] - p3[0]; 00499 p1ap3_1 = p1[1] + p3[1]; 00500 p1sp3_1 = p1[1] - p3[1]; 00501 00502 // col 2 00503 t2[0] = p1sp3_0 + p2[1] - p4[1]; 00504 t2[1] = p1sp3_1 - p2[0] + p4[0]; 00505 // col 3 00506 t3[0] = p1ap3_0 - p2[0] - p4[0]; 00507 t3[1] = p1ap3_1 - p2[1] - p4[1]; 00508 // col 4 00509 t4[0] = p1sp3_0 - p2[1] + p4[1]; 00510 t4[1] = p1sp3_1 + p2[0] - p4[0]; 00511 // col 1 - Top 00512 *p1++ = p1ap3_0 + p2[0] + p4[0]; 00513 *p1++ = p1ap3_1 + p2[1] + p4[1]; 00514 00515 // COL 2 00516 twR = tw2[0]; 00517 twI = tw2[1]; 00518 00519 m0 = t2[0] * twR; 00520 m1 = t2[1] * twI; 00521 m2 = t2[1] * twR; 00522 m3 = t2[0] * twI; 00523 00524 *p2++ = m0 + m1; 00525 *p2++ = m2 - m3; 00526 // COL 3 00527 twR = tw3[0]; 00528 twI = tw3[1]; 00529 00530 m0 = t3[0] * twR; 00531 m1 = t3[1] * twI; 00532 m2 = t3[1] * twR; 00533 m3 = t3[0] * twI; 00534 00535 *p3++ = m0 + m1; 00536 *p3++ = m2 - m3; 00537 // COL 4 00538 twR = tw4[0]; 00539 twI = tw4[1]; 00540 00541 m0 = t4[0] * twR; 00542 m1 = t4[1] * twI; 00543 m2 = t4[1] * twR; 00544 m3 = t4[0] * twI; 00545 00546 *p4++ = m0 + m1; 00547 *p4++ = m2 - m3; 00548 00549 // first col 00550 arm_radix8_butterfly_f32( pCol1, L, (float32_t *) S->pTwiddle, 4u); 00551 // second col 00552 arm_radix8_butterfly_f32( pCol2, L, (float32_t *) S->pTwiddle, 4u); 00553 // third col 00554 arm_radix8_butterfly_f32( pCol3, L, (float32_t *) S->pTwiddle, 4u); 00555 // fourth col 00556 arm_radix8_butterfly_f32( pCol4, L, (float32_t *) S->pTwiddle, 4u); 00557 } 00558 00559 /** 00560 * @addtogroup ComplexFFT 00561 * @{ 00562 */ 00563 00564 /** 00565 * @details 00566 * @brief Processing function for the floating-point complex FFT. 00567 * @param[in] *S points to an instance of the floating-point CFFT structure. 00568 * @param[in, out] *p1 points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place. 00569 * @param[in] ifftFlag flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. 00570 * @param[in] bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. 00571 * @return none. 00572 */ 00573 00574 void arm_cfft_f32( 00575 const arm_cfft_instance_f32 * S, 00576 float32_t * p1, 00577 uint8_t ifftFlag, 00578 uint8_t bitReverseFlag) 00579 { 00580 uint32_t L = S->fftLen, l; 00581 float32_t invL, * pSrc; 00582 00583 if(ifftFlag == 1u) 00584 { 00585 /* Conjugate input data */ 00586 pSrc = p1 + 1; 00587 for(l=0; l<L; l++) 00588 { 00589 *pSrc = -*pSrc; 00590 pSrc += 2; 00591 } 00592 } 00593 00594 switch (L) 00595 { 00596 case 16: 00597 case 128: 00598 case 1024: 00599 arm_cfft_radix8by2_f32 ( (arm_cfft_instance_f32 *) S, p1); 00600 break; 00601 case 32: 00602 case 256: 00603 case 2048: 00604 arm_cfft_radix8by4_f32 ( (arm_cfft_instance_f32 *) S, p1); 00605 break; 00606 case 64: 00607 case 512: 00608 case 4096: 00609 arm_radix8_butterfly_f32( p1, L, (float32_t *) S->pTwiddle, 1); 00610 break; 00611 } 00612 00613 if( bitReverseFlag ) 00614 arm_bitreversal_32((uint32_t*)p1,S->bitRevLength,S->pBitRevTable); 00615 00616 if(ifftFlag == 1u) 00617 { 00618 invL = 1.0f/(float32_t)L; 00619 /* Conjugate and scale output data */ 00620 pSrc = p1; 00621 for(l=0; l<L; l++) 00622 { 00623 *pSrc++ *= invL ; 00624 *pSrc = -(*pSrc) * invL; 00625 pSrc++; 00626 } 00627 } 00628 } 00629 00630 /** 00631 * @} end of ComplexFFT group 00632 */
Generated on Tue Jul 12 2022 11:59:15 by 1.7.2