Subversion Repositories DashDisplay

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
56 mjames 1
/* ----------------------------------------------------------------------
2
 * Project:      CMSIS DSP Library
3
 * Title:        arm_cfft_q31.c
4
 * Description:  Combined Radix Decimation in Frequency CFFT fixed point processing function
5
 *
6
 * $Date:        27. January 2017
7
 * $Revision:    V.1.5.1
8
 *
9
 * Target Processor: Cortex-M cores
10
 * -------------------------------------------------------------------- */
11
/*
12
 * Copyright (C) 2010-2017 ARM Limited or its affiliates. All rights reserved.
13
 *
14
 * SPDX-License-Identifier: Apache-2.0
15
 *
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
19
 *
20
 * www.apache.org/licenses/LICENSE-2.0
21
 *
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.
27
 */
28
 
29
#include "arm_math.h"
30
 
31
extern void arm_radix4_butterfly_q31(
32
    q31_t * pSrc,
33
    uint32_t fftLen,
34
    q31_t * pCoef,
35
    uint32_t twidCoefModifier);
36
 
37
extern void arm_radix4_butterfly_inverse_q31(
38
    q31_t * pSrc,
39
    uint32_t fftLen,
40
    q31_t * pCoef,
41
    uint32_t twidCoefModifier);
42
 
43
extern void arm_bitreversal_32(
44
    uint32_t * pSrc,
45
    const uint16_t bitRevLen,
46
    const uint16_t * pBitRevTable);
47
 
48
void arm_cfft_radix4by2_q31(
49
    q31_t * pSrc,
50
    uint32_t fftLen,
51
    const q31_t * pCoef);
52
 
53
void arm_cfft_radix4by2_inverse_q31(
54
    q31_t * pSrc,
55
    uint32_t fftLen,
56
    const q31_t * pCoef);
57
 
58
/**
59
* @ingroup groupTransforms
60
*/
61
 
62
/**
63
* @addtogroup ComplexFFT
64
* @{
65
*/
66
 
67
/**
68
* @details
69
* @brief       Processing function for the fixed-point complex FFT in Q31 format.
70
* @param[in]      *S    points to an instance of the fixed-point 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.
74
* @return none.
75
*/
76
 
77
void arm_cfft_q31(
78
    const arm_cfft_instance_q31 * S,
79
    q31_t * p1,
80
    uint8_t ifftFlag,
81
    uint8_t bitReverseFlag)
82
{
83
    uint32_t L = S->fftLen;
84
 
85
    if (ifftFlag == 1U)
86
    {
87
        switch (L)
88
        {
89
        case 16:
90
        case 64:
91
        case 256:
92
        case 1024:
93
        case 4096:
94
            arm_radix4_butterfly_inverse_q31  ( p1, L, (q31_t*)S->pTwiddle, 1 );
95
            break;
96
 
97
        case 32:
98
        case 128:
99
        case 512:
100
        case 2048:
101
            arm_cfft_radix4by2_inverse_q31  ( p1, L, S->pTwiddle );
102
            break;
103
        }
104
    }
105
    else
106
    {
107
        switch (L)
108
        {
109
        case 16:
110
        case 64:
111
        case 256:
112
        case 1024:
113
        case 4096:
114
            arm_radix4_butterfly_q31  ( p1, L, (q31_t*)S->pTwiddle, 1 );
115
            break;
116
 
117
        case 32:
118
        case 128:
119
        case 512:
120
        case 2048:
121
            arm_cfft_radix4by2_q31  ( p1, L, S->pTwiddle );
122
            break;
123
        }
124
    }
125
 
126
    if ( bitReverseFlag )
127
        arm_bitreversal_32((uint32_t*)p1,S->bitRevLength,S->pBitRevTable);
128
}
129
 
130
/**
131
* @} end of ComplexFFT group
132
*/
133
 
134
void arm_cfft_radix4by2_q31(
135
    q31_t * pSrc,
136
    uint32_t fftLen,
137
    const q31_t * pCoef)
138
{
139
    uint32_t i, l;
140
    uint32_t n2, ia;
141
    q31_t xt, yt, cosVal, sinVal;
142
    q31_t p0, p1;
143
 
144
    n2 = fftLen >> 1;
145
    ia = 0;
146
    for (i = 0; i < n2; i++)
147
    {
148
        cosVal = pCoef[2*ia];
149
        sinVal = pCoef[2*ia + 1];
150
        ia++;
151
 
152
        l = i + n2;
153
        xt = (pSrc[2 * i] >> 2) - (pSrc[2 * l] >> 2);
154
        pSrc[2 * i] = (pSrc[2 * i] >> 2) + (pSrc[2 * l] >> 2);
155
 
156
        yt = (pSrc[2 * i + 1] >> 2) - (pSrc[2 * l + 1] >> 2);
157
        pSrc[2 * i + 1] = (pSrc[2 * l + 1] >> 2) + (pSrc[2 * i + 1] >> 2);
158
 
159
        mult_32x32_keep32_R(p0, xt, cosVal);
160
        mult_32x32_keep32_R(p1, yt, cosVal);
161
        multAcc_32x32_keep32_R(p0, yt, sinVal);
162
        multSub_32x32_keep32_R(p1, xt, sinVal);
163
 
164
        pSrc[2U * l] = p0 << 1;
165
        pSrc[2U * l + 1U] = p1 << 1;
166
 
167
    }
168
 
169
    // first col
170
    arm_radix4_butterfly_q31( pSrc, n2, (q31_t*)pCoef, 2U);
171
    // second col
172
    arm_radix4_butterfly_q31( pSrc + fftLen, n2, (q31_t*)pCoef, 2U);
173
 
174
    for (i = 0; i < fftLen >> 1; i++)
175
    {
176
        p0 = pSrc[4*i+0];
177
        p1 = pSrc[4*i+1];
178
        xt = pSrc[4*i+2];
179
        yt = pSrc[4*i+3];
180
 
181
        p0 <<= 1;
182
        p1 <<= 1;
183
        xt <<= 1;
184
        yt <<= 1;
185
 
186
        pSrc[4*i+0] = p0;
187
        pSrc[4*i+1] = p1;
188
        pSrc[4*i+2] = xt;
189
        pSrc[4*i+3] = yt;
190
    }
191
 
192
}
193
 
194
void arm_cfft_radix4by2_inverse_q31(
195
    q31_t * pSrc,
196
    uint32_t fftLen,
197
    const q31_t * pCoef)
198
{
199
    uint32_t i, l;
200
    uint32_t n2, ia;
201
    q31_t xt, yt, cosVal, sinVal;
202
    q31_t p0, p1;
203
 
204
    n2 = fftLen >> 1;
205
    ia = 0;
206
    for (i = 0; i < n2; i++)
207
    {
208
        cosVal = pCoef[2*ia];
209
        sinVal = pCoef[2*ia + 1];
210
        ia++;
211
 
212
        l = i + n2;
213
        xt = (pSrc[2 * i] >> 2) - (pSrc[2 * l] >> 2);
214
        pSrc[2 * i] = (pSrc[2 * i] >> 2) + (pSrc[2 * l] >> 2);
215
 
216
        yt = (pSrc[2 * i + 1] >> 2) - (pSrc[2 * l + 1] >> 2);
217
        pSrc[2 * i + 1] = (pSrc[2 * l + 1] >> 2) + (pSrc[2 * i + 1] >> 2);
218
 
219
        mult_32x32_keep32_R(p0, xt, cosVal);
220
        mult_32x32_keep32_R(p1, yt, cosVal);
221
        multSub_32x32_keep32_R(p0, yt, sinVal);
222
        multAcc_32x32_keep32_R(p1, xt, sinVal);
223
 
224
        pSrc[2U * l] = p0 << 1;
225
        pSrc[2U * l + 1U] = p1 << 1;
226
 
227
    }
228
 
229
    // first col
230
    arm_radix4_butterfly_inverse_q31( pSrc, n2, (q31_t*)pCoef, 2U);
231
    // second col
232
    arm_radix4_butterfly_inverse_q31( pSrc + fftLen, n2, (q31_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
        xt = pSrc[4*i+2];
239
        yt = pSrc[4*i+3];
240
 
241
        p0 <<= 1;
242
        p1 <<= 1;
243
        xt <<= 1;
244
        yt <<= 1;
245
 
246
        pSrc[4*i+0] = p0;
247
        pSrc[4*i+1] = p1;
248
        pSrc[4*i+2] = xt;
249
        pSrc[4*i+3] = yt;
250
    }
251
}
252