1 /* ----------------------------------------------------------------------
2 * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
3 *
4 * $Date:         17. January 2013
5 * $Revision:     V1.4.0
6 *
7 * Project:       CMSIS DSP Library
8 * Title:         arm_signal_converge_example_f32.c
9 *
10 * Description:   Example code demonstrating convergence of an adaptive
11 *                filter.
12 *
13 * Target Processor: Cortex-M4/Cortex-M3
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 /**
43  * @addtogroup groupExamples
44  * @{
45  *
46  * @defgroup SignalConvergence Signal Convergence Example
47  *
48  * \par Description:
49  * \par
50  * Demonstrates the ability of an adaptive filter to "learn" the transfer function of
51  * a FIR lowpass filter using the Normalized LMS Filter, Finite Impulse
52  * Response (FIR) Filter, and Basic Math Functions.
53  *
54  * \par Algorithm:
55  * \par
56  * The figure below illustrates the signal flow in this example. Uniformly distributed white
57  * noise is passed through an FIR lowpass filter. The output of the FIR filter serves as the
58  * reference input of the adaptive filter (normalized LMS filter). The white noise is input
59  * to the adaptive filter. The adaptive filter learns the transfer function of the FIR filter.
60  * The filter outputs two signals: (1) the output of the internal adaptive FIR filter, and
61  * (2) the error signal which is the difference between the adaptive filter and the reference
62  * output of the FIR filter. Over time as the adaptive filter learns the transfer function
63  * of the FIR filter, the first output approaches the reference output of the FIR filter,
64  * and the error signal approaches zero.
65  * \par
66  * The adaptive filter converges properly even if the input signal has a large dynamic
67  * range (i.e., varies from small to large values). The coefficients of the adaptive filter
68  * are initially zero, and then converge over 1536 samples. The internal function test_signal_converge()
69  * implements the stopping condition. The function checks if all of the values of the error signal have a
70  * magnitude below a threshold DELTA.
71  *
72  * \par Block Diagram:
73  * \par
74  * \image html SignalFlow.gif
75  *
76  *
77  * \par Variables Description:
78  * \par
79  * \li \c testInput_f32 points to the input data
80  * \li \c firStateF32 points to FIR state buffer
81  * \li \c lmsStateF32 points to Normalised Least mean square FIR filter state buffer
82  * \li \c FIRCoeff_f32 points to coefficient buffer
83  * \li \c lmsNormCoeff_f32 points to Normalised Least mean square FIR filter coefficient buffer
84  * \li \c wire1, wir2, wire3 temporary buffers
85  * \li \c errOutput, err_signal temporary error buffers
86  *
87  * \par CMSIS DSP Software Library Functions Used:
88  * \par
89  * - arm_lms_norm_init_f32()
90  * - arm_fir_init_f32()
91  * - arm_fir_f32()
92  * - arm_lms_norm_f32()
93  * - arm_scale_f32()
94  * - arm_abs_f32()
95  * - arm_sub_f32()
96  * - arm_min_f32()
97  * - arm_copy_f32()
98  *
99  * <b> Refer  </b>
100  * \link arm_signal_converge_example_f32.c \endlink
101  *
102  * \example arm_signal_converge_example_f32.c
103  *
104  * @} */
105 
106 #include "arm_math.h"
107 #include "math_helper.h"
108 
109 #if defined(SEMIHOSTING)
110 #include <stdio.h>
111 #endif
112 
113 /* ----------------------------------------------------------------------
114 ** Global defines for the simulation
115 * ------------------------------------------------------------------- */
116 
117 #define TEST_LENGTH_SAMPLES 1536
118 #define NUMTAPS               32
119 #define BLOCKSIZE             32
120 #define DELTA_ERROR         0.00009f
121 #define DELTA_COEFF         0.0001f
122 #define MU                  0.5f
123 
124 #define NUMFRAMES (TEST_LENGTH_SAMPLES / BLOCKSIZE)
125 
126 /* ----------------------------------------------------------------------
127 * Declare FIR state buffers and structure
128 * ------------------------------------------------------------------- */
129 
130 #if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
131 float32_t firStateF32[2 * BLOCKSIZE + NUMTAPS - 1];
132 #else
133 float32_t firStateF32[NUMTAPS + BLOCKSIZE];
134 #endif
135 
136 arm_fir_instance_f32 LPF_instance;
137 
138 /* ----------------------------------------------------------------------
139 * Declare LMSNorm state buffers and structure
140 * ------------------------------------------------------------------- */
141 
142 float32_t lmsStateF32[NUMTAPS + BLOCKSIZE];
143 float32_t errOutput[TEST_LENGTH_SAMPLES];
144 arm_lms_norm_instance_f32 lmsNorm_instance;
145 
146 
147 /* ----------------------------------------------------------------------
148 * Function Declarations for Signal Convergence Example
149 * ------------------------------------------------------------------- */
150 
151 arm_status test_signal_converge_example( void );
152 
153 
154 /* ----------------------------------------------------------------------
155 * Internal functions
156 * ------------------------------------------------------------------- */
157 arm_status test_signal_converge(float32_t* err_signal,
158                         uint32_t blockSize);
159 
160 void getinput(float32_t* input,
161      uint32_t fr_cnt,
162           uint32_t blockSize);
163 
164 /* ----------------------------------------------------------------------
165 * External Declarations for FIR F32 module Test
166 * ------------------------------------------------------------------- */
167 extern float32_t testInput_f32[TEST_LENGTH_SAMPLES];
168 extern float32_t lmsNormCoeff_f32[32];
169 extern const float32_t FIRCoeff_f32[32];
170 extern arm_lms_norm_instance_f32 lmsNorm_instance;
171 
172 /* ----------------------------------------------------------------------
173 * Declare I/O buffers
174 * ------------------------------------------------------------------- */
175 
176 float32_t wire1[BLOCKSIZE];
177 float32_t wire2[BLOCKSIZE];
178 float32_t wire3[BLOCKSIZE];
179 float32_t err_signal[BLOCKSIZE];
180 
181 /* ----------------------------------------------------------------------
182 * Signal converge test
183 * ------------------------------------------------------------------- */
184 
main(void)185 int32_t main(void)
186 {
187   uint32_t i;
188   arm_status status;
189   uint32_t index;
190   float32_t minValue;
191 
192   /* Initialize the LMSNorm data structure */
193   arm_lms_norm_init_f32(&lmsNorm_instance, NUMTAPS, lmsNormCoeff_f32, lmsStateF32, MU, BLOCKSIZE);
194 
195   /* Initialize the FIR data structure */
196   arm_fir_init_f32(&LPF_instance, NUMTAPS, (float32_t *)FIRCoeff_f32, firStateF32, BLOCKSIZE);
197 
198   /* ----------------------------------------------------------------------
199   * Loop over the frames of data and execute each of the processing
200   * functions in the system.
201   * ------------------------------------------------------------------- */
202 
203   for(i=0; i < NUMFRAMES; i++)
204   {
205     /* Read the input data - uniformly distributed random noise - into wire1 */
206     arm_copy_f32(testInput_f32 + (i * BLOCKSIZE), wire1, BLOCKSIZE);
207 
208     /* Execute the FIR processing function.  Input wire1 and output wire2 */
209     arm_fir_f32(&LPF_instance, wire1, wire2, BLOCKSIZE);
210 
211     /* Execute the LMS Norm processing function*/
212 
213     arm_lms_norm_f32(&lmsNorm_instance, /* LMSNorm instance */
214          wire1,                         /* Input signal */
215          wire2,                         /* Reference Signal */
216          wire3,                         /* Converged Signal */
217          err_signal,                    /* Error Signal, this will become small as the signal converges */
218          BLOCKSIZE);                    /* BlockSize */
219 
220     /* apply overall gain */
221     arm_scale_f32(wire3, 5, wire3, BLOCKSIZE);   /* in-place buffer */
222   }
223 
224   status = ARM_MATH_SUCCESS;
225 
226   /* -------------------------------------------------------------------------------
227   * Test whether the error signal has reached towards 0.
228   * ----------------------------------------------------------------------------- */
229 
230   arm_abs_f32(err_signal, err_signal, BLOCKSIZE);
231   arm_min_f32(err_signal, BLOCKSIZE, &minValue, &index);
232 
233   if (minValue > DELTA_ERROR)
234   {
235     status = ARM_MATH_TEST_FAILURE;
236   }
237 
238   /* ----------------------------------------------------------------------
239   * Test whether the filter coefficients have converged.
240   * ------------------------------------------------------------------- */
241 
242   arm_sub_f32((float32_t *)FIRCoeff_f32, lmsNormCoeff_f32, lmsNormCoeff_f32, NUMTAPS);
243 
244   arm_abs_f32(lmsNormCoeff_f32, lmsNormCoeff_f32, NUMTAPS);
245   arm_min_f32(lmsNormCoeff_f32, NUMTAPS, &minValue, &index);
246 
247   status = (minValue > DELTA_COEFF) ? ARM_MATH_TEST_FAILURE : ARM_MATH_SUCCESS;
248 
249   if (status != ARM_MATH_SUCCESS)
250   {
251 #if defined (SEMIHOSTING)
252     printf("FAILURE\n");
253 #else
254     while (1);                             /* main function does not return */
255 #endif
256   }
257   else
258   {
259 #if defined (SEMIHOSTING)
260     printf("SUCCESS\n");
261 #else
262     while (1);                             /* main function does not return */
263 #endif
264   }
265 
266 }
267 
268  /** \endlink */
269