CMSIS DSP Library from CMSIS 2.0. See http://www.onarm.com/cmsis/ for full details
Dependents: K22F_DSP_Matrix_least_square BNO055-ELEC3810 1BNO055 ECE4180Project--Slave2 ... more
arm_rfft_f32.c
00001 /* ---------------------------------------------------------------------- 00002 * Copyright (C) 2010 ARM Limited. All rights reserved. 00003 * 00004 * $Date: 29. November 2010 00005 * $Revision: V1.0.3 00006 * 00007 * Project: CMSIS DSP Library 00008 * Title: arm_rfft_f32.c 00009 * 00010 * Description: RFFT & RIFFT Floating point process function 00011 * 00012 * Target Processor: Cortex-M4/Cortex-M3 00013 * 00014 * Version 1.0.3 2010/11/29 00015 * Re-organized the CMSIS folders and updated documentation. 00016 * 00017 * Version 1.0.2 2010/11/11 00018 * Documentation updated. 00019 * 00020 * Version 1.0.1 2010/10/05 00021 * Production release and review comments incorporated. 00022 * 00023 * Version 1.0.0 2010/09/20 00024 * Production release and review comments incorporated. 00025 * 00026 * Version 0.0.7 2010/06/10 00027 * Misra-C changes done 00028 * -------------------------------------------------------------------- */ 00029 00030 #include "arm_math.h" 00031 00032 /** 00033 * @ingroup groupTransforms 00034 */ 00035 00036 /** 00037 * @defgroup RFFT_RIFFT Real FFT Functions 00038 * 00039 * \par 00040 * Complex FFT/IFFT typically assumes complex input and output. However many applications use real valued data in time domain. 00041 * Real FFT/IFFT efficiently process real valued sequences with the advantage of requirement of low memory and with less complexity. 00042 * 00043 * \par 00044 * This set of functions implements Real Fast Fourier Transforms(RFFT) and Real Inverse Fast Fourier Transform(RIFFT) 00045 * for Q15, Q31, and floating-point data types. 00046 * 00047 * 00048 * \par Algorithm: 00049 * 00050 * <b>Real Fast Fourier Transform:</b> 00051 * \par 00052 * Real FFT of N-point is calculated using CFFT of N/2-point and Split RFFT process as shown below figure. 00053 * \par 00054 * \image html RFFT.gif "Real Fast Fourier Transform" 00055 * \par 00056 * The RFFT functions operate on blocks of input and output data and each call to the function processes 00057 * <code>fftLenR</code> samples through the transform. <code>pSrc</code> points to input array containing <code>fftLenR</code> values. 00058 * <code>pDst</code> points to output array containing <code>2*fftLenR</code> values. \n 00059 * Input for real FFT is in the order of 00060 * <pre>{real[0], real[1], real[2], real[3], ..}</pre> 00061 * Output for real FFT is complex and are in the order of 00062 * <pre>{real(0), imag(0), real(1), imag(1), ...}</pre> 00063 * 00064 * <b>Real Inverse Fast Fourier Transform:</b> 00065 * \par 00066 * Real IFFT of N-point is calculated using Split RIFFT process and CFFT of N/2-point as shown below figure. 00067 * \par 00068 * \image html RIFFT.gif "Real Inverse Fast Fourier Transform" 00069 * \par 00070 * The RIFFT functions operate on blocks of input and output data and each call to the function processes 00071 * <code>2*fftLenR</code> samples through the transform. <code>pSrc</code> points to input array containing <code>2*fftLenR</code> values. 00072 * <code>pDst</code> points to output array containing <code>fftLenR</code> values. \n 00073 * Input for real IFFT is complex and are in the order of 00074 * <pre>{real(0), imag(0), real(1), imag(1), ...}</pre> 00075 * Output for real IFFT is real and in the order of 00076 * <pre>{real[0], real[1], real[2], real[3], ..}</pre> 00077 * 00078 * \par Lengths supported by the transform: 00079 * \par 00080 * Real FFT/IFFT supports the lengths [128, 512, 2048], as it internally uses CFFT/CIFFT. 00081 * 00082 * \par Instance Structure 00083 * A separate instance structure must be defined for each Instance but the twiddle factors can be reused. 00084 * There are separate instance structure declarations for each of the 3 supported data types. 00085 * 00086 * \par Initialization Functions 00087 * There is also an associated initialization function for each data type. 00088 * The initialization function performs the following operations: 00089 * - Sets the values of the internal structure fields. 00090 * - Initializes twiddle factor tables. 00091 * - Initializes CFFT data structure fields. 00092 * \par 00093 * Use of the initialization function is optional. 00094 * However, if the initialization function is used, then the instance structure cannot be placed into a const data section. 00095 * To place an instance structure into a const data section, the instance structure must be manually initialized. 00096 * Manually initialize the instance structure as follows: 00097 * <pre> 00098 *arm_rfft_instance_f32 S = {fftLenReal, fftLenBy2, ifftFlagR, bitReverseFlagR, twidCoefRModifier, pTwiddleAReal, pTwiddleBReal, pCfft}; 00099 *arm_rfft_instance_q31 S = {fftLenReal, fftLenBy2, ifftFlagR, bitReverseFlagR, twidCoefRModifier, pTwiddleAReal, pTwiddleBReal, pCfft}; 00100 *arm_rfft_instance_q15 S = {fftLenReal, fftLenBy2, ifftFlagR, bitReverseFlagR, twidCoefRModifier, pTwiddleAReal, pTwiddleBReal, pCfft}; 00101 * </pre> 00102 * where <code>fftLenReal</code> length of RFFT/RIFFT; <code>fftLenBy2</code> length of CFFT/CIFFT. 00103 * <code>ifftFlagR</code> Flag for selection of RFFT or RIFFT(Set ifftFlagR to calculate RIFFT otherwise calculates RFFT); 00104 * <code>bitReverseFlagR</code> Flag for selection of output order(Set bitReverseFlagR to output in normal order otherwise output in bit reversed order); 00105 * <code>twidCoefRModifier</code> modifier for twiddle factor table which supports 128, 512, 2048 RFFT lengths with same table; 00106 * <code>pTwiddleAReal</code>points to A array of twiddle coefficients; <code>pTwiddleBReal</code>points to B array of twiddle coefficients; 00107 * <code>pCfft</code> points to the CFFT Instance structure. The CFFT structure also needs to be initialized, refer to arm_cfft_radix4_f32() for details regarding 00108 * static initialization of cfft structure. 00109 * 00110 * \par Fixed-Point Behavior 00111 * Care must be taken when using the fixed-point versions of the RFFT/RIFFT function. 00112 * Refer to the function specific documentation below for usage guidelines. 00113 */ 00114 00115 /*-------------------------------------------------------------------- 00116 * Internal functions prototypes 00117 *--------------------------------------------------------------------*/ 00118 00119 void arm_split_rfft_f32( 00120 float32_t * pSrc, 00121 uint32_t fftLen, 00122 float32_t * pATable, 00123 float32_t * pBTable, 00124 float32_t * pDst, 00125 uint32_t modifier); 00126 void arm_split_rifft_f32( 00127 float32_t * pSrc, 00128 uint32_t fftLen, 00129 float32_t * pATable, 00130 float32_t * pBTable, 00131 float32_t * pDst, 00132 uint32_t modifier); 00133 00134 /** 00135 * @addtogroup RFFT_RIFFT 00136 * @{ 00137 */ 00138 00139 /** 00140 * @brief Processing function for the floating-point RFFT/RIFFT. 00141 * @param[in] *S points to an instance of the floating-point RFFT/RIFFT structure. 00142 * @param[in] *pSrc points to the input buffer. 00143 * @param[out] *pDst points to the output buffer. 00144 * @return none. 00145 */ 00146 00147 void arm_rfft_f32( 00148 const arm_rfft_instance_f32 * S, 00149 float32_t * pSrc, 00150 float32_t * pDst) 00151 { 00152 const arm_cfft_radix4_instance_f32 *S_CFFT = S->pCfft; 00153 00154 00155 /* Calculation of Real IFFT of input */ 00156 if(S->ifftFlagR == 1u) 00157 { 00158 /* Real IFFT core process */ 00159 arm_split_rifft_f32(pSrc, S->fftLenBy2, S->pTwiddleAReal, 00160 S->pTwiddleBReal, pDst, S->twidCoefRModifier); 00161 00162 00163 /* Complex radix-4 IFFT process */ 00164 arm_radix4_butterfly_inverse_f32(pDst, S_CFFT->fftLen, 00165 S_CFFT->pTwiddle, 00166 S_CFFT->twidCoefModifier, 00167 S_CFFT->onebyfftLen); 00168 00169 /* Bit reversal process */ 00170 if(S->bitReverseFlagR == 1u) 00171 { 00172 arm_bitreversal_f32(pDst, S_CFFT->fftLen, 00173 S_CFFT->bitRevFactor, S_CFFT->pBitRevTable); 00174 } 00175 } 00176 else 00177 { 00178 00179 /* Calculation of RFFT of input */ 00180 00181 /* Complex radix-4 FFT process */ 00182 arm_radix4_butterfly_f32(pSrc, S_CFFT->fftLen, 00183 S_CFFT->pTwiddle, S_CFFT->twidCoefModifier); 00184 00185 /* Bit reversal process */ 00186 if(S->bitReverseFlagR == 1u) 00187 { 00188 arm_bitreversal_f32(pSrc, S_CFFT->fftLen, 00189 S_CFFT->bitRevFactor, S_CFFT->pBitRevTable); 00190 } 00191 00192 00193 /* Real FFT core process */ 00194 arm_split_rfft_f32(pSrc, S->fftLenBy2, S->pTwiddleAReal, 00195 S->pTwiddleBReal, pDst, S->twidCoefRModifier); 00196 } 00197 00198 } 00199 00200 /** 00201 * @} end of RFFT_RIFFT group 00202 */ 00203 00204 /** 00205 * @brief Core Real FFT process 00206 * @param[in] *pSrc points to the input buffer. 00207 * @param[in] fftLen length of FFT. 00208 * @param[in] *pATable points to the twiddle Coef A buffer. 00209 * @param[in] *pBTable points to the twiddle Coef B buffer. 00210 * @param[out] *pDst points to the output buffer. 00211 * @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. 00212 * @return none. 00213 */ 00214 00215 void arm_split_rfft_f32( 00216 float32_t * pSrc, 00217 uint32_t fftLen, 00218 float32_t * pATable, 00219 float32_t * pBTable, 00220 float32_t * pDst, 00221 uint32_t modifier) 00222 { 00223 uint32_t i; /* Loop Counter */ 00224 float32_t outR, outI; /* Temporary variables for output */ 00225 float32_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */ 00226 float32_t CoefA1, CoefA2, CoefB1; /* Temporary variables for twiddle coefficients */ 00227 float32_t *pDst1 = &pDst[2], *pDst2 = &pDst[(4u * fftLen) - 1u]; /* temp pointers for output buffer */ 00228 float32_t *pSrc1 = &pSrc[2], *pSrc2 = &pSrc[(2u * fftLen) - 1u]; /* temp pointers for input buffer */ 00229 00230 00231 pSrc[2u * fftLen] = pSrc[0]; 00232 pSrc[(2u * fftLen) + 1u] = pSrc[1]; 00233 00234 /* Init coefficient pointers */ 00235 pCoefA = &pATable[modifier * 2u]; 00236 pCoefB = &pBTable[modifier * 2u]; 00237 00238 i = fftLen - 1u; 00239 00240 while(i > 0u) 00241 { 00242 /* 00243 outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1] 00244 + pSrc[2 * n - 2 * i] * pBTable[2 * i] + 00245 pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]); 00246 */ 00247 00248 /* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] + 00249 pIn[2 * n - 2 * i] * pBTable[2 * i + 1] - 00250 pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); */ 00251 00252 /* read pATable[2 * i] */ 00253 CoefA1 = *pCoefA++; 00254 /* pATable[2 * i + 1] */ 00255 CoefA2 = *pCoefA; 00256 00257 /* pSrc[2 * i] * pATable[2 * i] */ 00258 outR = *pSrc1 * CoefA1; 00259 /* pSrc[2 * i] * CoefA2 */ 00260 outI = *pSrc1++ * CoefA2; 00261 00262 /* (pSrc[2 * i + 1] + pSrc[2 * fftLen - 2 * i + 1]) * CoefA2 */ 00263 outR -= (*pSrc1 + *pSrc2) * CoefA2; 00264 /* pSrc[2 * i + 1] * CoefA1 */ 00265 outI += *pSrc1++ * CoefA1; 00266 00267 CoefB1 = *pCoefB; 00268 00269 /* pSrc[2 * fftLen - 2 * i + 1] * CoefB1 */ 00270 outI -= *pSrc2-- * CoefB1; 00271 /* pSrc[2 * fftLen - 2 * i] * CoefA2 */ 00272 outI -= *pSrc2 * CoefA2; 00273 00274 /* pSrc[2 * fftLen - 2 * i] * CoefB1 */ 00275 outR += *pSrc2-- * CoefB1; 00276 00277 /* write output */ 00278 *pDst1++ = outR; 00279 *pDst1++ = outI; 00280 00281 /* write complex conjugate output */ 00282 *pDst2-- = -outI; 00283 *pDst2-- = outR; 00284 00285 /* update coefficient pointer */ 00286 pCoefB = pCoefB + (modifier * 2u); 00287 pCoefA = pCoefA + ((modifier * 2u) - 1u); 00288 00289 i--; 00290 00291 } 00292 00293 pDst[2u * fftLen] = pSrc[0] - pSrc[1]; 00294 pDst[(2u * fftLen) + 1u] = 0.0f; 00295 00296 pDst[0] = pSrc[0] + pSrc[1]; 00297 pDst[1] = 0.0f; 00298 00299 } 00300 00301 00302 /** 00303 * @brief Core Real IFFT process 00304 * @param[in] *pSrc points to the input buffer. 00305 * @param[in] fftLen length of FFT. 00306 * @param[in] *pATable points to the twiddle Coef A buffer. 00307 * @param[in] *pBTable points to the twiddle Coef B buffer. 00308 * @param[out] *pDst points to the output buffer. 00309 * @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. 00310 * @return none. 00311 */ 00312 00313 void arm_split_rifft_f32( 00314 float32_t * pSrc, 00315 uint32_t fftLen, 00316 float32_t * pATable, 00317 float32_t * pBTable, 00318 float32_t * pDst, 00319 uint32_t modifier) 00320 { 00321 float32_t outR, outI; /* Temporary variables for output */ 00322 float32_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */ 00323 float32_t CoefA1, CoefA2, CoefB1; /* Temporary variables for twiddle coefficients */ 00324 float32_t *pSrc1 = &pSrc[0], *pSrc2 = &pSrc[(2u * fftLen) + 1u]; 00325 00326 pCoefA = &pATable[0]; 00327 pCoefB = &pBTable[0]; 00328 00329 while(fftLen > 0u) 00330 { 00331 /* 00332 outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] + 00333 pIn[2 * n - 2 * i] * pBTable[2 * i] - 00334 pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]); 00335 00336 outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] - 00337 pIn[2 * n - 2 * i] * pBTable[2 * i + 1] - 00338 pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); 00339 00340 */ 00341 00342 CoefA1 = *pCoefA++; 00343 CoefA2 = *pCoefA; 00344 00345 /* outR = (pSrc[2 * i] * CoefA1 */ 00346 outR = *pSrc1 * CoefA1; 00347 00348 /* - pSrc[2 * i] * CoefA2 */ 00349 outI = -(*pSrc1++) * CoefA2; 00350 00351 /* (pSrc[2 * i + 1] + pSrc[2 * fftLen - 2 * i + 1]) * CoefA2 */ 00352 outR += (*pSrc1 + *pSrc2) * CoefA2; 00353 00354 /* pSrc[2 * i + 1] * CoefA1 */ 00355 outI += (*pSrc1++) * CoefA1; 00356 00357 CoefB1 = *pCoefB; 00358 00359 /* - pSrc[2 * fftLen - 2 * i + 1] * CoefB1 */ 00360 outI -= *pSrc2-- * CoefB1; 00361 00362 /* pSrc[2 * fftLen - 2 * i] * CoefB1 */ 00363 outR += *pSrc2 * CoefB1; 00364 00365 /* pSrc[2 * fftLen - 2 * i] * CoefA2 */ 00366 outI += *pSrc2-- * CoefA2; 00367 00368 /* write output */ 00369 *pDst++ = outR; 00370 *pDst++ = outI; 00371 00372 /* update coefficient pointer */ 00373 pCoefB = pCoefB + (modifier * 2u); 00374 pCoefA = pCoefA + ((modifier * 2u) - 1u); 00375 00376 /* Decrement loop count */ 00377 fftLen--; 00378 } 00379 00380 }
Generated on Tue Jul 12 2022 14:13:54 by 1.7.2