STM32F769IDiscovery  1.00
uDANTE Audio Networking with STM32F7 DISCO board
arm_cfft_q15.c
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------
2 * Copyright (C) 2010-2014 ARM Limited. All rights reserved.
3 *
4 * $Date: 19. March 2015
5 * $Revision: V.1.4.5
6 *
7 * Project: CMSIS DSP Library
8 * Title: arm_cfft_q15.c
9 *
10 * Description: Combined Radix Decimation in Q15 Frequency CFFT processing function
11 *
12 * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * - Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * - Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in
21 * the documentation and/or other materials provided with the
22 * distribution.
23 * - Neither the name of ARM LIMITED nor the names of its contributors
24 * may be used to endorse or promote products derived from this
25 * software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
31 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
33 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 * -------------------------------------------------------------------- */
40 
41 #include "arm_math.h"
42 
43 extern void arm_radix4_butterfly_q15(
44  q15_t * pSrc,
45  uint32_t fftLen,
46  q15_t * pCoef,
47  uint32_t twidCoefModifier);
48 
50  q15_t * pSrc,
51  uint32_t fftLen,
52  q15_t * pCoef,
53  uint32_t twidCoefModifier);
54 
55 extern void arm_bitreversal_16(
56  uint16_t * pSrc,
57  const uint16_t bitRevLen,
58  const uint16_t * pBitRevTable);
59 
61  q15_t * pSrc,
62  uint32_t fftLen,
63  const q15_t * pCoef);
64 
66  q15_t * pSrc,
67  uint32_t fftLen,
68  const q15_t * pCoef);
69 
90  const arm_cfft_instance_q15 * S,
91  q15_t * p1,
92  uint8_t ifftFlag,
93  uint8_t bitReverseFlag)
94 {
95  uint32_t L = S->fftLen;
96 
97  if(ifftFlag == 1u)
98  {
99  switch (L)
100  {
101  case 16:
102  case 64:
103  case 256:
104  case 1024:
105  case 4096:
107  break;
108 
109  case 32:
110  case 128:
111  case 512:
112  case 2048:
114  break;
115  }
116  }
117  else
118  {
119  switch (L)
120  {
121  case 16:
122  case 64:
123  case 256:
124  case 1024:
125  case 4096:
126  arm_radix4_butterfly_q15 ( p1, L, (q15_t*)S->pTwiddle, 1 );
127  break;
128 
129  case 32:
130  case 128:
131  case 512:
132  case 2048:
133  arm_cfft_radix4by2_q15 ( p1, L, S->pTwiddle );
134  break;
135  }
136  }
137 
138  if( bitReverseFlag )
139  arm_bitreversal_16((uint16_t*)p1,S->bitRevLength,S->pBitRevTable);
140 }
141 
147  q15_t * pSrc,
148  uint32_t fftLen,
149  const q15_t * pCoef)
150 {
151  uint32_t i;
152  uint32_t n2;
153  q15_t p0, p1, p2, p3;
154 #ifndef ARM_MATH_CM0_FAMILY
155  q31_t T, S, R;
156  q31_t coeff, out1, out2;
157  const q15_t *pC = pCoef;
158  q15_t *pSi = pSrc;
159  q15_t *pSl = pSrc + fftLen;
160 #else
161  uint32_t ia, l;
162  q15_t xt, yt, cosVal, sinVal;
163 #endif
164 
165  n2 = fftLen >> 1;
166 
167 #ifndef ARM_MATH_CM0_FAMILY
168 
169  for (i = n2; i > 0; i--)
170  {
171  coeff = _SIMD32_OFFSET(pC);
172  pC += 2;
173 
174  T = _SIMD32_OFFSET(pSi);
175  T = __SHADD16(T, 0); // this is just a SIMD arithmetic shift right by 1
176 
177  S = _SIMD32_OFFSET(pSl);
178  S = __SHADD16(S, 0); // this is just a SIMD arithmetic shift right by 1
179 
180  R = __QSUB16(T, S);
181 
182  _SIMD32_OFFSET(pSi) = __SHADD16(T, S);
183  pSi += 2;
184 
185  #ifndef ARM_MATH_BIG_ENDIAN
186 
187  out1 = __SMUAD(coeff, R) >> 16;
188  out2 = __SMUSDX(coeff, R);
189 
190  #else
191 
192  out1 = __SMUSDX(R, coeff) >> 16u;
193  out2 = __SMUAD(coeff, R);
194 
195  #endif // #ifndef ARM_MATH_BIG_ENDIAN
196 
197  _SIMD32_OFFSET(pSl) =
198  (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
199  pSl += 2;
200  }
201 
202 #else // #ifndef ARM_MATH_CM0_FAMILY
203 
204  ia = 0;
205  for (i = 0; i < n2; i++)
206  {
207  cosVal = pCoef[ia * 2];
208  sinVal = pCoef[(ia * 2) + 1];
209  ia++;
210 
211  l = i + n2;
212 
213  xt = (pSrc[2 * i] >> 1u) - (pSrc[2 * l] >> 1u);
214  pSrc[2 * i] = ((pSrc[2 * i] >> 1u) + (pSrc[2 * l] >> 1u)) >> 1u;
215 
216  yt = (pSrc[2 * i + 1] >> 1u) - (pSrc[2 * l + 1] >> 1u);
217  pSrc[2 * i + 1] =
218  ((pSrc[2 * l + 1] >> 1u) + (pSrc[2 * i + 1] >> 1u)) >> 1u;
219 
220  pSrc[2u * l] = (((int16_t) (((q31_t) xt * cosVal) >> 16)) +
221  ((int16_t) (((q31_t) yt * sinVal) >> 16)));
222 
223  pSrc[2u * l + 1u] = (((int16_t) (((q31_t) yt * cosVal) >> 16)) -
224  ((int16_t) (((q31_t) xt * sinVal) >> 16)));
225  }
226 
227 #endif // #ifndef ARM_MATH_CM0_FAMILY
228 
229  // first col
230  arm_radix4_butterfly_q15( pSrc, n2, (q15_t*)pCoef, 2u);
231  // second col
232  arm_radix4_butterfly_q15( pSrc + fftLen, n2, (q15_t*)pCoef, 2u);
233 
234  for (i = 0; i < fftLen >> 1; i++)
235  {
236  p0 = pSrc[4*i+0];
237  p1 = pSrc[4*i+1];
238  p2 = pSrc[4*i+2];
239  p3 = pSrc[4*i+3];
240 
241  p0 <<= 1;
242  p1 <<= 1;
243  p2 <<= 1;
244  p3 <<= 1;
245 
246  pSrc[4*i+0] = p0;
247  pSrc[4*i+1] = p1;
248  pSrc[4*i+2] = p2;
249  pSrc[4*i+3] = p3;
250  }
251 }
252 
254  q15_t * pSrc,
255  uint32_t fftLen,
256  const q15_t * pCoef)
257 {
258  uint32_t i;
259  uint32_t n2;
260  q15_t p0, p1, p2, p3;
261 #ifndef ARM_MATH_CM0_FAMILY
262  q31_t T, S, R;
263  q31_t coeff, out1, out2;
264  const q15_t *pC = pCoef;
265  q15_t *pSi = pSrc;
266  q15_t *pSl = pSrc + fftLen;
267 #else
268  uint32_t ia, l;
269  q15_t xt, yt, cosVal, sinVal;
270 #endif
271 
272  n2 = fftLen >> 1;
273 
274 #ifndef ARM_MATH_CM0_FAMILY
275 
276  for (i = n2; i > 0; i--)
277  {
278  coeff = _SIMD32_OFFSET(pC);
279  pC += 2;
280 
281  T = _SIMD32_OFFSET(pSi);
282  T = __SHADD16(T, 0); // this is just a SIMD arithmetic shift right by 1
283 
284  S = _SIMD32_OFFSET(pSl);
285  S = __SHADD16(S, 0); // this is just a SIMD arithmetic shift right by 1
286 
287  R = __QSUB16(T, S);
288 
289  _SIMD32_OFFSET(pSi) = __SHADD16(T, S);
290  pSi += 2;
291 
292  #ifndef ARM_MATH_BIG_ENDIAN
293 
294  out1 = __SMUSD(coeff, R) >> 16;
295  out2 = __SMUADX(coeff, R);
296  #else
297 
298  out1 = __SMUADX(R, coeff) >> 16u;
299  out2 = __SMUSD(__QSUB(0, coeff), R);
300 
301  #endif // #ifndef ARM_MATH_BIG_ENDIAN
302 
303  _SIMD32_OFFSET(pSl) =
304  (q31_t) ((out2) & 0xFFFF0000) | (out1 & 0x0000FFFF);
305  pSl += 2;
306  }
307 
308 #else // #ifndef ARM_MATH_CM0_FAMILY
309 
310  ia = 0;
311  for (i = 0; i < n2; i++)
312  {
313  cosVal = pCoef[ia * 2];
314  sinVal = pCoef[(ia * 2) + 1];
315  ia++;
316 
317  l = i + n2;
318  xt = (pSrc[2 * i] >> 1u) - (pSrc[2 * l] >> 1u);
319  pSrc[2 * i] = ((pSrc[2 * i] >> 1u) + (pSrc[2 * l] >> 1u)) >> 1u;
320 
321  yt = (pSrc[2 * i + 1] >> 1u) - (pSrc[2 * l + 1] >> 1u);
322  pSrc[2 * i + 1] =
323  ((pSrc[2 * l + 1] >> 1u) + (pSrc[2 * i + 1] >> 1u)) >> 1u;
324 
325  pSrc[2u * l] = (((int16_t) (((q31_t) xt * cosVal) >> 16)) -
326  ((int16_t) (((q31_t) yt * sinVal) >> 16)));
327 
328  pSrc[2u * l + 1u] = (((int16_t) (((q31_t) yt * cosVal) >> 16)) +
329  ((int16_t) (((q31_t) xt * sinVal) >> 16)));
330  }
331 
332 #endif // #ifndef ARM_MATH_CM0_FAMILY
333 
334  // first col
335  arm_radix4_butterfly_inverse_q15( pSrc, n2, (q15_t*)pCoef, 2u);
336  // second col
337  arm_radix4_butterfly_inverse_q15( pSrc + fftLen, n2, (q15_t*)pCoef, 2u);
338 
339  for (i = 0; i < fftLen >> 1; i++)
340  {
341  p0 = pSrc[4*i+0];
342  p1 = pSrc[4*i+1];
343  p2 = pSrc[4*i+2];
344  p3 = pSrc[4*i+3];
345 
346  p0 <<= 1;
347  p1 <<= 1;
348  p2 <<= 1;
349  p3 <<= 1;
350 
351  pSrc[4*i+0] = p0;
352  pSrc[4*i+1] = p1;
353  pSrc[4*i+2] = p2;
354  pSrc[4*i+3] = p3;
355  }
356 }
357 
void arm_bitreversal_16(uint16_t *pSrc, const uint16_t bitRevLen, const uint16_t *pBitRevTable)
void arm_radix4_butterfly_inverse_q15(q15_t *pSrc, uint32_t fftLen, q15_t *pCoef, uint32_t twidCoefModifier)
Core function for the Q15 CIFFT butterfly process.
void arm_cfft_radix4by2_inverse_q15(q15_t *pSrc, uint32_t fftLen, const q15_t *pCoef)
Definition: arm_cfft_q15.c:253
const q15_t * pTwiddle
Definition: arm_math.h:2110
void arm_cfft_q15(const arm_cfft_instance_q15 *S, q15_t *p1, uint8_t ifftFlag, uint8_t bitReverseFlag)
Processing function for the Q15 complex FFT.
Definition: arm_cfft_q15.c:89
int16_t q15_t
16-bit fractional data type in 1.15 format.
Definition: arm_math.h:392
const uint16_t * pBitRevTable
Definition: arm_math.h:2111
void arm_cfft_radix4by2_q15(q15_t *pSrc, uint32_t fftLen, const q15_t *pCoef)
Definition: arm_cfft_q15.c:146
void arm_radix4_butterfly_q15(q15_t *pSrc, uint32_t fftLen, q15_t *pCoef, uint32_t twidCoefModifier)
Core function for the Q15 CFFT butterfly process.
#define _SIMD32_OFFSET(addr)
Definition: arm_math.h:447
int32_t q31_t
32-bit fractional data type in 1.31 format.
Definition: arm_math.h:397
Instance structure for the fixed-point CFFT/CIFFT function.
Definition: arm_math.h:2107
uint32_t ifftFlag
Definition: FFT.c:112