ARM CMIS IIR filters

Me

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

Bandpass example spectrum

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.