Added all the F4 libraries to the project
[fw/stlink] / exampleF4 / CMSIS / DSP_Lib / Source / FilteringFunctions / arm_fir_sparse_q31.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_sparse_q31.c   
9 *   
10 * Description:  Q31 sparse 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.7  2010/06/10    
30 *    Misra-C changes done   
31 * ------------------------------------------------------------------- */
32 #include "arm_math.h"
33
34
35 /**   
36  * @addtogroup FIR_Sparse   
37  * @{   
38  */
39
40 /**  
41  * @brief Processing function for the Q31 sparse FIR filter.  
42  * @param[in]  *S          points to an instance of the Q31 sparse FIR structure.  
43  * @param[in]  *pSrc       points to the block of input data.  
44  * @param[out] *pDst       points to the block of output data  
45  * @param[in]  *pScratchIn points to a temporary buffer of size blockSize.  
46  * @param[in]  blockSize   number of input samples to process per call.  
47  * @return none.  
48  *   
49  * <b>Scaling and Overflow Behavior:</b>   
50  * \par   
51  * The function is implemented using an internal 32-bit accumulator.  
52  * The 1.31 x 1.31 multiplications are truncated to 2.30 format.  
53  * This leads to loss of precision on the intermediate multiplications and provides only a single guard bit.   
54  * If the accumulator result overflows, it wraps around rather than saturate.  
55  * In order to avoid overflows the input signal or coefficients must be scaled down by log2(numTaps) bits.  
56  */
57
58 void arm_fir_sparse_q31(
59   arm_fir_sparse_instance_q31 * S,
60   q31_t * pSrc,
61   q31_t * pDst,
62   q31_t * pScratchIn,
63   uint32_t blockSize)
64 {
65
66   q31_t *pState = S->pState;                     /* State pointer */
67   q31_t *pCoeffs = S->pCoeffs;                   /* Coefficient pointer */
68   q31_t *px;                                     /* Scratch buffer pointer */
69   q31_t *py = pState;                            /* Temporary pointers for state buffer */
70   q31_t *pb = pScratchIn;                        /* Temporary pointers for scratch buffer */
71   q31_t *pOut;                                   /* Destination pointer */
72   q63_t out;                                     /* Temporary output variable */
73   int32_t *pTapDelay = S->pTapDelay;             /* Pointer to the array containing offset of the non-zero tap values. */
74   uint32_t delaySize = S->maxDelay + blockSize;  /* state length */
75   uint16_t numTaps = S->numTaps;                 /* Filter order */
76   int32_t readIndex;                             /* Read index of the state buffer */
77   uint32_t tapCnt, blkCnt;                       /* loop counters */
78   q31_t coeff = *pCoeffs++;                      /* Read the first coefficient value */
79   q31_t in;
80
81
82   /* BlockSize of Input samples are copied into the state buffer */
83   /* StateIndex points to the starting position to write in the state buffer */
84   arm_circularWrite_f32((int32_t *) py, delaySize, &S->stateIndex, 1,
85                         (int32_t *) pSrc, 1, blockSize);
86
87   /* Read Index, from where the state buffer should be read, is calculated. */
88   readIndex = (int32_t) (S->stateIndex - blockSize) - *pTapDelay++;
89
90   /* Wraparound of readIndex */
91   if(readIndex < 0)
92   {
93     readIndex += (int32_t) delaySize;
94   }
95
96   /* Working pointer for state buffer is updated */
97   py = pState;
98
99   /* blockSize samples are read from the state buffer */
100   arm_circularRead_f32((int32_t *) py, delaySize, &readIndex, 1,
101                        (int32_t *) pb, (int32_t *) pb, blockSize, 1,
102                        blockSize);
103
104   /* Working pointer for the scratch buffer of state values */
105   px = pb;
106
107   /* Working pointer for scratch buffer of output values */
108   pOut = pDst;
109
110
111 #ifndef ARM_MATH_CM0
112
113   /* Run the below code for Cortex-M4 and Cortex-M3 */
114
115   /* Loop over the blockSize. Unroll by a factor of 4.   
116    * Compute 4 Multiplications at a time. */
117   blkCnt = blockSize >> 2;
118
119   while(blkCnt > 0u)
120   {
121     /* Perform Multiplications and store in the destination buffer */
122     *pOut++ = (q31_t) (((q63_t) * px++ * coeff) >> 32);
123     *pOut++ = (q31_t) (((q63_t) * px++ * coeff) >> 32);
124     *pOut++ = (q31_t) (((q63_t) * px++ * coeff) >> 32);
125     *pOut++ = (q31_t) (((q63_t) * px++ * coeff) >> 32);
126
127     /* Decrement the loop counter */
128     blkCnt--;
129   }
130
131   /* If the blockSize is not a multiple of 4,   
132    * compute the remaining samples */
133   blkCnt = blockSize % 0x4u;
134
135   while(blkCnt > 0u)
136   {
137     /* Perform Multiplications and store in the destination buffer */
138     *pOut++ = (q31_t) (((q63_t) * px++ * coeff) >> 32);
139
140     /* Decrement the loop counter */
141     blkCnt--;
142   }
143
144   /* Load the coefficient value and   
145    * increment the coefficient buffer for the next set of state values */
146   coeff = *pCoeffs++;
147
148   /* Read Index, from where the state buffer should be read, is calculated. */
149   readIndex = (int32_t) (S->stateIndex - blockSize) - *pTapDelay++;
150
151   /* Wraparound of readIndex */
152   if(readIndex < 0)
153   {
154     readIndex += (int32_t) delaySize;
155   }
156
157   /* Loop over the number of taps. */
158   tapCnt = (uint32_t) numTaps - 1u;
159
160   while(tapCnt > 0u)
161   {
162     /* Working pointer for state buffer is updated */
163     py = pState;
164
165     /* blockSize samples are read from the state buffer */
166     arm_circularRead_f32((int32_t *) py, delaySize, &readIndex, 1,
167                          (int32_t *) pb, (int32_t *) pb, blockSize, 1,
168                          blockSize);
169
170     /* Working pointer for the scratch buffer of state values */
171     px = pb;
172
173     /* Working pointer for scratch buffer of output values */
174     pOut = pDst;
175
176     /* Loop over the blockSize. Unroll by a factor of 4.   
177      * Compute 4 MACS at a time. */
178     blkCnt = blockSize >> 2;
179
180     while(blkCnt > 0u)
181     {
182       out = *pOut;
183       out += ((q63_t) * px++ * coeff) >> 32;
184       *pOut++ = (q31_t) (out);
185
186       out = *pOut;
187       out += ((q63_t) * px++ * coeff) >> 32;
188       *pOut++ = (q31_t) (out);
189
190       out = *pOut;
191       out += ((q63_t) * px++ * coeff) >> 32;
192       *pOut++ = (q31_t) (out);
193
194       out = *pOut;
195       out += ((q63_t) * px++ * coeff) >> 32;
196       *pOut++ = (q31_t) (out);
197
198       /* Decrement the loop counter */
199       blkCnt--;
200     }
201
202     /* If the blockSize is not a multiple of 4,   
203      * compute the remaining samples */
204     blkCnt = blockSize % 0x4u;
205
206     while(blkCnt > 0u)
207     {
208       /* Perform Multiply-Accumulate */
209       out = *pOut;
210       out += ((q63_t) * px++ * coeff) >> 32;
211       *pOut++ = (q31_t) (out);
212
213       /* Decrement the loop counter */
214       blkCnt--;
215     }
216
217     /* Load the coefficient value and   
218      * increment the coefficient buffer for the next set of state values */
219     coeff = *pCoeffs++;
220
221     /* Read Index, from where the state buffer should be read, is calculated. */
222     readIndex = (int32_t) (S->stateIndex - blockSize) - *pTapDelay++;
223
224     /* Wraparound of readIndex */
225     if(readIndex < 0)
226     {
227       readIndex += (int32_t) delaySize;
228     }
229
230     /* Decrement the tap loop counter */
231     tapCnt--;
232   }
233
234   /* Working output pointer is updated */
235   pOut = pDst;
236
237   /* Output is converted into 1.31 format. */
238   /* Loop over the blockSize. Unroll by a factor of 4.   
239    * process 4 output samples at a time. */
240   blkCnt = blockSize >> 2;
241
242   while(blkCnt > 0u)
243   {
244     in = *pOut << 1;
245     *pOut++ = in;
246     in = *pOut << 1;
247     *pOut++ = in;
248     in = *pOut << 1;
249     *pOut++ = in;
250     in = *pOut << 1;
251     *pOut++ = in;
252
253     /* Decrement the loop counter */
254     blkCnt--;
255   }
256
257   /* If the blockSize is not a multiple of 4,   
258    * process the remaining output samples */
259   blkCnt = blockSize % 0x4u;
260
261   while(blkCnt > 0u)
262   {
263     in = *pOut << 1;
264     *pOut++ = in;
265
266     /* Decrement the loop counter */
267     blkCnt--;
268   }
269
270 #else
271
272   /* Run the below code for Cortex-M0 */
273   blkCnt = blockSize;
274
275   while(blkCnt > 0u)
276   {
277     /* Perform Multiplications and store in the destination buffer */
278     *pOut++ = (q31_t) (((q63_t) * px++ * coeff) >> 32);
279
280     /* Decrement the loop counter */
281     blkCnt--;
282   }
283
284   /* Load the coefficient value and          
285    * increment the coefficient buffer for the next set of state values */
286   coeff = *pCoeffs++;
287
288   /* Read Index, from where the state buffer should be read, is calculated. */
289   readIndex = (int32_t) (S->stateIndex - blockSize) - *pTapDelay++;
290
291   /* Wraparound of readIndex */
292   if(readIndex < 0)
293   {
294     readIndex += (int32_t) delaySize;
295   }
296
297   /* Loop over the number of taps. */
298   tapCnt = (uint32_t) numTaps - 1u;
299
300   while(tapCnt > 0u)
301   {
302     /* Working pointer for state buffer is updated */
303     py = pState;
304
305     /* blockSize samples are read from the state buffer */
306     arm_circularRead_f32((int32_t *) py, delaySize, &readIndex, 1,
307                          (int32_t *) pb, (int32_t *) pb, blockSize, 1,
308                          blockSize);
309
310     /* Working pointer for the scratch buffer of state values */
311     px = pb;
312
313     /* Working pointer for scratch buffer of output values */
314     pOut = pDst;
315
316     blkCnt = blockSize;
317
318     while(blkCnt > 0u)
319     {
320       /* Perform Multiply-Accumulate */
321       out = *pOut;
322       out += ((q63_t) * px++ * coeff) >> 32;
323       *pOut++ = (q31_t) (out);
324
325       /* Decrement the loop counter */
326       blkCnt--;
327     }
328
329     /* Load the coefficient value and          
330      * increment the coefficient buffer for the next set of state values */
331     coeff = *pCoeffs++;
332
333     /* Read Index, from where the state buffer should be read, is calculated. */
334     readIndex = (int32_t) (S->stateIndex - blockSize) - *pTapDelay++;
335
336     /* Wraparound of readIndex */
337     if(readIndex < 0)
338     {
339       readIndex += (int32_t) delaySize;
340     }
341
342     /* Decrement the tap loop counter */
343     tapCnt--;
344   }
345
346   /* Working output pointer is updated */
347   pOut = pDst;
348
349   /* Output is converted into 1.31 format. */
350   blkCnt = blockSize;
351
352   while(blkCnt > 0u)
353   {
354     in = *pOut << 1;
355     *pOut++ = in;
356
357     /* Decrement the loop counter */
358     blkCnt--;
359   }
360
361 #endif /*   #ifndef ARM_MATH_CM0 */
362
363 }
364
365 /**   
366  * @} end of FIR_Sparse group   
367  */