Added all the F4 libraries to the project
[fw/stlink] / exampleF4 / CMSIS / DSP_Lib / Source / FilteringFunctions / arm_fir_q15.c
1 /* ----------------------------------------------------------------------   
2 * Copyright (C) 2010 ARM Limited. All rights reserved.   
3 *   
4 * $Date:        15. July 2011  
5 * $Revision:    V1.0.10  
6 *   
7 * Project:          CMSIS DSP Library   
8 * Title:        arm_fir_q15.c   
9 *   
10 * Description:  Q15 FIR filter processing function.   
11 *   
12 * Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
13 *  
14 * Version 1.0.10 2011/7/15 
15 *    Big Endian support added and Merged M0 and M3/M4 Source code.  
16 *   
17 * Version 1.0.3 2010/11/29  
18 *    Re-organized the CMSIS folders and updated documentation.   
19 *    
20 * Version 1.0.2 2010/11/11   
21 *    Documentation updated.    
22 *   
23 * Version 1.0.1 2010/10/05    
24 *    Production release and review comments incorporated.   
25 *   
26 * Version 1.0.0 2010/09/20    
27 *    Production release and review comments incorporated.   
28 *   
29 * Version 0.0.5  2010/04/26    
30 *        incorporated review comments and updated with latest CMSIS layer   
31 *   
32 * Version 0.0.3  2010/03/10    
33 *    Initial version   
34 * -------------------------------------------------------------------- */
35
36 #include "arm_math.h"
37
38 /**   
39  * @ingroup groupFilters   
40  */
41
42 /**   
43  * @addtogroup FIR   
44  * @{   
45  */
46
47 /**   
48  * @brief Processing function for the Q15 FIR filter.   
49  * @param[in] *S points to an instance of the Q15 FIR structure.   
50  * @param[in] *pSrc points to the block of input data.   
51  * @param[out] *pDst points to the block of output data.   
52  * @param[in]  blockSize number of samples to process per call.   
53  * @return none.   
54  *   
55  * <b>Scaling and Overflow Behavior:</b>   
56  * \par   
57  * The function is implemented using a 64-bit internal accumulator.   
58  * Both coefficients and state variables are represented in 1.15 format and multiplications yield a 2.30 result.   
59  * The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format.   
60  * There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved.   
61  * After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits.   
62  * Lastly, the accumulator is saturated to yield a result in 1.15 format.   
63  *   
64  * \par   
65  * Refer to the function <code>arm_fir_fast_q15()</code> for a faster but less precise implementation of this function for Cortex-M3 and Cortex-M4.   
66  */
67
68 void arm_fir_q15(
69   const arm_fir_instance_q15 * S,
70   q15_t * pSrc,
71   q15_t * pDst,
72   uint32_t blockSize)
73 {
74   q15_t *pState = S->pState;                     /* State pointer */
75   q15_t *pCoeffs = S->pCoeffs;                   /* Coefficient pointer */
76   q15_t *pStateCurnt;                            /* Points to the current sample of the state */
77
78
79 #ifndef ARM_MATH_CM0
80
81   /* Run the below code for Cortex-M4 and Cortex-M3 */
82
83   q15_t *px1;                                    /* Temporary q15 pointer for state buffer */
84   q31_t *pb;                                     /* Temporary pointer for coefficient buffer */
85   q31_t *px2;                                    /* Temporary q31 pointer for SIMD state buffer accesses */
86   q31_t x0, x1, x2, x3, c0;                      /* Temporary variables to hold SIMD state and coefficient values */
87   q63_t acc0, acc1, acc2, acc3;                  /* Accumulators */
88   uint32_t numTaps = S->numTaps;                 /* Number of taps in the filter */
89   uint32_t tapCnt, blkCnt;                       /* Loop counters */
90
91   /* S->pState points to state array which contains previous frame (numTaps - 1) samples */
92   /* pStateCurnt points to the location where the new input data should be written */
93   pStateCurnt = &(S->pState[(numTaps - 1u)]);
94
95   /* Apply loop unrolling and compute 4 output values simultaneously.   
96    * The variables acc0 ... acc3 hold output values that are being computed:   
97    *   
98    *    acc0 =  b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0]   
99    *    acc1 =  b[numTaps-1] * x[n-numTaps] +   b[numTaps-2] * x[n-numTaps-1] + b[numTaps-3] * x[n-numTaps-2] +...+ b[0] * x[1]   
100    *    acc2 =  b[numTaps-1] * x[n-numTaps+1] + b[numTaps-2] * x[n-numTaps] +   b[numTaps-3] * x[n-numTaps-1] +...+ b[0] * x[2]   
101    *    acc3 =  b[numTaps-1] * x[n-numTaps+2] + b[numTaps-2] * x[n-numTaps+1] + b[numTaps-3] * x[n-numTaps]   +...+ b[0] * x[3]   
102    */
103   blkCnt = blockSize >> 2;
104
105   /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.   
106    ** a second loop below computes the remaining 1 to 3 samples. */
107   while(blkCnt > 0u)
108   {
109     /* Copy four new input samples into the state buffer.   
110      ** Use 32-bit SIMD to move the 16-bit data.  Only requires two copies. */
111     *__SIMD32(pStateCurnt)++ = *__SIMD32(pSrc)++;
112     *__SIMD32(pStateCurnt)++ = *__SIMD32(pSrc)++;
113
114     /* Set all accumulators to zero */
115     acc0 = 0;
116     acc1 = 0;
117     acc2 = 0;
118     acc3 = 0;
119
120     /* Initialize state pointer of type q15 */
121     px1 = pState;
122
123     /* Initialize coeff pointer of type q31 */
124     pb = (q31_t *) (pCoeffs);
125
126     /* Read the first two samples from the state buffer:  x[n-N], x[n-N-1] */
127     x0 = *(q31_t *) (px1++);
128
129     /* Read the third and forth samples from the state buffer: x[n-N-1], x[n-N-2] */
130     x1 = *(q31_t *) (px1++);
131
132     /* Loop over the number of taps.  Unroll by a factor of 4.   
133      ** Repeat until we've computed numTaps-4 coefficients. */
134     tapCnt = numTaps >> 2;
135     do
136     {
137       /* Read the first two coefficients using SIMD:  b[N] and b[N-1] coefficients */
138       c0 = *(pb++);
139
140       /* acc0 +=  b[N] * x[n-N] + b[N-1] * x[n-N-1] */
141       acc0 = __SMLALD(x0, c0, acc0);
142
143       /* acc1 +=  b[N] * x[n-N-1] + b[N-1] * x[n-N-2] */
144       acc1 = __SMLALD(x1, c0, acc1);
145
146       /* Read state x[n-N-2], x[n-N-3] */
147       x2 = *(q31_t *) (px1++);
148
149       /* Read state x[n-N-3], x[n-N-4] */
150       x3 = *(q31_t *) (px1++);
151
152       /* acc2 +=  b[N] * x[n-N-2] + b[N-1] * x[n-N-3] */
153       acc2 = __SMLALD(x2, c0, acc2);
154
155       /* acc3 +=  b[N] * x[n-N-3] + b[N-1] * x[n-N-4] */
156       acc3 = __SMLALD(x3, c0, acc3);
157
158       /* Read coefficients b[N-2], b[N-3] */
159       c0 = *(pb++);
160
161       /* acc0 +=  b[N-2] * x[n-N-2] + b[N-3] * x[n-N-3] */
162       acc0 = __SMLALD(x2, c0, acc0);
163
164       /* acc1 +=  b[N-2] * x[n-N-3] + b[N-3] * x[n-N-4] */
165       acc1 = __SMLALD(x3, c0, acc1);
166
167       /* Read state x[n-N-4], x[n-N-5] */
168       x0 = *(q31_t *) (px1++);
169
170       /* Read state x[n-N-5], x[n-N-6] */
171       x1 = *(q31_t *) (px1++);
172
173       /* acc2 +=  b[N-2] * x[n-N-4] + b[N-3] * x[n-N-5] */
174       acc2 = __SMLALD(x0, c0, acc2);
175
176       /* acc3 +=  b[N-2] * x[n-N-5] + b[N-3] * x[n-N-6] */
177       acc3 = __SMLALD(x1, c0, acc3);
178       tapCnt--;
179
180     }
181     while(tapCnt > 0u);
182
183     /* If the filter length is not a multiple of 4, compute the remaining filter taps.   
184      ** This is always be 2 taps since the filter length is even. */
185     if((numTaps & 0x3u) != 0u)
186     {
187       /* Read 2 coefficients */
188       c0 = *(pb++);
189       /* Fetch 4 state variables */
190       x2 = *(q31_t *) (px1++);
191       x3 = *(q31_t *) (px1++);
192
193       /* Perform the multiply-accumulates */
194       acc0 = __SMLALD(x0, c0, acc0);
195       acc1 = __SMLALD(x1, c0, acc1);
196       acc2 = __SMLALD(x2, c0, acc2);
197       acc3 = __SMLALD(x3, c0, acc3);
198     }
199
200     /* The results in the 4 accumulators are in 2.30 format.  Convert to 1.15 with saturation.   
201      ** Then store the 4 outputs in the destination buffer. */
202
203 #ifndef ARM_MATH_BIG_ENDIAN
204
205     *__SIMD32(pDst)++ =
206       __PKHBT(__SSAT((acc0 >> 15), 16), __SSAT((acc1 >> 15), 16), 16);
207     *__SIMD32(pDst)++ =
208       __PKHBT(__SSAT((acc2 >> 15), 16), __SSAT((acc3 >> 15), 16), 16);
209
210 #else
211
212     *__SIMD32(pDst)++ =
213       __PKHBT(__SSAT((acc1 >> 15), 16), __SSAT((acc0 >> 15), 16), 16);
214     *__SIMD32(pDst)++ =
215       __PKHBT(__SSAT((acc3 >> 15), 16), __SSAT((acc2 >> 15), 16), 16);
216
217 #endif /*      #ifndef ARM_MATH_BIG_ENDIAN       */
218
219     /* Advance the state pointer by 4 to process the next group of 4 samples */
220     pState = pState + 4;
221
222     /* Decrement the loop counter */
223     blkCnt--;
224   }
225
226   /* If the blockSize is not a multiple of 4, compute any remaining output samples here.   
227    ** No loop unrolling is used. */
228   blkCnt = blockSize % 0x4u;
229   while(blkCnt > 0u)
230   {
231     /* Copy two samples into state buffer */
232     *pStateCurnt++ = *pSrc++;
233
234     /* Set the accumulator to zero */
235     acc0 = 0;
236
237     /* Use SIMD to hold states and coefficients */
238     px2 = (q31_t *) pState;
239     pb = (q31_t *) (pCoeffs);
240     tapCnt = numTaps >> 1;
241
242     do
243     {
244       acc0 = __SMLALD(*px2++, *(pb++), acc0);
245       tapCnt--;
246     }
247     while(tapCnt > 0u);
248
249     /* The result is in 2.30 format.  Convert to 1.15 with saturation.   
250      ** Then store the output in the destination buffer. */
251     *pDst++ = (q15_t) (__SSAT((acc0 >> 15), 16));
252
253     /* Advance state pointer by 1 for the next sample */
254     pState = pState + 1;
255
256     /* Decrement the loop counter */
257     blkCnt--;
258   }
259
260   /* Processing is complete.   
261    ** Now copy the last numTaps - 1 samples to the satrt of the state buffer.   
262    ** This prepares the state buffer for the next function call. */
263
264   /* Points to the start of the state buffer */
265   pStateCurnt = S->pState;
266
267   /* Calculation of count for copying integer writes */
268   tapCnt = (numTaps - 1u) >> 2;
269
270   while(tapCnt > 0u)
271   {
272     *__SIMD32(pStateCurnt)++ = *__SIMD32(pState)++;
273     *__SIMD32(pStateCurnt)++ = *__SIMD32(pState)++;
274
275     tapCnt--;
276
277   }
278
279   /* Calculation of count for remaining q15_t data */
280   tapCnt = (numTaps - 1u) % 0x4u;
281
282   /* copy remaining data */
283   while(tapCnt > 0u)
284   {
285     *pStateCurnt++ = *pState++;
286
287     /* Decrement the loop counter */
288     tapCnt--;
289   }
290
291 #else
292
293   /* Run the below code for Cortex-M0 */
294
295   q15_t *px;                                     /* Temporary pointer for state buffer */
296   q15_t *pb;                                     /* Temporary pointer for coefficient buffer */
297   q63_t acc;                                     /* Accumulator */
298   uint32_t numTaps = S->numTaps;                 /* Number of nTaps in the filter */
299   uint32_t tapCnt, blkCnt;                       /* Loop counters */
300
301   /* S->pState buffer contains previous frame (numTaps - 1) samples */
302   /* pStateCurnt points to the location where the new input data should be written */
303   pStateCurnt = &(S->pState[(numTaps - 1u)]);
304
305   /* Initialize blkCnt with blockSize */
306   blkCnt = blockSize;
307
308   while(blkCnt > 0u)
309   {
310     /* Copy one sample at a time into state buffer */
311     *pStateCurnt++ = *pSrc++;
312
313     /* Set the accumulator to zero */
314     acc = 0;
315
316     /* Initialize state pointer */
317     px = pState;
318
319     /* Initialize Coefficient pointer */
320     pb = pCoeffs;
321
322     tapCnt = numTaps;
323
324     /* Perform the multiply-accumulates */
325     do
326     {
327       /* acc =  b[numTaps-1] * x[n-numTaps-1] + b[numTaps-2] * x[n-numTaps-2] + b[numTaps-3] * x[n-numTaps-3] +...+ b[0] * x[0] */
328       acc += (q31_t) * px++ * *pb++;
329       tapCnt--;
330     } while(tapCnt > 0u);
331
332     /* The result is in 2.30 format.  Convert to 1.15        
333      ** Then store the output in the destination buffer. */
334     *pDst++ = (q15_t) __SSAT((acc >> 15u), 16);
335
336     /* Advance state pointer by 1 for the next sample */
337     pState = pState + 1;
338
339     /* Decrement the samples loop counter */
340     blkCnt--;
341   }
342
343   /* Processing is complete.        
344    ** Now copy the last numTaps - 1 samples to the satrt of the state buffer.      
345    ** This prepares the state buffer for the next function call. */
346
347   /* Points to the start of the state buffer */
348   pStateCurnt = S->pState;
349
350   /* Copy numTaps number of values */
351   tapCnt = (numTaps - 1u);
352
353   /* copy data */
354   while(tapCnt > 0u)
355   {
356     *pStateCurnt++ = *pState++;
357
358     /* Decrement the loop counter */
359     tapCnt--;
360   }
361
362 #endif /* #ifndef ARM_MATH_CM0 */
363
364 }
365
366 /**   
367  * @} end of FIR group   
368  */