Digital 2 order IIR filter implementation

cancel
Showing results for 
Search instead for 
Did you mean: 

Digital 2 order IIR filter implementation

Jump to solution
1,212 Views
sebastianprenge
Contributor II

Hello community,

I have implemented the following filter:

Filter.h:

 #ifndef __Filter_H #define __Filter_H  /* MODULE Filter */  typedef struct {     Int16    x_1;     Int16    x_2;     Int32    y_1;     Int32    y_2; } TFilter;  typedef struct {     Int16    B0;     Int16    B1;     Int16    B2;     Int16   gain;     Int16    A1;     Int16    A2; } TCoeff;  extern Int16 SecOrderFilter(Int16 *x, TFilter *filter, TCoeff *coeff);  /* END Filter */  #endif   extern Int16 SecOrderFilter(Int16 *x, TFilter *filter, TCoeff *coeff);  /* END Filter */  #endif 

 

Filter.c:

 #include "Cpu.h" #include "Filter.h"  Int16 SecOrderFilter(Int16 *x, TFilter *filter, TCoeff *coeff) {     register Int32 temp;     //L(z)=b0 + b1*z^-1 + b2*z^-2     //     ------------------------ * gain     //       1 + a1*z^-1 + a2*z^-2          temp= __L_mult_int(coeff->B0 , *x);     temp= __L_mac_int(temp, coeff->B1 , filter->x_1);     temp= __L_mac_int(temp, coeff->B2 , filter->x_2);     temp= __L_msu_int(temp, coeff->A1 , (Int16)(filter->y_1 >> coeff->gain)); //If shift is performed this way resolution is lost     temp= __L_msu_int(temp, coeff->A2 , (Int16)(filter->y_2 >> coeff->gain)); //If shift is performed this way resolution is lost               //Shift values     filter->x_2=filter->x_1;     filter->x_1=*x;     filter->y_2=filter->y_1;     filter->y_1=temp;     return extract_l(temp >> coeff->gain); //Return y value shifted with gain } }   /* END Filter */

 

My filter coeff for a low pass filter are b0=1; b1=2; b2=1; a1=-32380; a2=16000; gain=2^14. To have a proper resolution of the filter (x=1 after many cycles yield to y=1) I had to implement y as 32 bit value. Unfortunately this means a 16 bit x 32 bit = 48 bit multiplication which will be shifted 14 bits afterwards. If the shift is performed before the multiplication (refer source) the resolution is lost.

 

How can I implement a 16 Bit x 32 Bit integer multiplication with intrinsic56800 functions?

Is there a newer version of "intrinsics_56800E.h" Rev 1.29; Date 2007/11/01 CW 56800/E 8.3 Classic?

 

Thank you in advance!

 

Cheers

Sebastian

Labels (1)
Tags (3)
0 Kudos
1 Solution
475 Views
sebastianprenge
Contributor II

Hello Community,

I found the solution: __L_mult_ls_int can multiply 32bit x 16bit values. It generates a 48bit result which is shifted 16bits right a returns a 32bit value. Here is the c-code for the 2order IIR filter function.

#include "Cpu.h"

#include "Filter.h"

/* L_mult_int */

Int16 SecOrderFilter(Int16 *x, TFilter *filter, TCoeff *coeff)

{

    register Int32 temp;

    register Int16 gain2;

    //L(z)=b0 + b1*z^-1 + b2*z^-2

    //     ------------------------ * gain

    //       1 + a1*z^-1 + a2*z^-2

   

    //y=b0*x+b1*x(-1)+b2*x(-2)

    //    -a1*y(-1)-a2*y(-2)

   

   

    gain2=16-coeff->gain;

   

    temp= __L_mult_int(coeff->B0 , *x);

    temp= __L_mac_int(temp, coeff->B1 , filter->x_1);

    temp= __L_mac_int(temp, coeff->B2 , filter->x_2);

    temp=temp - __L_mult_ls_int(filter->y_1 << gain2, coeff->A1); // SHR(32Bit x 16Bit, 16)=32Bit

    temp=temp - __L_mult_ls_int(filter->y_2 << gain2, coeff->A2); // SHR(32Bit x 16Bit, 16)=32Bit

   

    //Werte schieben

    filter->x_2=filter->x_1;

    filter->x_1=*x;

    filter->y_2=filter->y_1;

    filter->y_1=temp;

    return extract_l(temp >> coeff->gain);

}

Attached you can find a excel sheet to design the filter an simulate the filter response.

Cheers

Seb.

View solution in original post

0 Kudos
1 Reply
476 Views
sebastianprenge
Contributor II

Hello Community,

I found the solution: __L_mult_ls_int can multiply 32bit x 16bit values. It generates a 48bit result which is shifted 16bits right a returns a 32bit value. Here is the c-code for the 2order IIR filter function.

#include "Cpu.h"

#include "Filter.h"

/* L_mult_int */

Int16 SecOrderFilter(Int16 *x, TFilter *filter, TCoeff *coeff)

{

    register Int32 temp;

    register Int16 gain2;

    //L(z)=b0 + b1*z^-1 + b2*z^-2

    //     ------------------------ * gain

    //       1 + a1*z^-1 + a2*z^-2

   

    //y=b0*x+b1*x(-1)+b2*x(-2)

    //    -a1*y(-1)-a2*y(-2)

   

   

    gain2=16-coeff->gain;

   

    temp= __L_mult_int(coeff->B0 , *x);

    temp= __L_mac_int(temp, coeff->B1 , filter->x_1);

    temp= __L_mac_int(temp, coeff->B2 , filter->x_2);

    temp=temp - __L_mult_ls_int(filter->y_1 << gain2, coeff->A1); // SHR(32Bit x 16Bit, 16)=32Bit

    temp=temp - __L_mult_ls_int(filter->y_2 << gain2, coeff->A2); // SHR(32Bit x 16Bit, 16)=32Bit

   

    //Werte schieben

    filter->x_2=filter->x_1;

    filter->x_1=*x;

    filter->y_2=filter->y_1;

    filter->y_1=temp;

    return extract_l(temp >> coeff->gain);

}

Attached you can find a excel sheet to design the filter an simulate the filter response.

Cheers

Seb.

View solution in original post

0 Kudos