CMSIS DSP library

Dependents:   performance_timer Surfboard_ gps2rtty Capstone ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_rfft_q31.c Source File

arm_rfft_q31.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_rfft_q31.c    
00009 *    
00010 * Description:  RFFT & RIFFT Q31 process function    
00011 *    
00012 *    
00013 * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
00014 *  
00015 * Redistribution and use in source and binary forms, with or without 
00016 * modification, are permitted provided that the following conditions
00017 * are met:
00018 *   - Redistributions of source code must retain the above copyright
00019 *     notice, this list of conditions and the following disclaimer.
00020 *   - Redistributions in binary form must reproduce the above copyright
00021 *     notice, this list of conditions and the following disclaimer in
00022 *     the documentation and/or other materials provided with the 
00023 *     distribution.
00024 *   - Neither the name of ARM LIMITED nor the names of its contributors
00025 *     may be used to endorse or promote products derived from this
00026 *     software without specific prior written permission.
00027 *
00028 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00029 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00030 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00031 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
00032 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00033 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00034 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00035 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00036 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00037 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00038 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00039 * POSSIBILITY OF SUCH DAMAGE.    
00040 * -------------------------------------------------------------------- */
00041 
00042 #include "arm_math.h"
00043 
00044 /*--------------------------------------------------------------------    
00045 *       Internal functions prototypes    
00046 --------------------------------------------------------------------*/
00047 
00048 void arm_split_rfft_q31(
00049     q31_t * pSrc,
00050     uint32_t fftLen,
00051     q31_t * pATable,
00052     q31_t * pBTable,
00053     q31_t * pDst,
00054     uint32_t modifier);
00055 
00056 void arm_split_rifft_q31(
00057     q31_t * pSrc,
00058     uint32_t fftLen,
00059     q31_t * pATable,
00060     q31_t * pBTable,
00061     q31_t * pDst,
00062     uint32_t modifier);
00063 
00064 /**    
00065 * @addtogroup RealFFT    
00066 * @{    
00067 */
00068 
00069 /**    
00070 * @brief Processing function for the Q31 RFFT/RIFFT.   
00071 * @param[in]  *S    points to an instance of the Q31 RFFT/RIFFT structure.   
00072 * @param[in]  *pSrc points to the input buffer.   
00073 * @param[out] *pDst points to the output buffer.   
00074 * @return none.   
00075 *    
00076 * \par Input an output formats:   
00077 * \par    
00078 * Internally input is downscaled by 2 for every stage to avoid saturations inside CFFT/CIFFT process.   
00079 * Hence the output format is different for different RFFT sizes.    
00080 * 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:   
00081 * \par    
00082 * \image html RFFTQ31.gif "Input and Output Formats for Q31 RFFT"    
00083 *    
00084 * \par    
00085 * \image html RIFFTQ31.gif "Input and Output Formats for Q31 RIFFT"    
00086 */
00087 void arm_rfft_q31(
00088     const arm_rfft_instance_q31 * S,
00089     q31_t * pSrc,
00090     q31_t * pDst)
00091 {
00092     const arm_cfft_instance_q31 *S_CFFT = S->pCfft;
00093     uint32_t i;
00094     uint32_t L2 = S->fftLenReal >> 1;
00095 
00096     /* Calculation of RIFFT of input */
00097     if(S->ifftFlagR == 1u)
00098     {
00099         /*  Real IFFT core process */
00100         arm_split_rifft_q31(pSrc, L2, S->pTwiddleAReal,
00101                             S->pTwiddleBReal, pDst, S->twidCoefRModifier);
00102         
00103         /* Complex IFFT process */
00104         arm_cfft_q31(S_CFFT, pDst, S->ifftFlagR, S->bitReverseFlagR);
00105         
00106         for(i=0;i<S->fftLenReal;i++)
00107         {
00108             pDst[i] = pDst[i] << 1;
00109         }
00110     }
00111     else
00112     {
00113         /* Calculation of RFFT of input */
00114         
00115         /* Complex FFT process */
00116         arm_cfft_q31(S_CFFT, pSrc, S->ifftFlagR, S->bitReverseFlagR);
00117 
00118         /*  Real FFT core process */
00119         arm_split_rfft_q31(pSrc, L2, S->pTwiddleAReal,
00120                             S->pTwiddleBReal, pDst, S->twidCoefRModifier);
00121     }
00122 }
00123 
00124 /**    
00125 * @} end of RealFFT group    
00126 */
00127 
00128 /**    
00129 * @brief  Core Real FFT process    
00130 * @param[in]   *pSrc                points to the input buffer.    
00131 * @param[in]   fftLen               length of FFT.   
00132 * @param[in]   *pATable             points to the twiddle Coef A buffer.    
00133 * @param[in]   *pBTable             points to the twiddle Coef B buffer.    
00134 * @param[out]  *pDst                points to the output buffer.    
00135 * @param[in]   modifier             twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.   
00136 * @return none.    
00137 */
00138 void arm_split_rfft_q31(
00139     q31_t * pSrc,
00140     uint32_t fftLen,
00141     q31_t * pATable,
00142     q31_t * pBTable,
00143     q31_t * pDst,
00144     uint32_t modifier)
00145 {
00146     uint32_t i;                                    /* Loop Counter */
00147     q31_t outR, outI;                              /* Temporary variables for output */
00148     q31_t *pCoefA, *pCoefB;                        /* Temporary pointers for twiddle factors */
00149     q31_t CoefA1, CoefA2, CoefB1;                  /* Temporary variables for twiddle coefficients */
00150     q31_t *pOut1 = &pDst[2], *pOut2 = &pDst[(4u * fftLen) - 1u];
00151     q31_t *pIn1 = &pSrc[2], *pIn2 = &pSrc[(2u * fftLen) - 1u];
00152 
00153     /* Init coefficient pointers */
00154     pCoefA = &pATable[modifier * 2u];
00155     pCoefB = &pBTable[modifier * 2u];
00156 
00157     i = fftLen - 1u;
00158 
00159     while(i > 0u)
00160     {
00161         /*    
00162         outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1]    
00163         + pSrc[2 * n - 2 * i] * pBTable[2 * i] +    
00164         pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);    
00165         */
00166 
00167         /* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] +    
00168         pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -    
00169         pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); */
00170 
00171         CoefA1 = *pCoefA++;
00172         CoefA2 = *pCoefA;
00173 
00174         /* outR = (pSrc[2 * i] * pATable[2 * i] */    
00175         mult_32x32_keep32_R(outR, *pIn1, CoefA1);
00176 
00177         /* outI = pIn[2 * i] * pATable[2 * i + 1] */
00178         mult_32x32_keep32_R(outI, *pIn1++, CoefA2);
00179 
00180         /* - pSrc[2 * i + 1] * pATable[2 * i + 1] */
00181         multSub_32x32_keep32_R(outR, *pIn1, CoefA2);
00182 
00183         /* (pIn[2 * i + 1] * pATable[2 * i] */
00184         multAcc_32x32_keep32_R(outI, *pIn1++, CoefA1);
00185 
00186         /* pSrc[2 * n - 2 * i] * pBTable[2 * i]  */
00187         multSub_32x32_keep32_R(outR, *pIn2, CoefA2);
00188         CoefB1 = *pCoefB;
00189 
00190         /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
00191         multSub_32x32_keep32_R(outI, *pIn2--, CoefB1);
00192 
00193         /* pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
00194         multAcc_32x32_keep32_R(outR, *pIn2, CoefB1);
00195 
00196         /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
00197         multSub_32x32_keep32_R(outI, *pIn2--, CoefA2);
00198 
00199         /* write output */
00200         *pOut1++ = outR;
00201         *pOut1++ = outI;
00202 
00203         /* write complex conjugate output */
00204         *pOut2-- = -outI;
00205         *pOut2-- = outR;
00206 
00207         /* update coefficient pointer */
00208         pCoefB = pCoefB + (modifier * 2u);
00209         pCoefA = pCoefA + ((modifier * 2u) - 1u);
00210 
00211         i--;
00212     }
00213     pDst[2u * fftLen] = (pSrc[0] - pSrc[1]) >> 1;
00214     pDst[(2u * fftLen) + 1u] = 0;
00215 
00216     pDst[0] = (pSrc[0] + pSrc[1]) >> 1;
00217     pDst[1] = 0;
00218 }
00219 
00220 /**    
00221 * @brief  Core Real IFFT process    
00222 * @param[in]   *pSrc                points to the input buffer.   
00223 * @param[in]   fftLen               length of FFT.    
00224 * @param[in]   *pATable             points to the twiddle Coef A buffer.   
00225 * @param[in]   *pBTable             points to the twiddle Coef B buffer.    
00226 * @param[out]  *pDst                points to the output buffer.   
00227 * @param[in]   modifier             twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.   
00228 * @return none.    
00229 */
00230 void arm_split_rifft_q31(
00231     q31_t * pSrc,
00232     uint32_t fftLen,
00233     q31_t * pATable,
00234     q31_t * pBTable,
00235     q31_t * pDst,
00236     uint32_t modifier)
00237 {
00238     q31_t outR, outI;                              /* Temporary variables for output */
00239     q31_t *pCoefA, *pCoefB;                        /* Temporary pointers for twiddle factors */
00240     q31_t CoefA1, CoefA2, CoefB1;                  /* Temporary variables for twiddle coefficients */
00241     q31_t *pIn1 = &pSrc[0], *pIn2 = &pSrc[(2u * fftLen) + 1u];
00242 
00243     pCoefA = &pATable[0];
00244     pCoefB = &pBTable[0];
00245 
00246     while(fftLen > 0u)
00247     {
00248         /*    
00249         outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +    
00250         pIn[2 * n - 2 * i] * pBTable[2 * i] -    
00251         pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);    
00252 
00253         outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] -    
00254         pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -    
00255         pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);   
00256         */
00257         CoefA1 = *pCoefA++;
00258         CoefA2 = *pCoefA;
00259 
00260         /* outR = (pIn[2 * i] * pATable[2 * i] */
00261         mult_32x32_keep32_R(outR, *pIn1, CoefA1);
00262 
00263         /* - pIn[2 * i] * pATable[2 * i + 1] */
00264         mult_32x32_keep32_R(outI, *pIn1++, -CoefA2);
00265         
00266         /* pIn[2 * i + 1] * pATable[2 * i + 1] */
00267         multAcc_32x32_keep32_R(outR, *pIn1, CoefA2);
00268 
00269         /* pIn[2 * i + 1] * pATable[2 * i] */
00270         multAcc_32x32_keep32_R(outI, *pIn1++, CoefA1);
00271 
00272         /* pIn[2 * n - 2 * i] * pBTable[2 * i] */
00273         multAcc_32x32_keep32_R(outR, *pIn2, CoefA2);
00274         CoefB1 = *pCoefB;
00275 
00276         /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
00277         multSub_32x32_keep32_R(outI, *pIn2--, CoefB1);
00278 
00279         /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
00280         multAcc_32x32_keep32_R(outR, *pIn2, CoefB1);
00281 
00282         /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
00283         multAcc_32x32_keep32_R(outI, *pIn2--, CoefA2);
00284 
00285         /* write output */
00286         *pDst++ = outR;
00287         *pDst++ = outI;
00288 
00289         /* update coefficient pointer */
00290         pCoefB = pCoefB + (modifier * 2u);
00291         pCoefA = pCoefA + ((modifier * 2u) - 1u);
00292 
00293         /* Decrement loop count */
00294         fftLen--;
00295     }
00296 }