QuakeGod
2023-10-08 483170e190a0dd4666b2a63e5d31466052ba0c6a
提交 | 用户 | age
483170 1 /* ----------------------------------------------------------------------    
Q 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
49 extern void arm_radix4_butterfly_inverse_q15(
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     
60 void arm_cfft_radix4by2_q15(
61     q15_t * pSrc,
62     uint32_t fftLen,
63     const q15_t * pCoef);
64     
65 void arm_cfft_radix4by2_inverse_q15(
66     q15_t * pSrc,
67     uint32_t fftLen,
68     const q15_t * pCoef);
69
70 /**   
71 * @ingroup groupTransforms   
72 */
73
74 /**
75 * @addtogroup ComplexFFT   
76 * @{   
77 */
78
79 /**   
80 * @details   
81 * @brief       Processing function for the Q15 complex FFT.
82 * @param[in]      *S    points to an instance of the Q15 CFFT structure.  
83 * @param[in, out] *p1   points to the complex data buffer of size <code>2*fftLen</code>. Processing occurs in-place.  
84 * @param[in]     ifftFlag       flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform.  
85 * @param[in]     bitReverseFlag flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output.  
86 * @return none.  
87 */
88
89 void arm_cfft_q15( 
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:
106             arm_radix4_butterfly_inverse_q15  ( p1, L, (q15_t*)S->pTwiddle, 1 );
107             break;
108             
109         case 32:
110         case 128:
111         case 512:
112         case 2048:
113             arm_cfft_radix4by2_inverse_q15  ( p1, L, S->pTwiddle );
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
142 /**    
143 * @} end of ComplexFFT group    
144 */
145
146 void arm_cfft_radix4by2_q15(
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
253 void arm_cfft_radix4by2_inverse_q15(
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