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_q15.c
00001 /* ---------------------------------------------------------------------- 00002 * Project: CMSIS DSP Library 00003 * Title: arm_rfft_q15.c 00004 * Description: RFFT & RIFFT Q15 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_q15( 00036 q15_t * pSrc, 00037 uint32_t fftLen, 00038 q15_t * pATable, 00039 q15_t * pBTable, 00040 q15_t * pDst, 00041 uint32_t modifier); 00042 00043 void arm_split_rifft_q15( 00044 q15_t * pSrc, 00045 uint32_t fftLen, 00046 q15_t * pATable, 00047 q15_t * pBTable, 00048 q15_t * pDst, 00049 uint32_t modifier); 00050 00051 /** 00052 * @addtogroup RealFFT 00053 * @{ 00054 */ 00055 00056 /** 00057 * @brief Processing function for the Q15 RFFT/RIFFT. 00058 * @param[in] *S points to an instance of the Q15 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 RFFTQ15.gif "Input and Output Formats for Q15 RFFT" 00070 * \par 00071 * \image html RIFFTQ15.gif "Input and Output Formats for Q15 RIFFT" 00072 */ 00073 00074 void arm_rfft_q15( 00075 const arm_rfft_instance_q15 * S, 00076 q15_t * pSrc, 00077 q15_t * pDst) 00078 { 00079 const arm_cfft_instance_q15 *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_q15(pSrc, L2, S->pTwiddleAReal, 00088 S->pTwiddleBReal, pDst, S->twidCoefRModifier); 00089 00090 /* Complex IFFT process */ 00091 arm_cfft_q15(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_q15(S_CFFT, pSrc, S->ifftFlagR, S->bitReverseFlagR); 00104 00105 /* Real FFT core process */ 00106 arm_split_rfft_q15(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 *pSrc points to the input buffer. 00118 * @param fftLen length of FFT. 00119 * @param *pATable points to the A twiddle Coef buffer. 00120 * @param *pBTable points to the B twiddle Coef buffer. 00121 * @param *pDst points to the output buffer. 00122 * @param modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. 00123 * @return none. 00124 * The function implements a Real FFT 00125 */ 00126 00127 void arm_split_rfft_q15( 00128 q15_t * pSrc, 00129 uint32_t fftLen, 00130 q15_t * pATable, 00131 q15_t * pBTable, 00132 q15_t * pDst, 00133 uint32_t modifier) 00134 { 00135 uint32_t i; /* Loop Counter */ 00136 q31_t outR, outI; /* Temporary variables for output */ 00137 q15_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */ 00138 q15_t *pSrc1, *pSrc2; 00139 #if defined (ARM_MATH_DSP) 00140 q15_t *pD1, *pD2; 00141 #endif 00142 00143 // pSrc[2U * fftLen] = pSrc[0]; 00144 // pSrc[(2U * fftLen) + 1U] = pSrc[1]; 00145 00146 pCoefA = &pATable[modifier * 2U]; 00147 pCoefB = &pBTable[modifier * 2U]; 00148 00149 pSrc1 = &pSrc[2]; 00150 pSrc2 = &pSrc[(2U * fftLen) - 2U]; 00151 00152 #if defined (ARM_MATH_DSP) 00153 00154 /* Run the below code for Cortex-M4 and Cortex-M3 */ 00155 i = 1U; 00156 pD1 = pDst + 2; 00157 pD2 = pDst + (4U * fftLen) - 2; 00158 00159 for(i = fftLen - 1; i > 0; i--) 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 00172 #ifndef ARM_MATH_BIG_ENDIAN 00173 00174 /* pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1] */ 00175 outR = __SMUSD(*__SIMD32(pSrc1), *__SIMD32(pCoefA)); 00176 00177 #else 00178 00179 /* -(pSrc[2 * i + 1] * pATable[2 * i + 1] - pSrc[2 * i] * pATable[2 * i]) */ 00180 outR = -(__SMUSD(*__SIMD32(pSrc1), *__SIMD32(pCoefA))); 00181 00182 #endif /* #ifndef ARM_MATH_BIG_ENDIAN */ 00183 00184 /* pSrc[2 * n - 2 * i] * pBTable[2 * i] + 00185 pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]) */ 00186 outR = __SMLAD(*__SIMD32(pSrc2), *__SIMD32(pCoefB), outR) >> 16U; 00187 00188 /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] - 00189 pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */ 00190 00191 #ifndef ARM_MATH_BIG_ENDIAN 00192 00193 outI = __SMUSDX(*__SIMD32(pSrc2)--, *__SIMD32(pCoefB)); 00194 00195 #else 00196 00197 outI = __SMUSDX(*__SIMD32(pCoefB), *__SIMD32(pSrc2)--); 00198 00199 #endif /* #ifndef ARM_MATH_BIG_ENDIAN */ 00200 00201 /* (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] */ 00202 outI = __SMLADX(*__SIMD32(pSrc1)++, *__SIMD32(pCoefA), outI); 00203 00204 /* write output */ 00205 *pD1++ = (q15_t) outR; 00206 *pD1++ = outI >> 16U; 00207 00208 /* write complex conjugate output */ 00209 pD2[0] = (q15_t) outR; 00210 pD2[1] = -(outI >> 16U); 00211 pD2 -= 2; 00212 00213 /* update coefficient pointer */ 00214 pCoefB = pCoefB + (2U * modifier); 00215 pCoefA = pCoefA + (2U * modifier); 00216 } 00217 00218 pDst[2U * fftLen] = (pSrc[0] - pSrc[1]) >> 1; 00219 pDst[(2U * fftLen) + 1U] = 0; 00220 00221 pDst[0] = (pSrc[0] + pSrc[1]) >> 1; 00222 pDst[1] = 0; 00223 00224 #else 00225 00226 /* Run the below code for Cortex-M0 */ 00227 i = 1U; 00228 00229 while (i < fftLen) 00230 { 00231 /* 00232 outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1] 00233 + pSrc[2 * n - 2 * i] * pBTable[2 * i] + 00234 pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]); 00235 */ 00236 00237 outR = *pSrc1 * *pCoefA; 00238 outR = outR - (*(pSrc1 + 1) * *(pCoefA + 1)); 00239 outR = outR + (*pSrc2 * *pCoefB); 00240 outR = (outR + (*(pSrc2 + 1) * *(pCoefB + 1))) >> 16; 00241 00242 00243 /* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] + 00244 pIn[2 * n - 2 * i] * pBTable[2 * i + 1] - 00245 pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); 00246 */ 00247 00248 outI = *pSrc2 * *(pCoefB + 1); 00249 outI = outI - (*(pSrc2 + 1) * *pCoefB); 00250 outI = outI + (*(pSrc1 + 1) * *pCoefA); 00251 outI = outI + (*pSrc1 * *(pCoefA + 1)); 00252 00253 /* update input pointers */ 00254 pSrc1 += 2U; 00255 pSrc2 -= 2U; 00256 00257 /* write output */ 00258 pDst[2U * i] = (q15_t) outR; 00259 pDst[(2U * i) + 1U] = outI >> 16U; 00260 00261 /* write complex conjugate output */ 00262 pDst[(4U * fftLen) - (2U * i)] = (q15_t) outR; 00263 pDst[((4U * fftLen) - (2U * i)) + 1U] = -(outI >> 16U); 00264 00265 /* update coefficient pointer */ 00266 pCoefB = pCoefB + (2U * modifier); 00267 pCoefA = pCoefA + (2U * modifier); 00268 00269 i++; 00270 } 00271 00272 pDst[2U * fftLen] = (pSrc[0] - pSrc[1]) >> 1; 00273 pDst[(2U * fftLen) + 1U] = 0; 00274 00275 pDst[0] = (pSrc[0] + pSrc[1]) >> 1; 00276 pDst[1] = 0; 00277 00278 #endif /* #if defined (ARM_MATH_DSP) */ 00279 } 00280 00281 00282 /** 00283 * @brief Core Real IFFT process 00284 * @param[in] *pSrc points to the input buffer. 00285 * @param[in] fftLen length of FFT. 00286 * @param[in] *pATable points to the twiddle Coef A buffer. 00287 * @param[in] *pBTable points to the twiddle Coef B buffer. 00288 * @param[out] *pDst points to the output buffer. 00289 * @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. 00290 * @return none. 00291 * The function implements a Real IFFT 00292 */ 00293 void arm_split_rifft_q15( 00294 q15_t * pSrc, 00295 uint32_t fftLen, 00296 q15_t * pATable, 00297 q15_t * pBTable, 00298 q15_t * pDst, 00299 uint32_t modifier) 00300 { 00301 uint32_t i; /* Loop Counter */ 00302 q31_t outR, outI; /* Temporary variables for output */ 00303 q15_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */ 00304 q15_t *pSrc1, *pSrc2; 00305 q15_t *pDst1 = &pDst[0]; 00306 00307 pCoefA = &pATable[0]; 00308 pCoefB = &pBTable[0]; 00309 00310 pSrc1 = &pSrc[0]; 00311 pSrc2 = &pSrc[2U * fftLen]; 00312 00313 #if defined (ARM_MATH_DSP) 00314 00315 /* Run the below code for Cortex-M4 and Cortex-M3 */ 00316 i = fftLen; 00317 00318 while (i > 0U) 00319 { 00320 /* 00321 outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] + 00322 pIn[2 * n - 2 * i] * pBTable[2 * i] - 00323 pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]); 00324 00325 outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] - 00326 pIn[2 * n - 2 * i] * pBTable[2 * i + 1] - 00327 pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); 00328 */ 00329 00330 00331 #ifndef ARM_MATH_BIG_ENDIAN 00332 00333 /* pIn[2 * n - 2 * i] * pBTable[2 * i] - 00334 pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]) */ 00335 outR = __SMUSD(*__SIMD32(pSrc2), *__SIMD32(pCoefB)); 00336 00337 #else 00338 00339 /* -(-pIn[2 * n - 2 * i] * pBTable[2 * i] + 00340 pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1])) */ 00341 outR = -(__SMUSD(*__SIMD32(pSrc2), *__SIMD32(pCoefB))); 00342 00343 #endif /* #ifndef ARM_MATH_BIG_ENDIAN */ 00344 00345 /* pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] + 00346 pIn[2 * n - 2 * i] * pBTable[2 * i] */ 00347 outR = __SMLAD(*__SIMD32(pSrc1), *__SIMD32(pCoefA), outR) >> 16U; 00348 00349 /* 00350 -pIn[2 * n - 2 * i] * pBTable[2 * i + 1] + 00351 pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */ 00352 outI = __SMUADX(*__SIMD32(pSrc2)--, *__SIMD32(pCoefB)); 00353 00354 /* pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] */ 00355 00356 #ifndef ARM_MATH_BIG_ENDIAN 00357 00358 outI = __SMLSDX(*__SIMD32(pCoefA), *__SIMD32(pSrc1)++, -outI); 00359 00360 #else 00361 00362 outI = __SMLSDX(*__SIMD32(pSrc1)++, *__SIMD32(pCoefA), -outI); 00363 00364 #endif /* #ifndef ARM_MATH_BIG_ENDIAN */ 00365 /* write output */ 00366 00367 #ifndef ARM_MATH_BIG_ENDIAN 00368 00369 *__SIMD32(pDst1)++ = __PKHBT(outR, (outI >> 16U), 16); 00370 00371 #else 00372 00373 *__SIMD32(pDst1)++ = __PKHBT((outI >> 16U), outR, 16); 00374 00375 #endif /* #ifndef ARM_MATH_BIG_ENDIAN */ 00376 00377 /* update coefficient pointer */ 00378 pCoefB = pCoefB + (2U * modifier); 00379 pCoefA = pCoefA + (2U * modifier); 00380 00381 i--; 00382 } 00383 #else 00384 /* Run the below code for Cortex-M0 */ 00385 i = fftLen; 00386 00387 while (i > 0U) 00388 { 00389 /* 00390 outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] + 00391 pIn[2 * n - 2 * i] * pBTable[2 * i] - 00392 pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]); 00393 */ 00394 00395 outR = *pSrc2 * *pCoefB; 00396 outR = outR - (*(pSrc2 + 1) * *(pCoefB + 1)); 00397 outR = outR + (*pSrc1 * *pCoefA); 00398 outR = (outR + (*(pSrc1 + 1) * *(pCoefA + 1))) >> 16; 00399 00400 /* 00401 outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] - 00402 pIn[2 * n - 2 * i] * pBTable[2 * i + 1] - 00403 pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); 00404 */ 00405 00406 outI = *(pSrc1 + 1) * *pCoefA; 00407 outI = outI - (*pSrc1 * *(pCoefA + 1)); 00408 outI = outI - (*pSrc2 * *(pCoefB + 1)); 00409 outI = outI - (*(pSrc2 + 1) * *(pCoefB)); 00410 00411 /* update input pointers */ 00412 pSrc1 += 2U; 00413 pSrc2 -= 2U; 00414 00415 /* write output */ 00416 *pDst1++ = (q15_t) outR; 00417 *pDst1++ = (q15_t) (outI >> 16); 00418 00419 /* update coefficient pointer */ 00420 pCoefB = pCoefB + (2U * modifier); 00421 pCoefA = pCoefA + (2U * modifier); 00422 00423 i--; 00424 } 00425 #endif /* #if defined (ARM_MATH_DSP) */ 00426 } 00427
Generated on Tue Jul 12 2022 16:47:28 by
