Robert Lopez / CMSIS5
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_rfft_q31.c Source File

arm_rfft_q31.c

00001 /* ----------------------------------------------------------------------
00002  * Project:      CMSIS DSP Library
00003  * Title:        arm_rfft_q31.c
00004  * Description:  FFT & RIFFT Q31 process function
00005  *
00006  * $Date:        27. January 2017
00007  * $Revision:    V.1.5.1
00008  *
00009  * Target Processor: Cortex-M cores
00010  * -------------------------------------------------------------------- */
00011 /*
00012  * Copyright (C) 2010-2017 ARM Limited or its affiliates. All rights reserved.
00013  *
00014  * SPDX-License-Identifier: Apache-2.0
00015  *
00016  * Licensed under the Apache License, Version 2.0 (the License); you may
00017  * not use this file except in compliance with the License.
00018  * You may obtain a copy of the License at
00019  *
00020  * www.apache.org/licenses/LICENSE-2.0
00021  *
00022  * Unless required by applicable law or agreed to in writing, software
00023  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00024  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00025  * See the License for the specific language governing permissions and
00026  * limitations under the License.
00027  */
00028 
00029 #include "arm_math.h"
00030 
00031 /* ----------------------------------------------------------------------
00032  * Internal functions prototypes
00033  * -------------------------------------------------------------------- */
00034 
00035 void arm_split_rfft_q31(
00036     q31_t * pSrc,
00037     uint32_t fftLen,
00038     q31_t * pATable,
00039     q31_t * pBTable,
00040     q31_t * pDst,
00041     uint32_t modifier);
00042 
00043 void arm_split_rifft_q31(
00044     q31_t * pSrc,
00045     uint32_t fftLen,
00046     q31_t * pATable,
00047     q31_t * pBTable,
00048     q31_t * pDst,
00049     uint32_t modifier);
00050 
00051 /**
00052 * @addtogroup RealFFT
00053 * @{
00054 */
00055 
00056 /**
00057 * @brief Processing function for the Q31 RFFT/RIFFT.
00058 * @param[in]  *S    points to an instance of the Q31 RFFT/RIFFT structure.
00059 * @param[in]  *pSrc points to the input buffer.
00060 * @param[out] *pDst points to the output buffer.
00061 * @return none.
00062 *
00063 * \par Input an output formats:
00064 * \par
00065 * Internally input is downscaled by 2 for every stage to avoid saturations inside CFFT/CIFFT process.
00066 * Hence the output format is different for different RFFT sizes.
00067 * 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:
00068 * \par
00069 * \image html RFFTQ31.gif "Input and Output Formats for Q31 RFFT"
00070 *
00071 * \par
00072 * \image html RIFFTQ31.gif "Input and Output Formats for Q31 RIFFT"
00073 */
00074 void arm_rfft_q31(
00075     const arm_rfft_instance_q31 * S,
00076     q31_t * pSrc,
00077     q31_t * pDst)
00078 {
00079     const arm_cfft_instance_q31 *S_CFFT = S->pCfft;
00080     uint32_t i;
00081     uint32_t L2 = S->fftLenReal >> 1;
00082 
00083     /* Calculation of RIFFT of input */
00084     if (S->ifftFlagR == 1U)
00085     {
00086         /*  Real IFFT core process */
00087         arm_split_rifft_q31(pSrc, L2, S->pTwiddleAReal,
00088                             S->pTwiddleBReal, pDst, S->twidCoefRModifier);
00089 
00090         /* Complex IFFT process */
00091         arm_cfft_q31(S_CFFT, pDst, S->ifftFlagR, S->bitReverseFlagR);
00092 
00093         for(i=0;i<S->fftLenReal;i++)
00094         {
00095             pDst[i] = pDst[i] << 1;
00096         }
00097     }
00098     else
00099     {
00100         /* Calculation of RFFT of input */
00101 
00102         /* Complex FFT process */
00103         arm_cfft_q31(S_CFFT, pSrc, S->ifftFlagR, S->bitReverseFlagR);
00104 
00105         /*  Real FFT core process */
00106         arm_split_rfft_q31(pSrc, L2, S->pTwiddleAReal,
00107                             S->pTwiddleBReal, pDst, S->twidCoefRModifier);
00108     }
00109 }
00110 
00111 /**
00112 * @} end of RealFFT group
00113 */
00114 
00115 /**
00116 * @brief  Core Real FFT process
00117 * @param[in]   *pSrc                points to the input buffer.
00118 * @param[in]   fftLen               length of FFT.
00119 * @param[in]   *pATable             points to the twiddle Coef A buffer.
00120 * @param[in]   *pBTable             points to the twiddle Coef B buffer.
00121 * @param[out]  *pDst                points to the output buffer.
00122 * @param[in]   modifier             twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
00123 * @return none.
00124 */
00125 void arm_split_rfft_q31(
00126     q31_t * pSrc,
00127     uint32_t fftLen,
00128     q31_t * pATable,
00129     q31_t * pBTable,
00130     q31_t * pDst,
00131     uint32_t modifier)
00132 {
00133     uint32_t i;                                    /* Loop Counter */
00134     q31_t outR, outI;                              /* Temporary variables for output */
00135     q31_t *pCoefA, *pCoefB;                        /* Temporary pointers for twiddle factors */
00136     q31_t CoefA1, CoefA2, CoefB1;                  /* Temporary variables for twiddle coefficients */
00137     q31_t *pOut1 = &pDst[2], *pOut2 = &pDst[(4U * fftLen) - 1U];
00138     q31_t *pIn1 = &pSrc[2], *pIn2 = &pSrc[(2U * fftLen) - 1U];
00139 
00140     /* Init coefficient pointers */
00141     pCoefA = &pATable[modifier * 2U];
00142     pCoefB = &pBTable[modifier * 2U];
00143 
00144     i = fftLen - 1U;
00145 
00146     while (i > 0U)
00147     {
00148         /*
00149         outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1]
00150         + pSrc[2 * n - 2 * i] * pBTable[2 * i] +
00151         pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
00152         */
00153 
00154         /* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] +
00155         pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
00156         pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); */
00157 
00158         CoefA1 = *pCoefA++;
00159         CoefA2 = *pCoefA;
00160 
00161         /* outR = (pSrc[2 * i] * pATable[2 * i] */
00162         mult_32x32_keep32_R(outR, *pIn1, CoefA1);
00163 
00164         /* outI = pIn[2 * i] * pATable[2 * i + 1] */
00165         mult_32x32_keep32_R(outI, *pIn1++, CoefA2);
00166 
00167         /* - pSrc[2 * i + 1] * pATable[2 * i + 1] */
00168         multSub_32x32_keep32_R(outR, *pIn1, CoefA2);
00169 
00170         /* (pIn[2 * i + 1] * pATable[2 * i] */
00171         multAcc_32x32_keep32_R(outI, *pIn1++, CoefA1);
00172 
00173         /* pSrc[2 * n - 2 * i] * pBTable[2 * i]  */
00174         multSub_32x32_keep32_R(outR, *pIn2, CoefA2);
00175         CoefB1 = *pCoefB;
00176 
00177         /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
00178         multSub_32x32_keep32_R(outI, *pIn2--, CoefB1);
00179 
00180         /* pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
00181         multAcc_32x32_keep32_R(outR, *pIn2, CoefB1);
00182 
00183         /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
00184         multSub_32x32_keep32_R(outI, *pIn2--, CoefA2);
00185 
00186         /* write output */
00187         *pOut1++ = outR;
00188         *pOut1++ = outI;
00189 
00190         /* write complex conjugate output */
00191         *pOut2-- = -outI;
00192         *pOut2-- = outR;
00193 
00194         /* update coefficient pointer */
00195         pCoefB = pCoefB + (modifier * 2U);
00196         pCoefA = pCoefA + ((modifier * 2U) - 1U);
00197 
00198         i--;
00199     }
00200     pDst[2U * fftLen] = (pSrc[0] - pSrc[1]) >> 1;
00201     pDst[(2U * fftLen) + 1U] = 0;
00202 
00203     pDst[0] = (pSrc[0] + pSrc[1]) >> 1;
00204     pDst[1] = 0;
00205 }
00206 
00207 /**
00208 * @brief  Core Real IFFT process
00209 * @param[in]   *pSrc                points to the input buffer.
00210 * @param[in]   fftLen               length of FFT.
00211 * @param[in]   *pATable             points to the twiddle Coef A buffer.
00212 * @param[in]   *pBTable             points to the twiddle Coef B buffer.
00213 * @param[out]  *pDst                points to the output buffer.
00214 * @param[in]   modifier             twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
00215 * @return none.
00216 */
00217 void arm_split_rifft_q31(
00218     q31_t * pSrc,
00219     uint32_t fftLen,
00220     q31_t * pATable,
00221     q31_t * pBTable,
00222     q31_t * pDst,
00223     uint32_t modifier)
00224 {
00225     q31_t outR, outI;                              /* Temporary variables for output */
00226     q31_t *pCoefA, *pCoefB;                        /* Temporary pointers for twiddle factors */
00227     q31_t CoefA1, CoefA2, CoefB1;                  /* Temporary variables for twiddle coefficients */
00228     q31_t *pIn1 = &pSrc[0], *pIn2 = &pSrc[(2U * fftLen) + 1U];
00229 
00230     pCoefA = &pATable[0];
00231     pCoefB = &pBTable[0];
00232 
00233     while (fftLen > 0U)
00234     {
00235         /*
00236         outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +
00237         pIn[2 * n - 2 * i] * pBTable[2 * i] -
00238         pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
00239 
00240         outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] -
00241         pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
00242         pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);
00243         */
00244         CoefA1 = *pCoefA++;
00245         CoefA2 = *pCoefA;
00246 
00247         /* outR = (pIn[2 * i] * pATable[2 * i] */
00248         mult_32x32_keep32_R(outR, *pIn1, CoefA1);
00249 
00250         /* - pIn[2 * i] * pATable[2 * i + 1] */
00251         mult_32x32_keep32_R(outI, *pIn1++, -CoefA2);
00252 
00253         /* pIn[2 * i + 1] * pATable[2 * i + 1] */
00254         multAcc_32x32_keep32_R(outR, *pIn1, CoefA2);
00255 
00256         /* pIn[2 * i + 1] * pATable[2 * i] */
00257         multAcc_32x32_keep32_R(outI, *pIn1++, CoefA1);
00258 
00259         /* pIn[2 * n - 2 * i] * pBTable[2 * i] */
00260         multAcc_32x32_keep32_R(outR, *pIn2, CoefA2);
00261         CoefB1 = *pCoefB;
00262 
00263         /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
00264         multSub_32x32_keep32_R(outI, *pIn2--, CoefB1);
00265 
00266         /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
00267         multAcc_32x32_keep32_R(outR, *pIn2, CoefB1);
00268 
00269         /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
00270         multAcc_32x32_keep32_R(outI, *pIn2--, CoefA2);
00271 
00272         /* write output */
00273         *pDst++ = outR;
00274         *pDst++ = outI;
00275 
00276         /* update coefficient pointer */
00277         pCoefB = pCoefB + (modifier * 2U);
00278         pCoefA = pCoefA + ((modifier * 2U) - 1U);
00279 
00280         /* Decrement loop count */
00281         fftLen--;
00282     }
00283 }
00284