Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Tue Jul 12 2022 16:47:28 by
