Subversion Repositories ScreenTimer

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 mjames 1
/* ----------------------------------------------------------------------
2
 * Project:      CMSIS DSP Library
3
 * Title:        arm_rfft_q31.c
4
 * Description:  FFT & RIFFT Q31 process 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
/* ----------------------------------------------------------------------
32
 * Internal functions prototypes
33
 * -------------------------------------------------------------------- */
34
 
35
void arm_split_rfft_q31(
36
    q31_t * pSrc,
37
    uint32_t fftLen,
38
    q31_t * pATable,
39
    q31_t * pBTable,
40
    q31_t * pDst,
41
    uint32_t modifier);
42
 
43
void arm_split_rifft_q31(
44
    q31_t * pSrc,
45
    uint32_t fftLen,
46
    q31_t * pATable,
47
    q31_t * pBTable,
48
    q31_t * pDst,
49
    uint32_t modifier);
50
 
51
/**
52
* @addtogroup RealFFT
53
* @{
54
*/
55
 
56
/**
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.
61
* @return none.
62
*
63
* \par Input an output formats:
64
* \par
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:
68
* \par
69
* \image html RFFTQ31.gif "Input and Output Formats for Q31 RFFT"
70
*
71
* \par
72
* \image html RIFFTQ31.gif "Input and Output Formats for Q31 RIFFT"
73
*/
74
void arm_rfft_q31(
75
    const arm_rfft_instance_q31 * S,
76
    q31_t * pSrc,
77
    q31_t * pDst)
78
{
79
    const arm_cfft_instance_q31 *S_CFFT = S->pCfft;
80
    uint32_t i;
81
    uint32_t L2 = S->fftLenReal >> 1;
82
 
83
    /* Calculation of RIFFT of input */
84
    if (S->ifftFlagR == 1U)
85
    {
86
        /*  Real IFFT core process */
87
        arm_split_rifft_q31(pSrc, L2, S->pTwiddleAReal,
88
                            S->pTwiddleBReal, pDst, S->twidCoefRModifier);
89
 
90
        /* Complex IFFT process */
91
        arm_cfft_q31(S_CFFT, pDst, S->ifftFlagR, S->bitReverseFlagR);
92
 
93
        for(i=0;i<S->fftLenReal;i++)
94
        {
95
            pDst[i] = pDst[i] << 1;
96
        }
97
    }
98
    else
99
    {
100
        /* Calculation of RFFT of input */
101
 
102
        /* Complex FFT process */
103
        arm_cfft_q31(S_CFFT, pSrc, S->ifftFlagR, S->bitReverseFlagR);
104
 
105
        /*  Real FFT core process */
106
        arm_split_rfft_q31(pSrc, L2, S->pTwiddleAReal,
107
                            S->pTwiddleBReal, pDst, S->twidCoefRModifier);
108
    }
109
}
110
 
111
/**
112
* @} end of RealFFT group
113
*/
114
 
115
/**
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.
123
* @return none.
124
*/
125
void arm_split_rfft_q31(
126
    q31_t * pSrc,
127
    uint32_t fftLen,
128
    q31_t * pATable,
129
    q31_t * pBTable,
130
    q31_t * pDst,
131
    uint32_t modifier)
132
{
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];
139
 
140
    /* Init coefficient pointers */
141
    pCoefA = &pATable[modifier * 2U];
142
    pCoefB = &pBTable[modifier * 2U];
143
 
144
    i = fftLen - 1U;
145
 
146
    while (i > 0U)
147
    {
148
        /*
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]);
152
        */
153
 
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]); */
157
 
158
        CoefA1 = *pCoefA++;
159
        CoefA2 = *pCoefA;
160
 
161
        /* outR = (pSrc[2 * i] * pATable[2 * i] */
162
        mult_32x32_keep32_R(outR, *pIn1, CoefA1);
163
 
164
        /* outI = pIn[2 * i] * pATable[2 * i + 1] */
165
        mult_32x32_keep32_R(outI, *pIn1++, CoefA2);
166
 
167
        /* - pSrc[2 * i + 1] * pATable[2 * i + 1] */
168
        multSub_32x32_keep32_R(outR, *pIn1, CoefA2);
169
 
170
        /* (pIn[2 * i + 1] * pATable[2 * i] */
171
        multAcc_32x32_keep32_R(outI, *pIn1++, CoefA1);
172
 
173
        /* pSrc[2 * n - 2 * i] * pBTable[2 * i]  */
174
        multSub_32x32_keep32_R(outR, *pIn2, CoefA2);
175
        CoefB1 = *pCoefB;
176
 
177
        /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
178
        multSub_32x32_keep32_R(outI, *pIn2--, CoefB1);
179
 
180
        /* pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
181
        multAcc_32x32_keep32_R(outR, *pIn2, CoefB1);
182
 
183
        /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
184
        multSub_32x32_keep32_R(outI, *pIn2--, CoefA2);
185
 
186
        /* write output */
187
        *pOut1++ = outR;
188
        *pOut1++ = outI;
189
 
190
        /* write complex conjugate output */
191
        *pOut2-- = -outI;
192
        *pOut2-- = outR;
193
 
194
        /* update coefficient pointer */
195
        pCoefB = pCoefB + (modifier * 2U);
196
        pCoefA = pCoefA + ((modifier * 2U) - 1U);
197
 
198
        i--;
199
    }
200
    pDst[2U * fftLen] = (pSrc[0] - pSrc[1]) >> 1;
201
    pDst[(2U * fftLen) + 1U] = 0;
202
 
203
    pDst[0] = (pSrc[0] + pSrc[1]) >> 1;
204
    pDst[1] = 0;
205
}
206
 
207
/**
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.
215
* @return none.
216
*/
217
void arm_split_rifft_q31(
218
    q31_t * pSrc,
219
    uint32_t fftLen,
220
    q31_t * pATable,
221
    q31_t * pBTable,
222
    q31_t * pDst,
223
    uint32_t modifier)
224
{
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];
229
 
230
    pCoefA = &pATable[0];
231
    pCoefB = &pBTable[0];
232
 
233
    while (fftLen > 0U)
234
    {
235
        /*
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]);
239
 
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]);
243
        */
244
        CoefA1 = *pCoefA++;
245
        CoefA2 = *pCoefA;
246
 
247
        /* outR = (pIn[2 * i] * pATable[2 * i] */
248
        mult_32x32_keep32_R(outR, *pIn1, CoefA1);
249
 
250
        /* - pIn[2 * i] * pATable[2 * i + 1] */
251
        mult_32x32_keep32_R(outI, *pIn1++, -CoefA2);
252
 
253
        /* pIn[2 * i + 1] * pATable[2 * i + 1] */
254
        multAcc_32x32_keep32_R(outR, *pIn1, CoefA2);
255
 
256
        /* pIn[2 * i + 1] * pATable[2 * i] */
257
        multAcc_32x32_keep32_R(outI, *pIn1++, CoefA1);
258
 
259
        /* pIn[2 * n - 2 * i] * pBTable[2 * i] */
260
        multAcc_32x32_keep32_R(outR, *pIn2, CoefA2);
261
        CoefB1 = *pCoefB;
262
 
263
        /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
264
        multSub_32x32_keep32_R(outI, *pIn2--, CoefB1);
265
 
266
        /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
267
        multAcc_32x32_keep32_R(outR, *pIn2, CoefB1);
268
 
269
        /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
270
        multAcc_32x32_keep32_R(outI, *pIn2--, CoefA2);
271
 
272
        /* write output */
273
        *pDst++ = outR;
274
        *pDst++ = outI;
275
 
276
        /* update coefficient pointer */
277
        pCoefB = pCoefB + (modifier * 2U);
278
        pCoefA = pCoefA + ((modifier * 2U) - 1U);
279
 
280
        /* Decrement loop count */
281
        fftLen--;
282
    }
283
}