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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_rfft_f32.c Source File

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 }