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