Logo
MSP DSP Library
filter_ex4_biquad_cascade_df2_q15.c

This example demonstrates how to use the msp_fir_q15 API to filter 16-bit input data. The input signal is the sum of two signals, one that will pass though the filter and one that will be filtered out. The input and result can be compared to see the effect of the filter.

//******************************************************************************
// IIR filter using a cascaded DF2 biquad.
//
// Brent Peterson, Jeremy Friesenhahn
// Texas Instruments Inc.
// April 2016
//******************************************************************************
#include "msp430.h"
#include <math.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include "DSPLib.h"
/* Include header generated from DSPLib GUI here (optional). */
//#include "myCoeffs_ex4.h"
/* Input signal parameters */
#define FS 8192
#define SIGNAL_LENGTH 256
#define SIGNAL_FREQUENCY1 200
#define SIGNAL_AMPLITUDE1 0.6
#define SIGNAL_FREQUENCY2 2100
#define SIGNAL_AMPLITUDE2 0.15
/* Constants */
#define PI 3.1415926536
/* Define example coefficients if no DSPLib GUI header is provided. */
#ifndef FILTER_COEFFS_EX4
/* Second-order sections for 16th order low pass filter (Fs=8192, Fc=1800) */
const msp_biquad_df2_q15_coeffs FILTER_COEFFS_EX4[8] = {
{
.b0 = _Q15(+0.312963),
.b1By2 = _Q15(+0.608536/2),
.b2 = _Q15(+0.312963),
.a0 = _Q15(+1.000000),
.a1By2 = _Q15(-0.215187/2),
.a2 = _Q15(-0.019276)
},
{
.b0 = _Q15(+0.341644),
.b1By2 = _Q15(+0.533004/2),
.b2 = _Q15(+0.341644),
.a0 = _Q15(+1.000000),
.a1By2 = _Q15(-0.145445/2),
.a2 = _Q15(-0.070846)
},
{
.b0 = _Q15(+0.393284),
.b1By2 = _Q15(+0.399958/2),
.b2 = _Q15(+0.393284),
.a0 = _Q15(+1.000000),
.a1By2 = _Q15(-0.021883/2),
.a2 = _Q15(-0.164643)
},
{
.b0 = _Q15(+0.459362),
.b1By2 = _Q15(+0.236817/2),
.b2 = _Q15(+0.459362),
.a0 = _Q15(+1.000000),
.a1By2 = _Q15(+0.131385/2),
.a2 = _Q15(-0.286925)
},
{
.b0 = _Q15(+0.532049),
.b1By2 = _Q15(+0.070226/2),
.b2 = _Q15(+0.532049),
.a0 = _Q15(+1.000000),
.a1By2 = _Q15(+0.291215/2),
.a2 = _Q15(-0.425539)
},
{
.b0 = _Q15(+0.606300),
.b1By2 = _Q15(-0.079576/2),
.b2 = _Q15(+0.606300),
.a0 = _Q15(+1.000000),
.a1By2 = _Q15(+0.440602/2),
.a2 = _Q15(-0.573626)
},
{
.b0 = _Q15(+0.680340),
.b1By2 = _Q15(-0.199067/2),
.b2 = _Q15(+0.680340),
.a0 = _Q15(+1.000000),
.a1By2 = _Q15(+0.569203/2),
.a2 = _Q15(-0.730815)
},
{
.b0 = _Q15(+0.755460),
.b1By2 = _Q15(-0.278629/2),
.b2 = _Q15(+0.755460),
.a0 = _Q15(+1.000000),
.a1By2 = _Q15(+0.671286/2),
.a2 = _Q15(-0.903577)
}
};
#endif
/* Filter parameters */
#define FILTER_LENGTH (SIGNAL_LENGTH)
#define FILTER_STAGES (sizeof(FILTER_COEFFS_EX4)/sizeof(msp_biquad_df2_q15_coeffs))
/* Filter coefficients */
DSPLIB_DATA(filterCoeffs,4)
msp_biquad_df2_q15_coeffs filterCoeffs[FILTER_STAGES];
/* Filter input signal */
DSPLIB_DATA(input,4)
_q15 input[SIGNAL_LENGTH];
/* Temporary data array for processing */
DSPLIB_DATA(temp,4)
_q15 temp[SIGNAL_LENGTH];
/* Filter result */
DSPLIB_DATA(result,4)
_q15 result[SIGNAL_LENGTH];
/* State buffer */
DSPLIB_DATA(states,4)
msp_biquad_df2_q15_states states[FILTER_STAGES];
/* Benchmark cycle counts */
volatile uint32_t cycleCount = 0;
/* Function prototypes */
extern void initSignal(void);
void main(void)
{
msp_status status;
msp_fill_q15_params fillParams;
/* Disable WDT. */
WDTCTL = WDTPW + WDTHOLD;
#ifdef __MSP430_HAS_PMM__
/* Disable GPIO power-on default high-impedance mode for FRAM devices */
PM5CTL0 &= ~LOCKLPM5;
#endif
/* Initialize input signal */
initSignal();
/* Initialize filter coefficients. */
memcpy(filterCoeffs, FILTER_COEFFS_EX4, sizeof(filterCoeffs));
/* Zero initialize filter states. */
fillParams.length = sizeof(states)/sizeof(_q15);
fillParams.value = 0;
status = msp_fill_q15(&fillParams, (void *)states);
msp_checkStatus(status);
/* Initialize the parameter structure. */
df2Params.length = FILTER_LENGTH;
df2Params.stages = FILTER_STAGES;
df2Params.coeffs = filterCoeffs;
df2Params.states = states;
/* Invoke the msp_biquad_cascade_df2_q15 function. */
msp_benchmarkStart(MSP_BENCHMARK_BASE, 8);
status = msp_biquad_cascade_df2_q15(&df2Params, input, result);
cycleCount = msp_benchmarkStop(MSP_BENCHMARK_BASE);
msp_checkStatus(status);
/* End of program. */
__no_operation();
}
void initSignal(void)
{
msp_status status;
msp_add_q15_params addParams;
/* Generate Q15 input signal 1 */
sinParams.length = SIGNAL_LENGTH;
sinParams.amplitude = _Q15(SIGNAL_AMPLITUDE1);
sinParams.cosOmega = _Q15(cosf(2*PI*SIGNAL_FREQUENCY1/FS));
sinParams.sinOmega = _Q15(sinf(2*PI*SIGNAL_FREQUENCY1/FS));
status = msp_sinusoid_q15(&sinParams, input);
msp_checkStatus(status);
/* Generate Q15 input signal 2 to temporary array */
sinParams.length = SIGNAL_LENGTH;
sinParams.amplitude = _Q15(SIGNAL_AMPLITUDE2);
sinParams.cosOmega = _Q15(cosf(2*PI*SIGNAL_FREQUENCY2/FS));
sinParams.sinOmega = _Q15(sinf(2*PI*SIGNAL_FREQUENCY2/FS));
status = msp_sinusoid_q15(&sinParams, temp);
msp_checkStatus(status);
/* Add input signals */
addParams.length = SIGNAL_LENGTH;
status = msp_add_q15(&addParams, input, temp, input);
msp_checkStatus(status);
}