There seems to be little information on the web about using Matlab and ARM CMSIS IIR functions. In princple it should be easy to design a filter in Matlab and run it on an an ARM chip. Well it is, its just the information seems to be spread over a number documents.
The design steps are as follows. Use Matlab to design an IIR filter and export the filter to the work space. (Or use any other method but convert it to SOS form). The format the CMSIS is expecting is slightly different to Matlab. Here is an example bandpass filter:
SOS = 1.0000 -0.9417 1.0000 1.0000 0.1845 0.8716 1.0000 1.7675 1.0000 1.0000 1.2434 0.9009 1.0000 -1.7449 1.0000 1.0000 0.5365 0.8054 1.0000 1.9538 1.0000 1.0000 0.9467 0.8240 1.0000 -0.6225 1.0000 1.0000 1.3914 0.9702 1.0000 1.6693 1.0000 1.0000 0.0035 0.9582 G = 0.6502 0.6502 0.8174 0.8174 0.0694 0.0694 1.0000
Each row of SOS is a stage and the parameters as [b0,b1,b2,a0,a1,a2]
Note a0
is always one and is not needed. Looking at the
Biquad Cascade IIR Filters Using Direct Form I Structure page we see the formula for each stage is
y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2]
, which differs from
Matlab's y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a2 * y[n-2]
. To correct
for this we simply mutliple a1
, and a2
by -1. However, this also ignores the gain
on each stage. To correct for this multiply b1,b2,b3
by the stage gain value in G
.
The new coefficent matrix that is in the correct format form CMSIS is now
Coeff = 0.6502 -0.6123 0.6502 -0.1845 -0.8716 0.6502 1.1491 0.6502 -1.2434 -0.9009 0.8174 -1.4262 0.8174 -0.5365 -0.8054 0.8174 1.5970 0.8174 -0.9467 -0.8240 0.0694 -0.0432 0.0694 -1.3914 -0.9702 0.0694 0.1159 0.0694 -0.0035 -0.9582
Note how a0
has been removed. To automate this I have created a
simple Matlab file which produces the header file.
An example snippet of C code is here
#include "test.h" //the file generated by MatlabSOS2CMSIS float32_t pState[NUM_SECTIONS*4]={0}; //NUM_SECTIONS is define in test.h arm_biquad_casd_df1_inst_f32 S; //structure the defines the filter
In the your main function init the filter.
arm_biquad_cascade_df1_init_f32(&S,NUM_SECTIONS,pCoeffs,pState);
To run the filter:
arm_biquad_cascade_df1_f32(&S,pSrc,pDest,BUFFER_SIZE);
See CMSIS doc for varible descriptions
The figure above shows the response curve of the filter. This was generated by passing random white noise into the filter, converting it to audio and capturing via a PC sound card and FFTing in Matlab.