Logo
MSP DSP Library
filter_ex1_fir_q15.c

This example demonstrates how to use the msp_fir_q15 API and circular buffer feature to filter 16-bit input data. The input signal is composed of two generated sinusoidal signals added together, one sinusoid with a frequency that will pass though the filter and one with a frequency that will be filtered out. The inputs are copied into a circular buffer with twice the length of the filter and allows input history from previous filter operations to be reused without allocating and copying additional samples to the start of the input data. The generated input and result can be compared to see the effect of the filter.

//******************************************************************************
// Real 16-bit FIR filter.
//
// 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_ex1.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_EX1
/* 15th-order low pass filter coefficients (Fs=8192, Fc=1200) */
const _q15 FILTER_COEFFS_EX1[16] = {
_Q15(+0.001962), _Q15(-0.001728), _Q15(-0.012558), _Q15(-0.023557),
_Q15(-0.004239), _Q15(+0.072656), _Q15(+0.189060), _Q15(+0.278404),
_Q15(+0.278404), _Q15(+0.189060), _Q15(+0.072656), _Q15(-0.004239),
_Q15(-0.023557), _Q15(-0.012558), _Q15(-0.001728), _Q15(+0.001962)
};
#endif
/* Filter parameters */
#define FIR_LENGTH 64
#define COEFF_LENTH sizeof(FILTER_COEFFS_EX1)/sizeof(FILTER_COEFFS_EX1[0])
/*
* Circular buffer of size 2*FIR_LENGTH, aligned to 4*FIR_LENGTH in order to
* use the circular buffer feature.
*/
DSPLIB_DATA(circularBuffer,MSP_ALIGN_FIR_Q15(FIR_LENGTH))
_q15 circularBuffer[2*FIR_LENGTH];
/* Filter coefficients */
DSPLIB_DATA(filterCoeffs,4)
_q15 filterCoeffs[COEFF_LENTH];
/* Generated 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];
/* Benchmark cycle counts */
volatile uint32_t cycleCount = 0;
/* Function prototypes */
extern void initSignal(void);
void main(void)
{
uint16_t samples;
uint16_t copyindex;
uint16_t filterIndex;
msp_status status;
msp_fir_q15_params firParams;
msp_fill_q15_params fillParams;
msp_copy_q15_params copyParams;
/* 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_EX1, sizeof(filterCoeffs));
/* Zero initialize FIR input for use with circular buffer. */
fillParams.length = FIR_LENGTH*2;
fillParams.value = 0;
status = msp_fill_q15(&fillParams, circularBuffer);
msp_checkStatus(status);
/* Initialize the copy parameter structure. */
copyParams.length = FIR_LENGTH;
/* Initialize the FIR parameter structure. */
firParams.length = FIR_LENGTH;
firParams.tapLength = COEFF_LENTH;
firParams.coeffs = filterCoeffs;
firParams.enableCircularBuffer = true;
/* Initialize counters. */
samples = 0;
copyindex = 0;
filterIndex = 2*FIR_LENGTH - COEFF_LENTH;
/* Run FIR filter with 128 sample circular buffer. */
while (samples < SIGNAL_LENGTH) {
/* Copy FIR_LENGTH samples to filter input. */
status = msp_copy_q15(&copyParams, &input[samples], &circularBuffer[copyindex]);
msp_checkStatus(status);
/* Invoke the msp_fir_q15 function. */
msp_benchmarkStart(MSP_BENCHMARK_BASE, 16);
status = msp_fir_q15(&firParams, &circularBuffer[filterIndex], &result[samples]);
cycleCount += msp_benchmarkStop(MSP_BENCHMARK_BASE);
msp_checkStatus(status);
/* Update counters. */
copyindex ^= FIR_LENGTH;
filterIndex ^= FIR_LENGTH;
samples += FIR_LENGTH;
}
/* 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);
}