Added all the F4 libraries to the project
[fw/stlink] / exampleF4 / CMSIS / DSP_Lib / Source / FilteringFunctions / arm_lms_norm_f32.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_lms_norm_f32.c   
9 *   
10 * Description:  Processing function for the floating-point Normalised LMS.   
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
33 #include "arm_math.h"
34
35 /**   
36  * @ingroup groupFilters   
37  */
38
39 /**   
40  * @defgroup LMS_NORM Normalized LMS Filters   
41  *   
42  * This set of functions implements a commonly used adaptive filter.   
43  * It is related to the Least Mean Square (LMS) adaptive filter and includes an additional normalization   
44  * factor which increases the adaptation rate of the filter.   
45  * The CMSIS DSP Library contains normalized LMS filter functions that operate on Q15, Q31, and floating-point data types.   
46  *   
47  * A normalized least mean square (NLMS) filter consists of two components as shown below.   
48  * The first component is a standard transversal or FIR filter.   
49  * The second component is a coefficient update mechanism.   
50  * The NLMS filter has two input signals.   
51  * The "input" feeds the FIR filter while the "reference input" corresponds to the desired output of the FIR filter.   
52  * That is, the FIR filter coefficients are updated so that the output of the FIR filter matches the reference input.   
53  * The filter coefficient update mechanism is based on the difference between the FIR filter output and the reference input.   
54  * This "error signal" tends towards zero as the filter adapts.   
55  * The NLMS processing functions accept the input and reference input signals and generate the filter output and error signal.   
56  * \image html LMS.gif "Internal structure of the NLMS adaptive filter"   
57  *   
58  * The functions operate on blocks of data and each call to the function processes   
59  * <code>blockSize</code> samples through the filter.   
60  * <code>pSrc</code> points to input signal, <code>pRef</code> points to reference signal,   
61  * <code>pOut</code> points to output signal and <code>pErr</code> points to error signal.   
62  * All arrays contain <code>blockSize</code> values.   
63  *   
64  * The functions operate on a block-by-block basis.   
65  * Internally, the filter coefficients <code>b[n]</code> are updated on a sample-by-sample basis.   
66  * The convergence of the LMS filter is slower compared to the normalized LMS algorithm.   
67  *   
68  * \par Algorithm:   
69  * The output signal <code>y[n]</code> is computed by a standard FIR filter:   
70  * <pre>   
71  *     y[n] = b[0] * x[n] + b[1] * x[n-1] + b[2] * x[n-2] + ...+ b[numTaps-1] * x[n-numTaps+1]   
72  * </pre>   
73  *   
74  * \par   
75  * The error signal equals the difference between the reference signal <code>d[n]</code> and the filter output:   
76  * <pre>   
77  *     e[n] = d[n] - y[n].   
78  * </pre>   
79  *   
80  * \par   
81  * After each sample of the error signal is computed the instanteous energy of the filter state variables is calculated:   
82  * <pre>   
83  *    E = x[n]^2 + x[n-1]^2 + ... + x[n-numTaps+1]^2.   
84  * </pre>   
85  * The filter coefficients <code>b[k]</code> are then updated on a sample-by-sample basis:   
86  * <pre>   
87  *     b[k] = b[k] + e[n] * (mu/E) * x[n-k],  for k=0, 1, ..., numTaps-1   
88  * </pre>   
89  * where <code>mu</code> is the step size and controls the rate of coefficient convergence.   
90  *\par   
91  * In the APIs, <code>pCoeffs</code> points to a coefficient array of size <code>numTaps</code>.   
92  * Coefficients are stored in time reversed order.   
93  * \par   
94  * <pre>   
95  *    {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}   
96  * </pre>   
97  * \par   
98  * <code>pState</code> points to a state array of size <code>numTaps + blockSize - 1</code>.   
99  * Samples in the state buffer are stored in the order:   
100  * \par   
101  * <pre>   
102  *    {x[n-numTaps+1], x[n-numTaps], x[n-numTaps-1], x[n-numTaps-2]....x[0], x[1], ..., x[blockSize-1]}   
103  * </pre>   
104  * \par   
105  * Note that the length of the state buffer exceeds the length of the coefficient array by <code>blockSize-1</code> samples.   
106  * The increased state buffer length allows circular addressing, which is traditionally used in FIR filters,   
107  * to be avoided and yields a significant speed improvement.   
108  * The state variables are updated after each block of data is processed.   
109  * \par Instance Structure   
110  * The coefficients and state variables for a filter are stored together in an instance data structure.   
111  * A separate instance structure must be defined for each filter and   
112  * coefficient and state arrays cannot be shared among instances.   
113  * There are separate instance structure declarations for each of the 3 supported data types.   
114  *   
115  * \par Initialization Functions   
116  * There is also an associated initialization function for each data type.   
117  * The initialization function performs the following operations:   
118  * - Sets the values of the internal structure fields.   
119  * - Zeros out the values in the state buffer.   
120  * \par   
121  * Instance structure cannot be placed into a const data section and it is recommended to use the initialization function.   
122  * \par Fixed-Point Behavior:   
123  * Care must be taken when using the Q15 and Q31 versions of the normalised LMS filter.   
124  * The following issues must be considered:   
125  * - Scaling of coefficients   
126  * - Overflow and saturation   
127  *   
128  * \par Scaling of Coefficients:   
129  * Filter coefficients are represented as fractional values and   
130  * coefficients are restricted to lie in the range <code>[-1 +1)</code>.   
131  * The fixed-point functions have an additional scaling parameter <code>postShift</code>.   
132  * At the output of the filter's accumulator is a shift register which shifts the result by <code>postShift</code> bits.   
133  * This essentially scales the filter coefficients by <code>2^postShift</code> and   
134  * allows the filter coefficients to exceed the range <code>[+1 -1)</code>.   
135  * The value of <code>postShift</code> is set by the user based on the expected gain through the system being modeled.   
136  *   
137  * \par Overflow and Saturation:   
138  * Overflow and saturation behavior of the fixed-point Q15 and Q31 versions are   
139  * described separately as part of the function specific documentation below.   
140  */
141
142
143 /**   
144  * @addtogroup LMS_NORM   
145  * @{   
146  */
147
148
149   /**   
150    * @brief Processing function for floating-point normalized LMS filter.   
151    * @param[in] *S points to an instance of the floating-point normalized LMS filter structure.   
152    * @param[in] *pSrc points to the block of input data.   
153    * @param[in] *pRef points to the block of reference data.   
154    * @param[out] *pOut points to the block of output data.   
155    * @param[out] *pErr points to the block of error data.   
156    * @param[in] blockSize number of samples to process.   
157    * @return none.   
158    */
159
160 void arm_lms_norm_f32(
161   arm_lms_norm_instance_f32 * S,
162   float32_t * pSrc,
163   float32_t * pRef,
164   float32_t * pOut,
165   float32_t * pErr,
166   uint32_t blockSize)
167 {
168   float32_t *pState = S->pState;                 /* State pointer */
169   float32_t *pCoeffs = S->pCoeffs;               /* Coefficient pointer */
170   float32_t *pStateCurnt;                        /* Points to the current sample of the state */
171   float32_t *px, *pb;                            /* Temporary pointers for state and coefficient buffers */
172   float32_t mu = S->mu;                          /* Adaptive factor */
173   uint32_t numTaps = S->numTaps;                 /* Number of filter coefficients in the filter */
174   uint32_t tapCnt, blkCnt;                       /* Loop counters */
175   float32_t energy;                              /* Energy of the input */
176   float32_t sum, e, d;                           /* accumulator, error, reference data sample */
177   float32_t w, x0, in;                           /* weight factor, temporary variable to hold input sample and state */
178
179   /* Initializations of error,  difference, Coefficient update */
180   e = 0.0f;
181   d = 0.0f;
182   w = 0.0f;
183
184   energy = S->energy;
185   x0 = S->x0;
186
187   /* S->pState points to buffer which contains previous frame (numTaps - 1) samples */
188   /* pStateCurnt points to the location where the new input data should be written */
189   pStateCurnt = &(S->pState[(numTaps - 1u)]);
190
191   /* Loop over blockSize number of values */
192   blkCnt = blockSize;
193
194
195 #ifndef ARM_MATH_CM0
196
197   /* Run the below code for Cortex-M4 and Cortex-M3 */
198
199   while(blkCnt > 0u)
200   {
201     /* Copy the new input sample into the state buffer */
202     *pStateCurnt++ = *pSrc;
203
204     /* Initialize pState pointer */
205     px = pState;
206
207     /* Initialize coeff pointer */
208     pb = (pCoeffs);
209
210     /* Read the sample from input buffer */
211     in = *pSrc++;
212
213     /* Update the energy calculation */
214     energy -= x0 * x0;
215     energy += in * in;
216
217     /* Set the accumulator to zero */
218     sum = 0.0f;
219
220     /* Loop unrolling.  Process 4 taps at a time. */
221     tapCnt = numTaps >> 2;
222
223     while(tapCnt > 0u)
224     {
225       /* Perform the multiply-accumulate */
226       sum += (*px++) * (*pb++);
227       sum += (*px++) * (*pb++);
228       sum += (*px++) * (*pb++);
229       sum += (*px++) * (*pb++);
230
231       /* Decrement the loop counter */
232       tapCnt--;
233     }
234
235     /* If the filter length is not a multiple of 4, compute the remaining filter taps */
236     tapCnt = numTaps % 0x4u;
237
238     while(tapCnt > 0u)
239     {
240       /* Perform the multiply-accumulate */
241       sum += (*px++) * (*pb++);
242
243       /* Decrement the loop counter */
244       tapCnt--;
245     }
246
247     /* The result in the accumulator, store in the destination buffer. */
248     *pOut++ = sum;
249
250     /* Compute and store error */
251     d = (float32_t) (*pRef++);
252     e = d - sum;
253     *pErr++ = e;
254
255     /* Calculation of Weighting factor for updating filter coefficients */
256     /* epsilon value 0.000000119209289f */
257     w = (e * mu) / (energy + 0.000000119209289f);
258
259     /* Initialize pState pointer */
260     px = pState;
261
262     /* Initialize coeff pointer */
263     pb = (pCoeffs);
264
265     /* Loop unrolling.  Process 4 taps at a time. */
266     tapCnt = numTaps >> 2;
267
268     /* Update filter coefficients */
269     while(tapCnt > 0u)
270     {
271       /* Perform the multiply-accumulate */
272       *pb += w * (*px++);
273       pb++;
274
275       *pb += w * (*px++);
276       pb++;
277
278       *pb += w * (*px++);
279       pb++;
280
281       *pb += w * (*px++);
282       pb++;
283
284
285       /* Decrement the loop counter */
286       tapCnt--;
287     }
288
289     /* If the filter length is not a multiple of 4, compute the remaining filter taps */
290     tapCnt = numTaps % 0x4u;
291
292     while(tapCnt > 0u)
293     {
294       /* Perform the multiply-accumulate */
295       *pb += w * (*px++);
296       pb++;
297
298       /* Decrement the loop counter */
299       tapCnt--;
300     }
301
302     x0 = *pState;
303
304     /* Advance state pointer by 1 for the next sample */
305     pState = pState + 1;
306
307     /* Decrement the loop counter */
308     blkCnt--;
309   }
310
311   S->energy = energy;
312   S->x0 = x0;
313
314   /* Processing is complete. Now copy the last numTaps - 1 samples to the   
315      satrt of the state buffer. This prepares the state buffer for the   
316      next function call. */
317
318   /* Points to the start of the pState buffer */
319   pStateCurnt = S->pState;
320
321   /* Loop unrolling for (numTaps - 1u)/4 samples copy */
322   tapCnt = (numTaps - 1u) >> 2u;
323
324   /* copy data */
325   while(tapCnt > 0u)
326   {
327     *pStateCurnt++ = *pState++;
328     *pStateCurnt++ = *pState++;
329     *pStateCurnt++ = *pState++;
330     *pStateCurnt++ = *pState++;
331
332     /* Decrement the loop counter */
333     tapCnt--;
334   }
335
336   /* Calculate remaining number of copies */
337   tapCnt = (numTaps - 1u) % 0x4u;
338
339   /* Copy the remaining q31_t data */
340   while(tapCnt > 0u)
341   {
342     *pStateCurnt++ = *pState++;
343
344     /* Decrement the loop counter */
345     tapCnt--;
346   }
347
348 #else
349
350   /* Run the below code for Cortex-M0 */
351
352   while(blkCnt > 0u)
353   {
354     /* Copy the new input sample into the state buffer */
355     *pStateCurnt++ = *pSrc;
356
357     /* Initialize pState pointer */
358     px = pState;
359
360     /* Initialize pCoeffs pointer */
361     pb = pCoeffs;
362
363     /* Read the sample from input buffer */
364     in = *pSrc++;
365
366     /* Update the energy calculation */
367     energy -= x0 * x0;
368     energy += in * in;
369
370     /* Set the accumulator to zero */
371     sum = 0.0f;
372
373     /* Loop over numTaps number of values */
374     tapCnt = numTaps;
375
376     while(tapCnt > 0u)
377     {
378       /* Perform the multiply-accumulate */
379       sum += (*px++) * (*pb++);
380
381       /* Decrement the loop counter */
382       tapCnt--;
383     }
384
385     /* The result in the accumulator is stored in the destination buffer. */
386     *pOut++ = sum;
387
388     /* Compute and store error */
389     d = (float32_t) (*pRef++);
390     e = d - sum;
391     *pErr++ = e;
392
393     /* Calculation of Weighting factor for updating filter coefficients */
394     /* epsilon value 0.000000119209289f */
395     w = (e * mu) / (energy + 0.000000119209289f);
396
397     /* Initialize pState pointer */
398     px = pState;
399
400     /* Initialize pCcoeffs pointer */
401     pb = pCoeffs;
402
403     /* Loop over numTaps number of values */
404     tapCnt = numTaps;
405
406     while(tapCnt > 0u)
407     {
408       /* Perform the multiply-accumulate */
409       *pb += w * (*px++);
410       pb++;
411
412       /* Decrement the loop counter */
413       tapCnt--;
414     }
415
416     x0 = *pState;
417
418     /* Advance state pointer by 1 for the next sample */
419     pState = pState + 1;
420
421     /* Decrement the loop counter */
422     blkCnt--;
423   }
424
425   S->energy = energy;
426   S->x0 = x0;
427
428   /* Processing is complete. Now copy the last numTaps - 1 samples to the       
429      satrt of the state buffer. This prepares the state buffer for the       
430      next function call. */
431
432   /* Points to the start of the pState buffer */
433   pStateCurnt = S->pState;
434
435   /* Copy (numTaps - 1u) samples  */
436   tapCnt = (numTaps - 1u);
437
438   /* Copy the remaining q31_t data */
439   while(tapCnt > 0u)
440   {
441     *pStateCurnt++ = *pState++;
442
443     /* Decrement the loop counter */
444     tapCnt--;
445   }
446
447 #endif /*   #ifndef ARM_MATH_CM0 */
448
449 }
450
451 /**   
452    * @} end of LMS_NORM group   
453    */