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