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