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_fir_example_f32.c
9 *
10 * Description: Example code demonstrating how an FIR filter can be used
11 * as a low pass 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 FIRLPF FIR Lowpass Filter Example
47 *
48 * \par Description:
49 * \par
50 * Removes high frequency signal components from the input using an FIR lowpass filter.
51 * The example demonstrates how to configure an FIR filter and then pass data through
52 * it in a block-by-block fashion.
53 * \image html FIRLPF_signalflow.gif
54 *
55 * \par Algorithm:
56 * \par
57 * The input signal is a sum of two sine waves: 1 kHz and 15 kHz.
58 * This is processed by an FIR lowpass filter with cutoff frequency 6 kHz.
59 * The lowpass filter eliminates the 15 kHz signal leaving only the 1 kHz sine wave at the output.
60 * \par
61 * The lowpass filter was designed using MATLAB with a sample rate of 48 kHz and
62 * a length of 29 points.
63 * The MATLAB code to generate the filter coefficients is shown below:
64 * <pre>
65 * h = fir1(28, 6/24);
66 * </pre>
67 * The first argument is the "order" of the filter and is always one less than the desired length.
68 * The second argument is the normalized cutoff frequency. This is in the range 0 (DC) to 1.0 (Nyquist).
69 * A 6 kHz cutoff with a Nyquist frequency of 24 kHz lies at a normalized frequency of 6/24 = 0.25.
70 * The CMSIS FIR filter function requires the coefficients to be in time reversed order.
71 * <pre>
72 * fliplr(h)
73 * </pre>
74 * The resulting filter coefficients and are shown below.
75 * Note that the filter is symmetric (a property of linear phase FIR filters)
76 * and the point of symmetry is sample 14. Thus the filter will have a delay of
77 * 14 samples for all frequencies.
78 * \par
79 * \image html FIRLPF_coeffs.gif
80 * \par
81 * The frequency response of the filter is shown next.
82 * The passband gain of the filter is 1.0 and it reaches 0.5 at the cutoff frequency 6 kHz.
83 * \par
84 * \image html FIRLPF_response.gif
85 * \par
86 * The input signal is shown below.
87 * The left hand side shows the signal in the time domain while the right hand side is a frequency domain representation.
88 * The two sine wave components can be clearly seen.
89 * \par
90 * \image html FIRLPF_input.gif
91 * \par
92 * The output of the filter is shown below. The 15 kHz component has been eliminated.
93 * \par
94 * \image html FIRLPF_output.gif
95 *
96 * \par Variables Description:
97 * \par
98 * \li \c testInput_f32_1kHz_15kHz points to the input data
99 * \li \c refOutput points to the reference output data
100 * \li \c testOutput points to the test output data
101 * \li \c firStateF32 points to state buffer
102 * \li \c firCoeffs32 points to coefficient buffer
103 * \li \c blockSize number of samples processed at a time
104 * \li \c numBlocks number of frames
105 *
106 * \par CMSIS DSP Software Library Functions Used:
107 * \par
108 * - arm_fir_init_f32()
109 * - arm_fir_f32()
110 *
111 * <b> Refer </b>
112 * \link arm_fir_example_f32.c \endlink
113 *
114 * \example arm_fir_example_f32.c
115 *
116 * @} */
117
118 /* ----------------------------------------------------------------------
119 ** Include Files
120 ** ------------------------------------------------------------------- */
121
122 #include "arm_math.h"
123 #include "math_helper.h"
124
125 #if defined(SEMIHOSTING)
126 #include <stdio.h>
127 #endif
128
129
130 /* ----------------------------------------------------------------------
131 ** Macro Defines
132 ** ------------------------------------------------------------------- */
133
134 #define TEST_LENGTH_SAMPLES 320
135 /*
136
137 This SNR is a bit small. Need to understand why
138 this example is not giving better SNR ...
139
140 */
141 #define SNR_THRESHOLD_F32 75.0f
142 #define BLOCK_SIZE 32
143
144 #if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
145 /* Must be a multiple of 16 */
146 #define NUM_TAPS_ARRAY_SIZE 32
147 #else
148 #define NUM_TAPS_ARRAY_SIZE 29
149 #endif
150
151 #define NUM_TAPS 29
152
153 /* -------------------------------------------------------------------
154 * The input signal and reference output (computed with MATLAB)
155 * are defined externally in arm_fir_lpf_data.c.
156 * ------------------------------------------------------------------- */
157
158 extern float32_t testInput_f32_1kHz_15kHz[TEST_LENGTH_SAMPLES];
159 extern float32_t refOutput[TEST_LENGTH_SAMPLES];
160
161 /* -------------------------------------------------------------------
162 * Declare Test output buffer
163 * ------------------------------------------------------------------- */
164
165 static float32_t testOutput[TEST_LENGTH_SAMPLES];
166
167 /* -------------------------------------------------------------------
168 * Declare State buffer of size (numTaps + blockSize - 1)
169 * ------------------------------------------------------------------- */
170 #if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
171 static float32_t firStateF32[2 * BLOCK_SIZE + NUM_TAPS - 1];
172 #else
173 static float32_t firStateF32[BLOCK_SIZE + NUM_TAPS - 1];
174 #endif
175
176 /* ----------------------------------------------------------------------
177 ** FIR Coefficients buffer generated using fir1() MATLAB function.
178 ** fir1(28, 6/24)
179 ** ------------------------------------------------------------------- */
180 #if defined(ARM_MATH_MVEF) && !defined(ARM_MATH_AUTOVECTORIZE)
181 const float32_t firCoeffs32[NUM_TAPS_ARRAY_SIZE] = {
182 -0.0018225230f, -0.0015879294f, +0.0000000000f, +0.0036977508f, +0.0080754303f, +0.0085302217f, -0.0000000000f, -0.0173976984f,
183 -0.0341458607f, -0.0333591565f, +0.0000000000f, +0.0676308395f, +0.1522061835f, +0.2229246956f, +0.2504960933f, +0.2229246956f,
184 +0.1522061835f, +0.0676308395f, +0.0000000000f, -0.0333591565f, -0.0341458607f, -0.0173976984f, -0.0000000000f, +0.0085302217f,
185 +0.0080754303f, +0.0036977508f, +0.0000000000f, -0.0015879294f, -0.0018225230f, 0.0f,0.0f,0.0f
186 };
187 #else
188 const float32_t firCoeffs32[NUM_TAPS_ARRAY_SIZE] = {
189 -0.0018225230f, -0.0015879294f, +0.0000000000f, +0.0036977508f, +0.0080754303f, +0.0085302217f, -0.0000000000f, -0.0173976984f,
190 -0.0341458607f, -0.0333591565f, +0.0000000000f, +0.0676308395f, +0.1522061835f, +0.2229246956f, +0.2504960933f, +0.2229246956f,
191 +0.1522061835f, +0.0676308395f, +0.0000000000f, -0.0333591565f, -0.0341458607f, -0.0173976984f, -0.0000000000f, +0.0085302217f,
192 +0.0080754303f, +0.0036977508f, +0.0000000000f, -0.0015879294f, -0.0018225230f
193 };
194 #endif
195
196 /* ------------------------------------------------------------------
197 * Global variables for FIR LPF Example
198 * ------------------------------------------------------------------- */
199
200 uint32_t blockSize = BLOCK_SIZE;
201 uint32_t numBlocks = TEST_LENGTH_SAMPLES/BLOCK_SIZE;
202
203 float32_t snr;
204
205 /* ----------------------------------------------------------------------
206 * FIR LPF Example
207 * ------------------------------------------------------------------- */
208
main(void)209 int32_t main(void)
210 {
211 uint32_t i;
212 arm_fir_instance_f32 S;
213 arm_status status;
214 float32_t *inputF32, *outputF32;
215
216 /* Initialize input and output buffer pointers */
217 inputF32 = &testInput_f32_1kHz_15kHz[0];
218 outputF32 = &testOutput[0];
219
220 /* Call FIR init function to initialize the instance structure. */
221 arm_fir_init_f32(&S, NUM_TAPS, (float32_t *)&firCoeffs32[0], &firStateF32[0], blockSize);
222
223 /* ----------------------------------------------------------------------
224 ** Call the FIR process function for every blockSize samples
225 ** ------------------------------------------------------------------- */
226
227 for(i=0; i < numBlocks; i++)
228 {
229 arm_fir_f32(&S, inputF32 + (i * blockSize), outputF32 + (i * blockSize), blockSize);
230 }
231
232 /* ----------------------------------------------------------------------
233 ** Compare the generated output against the reference output computed
234 ** in MATLAB.
235 ** ------------------------------------------------------------------- */
236
237 snr = arm_snr_f32(&refOutput[0], &testOutput[0], TEST_LENGTH_SAMPLES);
238
239 status = (snr < SNR_THRESHOLD_F32) ? ARM_MATH_TEST_FAILURE : ARM_MATH_SUCCESS;
240
241 if (status != ARM_MATH_SUCCESS)
242 {
243 #if defined (SEMIHOSTING)
244 printf("FAILURE\n");
245 #else
246 while (1); /* main function does not return */
247 #endif
248 }
249 else
250 {
251 #if defined (SEMIHOSTING)
252 printf("SUCCESS\n");
253 #else
254 while (1); /* main function does not return */
255 #endif
256 }
257 }
258
259 /** \endlink */
260