]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/dsp/cmsis_dsp/FilteringFunctions/arm_biquad_cascade_df1_f32.c
Merge commit '1fe4406f374291ab2e86e95a97341fd9c475fcb8'
[qmk_firmware.git] / tmk_core / tool / mbed / mbed-sdk / libraries / dsp / cmsis_dsp / FilteringFunctions / arm_biquad_cascade_df1_f32.c
1 /* ----------------------------------------------------------------------    
2 * Copyright (C) 2010-2013 ARM Limited. All rights reserved.    
3 *    
4 * $Date:        17. January 2013
5 * $Revision:    V1.4.1
6 *    
7 * Project:          CMSIS DSP Library    
8 * Title:            arm_biquad_cascade_df1_f32.c    
9 *    
10 * Description:  Processing function for the    
11 *               floating-point Biquad cascade DirectFormI(DF1) filter.    
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  * @ingroup groupFilters    
46  */
47
48 /**    
49  * @defgroup BiquadCascadeDF1 Biquad Cascade IIR Filters Using Direct Form I Structure    
50  *    
51  * This set of functions implements arbitrary order recursive (IIR) filters.    
52  * The filters are implemented as a cascade of second order Biquad sections.    
53  * The functions support Q15, Q31 and floating-point data types.  
54  * Fast version of Q15 and Q31 also supported on CortexM4 and Cortex-M3.    
55  *    
56  * The functions operate on blocks of input and output data and each call to the function    
57  * processes <code>blockSize</code> samples through the filter.    
58  * <code>pSrc</code> points to the array of input data and    
59  * <code>pDst</code> points to the array of output data.    
60  * Both arrays contain <code>blockSize</code> values.    
61  *    
62  * \par Algorithm    
63  * Each Biquad stage implements a second order filter using the difference equation:    
64  * <pre>    
65  *     y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2]    
66  * </pre>    
67  * A Direct Form I algorithm is used with 5 coefficients and 4 state variables per stage.    
68  * \image html Biquad.gif "Single Biquad filter stage"    
69  * Coefficients <code>b0, b1 and b2 </code> multiply the input signal <code>x[n]</code> and are referred to as the feedforward coefficients.    
70  * Coefficients <code>a1</code> and <code>a2</code> multiply the output signal <code>y[n]</code> and are referred to as the feedback coefficients.    
71  * Pay careful attention to the sign of the feedback coefficients.    
72  * Some design tools use the difference equation    
73  * <pre>    
74  *     y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a2 * y[n-2]    
75  * </pre>    
76  * In this case the feedback coefficients <code>a1</code> and <code>a2</code> must be negated when used with the CMSIS DSP Library.    
77  *    
78  * \par    
79  * Higher order filters are realized as a cascade of second order sections.    
80  * <code>numStages</code> refers to the number of second order stages used.    
81  * For example, an 8th order filter would be realized with <code>numStages=4</code> second order stages.    
82  * \image html BiquadCascade.gif "8th order filter using a cascade of Biquad stages"    
83  * A 9th order filter would be realized with <code>numStages=5</code> second order stages with the coefficients for one of the stages configured as a first order filter (<code>b2=0</code> and <code>a2=0</code>).    
84  *    
85  * \par    
86  * The <code>pState</code> points to state variables array.    
87  * Each Biquad stage has 4 state variables <code>x[n-1], x[n-2], y[n-1],</code> and <code>y[n-2]</code>.    
88  * The state variables are arranged in the <code>pState</code> array as:    
89  * <pre>    
90  *     {x[n-1], x[n-2], y[n-1], y[n-2]}    
91  * </pre>    
92  *    
93  * \par    
94  * The 4 state variables for stage 1 are first, then the 4 state variables for stage 2, and so on.    
95  * The state array has a total length of <code>4*numStages</code> values.    
96  * The state variables are updated after each block of data is processed, the coefficients are untouched.    
97  *    
98  * \par Instance Structure    
99  * The coefficients and state variables for a filter are stored together in an instance data structure.    
100  * A separate instance structure must be defined for each filter.    
101  * Coefficient arrays may be shared among several instances while state variable arrays cannot be shared.    
102  * There are separate instance structure declarations for each of the 3 supported data types.    
103  *    
104  * \par Init Functions    
105  * There is also an associated initialization function for each data type.    
106  * The initialization function performs following operations:    
107  * - Sets the values of the internal structure fields.    
108  * - Zeros out the values in the state buffer.    
109  * To do this manually without calling the init function, assign the follow subfields of the instance structure:
110  * numStages, pCoeffs, pState. Also set all of the values in pState to zero. 
111  *    
112  * \par    
113  * Use of the initialization function is optional.    
114  * However, if the initialization function is used, then the instance structure cannot be placed into a const data section.    
115  * To place an instance structure into a const data section, the instance structure must be manually initialized.    
116  * Set the values in the state buffer to zeros before static initialization.    
117  * The code below statically initializes each of the 3 different data type filter instance structures    
118  * <pre>    
119  *     arm_biquad_casd_df1_inst_f32 S1 = {numStages, pState, pCoeffs};    
120  *     arm_biquad_casd_df1_inst_q15 S2 = {numStages, pState, pCoeffs, postShift};    
121  *     arm_biquad_casd_df1_inst_q31 S3 = {numStages, pState, pCoeffs, postShift};    
122  * </pre>    
123  * where <code>numStages</code> is the number of Biquad stages in the filter; <code>pState</code> is the address of the state buffer;    
124  * <code>pCoeffs</code> is the address of the coefficient buffer; <code>postShift</code> shift to be applied.    
125  *    
126  * \par Fixed-Point Behavior    
127  * Care must be taken when using the Q15 and Q31 versions of the Biquad Cascade filter functions.    
128  * Following issues must be considered:    
129  * - Scaling of coefficients    
130  * - Filter gain    
131  * - Overflow and saturation    
132  *    
133  * \par    
134  * <b>Scaling of coefficients: </b>    
135  * Filter coefficients are represented as fractional values and    
136  * coefficients are restricted to lie in the range <code>[-1 +1)</code>.    
137  * The fixed-point functions have an additional scaling parameter <code>postShift</code>    
138  * which allow the filter coefficients to exceed the range <code>[+1 -1)</code>.    
139  * At the output of the filter's accumulator is a shift register which shifts the result by <code>postShift</code> bits.    
140  * \image html BiquadPostshift.gif "Fixed-point Biquad with shift by postShift bits after accumulator"    
141  * This essentially scales the filter coefficients by <code>2^postShift</code>.    
142  * For example, to realize the coefficients    
143  * <pre>    
144  *    {1.5, -0.8, 1.2, 1.6, -0.9}    
145  * </pre>    
146  * set the pCoeffs array to:    
147  * <pre>    
148  *    {0.75, -0.4, 0.6, 0.8, -0.45}    
149  * </pre>    
150  * and set <code>postShift=1</code>    
151  *    
152  * \par    
153  * <b>Filter gain: </b>    
154  * The frequency response of a Biquad filter is a function of its coefficients.    
155  * It is possible for the gain through the filter to exceed 1.0 meaning that the filter increases the amplitude of certain frequencies.    
156  * This means that an input signal with amplitude < 1.0 may result in an output > 1.0 and these are saturated or overflowed based on the implementation of the filter.    
157  * To avoid this behavior the filter needs to be scaled down such that its peak gain < 1.0 or the input signal must be scaled down so that the combination of input and filter are never overflowed.    
158  *    
159  * \par    
160  * <b>Overflow and saturation: </b>    
161  * For Q15 and Q31 versions, it is described separately as part of the function specific documentation below.    
162  */
163
164 /**    
165  * @addtogroup BiquadCascadeDF1    
166  * @{    
167  */
168
169 /**    
170  * @param[in]  *S         points to an instance of the floating-point Biquad cascade structure.    
171  * @param[in]  *pSrc      points to the block of input data.    
172  * @param[out] *pDst      points to the block of output data.    
173  * @param[in]  blockSize  number of samples to process per call.    
174  * @return     none.    
175  *    
176  */
177
178 void arm_biquad_cascade_df1_f32(
179   const arm_biquad_casd_df1_inst_f32 * S,
180   float32_t * pSrc,
181   float32_t * pDst,
182   uint32_t blockSize)
183 {
184   float32_t *pIn = pSrc;                         /*  source pointer            */
185   float32_t *pOut = pDst;                        /*  destination pointer       */
186   float32_t *pState = S->pState;                 /*  pState pointer            */
187   float32_t *pCoeffs = S->pCoeffs;               /*  coefficient pointer       */
188   float32_t acc;                                 /*  Simulates the accumulator */
189   float32_t b0, b1, b2, a1, a2;                  /*  Filter coefficients       */
190   float32_t Xn1, Xn2, Yn1, Yn2;                  /*  Filter pState variables   */
191   float32_t Xn;                                  /*  temporary input           */
192   uint32_t sample, stage = S->numStages;         /*  loop counters             */
193
194
195 #ifndef ARM_MATH_CM0_FAMILY
196
197   /* Run the below code for Cortex-M4 and Cortex-M3 */
198
199   do
200   {
201     /* Reading the coefficients */
202     b0 = *pCoeffs++;
203     b1 = *pCoeffs++;
204     b2 = *pCoeffs++;
205     a1 = *pCoeffs++;
206     a2 = *pCoeffs++;
207
208     /* Reading the pState values */
209     Xn1 = pState[0];
210     Xn2 = pState[1];
211     Yn1 = pState[2];
212     Yn2 = pState[3];
213
214     /* Apply loop unrolling and compute 4 output values simultaneously. */
215     /*      The variable acc hold output values that are being computed:    
216      *    
217      *    acc =  b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1]   + a2 * y[n-2]    
218      *    acc =  b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1]   + a2 * y[n-2]    
219      *    acc =  b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1]   + a2 * y[n-2]    
220      *    acc =  b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1]   + a2 * y[n-2]    
221      */
222
223     sample = blockSize >> 2u;
224
225     /* First part of the processing with loop unrolling.  Compute 4 outputs at a time.    
226      ** a second loop below computes the remaining 1 to 3 samples. */
227     while(sample > 0u)
228     {
229       /* Read the first input */
230       Xn = *pIn++;
231
232       /* acc =  b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
233       Yn2 = (b0 * Xn) + (b1 * Xn1) + (b2 * Xn2) + (a1 * Yn1) + (a2 * Yn2);
234
235       /* Store the result in the accumulator in the destination buffer. */
236       *pOut++ = Yn2;
237
238       /* Every time after the output is computed state should be updated. */
239       /* The states should be updated as:  */
240       /* Xn2 = Xn1    */
241       /* Xn1 = Xn     */
242       /* Yn2 = Yn1    */
243       /* Yn1 = acc   */
244
245       /* Read the second input */
246       Xn2 = *pIn++;
247
248       /* acc =  b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
249       Yn1 = (b0 * Xn2) + (b1 * Xn) + (b2 * Xn1) + (a1 * Yn2) + (a2 * Yn1);
250
251       /* Store the result in the accumulator in the destination buffer. */
252       *pOut++ = Yn1;
253
254       /* Every time after the output is computed state should be updated. */
255       /* The states should be updated as:  */
256       /* Xn2 = Xn1    */
257       /* Xn1 = Xn     */
258       /* Yn2 = Yn1    */
259       /* Yn1 = acc   */
260
261       /* Read the third input */
262       Xn1 = *pIn++;
263
264       /* acc =  b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
265       Yn2 = (b0 * Xn1) + (b1 * Xn2) + (b2 * Xn) + (a1 * Yn1) + (a2 * Yn2);
266
267       /* Store the result in the accumulator in the destination buffer. */
268       *pOut++ = Yn2;
269
270       /* Every time after the output is computed state should be updated. */
271       /* The states should be updated as: */
272       /* Xn2 = Xn1    */
273       /* Xn1 = Xn     */
274       /* Yn2 = Yn1    */
275       /* Yn1 = acc   */
276
277       /* Read the forth input */
278       Xn = *pIn++;
279
280       /* acc =  b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
281       Yn1 = (b0 * Xn) + (b1 * Xn1) + (b2 * Xn2) + (a1 * Yn2) + (a2 * Yn1);
282
283       /* Store the result in the accumulator in the destination buffer. */
284       *pOut++ = Yn1;
285
286       /* Every time after the output is computed state should be updated. */
287       /* The states should be updated as:  */
288       /* Xn2 = Xn1    */
289       /* Xn1 = Xn     */
290       /* Yn2 = Yn1    */
291       /* Yn1 = acc   */
292       Xn2 = Xn1;
293       Xn1 = Xn;
294
295       /* decrement the loop counter */
296       sample--;
297
298     }
299
300     /* If the blockSize is not a multiple of 4, compute any remaining output samples here.    
301      ** No loop unrolling is used. */
302     sample = blockSize & 0x3u;
303
304     while(sample > 0u)
305     {
306       /* Read the input */
307       Xn = *pIn++;
308
309       /* acc =  b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
310       acc = (b0 * Xn) + (b1 * Xn1) + (b2 * Xn2) + (a1 * Yn1) + (a2 * Yn2);
311
312       /* Store the result in the accumulator in the destination buffer. */
313       *pOut++ = acc;
314
315       /* Every time after the output is computed state should be updated. */
316       /* The states should be updated as:    */
317       /* Xn2 = Xn1    */
318       /* Xn1 = Xn     */
319       /* Yn2 = Yn1    */
320       /* Yn1 = acc   */
321       Xn2 = Xn1;
322       Xn1 = Xn;
323       Yn2 = Yn1;
324       Yn1 = acc;
325
326       /* decrement the loop counter */
327       sample--;
328
329     }
330
331     /*  Store the updated state variables back into the pState array */
332     *pState++ = Xn1;
333     *pState++ = Xn2;
334     *pState++ = Yn1;
335     *pState++ = Yn2;
336
337     /*  The first stage goes from the input buffer to the output buffer. */
338     /*  Subsequent numStages  occur in-place in the output buffer */
339     pIn = pDst;
340
341     /* Reset the output pointer */
342     pOut = pDst;
343
344     /* decrement the loop counter */
345     stage--;
346
347   } while(stage > 0u);
348
349 #else
350
351   /* Run the below code for Cortex-M0 */
352
353   do
354   {
355     /* Reading the coefficients */
356     b0 = *pCoeffs++;
357     b1 = *pCoeffs++;
358     b2 = *pCoeffs++;
359     a1 = *pCoeffs++;
360     a2 = *pCoeffs++;
361
362     /* Reading the pState values */
363     Xn1 = pState[0];
364     Xn2 = pState[1];
365     Yn1 = pState[2];
366     Yn2 = pState[3];
367
368     /*      The variables acc holds the output value that is computed:        
369      *    acc =  b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1]   + a2 * y[n-2]        
370      */
371
372     sample = blockSize;
373
374     while(sample > 0u)
375     {
376       /* Read the input */
377       Xn = *pIn++;
378
379       /* acc =  b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2] */
380       acc = (b0 * Xn) + (b1 * Xn1) + (b2 * Xn2) + (a1 * Yn1) + (a2 * Yn2);
381
382       /* Store the result in the accumulator in the destination buffer. */
383       *pOut++ = acc;
384
385       /* Every time after the output is computed state should be updated. */
386       /* The states should be updated as:    */
387       /* Xn2 = Xn1    */
388       /* Xn1 = Xn     */
389       /* Yn2 = Yn1    */
390       /* Yn1 = acc   */
391       Xn2 = Xn1;
392       Xn1 = Xn;
393       Yn2 = Yn1;
394       Yn1 = acc;
395
396       /* decrement the loop counter */
397       sample--;
398     }
399
400     /*  Store the updated state variables back into the pState array */
401     *pState++ = Xn1;
402     *pState++ = Xn2;
403     *pState++ = Yn1;
404     *pState++ = Yn2;
405
406     /*  The first stage goes from the input buffer to the output buffer. */
407     /*  Subsequent numStages  occur in-place in the output buffer */
408     pIn = pDst;
409
410     /* Reset the output pointer */
411     pOut = pDst;
412
413     /* decrement the loop counter */
414     stage--;
415
416   } while(stage > 0u);
417
418 #endif /*   #ifndef ARM_MATH_CM0_FAMILY         */
419
420 }
421
422
423   /**    
424    * @} end of BiquadCascadeDF1 group    
425    */