1 /* ----------------------------------------------------------------------
2 * Project: CMSIS DSP Library
3 * Title: arm_cfft_q15.c
4 * Description: Combined Radix Decimation in Q15 Frequency CFFT processing 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 extern void arm_radix4_butterfly_q15(
35 uint32_t twidCoefModifier
);
37 extern void arm_radix4_butterfly_inverse_q15(
41 uint32_t twidCoefModifier
);
43 extern void arm_bitreversal_16(
45 const uint16_t bitRevLen
,
46 const uint16_t * pBitRevTable
);
48 void arm_cfft_radix4by2_q15(
53 void arm_cfft_radix4by2_inverse_q15(
59 * @ingroup groupTransforms
63 * @addtogroup ComplexFFT
69 * @brief Processing function for the Q15 complex FFT.
70 * @param[in] *S points to an instance of the Q15 CFFT structure.
71 * @param[in, out] *p1 points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place.
72 * @param[in] ifftFlag flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.
73 * @param[in] bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.
78 const arm_cfft_instance_q15
* S
,
81 uint8_t bitReverseFlag
)
83 uint32_t L
= S
->fftLen
;
94 arm_radix4_butterfly_inverse_q15 ( p1
, L
, (q15_t
*)S
->pTwiddle
, 1 );
101 arm_cfft_radix4by2_inverse_q15 ( p1
, L
, S
->pTwiddle
);
114 arm_radix4_butterfly_q15 ( p1
, L
, (q15_t
*)S
->pTwiddle
, 1 );
121 arm_cfft_radix4by2_q15 ( p1
, L
, S
->pTwiddle
);
126 if ( bitReverseFlag
)
127 arm_bitreversal_16((uint16_t*)p1
,S
->bitRevLength
,S
->pBitRevTable
);
131 * @} end of ComplexFFT group
134 void arm_cfft_radix4by2_q15(
141 q15_t p0
, p1
, p2
, p3
;
142 #if defined (ARM_MATH_DSP)
144 q31_t coeff
, out1
, out2
;
145 const q15_t
*pC
= pCoef
;
147 q15_t
*pSl
= pSrc
+ fftLen
;
150 q15_t xt
, yt
, cosVal
, sinVal
;
155 #if defined (ARM_MATH_DSP)
157 for (i
= n2
; i
> 0; i
--)
159 coeff
= _SIMD32_OFFSET(pC
);
162 T
= _SIMD32_OFFSET(pSi
);
163 T
= __SHADD16(T
, 0); // this is just a SIMD arithmetic shift right by 1
165 S
= _SIMD32_OFFSET(pSl
);
166 S
= __SHADD16(S
, 0); // this is just a SIMD arithmetic shift right by 1
170 _SIMD32_OFFSET(pSi
) = __SHADD16(T
, S
);
173 #ifndef ARM_MATH_BIG_ENDIAN
175 out1
= __SMUAD(coeff
, R
) >> 16;
176 out2
= __SMUSDX(coeff
, R
);
180 out1
= __SMUSDX(R
, coeff
) >> 16U;
181 out2
= __SMUAD(coeff
, R
);
183 #endif // #ifndef ARM_MATH_BIG_ENDIAN
185 _SIMD32_OFFSET(pSl
) =
186 (q31_t
) ((out2
) & 0xFFFF0000) | (out1
& 0x0000FFFF);
190 #else // #if defined (ARM_MATH_DSP)
193 for (i
= 0; i
< n2
; i
++)
195 cosVal
= pCoef
[ia
* 2];
196 sinVal
= pCoef
[(ia
* 2) + 1];
201 xt
= (pSrc
[2 * i
] >> 1U) - (pSrc
[2 * l
] >> 1U);
202 pSrc
[2 * i
] = ((pSrc
[2 * i
] >> 1U) + (pSrc
[2 * l
] >> 1U)) >> 1U;
204 yt
= (pSrc
[2 * i
+ 1] >> 1U) - (pSrc
[2 * l
+ 1] >> 1U);
206 ((pSrc
[2 * l
+ 1] >> 1U) + (pSrc
[2 * i
+ 1] >> 1U)) >> 1U;
208 pSrc
[2U * l
] = (((int16_t) (((q31_t
) xt
* cosVal
) >> 16)) +
209 ((int16_t) (((q31_t
) yt
* sinVal
) >> 16)));
211 pSrc
[2U * l
+ 1U] = (((int16_t) (((q31_t
) yt
* cosVal
) >> 16)) -
212 ((int16_t) (((q31_t
) xt
* sinVal
) >> 16)));
215 #endif // #if defined (ARM_MATH_DSP)
218 arm_radix4_butterfly_q15( pSrc
, n2
, (q15_t
*)pCoef
, 2U);
220 arm_radix4_butterfly_q15( pSrc
+ fftLen
, n2
, (q15_t
*)pCoef
, 2U);
222 for (i
= 0; i
< fftLen
>> 1; i
++)
241 void arm_cfft_radix4by2_inverse_q15(
248 q15_t p0
, p1
, p2
, p3
;
249 #if defined (ARM_MATH_DSP)
251 q31_t coeff
, out1
, out2
;
252 const q15_t
*pC
= pCoef
;
254 q15_t
*pSl
= pSrc
+ fftLen
;
257 q15_t xt
, yt
, cosVal
, sinVal
;
262 #if defined (ARM_MATH_DSP)
264 for (i
= n2
; i
> 0; i
--)
266 coeff
= _SIMD32_OFFSET(pC
);
269 T
= _SIMD32_OFFSET(pSi
);
270 T
= __SHADD16(T
, 0); // this is just a SIMD arithmetic shift right by 1
272 S
= _SIMD32_OFFSET(pSl
);
273 S
= __SHADD16(S
, 0); // this is just a SIMD arithmetic shift right by 1
277 _SIMD32_OFFSET(pSi
) = __SHADD16(T
, S
);
280 #ifndef ARM_MATH_BIG_ENDIAN
282 out1
= __SMUSD(coeff
, R
) >> 16;
283 out2
= __SMUADX(coeff
, R
);
286 out1
= __SMUADX(R
, coeff
) >> 16U;
287 out2
= __SMUSD(__QSUB(0, coeff
), R
);
289 #endif // #ifndef ARM_MATH_BIG_ENDIAN
291 _SIMD32_OFFSET(pSl
) =
292 (q31_t
) ((out2
) & 0xFFFF0000) | (out1
& 0x0000FFFF);
296 #else // #if defined (ARM_MATH_DSP)
299 for (i
= 0; i
< n2
; i
++)
301 cosVal
= pCoef
[ia
* 2];
302 sinVal
= pCoef
[(ia
* 2) + 1];
306 xt
= (pSrc
[2 * i
] >> 1U) - (pSrc
[2 * l
] >> 1U);
307 pSrc
[2 * i
] = ((pSrc
[2 * i
] >> 1U) + (pSrc
[2 * l
] >> 1U)) >> 1U;
309 yt
= (pSrc
[2 * i
+ 1] >> 1U) - (pSrc
[2 * l
+ 1] >> 1U);
311 ((pSrc
[2 * l
+ 1] >> 1U) + (pSrc
[2 * i
+ 1] >> 1U)) >> 1U;
313 pSrc
[2U * l
] = (((int16_t) (((q31_t
) xt
* cosVal
) >> 16)) -
314 ((int16_t) (((q31_t
) yt
* sinVal
) >> 16)));
316 pSrc
[2U * l
+ 1U] = (((int16_t) (((q31_t
) yt
* cosVal
) >> 16)) +
317 ((int16_t) (((q31_t
) xt
* sinVal
) >> 16)));
320 #endif // #if defined (ARM_MATH_DSP)
323 arm_radix4_butterfly_inverse_q15( pSrc
, n2
, (q15_t
*)pCoef
, 2U);
325 arm_radix4_butterfly_inverse_q15( pSrc
+ fftLen
, n2
, (q15_t
*)pCoef
, 2U);
327 for (i
= 0; i
< fftLen
>> 1; i
++)