1 /* ----------------------------------------------------------------------
2 * Project: CMSIS DSP Library
3 * Title: arm_rfft_q31.c
4 * Description: FFT & RIFFT Q31 process function
6 * $Date: 27. January 2017
9 * Target Processor: Cortex-M cores
10 * -------------------------------------------------------------------- */
12 * Copyright (C) 2010-2017 ARM Limited or its affiliates. All rights reserved.
14 * SPDX-License-Identifier: Apache-2.0
16 * Licensed under the Apache License, Version 2.0 (the License); you may
17 * not use this file except in compliance with the License.
18 * You may obtain a copy of the License at
20 * www.apache.org/licenses/LICENSE-2.0
22 * Unless required by applicable law or agreed to in writing, software
23 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
24 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 * See the License for the specific language governing permissions and
26 * limitations under the License.
31 /* ----------------------------------------------------------------------
32 * Internal functions prototypes
33 * -------------------------------------------------------------------- */
35 void arm_split_rfft_q31(
43 void arm_split_rifft_q31(
57 * @brief Processing function for the Q31 RFFT/RIFFT.
58 * @param[in] *S points to an instance of the Q31 RFFT/RIFFT structure.
59 * @param[in] *pSrc points to the input buffer.
60 * @param[out] *pDst points to the output buffer.
63 * \par Input an output formats:
65 * Internally input is downscaled by 2 for every stage to avoid saturations inside CFFT/CIFFT process.
66 * Hence the output format is different for different RFFT sizes.
67 * 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:
69 * \image html RFFTQ31.gif "Input and Output Formats for Q31 RFFT"
72 * \image html RIFFTQ31.gif "Input and Output Formats for Q31 RIFFT"
75 const arm_rfft_instance_q31
* S
,
79 const arm_cfft_instance_q31
*S_CFFT
= S
->pCfft
;
81 uint32_t L2
= S
->fftLenReal
>> 1;
83 /* Calculation of RIFFT of input */
84 if (S
->ifftFlagR
== 1U)
86 /* Real IFFT core process */
87 arm_split_rifft_q31(pSrc
, L2
, S
->pTwiddleAReal
,
88 S
->pTwiddleBReal
, pDst
, S
->twidCoefRModifier
);
90 /* Complex IFFT process */
91 arm_cfft_q31(S_CFFT
, pDst
, S
->ifftFlagR
, S
->bitReverseFlagR
);
93 for(i
=0;i
<S
->fftLenReal
;i
++)
95 pDst
[i
] = pDst
[i
] << 1;
100 /* Calculation of RFFT of input */
102 /* Complex FFT process */
103 arm_cfft_q31(S_CFFT
, pSrc
, S
->ifftFlagR
, S
->bitReverseFlagR
);
105 /* Real FFT core process */
106 arm_split_rfft_q31(pSrc
, L2
, S
->pTwiddleAReal
,
107 S
->pTwiddleBReal
, pDst
, S
->twidCoefRModifier
);
112 * @} end of RealFFT group
116 * @brief Core Real FFT process
117 * @param[in] *pSrc points to the input buffer.
118 * @param[in] fftLen length of FFT.
119 * @param[in] *pATable points to the twiddle Coef A buffer.
120 * @param[in] *pBTable points to the twiddle Coef B buffer.
121 * @param[out] *pDst points to the output buffer.
122 * @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
125 void arm_split_rfft_q31(
133 uint32_t i
; /* Loop Counter */
134 q31_t outR
, outI
; /* Temporary variables for output */
135 q31_t
*pCoefA
, *pCoefB
; /* Temporary pointers for twiddle factors */
136 q31_t CoefA1
, CoefA2
, CoefB1
; /* Temporary variables for twiddle coefficients */
137 q31_t
*pOut1
= &pDst
[2], *pOut2
= &pDst
[(4U * fftLen
) - 1U];
138 q31_t
*pIn1
= &pSrc
[2], *pIn2
= &pSrc
[(2U * fftLen
) - 1U];
140 /* Init coefficient pointers */
141 pCoefA
= &pATable
[modifier
* 2U];
142 pCoefB
= &pBTable
[modifier
* 2U];
149 outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1]
150 + pSrc[2 * n - 2 * i] * pBTable[2 * i] +
151 pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
154 /* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] +
155 pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
156 pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); */
161 /* outR = (pSrc[2 * i] * pATable[2 * i] */
162 mult_32x32_keep32_R(outR
, *pIn1
, CoefA1
);
164 /* outI = pIn[2 * i] * pATable[2 * i + 1] */
165 mult_32x32_keep32_R(outI
, *pIn1
++, CoefA2
);
167 /* - pSrc[2 * i + 1] * pATable[2 * i + 1] */
168 multSub_32x32_keep32_R(outR
, *pIn1
, CoefA2
);
170 /* (pIn[2 * i + 1] * pATable[2 * i] */
171 multAcc_32x32_keep32_R(outI
, *pIn1
++, CoefA1
);
173 /* pSrc[2 * n - 2 * i] * pBTable[2 * i] */
174 multSub_32x32_keep32_R(outR
, *pIn2
, CoefA2
);
177 /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
178 multSub_32x32_keep32_R(outI
, *pIn2
--, CoefB1
);
180 /* pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
181 multAcc_32x32_keep32_R(outR
, *pIn2
, CoefB1
);
183 /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
184 multSub_32x32_keep32_R(outI
, *pIn2
--, CoefA2
);
190 /* write complex conjugate output */
194 /* update coefficient pointer */
195 pCoefB
= pCoefB
+ (modifier
* 2U);
196 pCoefA
= pCoefA
+ ((modifier
* 2U) - 1U);
200 pDst
[2U * fftLen
] = (pSrc
[0] - pSrc
[1]) >> 1;
201 pDst
[(2U * fftLen
) + 1U] = 0;
203 pDst
[0] = (pSrc
[0] + pSrc
[1]) >> 1;
208 * @brief Core Real IFFT process
209 * @param[in] *pSrc points to the input buffer.
210 * @param[in] fftLen length of FFT.
211 * @param[in] *pATable points to the twiddle Coef A buffer.
212 * @param[in] *pBTable points to the twiddle Coef B buffer.
213 * @param[out] *pDst points to the output buffer.
214 * @param[in] modifier twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.
217 void arm_split_rifft_q31(
225 q31_t outR
, outI
; /* Temporary variables for output */
226 q31_t
*pCoefA
, *pCoefB
; /* Temporary pointers for twiddle factors */
227 q31_t CoefA1
, CoefA2
, CoefB1
; /* Temporary variables for twiddle coefficients */
228 q31_t
*pIn1
= &pSrc
[0], *pIn2
= &pSrc
[(2U * fftLen
) + 1U];
230 pCoefA
= &pATable
[0];
231 pCoefB
= &pBTable
[0];
236 outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +
237 pIn[2 * n - 2 * i] * pBTable[2 * i] -
238 pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);
240 outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] -
241 pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -
242 pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);
247 /* outR = (pIn[2 * i] * pATable[2 * i] */
248 mult_32x32_keep32_R(outR
, *pIn1
, CoefA1
);
250 /* - pIn[2 * i] * pATable[2 * i + 1] */
251 mult_32x32_keep32_R(outI
, *pIn1
++, -CoefA2
);
253 /* pIn[2 * i + 1] * pATable[2 * i + 1] */
254 multAcc_32x32_keep32_R(outR
, *pIn1
, CoefA2
);
256 /* pIn[2 * i + 1] * pATable[2 * i] */
257 multAcc_32x32_keep32_R(outI
, *pIn1
++, CoefA1
);
259 /* pIn[2 * n - 2 * i] * pBTable[2 * i] */
260 multAcc_32x32_keep32_R(outR
, *pIn2
, CoefA2
);
263 /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
264 multSub_32x32_keep32_R(outI
, *pIn2
--, CoefB1
);
266 /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
267 multAcc_32x32_keep32_R(outR
, *pIn2
, CoefB1
);
269 /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
270 multAcc_32x32_keep32_R(outI
, *pIn2
--, CoefA2
);
276 /* update coefficient pointer */
277 pCoefB
= pCoefB
+ (modifier
* 2U);
278 pCoefA
= pCoefA
+ ((modifier
* 2U) - 1U);
280 /* Decrement loop count */