1 /* ----------------------------------------------------------------------
2 * Copyright (C) 2010 ARM Limited. All rights reserved.
7 * Project: CMSIS DSP Library
8 * Title: arm_rfft_q31.c
10 * Description: RFFT & RIFFT Q31 process function
13 * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
15 * Version 1.0.10 2011/7/15
16 * Big Endian support added and Merged M0 and M3/M4 Source code.
18 * Version 1.0.3 2010/11/29
19 * Re-organized the CMSIS folders and updated documentation.
21 * Version 1.0.2 2010/11/11
22 * Documentation updated.
24 * Version 1.0.1 2010/10/05
25 * Production release and review comments incorporated.
27 * Version 1.0.0 2010/09/20
28 * Production release and review comments incorporated.
30 * Version 0.0.7 2010/06/10
31 * Misra-C changes done
32 * -------------------------------------------------------------------- */
36 /*--------------------------------------------------------------------
37 * Internal functions prototypes
38 --------------------------------------------------------------------*/
40 void arm_split_rfft_q31(
48 void arm_split_rifft_q31(
57 * @addtogroup RFFT_RIFFT
62 * @brief Processing function for the Q31 RFFT/RIFFT.
63 * @param[in] *S points to an instance of the Q31 RFFT/RIFFT structure.
64 * @param[in] *pSrc points to the input buffer.
65 * @param[out] *pDst points to the output buffer.
68 * \par Input an output formats:
70 * Internally input is downscaled by 2 for every stage to avoid saturations inside CFFT/CIFFT process.
71 * Hence the output format is different for different RFFT sizes.
72 * 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:
74 * \image html RFFTQ31.gif "Input and Output Formats for Q31 RFFT"
77 * \image html RIFFTQ31.gif "Input and Output Formats for Q31 RIFFT"
81 const arm_rfft_instance_q31 * S,
85 const arm_cfft_radix4_instance_q31 *S_CFFT = S->pCfft;
87 /* Calculation of RIFFT of input */
88 if(S->ifftFlagR == 1u)
90 /* Real IFFT core process */
91 arm_split_rifft_q31(pSrc, S->fftLenBy2, S->pTwiddleAReal,
92 S->pTwiddleBReal, pDst, S->twidCoefRModifier);
94 /* Complex readix-4 IFFT process */
95 arm_radix4_butterfly_inverse_q31(pDst, S_CFFT->fftLen,
97 S_CFFT->twidCoefModifier);
98 /* Bit reversal process */
99 if(S->bitReverseFlagR == 1u)
101 arm_bitreversal_q31(pDst, S_CFFT->fftLen,
102 S_CFFT->bitRevFactor, S_CFFT->pBitRevTable);
107 /* Calculation of RFFT of input */
109 /* Complex readix-4 FFT process */
110 arm_radix4_butterfly_q31(pSrc, S_CFFT->fftLen,
111 S_CFFT->pTwiddle, S_CFFT->twidCoefModifier);
113 /* Bit reversal process */
114 if(S->bitReverseFlagR == 1u)
116 arm_bitreversal_q31(pSrc, S_CFFT->fftLen,
117 S_CFFT->bitRevFactor, S_CFFT->pBitRevTable);
120 /* Real FFT core process */
121 arm_split_rfft_q31(pSrc, S->fftLenBy2, S->pTwiddleAReal,
122 S->pTwiddleBReal, pDst, S->twidCoefRModifier);
129 * @} end of RFFT_RIFFT group
133 * @brief Core Real FFT process
134 * @param[in] *pSrc points to the input buffer.
135 * @param[in] fftLen length of FFT.
136 * @param[in] *pATable points to the twiddle Coef A buffer.
137 * @param[in] *pBTable points to the twiddle Coef B buffer.
138 * @param[out] *pDst points to the output buffer.
139 * @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
143 void arm_split_rfft_q31(
151 uint32_t i; /* Loop Counter */
152 q31_t outR, outI; /* Temporary variables for output */
153 q31_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */
154 q31_t CoefA1, CoefA2, CoefB1; /* Temporary variables for twiddle coefficients */
155 q31_t *pOut1 = &pDst[2], *pOut2 = &pDst[(4u * fftLen) - 1u];
156 q31_t *pIn1 = &pSrc[2], *pIn2 = &pSrc[(2u * fftLen) - 1u];
158 pSrc[2u * fftLen] = pSrc[0];
159 pSrc[(2u * fftLen) + 1u] = pSrc[1];
161 /* Init coefficient pointers */
162 pCoefA = &pATable[modifier * 2u];
163 pCoefB = &pBTable[modifier * 2u];
170 outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1]
171 + pSrc[2 * n - 2 * i] * pBTable[2 * i] +
172 pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
175 /* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] +
176 pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
177 pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); */
182 /* outR = (pSrc[2 * i] * pATable[2 * i] */
183 outR = ((int32_t) (((q63_t) * pIn1 * CoefA1) >> 32));
185 /* outI = pIn[2 * i] * pATable[2 * i + 1] */
186 outI = ((int32_t) (((q63_t) * pIn1++ * CoefA2) >> 32));
188 /* - pSrc[2 * i + 1] * pATable[2 * i + 1] */
190 (q31_t) ((((q63_t) outR << 32) + ((q63_t) * pIn1 * (-CoefA2))) >> 32);
192 /* (pIn[2 * i + 1] * pATable[2 * i] */
194 (q31_t) ((((q63_t) outI << 32) + ((q63_t) * pIn1++ * (CoefA1))) >> 32);
196 /* pSrc[2 * n - 2 * i] * pBTable[2 * i] */
198 (q31_t) ((((q63_t) outR << 32) + ((q63_t) * pIn2 * (-CoefA2))) >> 32);
201 /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
203 (q31_t) ((((q63_t) outI << 32) + ((q63_t) * pIn2-- * (-CoefB1))) >> 32);
205 /* pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
207 (q31_t) ((((q63_t) outR << 32) + ((q63_t) * pIn2 * (CoefB1))) >> 32);
209 /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
211 (q31_t) ((((q63_t) outI << 32) + ((q63_t) * pIn2-- * (-CoefA2))) >> 32);
214 *pOut1++ = (outR << 1u);
215 *pOut1++ = (outI << 1u);
217 /* write complex conjugate output */
218 *pOut2-- = -(outI << 1u);
219 *pOut2-- = (outR << 1u);
221 /* update coefficient pointer */
222 pCoefB = pCoefB + (modifier * 2u);
223 pCoefA = pCoefA + ((modifier * 2u) - 1u);
229 pDst[2u * fftLen] = pSrc[0] - pSrc[1];
230 pDst[(2u * fftLen) + 1u] = 0;
232 pDst[0] = pSrc[0] + pSrc[1];
239 * @brief Core Real IFFT process
240 * @param[in] *pSrc points to the input buffer.
241 * @param[in] fftLen length of FFT.
242 * @param[in] *pATable points to the twiddle Coef A buffer.
243 * @param[in] *pBTable points to the twiddle Coef B buffer.
244 * @param[out] *pDst points to the output buffer.
245 * @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
249 void arm_split_rifft_q31(
257 q31_t outR, outI; /* Temporary variables for output */
258 q31_t *pCoefA, *pCoefB; /* Temporary pointers for twiddle factors */
259 q31_t CoefA1, CoefA2, CoefB1; /* Temporary variables for twiddle coefficients */
260 q31_t *pIn1 = &pSrc[0], *pIn2 = &pSrc[(2u * fftLen) + 1u];
262 pCoefA = &pATable[0];
263 pCoefB = &pBTable[0];
268 outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +
269 pIn[2 * n - 2 * i] * pBTable[2 * i] -
270 pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
272 outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] -
273 pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
274 pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);
280 /* outR = (pIn[2 * i] * pATable[2 * i] */
281 outR = ((int32_t) (((q63_t) * pIn1 * CoefA1) >> 32));
283 /* - pIn[2 * i] * pATable[2 * i + 1] */
284 outI = -((int32_t) (((q63_t) * pIn1++ * CoefA2) >> 32));
286 /* pIn[2 * i + 1] * pATable[2 * i + 1] */
288 (q31_t) ((((q63_t) outR << 32) + ((q63_t) * pIn1 * (CoefA2))) >> 32);
290 /* pIn[2 * i + 1] * pATable[2 * i] */
292 (q31_t) ((((q63_t) outI << 32) + ((q63_t) * pIn1++ * (CoefA1))) >> 32);
294 /* pIn[2 * n - 2 * i] * pBTable[2 * i] */
296 (q31_t) ((((q63_t) outR << 32) + ((q63_t) * pIn2 * (CoefA2))) >> 32);
300 /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
302 (q31_t) ((((q63_t) outI << 32) - ((q63_t) * pIn2-- * (CoefB1))) >> 32);
304 /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
306 (q31_t) ((((q63_t) outR << 32) + ((q63_t) * pIn2 * (CoefB1))) >> 32);
308 /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
310 (q31_t) ((((q63_t) outI << 32) + ((q63_t) * pIn2-- * (CoefA2))) >> 32);
313 *pDst++ = (outR << 1u);
314 *pDst++ = (outI << 1u);
316 /* update coefficient pointer */
317 pCoefB = pCoefB + (modifier * 2u);
318 pCoefA = pCoefA + ((modifier * 2u) - 1u);
320 /* Decrement loop count */