/ Drivers / CMSIS / DSP / Examples / ARM / arm_fir_example / arm_fir_example_f32.c
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 */