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_q15.c Source File

arm_rfft_q15.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_q15.c  
00009 *  
00010 * Description:  RFFT & RIFFT Q15 process function  
00011 *  
00012 *  
00013 * Target Processor: Cortex-M4/Cortex-M3
00014 *  
00015 * Version 1.0.3 2010/11/29 
00016 *    Re-organized the CMSIS folders and updated documentation.  
00017 *   
00018 * Version 1.0.2 2010/11/11  
00019 *    Documentation updated.   
00020 *  
00021 * Version 1.0.1 2010/10/05   
00022 *    Production release and review comments incorporated.  
00023 *  
00024 * Version 1.0.0 2010/09/20   
00025 *    Production release and review comments incorporated  
00026 *  
00027 * Version 0.0.7  2010/06/10   
00028 *    Misra-C changes done  
00029 * -------------------------------------------------------------------- */ 
00030  
00031  
00032 #include "arm_math.h" 
00033  
00034 /*--------------------------------------------------------------------  
00035 *       Internal functions prototypes  
00036 --------------------------------------------------------------------*/ 
00037  
00038 void arm_split_rfft_q15( 
00039   q15_t * pSrc, 
00040   uint32_t fftLen, 
00041   q15_t * pATable, 
00042   q15_t * pBTable, 
00043   q15_t * pDst, 
00044   uint32_t modifier); 
00045  
00046 void arm_split_rifft_q15( 
00047   q15_t * pSrc, 
00048   uint32_t fftLen, 
00049   q15_t * pATable, 
00050   q15_t * pBTable, 
00051   q15_t * pDst, 
00052   uint32_t modifier); 
00053  
00054 /**  
00055  * @addtogroup RFFT_RIFFT  
00056  * @{  
00057  */ 
00058  
00059 /**  
00060  * @brief Processing function for the Q15 RFFT/RIFFT. 
00061  * @param[in]  *S    points to an instance of the Q15 RFFT/RIFFT structure. 
00062  * @param[in]  *pSrc points to the input buffer. 
00063  * @param[out] *pDst points to the output buffer. 
00064  * @return none. 
00065  *  
00066  * \par Input an output formats: 
00067  * \par  
00068  * Internally input is downscaled by 2 for every stage to avoid saturations inside CFFT/CIFFT process.  
00069  * Hence the output format is different for different RFFT sizes.  
00070  * The input and output formats for different RFFT sizes and number of bits to upscale are mentioned in the tables below for RFFT and RIFFT: 
00071  * \par  
00072  * \image html RFFTQ15.gif "Input and Output Formats for Q15 RFFT"  
00073  * \par  
00074  * \image html RIFFTQ15.gif "Input and Output Formats for Q15 RIFFT"  
00075  */ 
00076  
00077 void arm_rfft_q15( 
00078   const arm_rfft_instance_q15 * S, 
00079   q15_t * pSrc, 
00080   q15_t * pDst) 
00081 { 
00082   const arm_cfft_radix4_instance_q15 *S_CFFT = S->pCfft; 
00083  
00084   /* Calculation of RIFFT of input */ 
00085   if(S->ifftFlagR == 1u) 
00086   { 
00087     /*  Real IFFT core process */ 
00088     arm_split_rifft_q15(pSrc, S->fftLenBy2, S->pTwiddleAReal, 
00089                         S->pTwiddleBReal, pDst, S->twidCoefRModifier); 
00090  
00091     /* Complex readix-4 IFFT process */ 
00092     arm_radix4_butterfly_inverse_q15(pDst, S_CFFT->fftLen, 
00093                                      S_CFFT->pTwiddle, 
00094                                      S_CFFT->twidCoefModifier); 
00095  
00096     /* Bit reversal process */ 
00097     if(S->bitReverseFlagR == 1u) 
00098     { 
00099       arm_bitreversal_q15(pDst, S_CFFT->fftLen, 
00100                           S_CFFT->bitRevFactor, S_CFFT->pBitRevTable); 
00101     } 
00102   } 
00103   else 
00104   { 
00105     /* Calculation of RFFT of input */ 
00106  
00107     /* Complex readix-4 FFT process */ 
00108     arm_radix4_butterfly_q15(pSrc, S_CFFT->fftLen, 
00109                              S_CFFT->pTwiddle, S_CFFT->twidCoefModifier); 
00110  
00111     /* Bit reversal process */ 
00112     if(S->bitReverseFlagR == 1u) 
00113     { 
00114       arm_bitreversal_q15(pSrc, S_CFFT->fftLen, 
00115                           S_CFFT->bitRevFactor, S_CFFT->pBitRevTable); 
00116     } 
00117  
00118     arm_split_rfft_q15(pSrc, S->fftLenBy2, S->pTwiddleAReal, 
00119                        S->pTwiddleBReal, pDst, S->twidCoefRModifier); 
00120   } 
00121  
00122 } 
00123  
00124   /**  
00125    * @} end of RFFT_RIFFT group  
00126    */ 
00127  
00128 /**  
00129  * @brief  Core Real FFT process  
00130  * @param  *pSrc                points to the input buffer. 
00131  * @param  fftLen               length of FFT. 
00132  * @param  *pATable             points to the A twiddle Coef buffer.  
00133  * @param  *pBTable             points to the B twiddle Coef buffer. 
00134  * @param  *pDst                points to the output buffer. 
00135  * @param  modifier             twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. 
00136  * @return none.  
00137  * The function implements a Real FFT  
00138  */ 
00139  
00140 void arm_split_rfft_q15( 
00141   q15_t * pSrc, 
00142   uint32_t fftLen, 
00143   q15_t * pATable, 
00144   q15_t * pBTable, 
00145   q15_t * pDst, 
00146   uint32_t modifier) 
00147 { 
00148   uint32_t i;                                    /* Loop Counter */ 
00149   q31_t outR, outI;                              /* Temporary variables for output */ 
00150   q15_t *pCoefA, *pCoefB;                        /* Temporary pointers for twiddle factors */ 
00151   q15_t *pSrc1, *pSrc2; 
00152  
00153  
00154   pSrc[2u * fftLen] = pSrc[0]; 
00155   pSrc[(2u * fftLen) + 1u] = pSrc[1]; 
00156  
00157   pCoefA = &pATable[modifier * 2u]; 
00158   pCoefB = &pBTable[modifier * 2u]; 
00159  
00160   pSrc1 = &pSrc[2]; 
00161   pSrc2 = &pSrc[(2u * fftLen) - 2u]; 
00162  
00163   i = 1u; 
00164  
00165   while(i < fftLen) 
00166   { 
00167     /*  
00168        outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1]  
00169        + pSrc[2 * n - 2 * i] * pBTable[2 * i] +  
00170        pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);  
00171      */ 
00172  
00173     /* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] +  
00174        pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -  
00175        pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); */ 
00176  
00177     /* pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1] */ 
00178     outR = __SMUSD(*__SIMD32(pSrc1), *__SIMD32(pCoefA)); 
00179  
00180     /* pSrc[2 * n - 2 * i] * pBTable[2 * i] +  
00181        pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]) */ 
00182     outR = __SMLAD(*__SIMD32(pSrc2), *__SIMD32(pCoefB), outR) >> 15u; 
00183  
00184     /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -  
00185        pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */ 
00186     outI = __SMUSDX(*__SIMD32(pSrc2)--, *__SIMD32(pCoefB)); 
00187  
00188     /* (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] */ 
00189     outI = __SMLADX(*__SIMD32(pSrc1)++, *__SIMD32(pCoefA), outI); 
00190  
00191     /* write output */ 
00192     pDst[2u * i] = (q15_t) outR; 
00193     pDst[(2u * i) + 1u] = outI >> 15u; 
00194  
00195     /* write complex conjugate output */ 
00196     pDst[(4u * fftLen) - (2u * i)] = (q15_t) outR; 
00197     pDst[((4u * fftLen) - (2u * i)) + 1u] = -(outI >> 15u); 
00198  
00199     /* update coefficient pointer */ 
00200     pCoefB = pCoefB + (2u * modifier); 
00201     pCoefA = pCoefA + (2u * modifier); 
00202  
00203     i++; 
00204  
00205   } 
00206  
00207   pDst[2u * fftLen] = pSrc[0] - pSrc[1]; 
00208   pDst[(2u * fftLen) + 1u] = 0; 
00209  
00210   pDst[0] = pSrc[0] + pSrc[1]; 
00211   pDst[1] = 0; 
00212  
00213 } 
00214  
00215  
00216 /**  
00217  * @brief  Core Real IFFT process  
00218  * @param[in]   *pSrc               points to the input buffer.  
00219  * @param[in]   fftLen              length of FFT. 
00220  * @param[in]   *pATable            points to the twiddle Coef A buffer. 
00221  * @param[in]   *pBTable            points to the twiddle Coef B buffer.  
00222  * @param[out]  *pDst               points to the output buffer. 
00223  * @param[in]   modifier            twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. 
00224  * @return none.  
00225  * The function implements a Real IFFT  
00226  */ 
00227  
00228 void arm_split_rifft_q15( 
00229   q15_t * pSrc, 
00230   uint32_t fftLen, 
00231   q15_t * pATable, 
00232   q15_t * pBTable, 
00233   q15_t * pDst, 
00234   uint32_t modifier) 
00235 { 
00236   uint32_t i;                                    /* Loop Counter */ 
00237   q31_t outR, outI;                              /* Temporary variables for output */ 
00238   q15_t *pCoefA, *pCoefB;                        /* Temporary pointers for twiddle factors */ 
00239   q15_t *pSrc1, *pSrc2; 
00240   q15_t *pDst1 = &pDst[0]; 
00241  
00242   pCoefA = &pATable[0]; 
00243   pCoefB = &pBTable[0]; 
00244  
00245   pSrc1 = &pSrc[0]; 
00246   pSrc2 = &pSrc[2u * fftLen]; 
00247  
00248   i = fftLen; 
00249  
00250   while(i > 0u) 
00251   { 
00252  
00253     /*  
00254        outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +  
00255        pIn[2 * n - 2 * i] * pBTable[2 * i] -  
00256        pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);  
00257  
00258        outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] -  
00259        pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -  
00260        pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);  
00261  
00262      */ 
00263  
00264     /* pIn[2 * n - 2 * i] * pBTable[2 * i] -  
00265        pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]) */ 
00266     outR = __SMUSD(*__SIMD32(pSrc2), *__SIMD32(pCoefB)); 
00267  
00268     /* pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +  
00269        pIn[2 * n - 2 * i] * pBTable[2 * i] */ 
00270     outR = __SMLAD(*__SIMD32(pSrc1), *__SIMD32(pCoefA), outR) >> 15u; 
00271  
00272     /*  
00273        -pIn[2 * n - 2 * i] * pBTable[2 * i + 1] +  
00274        pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */ 
00275     outI = __SMUADX(*__SIMD32(pSrc2)--, *__SIMD32(pCoefB)); 
00276  
00277     /* pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] */ 
00278     outI = __SMLSDX(*__SIMD32(pCoefA), *__SIMD32(pSrc1)++, -outI); 
00279  
00280     /* write output */ 
00281     *__SIMD32(pDst1)++ = 
00282       (q31_t) ((outI << 1u) & 0xFFFF0000) | (outR & 0x0000FFFF); 
00283  
00284     /* update coefficient pointer */ 
00285     pCoefB = pCoefB + (2u * modifier); 
00286     pCoefA = pCoefA + (2u * modifier); 
00287  
00288     i--; 
00289  
00290   } 
00291  
00292 }