Subversion Repositories DashDisplay

Rev

Rev 28 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 mjames 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_rfft_q31.c    
9
*    
10
* Description:  RFFT & RIFFT Q31 process function    
11
*    
12
*    
13
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
14
*  
15
* Redistribution and use in source and binary forms, with or without
16
* modification, are permitted provided that the following conditions
17
* are met:
18
*   - Redistributions of source code must retain the above copyright
19
*     notice, this list of conditions and the following disclaimer.
20
*   - Redistributions in binary form must reproduce the above copyright
21
*     notice, this list of conditions and the following disclaimer in
22
*     the documentation and/or other materials provided with the
23
*     distribution.
24
*   - Neither the name of ARM LIMITED nor the names of its contributors
25
*     may be used to endorse or promote products derived from this
26
*     software without specific prior written permission.
27
*
28
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39
* POSSIBILITY OF SUCH DAMAGE.    
40
* -------------------------------------------------------------------- */
41
 
42
#include "arm_math.h"
43
 
44
/*--------------------------------------------------------------------    
45
*               Internal functions prototypes    
46
--------------------------------------------------------------------*/
47
 
48
void arm_split_rfft_q31(
49
    q31_t * pSrc,
50
    uint32_t fftLen,
51
    q31_t * pATable,
52
    q31_t * pBTable,
53
    q31_t * pDst,
54
    uint32_t modifier);
55
 
56
void arm_split_rifft_q31(
57
    q31_t * pSrc,
58
    uint32_t fftLen,
59
    q31_t * pATable,
60
    q31_t * pBTable,
61
    q31_t * pDst,
62
    uint32_t modifier);
63
 
64
/**    
65
* @addtogroup RealFFT    
66
* @{    
67
*/
68
 
69
/**    
70
* @brief Processing function for the Q31 RFFT/RIFFT.  
71
* @param[in]  *S    points to an instance of the Q31 RFFT/RIFFT structure.  
72
* @param[in]  *pSrc points to the input buffer.  
73
* @param[out] *pDst points to the output buffer.  
74
* @return none.  
75
*    
76
* \par Input an output formats:  
77
* \par    
78
* Internally input is downscaled by 2 for every stage to avoid saturations inside CFFT/CIFFT process.  
79
* Hence the output format is different for different RFFT sizes.    
80
* 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:  
81
* \par    
82
* \image html RFFTQ31.gif "Input and Output Formats for Q31 RFFT"    
83
*    
84
* \par    
85
* \image html RIFFTQ31.gif "Input and Output Formats for Q31 RIFFT"    
86
*/
87
void arm_rfft_q31(
88
    const arm_rfft_instance_q31 * S,
89
    q31_t * pSrc,
90
    q31_t * pDst)
91
{
92
    const arm_cfft_instance_q31 *S_CFFT = S->pCfft;
93
    uint32_t i;
94
    uint32_t L2 = S->fftLenReal >> 1;
95
 
96
    /* Calculation of RIFFT of input */
97
    if(S->ifftFlagR == 1u)
98
    {
99
        /*  Real IFFT core process */
100
        arm_split_rifft_q31(pSrc, L2, S->pTwiddleAReal,
101
                            S->pTwiddleBReal, pDst, S->twidCoefRModifier);
102
 
103
        /* Complex IFFT process */
104
        arm_cfft_q31(S_CFFT, pDst, S->ifftFlagR, S->bitReverseFlagR);
105
 
106
        for(i=0;i<S->fftLenReal;i++)
107
        {
108
            pDst[i] = pDst[i] << 1;
109
        }
110
    }
111
    else
112
    {
113
        /* Calculation of RFFT of input */
114
 
115
        /* Complex FFT process */
116
        arm_cfft_q31(S_CFFT, pSrc, S->ifftFlagR, S->bitReverseFlagR);
117
 
118
        /*  Real FFT core process */
119
        arm_split_rfft_q31(pSrc, L2, S->pTwiddleAReal,
120
                            S->pTwiddleBReal, pDst, S->twidCoefRModifier);
121
    }
122
}
123
 
124
/**    
125
* @} end of RealFFT group    
126
*/
127
 
128
/**    
129
* @brief  Core Real FFT process    
130
* @param[in]   *pSrc                            points to the input buffer.    
131
* @param[in]   fftLen                       length of FFT.  
132
* @param[in]   *pATable                         points to the twiddle Coef A buffer.    
133
* @param[in]   *pBTable                         points to the twiddle Coef B buffer.    
134
* @param[out]  *pDst                            points to the output buffer.    
135
* @param[in]   modifier                 twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.  
136
* @return none.    
137
*/
138
void arm_split_rfft_q31(
139
    q31_t * pSrc,
140
    uint32_t fftLen,
141
    q31_t * pATable,
142
    q31_t * pBTable,
143
    q31_t * pDst,
144
    uint32_t modifier)
145
{
146
    uint32_t i;                                    /* Loop Counter */
147
    q31_t outR, outI;                              /* Temporary variables for output */
148
    q31_t *pCoefA, *pCoefB;                        /* Temporary pointers for twiddle factors */
149
    q31_t CoefA1, CoefA2, CoefB1;                  /* Temporary variables for twiddle coefficients */
150
    q31_t *pOut1 = &pDst[2], *pOut2 = &pDst[(4u * fftLen) - 1u];
151
    q31_t *pIn1 = &pSrc[2], *pIn2 = &pSrc[(2u * fftLen) - 1u];
152
 
153
    /* Init coefficient pointers */
154
    pCoefA = &pATable[modifier * 2u];
155
    pCoefB = &pBTable[modifier * 2u];
156
 
157
    i = fftLen - 1u;
158
 
159
    while(i > 0u)
160
    {
161
        /*    
162
        outR = (pSrc[2 * i] * pATable[2 * i] - pSrc[2 * i + 1] * pATable[2 * i + 1]    
163
        + pSrc[2 * n - 2 * i] * pBTable[2 * i] +    
164
        pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);    
165
        */
166
 
167
        /* outI = (pIn[2 * i + 1] * pATable[2 * i] + pIn[2 * i] * pATable[2 * i + 1] +    
168
        pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -    
169
        pIn[2 * n - 2 * i + 1] * pBTable[2 * i]); */
170
 
171
        CoefA1 = *pCoefA++;
172
        CoefA2 = *pCoefA;
173
 
174
        /* outR = (pSrc[2 * i] * pATable[2 * i] */    
175
        mult_32x32_keep32_R(outR, *pIn1, CoefA1);
176
 
177
        /* outI = pIn[2 * i] * pATable[2 * i + 1] */
178
        mult_32x32_keep32_R(outI, *pIn1++, CoefA2);
179
 
180
        /* - pSrc[2 * i + 1] * pATable[2 * i + 1] */
181
        multSub_32x32_keep32_R(outR, *pIn1, CoefA2);
182
 
183
        /* (pIn[2 * i + 1] * pATable[2 * i] */
184
        multAcc_32x32_keep32_R(outI, *pIn1++, CoefA1);
185
 
186
        /* pSrc[2 * n - 2 * i] * pBTable[2 * i]  */
187
        multSub_32x32_keep32_R(outR, *pIn2, CoefA2);
188
        CoefB1 = *pCoefB;
189
 
190
        /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
191
        multSub_32x32_keep32_R(outI, *pIn2--, CoefB1);
192
 
193
        /* pSrc[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
194
        multAcc_32x32_keep32_R(outR, *pIn2, CoefB1);
195
 
196
        /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
197
        multSub_32x32_keep32_R(outI, *pIn2--, CoefA2);
198
 
199
        /* write output */
200
        *pOut1++ = outR;
201
        *pOut1++ = outI;
202
 
203
        /* write complex conjugate output */
204
        *pOut2-- = -outI;
205
        *pOut2-- = outR;
206
 
207
        /* update coefficient pointer */
208
        pCoefB = pCoefB + (modifier * 2u);
209
        pCoefA = pCoefA + ((modifier * 2u) - 1u);
210
 
211
        i--;
212
    }
213
    pDst[2u * fftLen] = (pSrc[0] - pSrc[1]) >> 1;
214
    pDst[(2u * fftLen) + 1u] = 0;
215
 
216
    pDst[0] = (pSrc[0] + pSrc[1]) >> 1;
217
    pDst[1] = 0;
218
}
219
 
220
/**    
221
* @brief  Core Real IFFT process    
222
* @param[in]   *pSrc                            points to the input buffer.  
223
* @param[in]   fftLen                       length of FFT.    
224
* @param[in]   *pATable                         points to the twiddle Coef A buffer.  
225
* @param[in]   *pBTable                         points to the twiddle Coef B buffer.    
226
* @param[out]  *pDst                            points to the output buffer.  
227
* @param[in]   modifier                 twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table.  
228
* @return none.    
229
*/
230
void arm_split_rifft_q31(
231
    q31_t * pSrc,
232
    uint32_t fftLen,
233
    q31_t * pATable,
234
    q31_t * pBTable,
235
    q31_t * pDst,
236
    uint32_t modifier)
237
{
238
    q31_t outR, outI;                              /* Temporary variables for output */
239
    q31_t *pCoefA, *pCoefB;                        /* Temporary pointers for twiddle factors */
240
    q31_t CoefA1, CoefA2, CoefB1;                  /* Temporary variables for twiddle coefficients */
241
    q31_t *pIn1 = &pSrc[0], *pIn2 = &pSrc[(2u * fftLen) + 1u];
242
 
243
    pCoefA = &pATable[0];
244
    pCoefB = &pBTable[0];
245
 
246
    while(fftLen > 0u)
247
    {
248
        /*    
249
        outR = (pIn[2 * i] * pATable[2 * i] + pIn[2 * i + 1] * pATable[2 * i + 1] +    
250
        pIn[2 * n - 2 * i] * pBTable[2 * i] -    
251
        pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1]);    
252
 
253
        outI = (pIn[2 * i + 1] * pATable[2 * i] - pIn[2 * i] * pATable[2 * i + 1] -    
254
        pIn[2 * n - 2 * i] * pBTable[2 * i + 1] -    
255
        pIn[2 * n - 2 * i + 1] * pBTable[2 * i]);  
256
        */
257
        CoefA1 = *pCoefA++;
258
        CoefA2 = *pCoefA;
259
 
260
        /* outR = (pIn[2 * i] * pATable[2 * i] */
261
        mult_32x32_keep32_R(outR, *pIn1, CoefA1);
262
 
263
        /* - pIn[2 * i] * pATable[2 * i + 1] */
264
        mult_32x32_keep32_R(outI, *pIn1++, -CoefA2);
265
 
266
        /* pIn[2 * i + 1] * pATable[2 * i + 1] */
267
        multAcc_32x32_keep32_R(outR, *pIn1, CoefA2);
268
 
269
        /* pIn[2 * i + 1] * pATable[2 * i] */
270
        multAcc_32x32_keep32_R(outI, *pIn1++, CoefA1);
271
 
272
        /* pIn[2 * n - 2 * i] * pBTable[2 * i] */
273
        multAcc_32x32_keep32_R(outR, *pIn2, CoefA2);
274
        CoefB1 = *pCoefB;
275
 
276
        /* pIn[2 * n - 2 * i] * pBTable[2 * i + 1] */
277
        multSub_32x32_keep32_R(outI, *pIn2--, CoefB1);
278
 
279
        /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i + 1] */
280
        multAcc_32x32_keep32_R(outR, *pIn2, CoefB1);
281
 
282
        /* pIn[2 * n - 2 * i + 1] * pBTable[2 * i] */
283
        multAcc_32x32_keep32_R(outI, *pIn2--, CoefA2);
284
 
285
        /* write output */
286
        *pDst++ = outR;
287
        *pDst++ = outI;
288
 
289
        /* update coefficient pointer */
290
        pCoefB = pCoefB + (modifier * 2u);
291
        pCoefA = pCoefA + ((modifier * 2u) - 1u);
292
 
293
        /* Decrement loop count */
294
        fftLen--;
295
    }
296
}