Hi,

have a problem with IIR filter implementation in assembler.

Here is C code:

w=sample+cbuf[0]*coeff[4]+cbuf[1]*coeff[3]; |

y=w*coeff[2]+cbuf[0]*coeff[1]+cbuf[1]*coeff[0];

cbuf[1]=cbuf[0];

cbuf[0]=w;

And the assembler version:

_IIRbiquad:

.global _IIRbiquad;

/* r4=sample

r8=coefficients

r12=state */

i4=r12; // i4->stat

i12=r8; // i12->coef+4

modify(i12,4);

m12=-1; m4=1;

r0=dm(i4,m4), r8=pm(i12,m12);

mrf=r0*r8(SSF), r0=dm(i4,m4), r8=pm(i12,m12);

mrf=mrf+r0*r8(SSF), r8=pm(i12,m12);

r12=mr1f;

modify(i4,-2);

r12=r12+r4; // w

mrf=r12*r8(SSF), r4=dm(i4,m4), r8=pm(i12,m12); // w*coef(2)

mrf=mrf+r4*r8(SSF), r0=dm(i4,m4), r8=pm(i12,m12);

mrf=mrf+r0*r8(SSF);

r0=mr1f;

dm(-1,i4)=r4;

dm(-2,i4)=r12; //*/

leaf_exit;

_IIRbiquad.end:

==================================

I do not know, why this code is not working, but should.

I don't see any logical error.

Maybe someone has an example of fixed point IIR filter implementation for SHARC ?

Regards

Roman

Hi Mitesh,

thanks for the answer.

Yes, talk through demos you give for SHARC evalboard convert fractionals to floats, and than back: floats to fractionals (or signed integers). It is unnecessary waste of time.

Why I use fixed-point numbers ? Because of result precision. In case of low frequency filters the precision is crucial, also for stability. Fixed-point give 8-bits better precision.

I resolved my problem. Filters coefficients have to be scaled down in order to keep intermediate data and results in [-1.0, 1.0) range.

The algorithm is O.K., I checked it in C using float and fract numbers.

Hand written C code also works fine, the library biquad and IIR functions for floats are good and optimal ( I looked at disassembled code in debugger).

In last 20 years I used fixed-point Motorola DSP56300 processors, so my programs for multichannel audio were highly optimal in sens o code size and execution speed.

Now I switched to SHARC, but want to show my students the beauty of assembler and fixed-point representation for critical sections of application code. The C code hides numerical details so is dry and dull.

The final, second version of biquad (direct form I structure) is:

_IIRbiquad:.global _IIRbiquad;/* r4=sampler8=coefr12=stat */i4=r12; // i4->stati12=r8; // i12->coefmodify(i12,4); //i12->coef+4m12=-1; m4=1;r12=dm(i4,m4), r8=pm(i12,m12); //y(n-1)|-A1mrf=r12*r8(SSF), r0=dm(i4,m4), r8=pm(i12,m12); //y(n-2)|-A2dm(-1,i4)=r12; // y(n-2)=y(n-1)mrf=mrf+r0*r8(SSF), r8=pm(i12,m12); //B0r2=rnd mrf(SF);r2=ashift r2 by 1; // unscale denmrf=r4*r8(SSF), r12=dm(i4,m4), r8=pm(i12,m12); // x(n-1)|B1mrf=mrf+r12*r8(SSF), r0=dm(i4,m4), r8=pm(i12,m12); // x(n-2)|B2dm(-1,i4)=r12;// x(n-2)=x(n-1)mrf=mrf+r0*r8(SSF);r0=rnd mrf(SF);r0=ashift r0 by 1; // unscale numr0=r0+r2;dm(-2,i4)=r4; // update x/y(n-1) memory datadm(-4,i4)=r0;leaf_exit;_IIRbiquad.end:The filter is a notch type:

fract pm coefN[5] = {0.499928014591599, -0.995054474346837, 0.499941102847739, -0.499869117439335, 0.995054474346835}; // 0.5* [B2 B1 B0 -A2 -A1]Kind regards

Roman