/* Cascaded IIR Biquad Sections (Direct Form II or Transposed Direct Form I) w(n) = x(n) + a1*w(n-1) + a2*w(n-2) beware of signs here! y(n) = w(n) + b1*w(n-1) + b2*w(n-2) Each section consists of: b2,b1,a2,a1,w(n-1),w(n-2) Notice that coefs have been normalized such that b0=1.0 Calling Parameters __cascaded_biquad_ L0, L1, L8 = 0 M1, M8 = 1 F8 = first x(n) R0 = number of biquad sections (filter order / 2) B0 = address of delay line buffer B8 = address of coefficient buffer __cascaded_biquad_init_ L0 = 0 R0 = number of biquad sections (filter order / 2) B0 = address of delay line buffer Returned Values F8 = last y(n) __cascaded_biquad_ delay line zeroed __cascaded_biquad_init_ Register File Usage: f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 ----------------------------------------------------------------+ * * * * * ! __cascaded_biquad_ * ! __cascade_biquad_init_ ----------------------------------------------------------------+ Data Address Generator Usage I0, B1, I1, I8, M1, M8 __cascaded_biquad_ I0 __cascaded_biquad_init_ Benchmark 6 + 4*(sections) cycles __cascaded_biquad_ 5 + 2*(sections) cycles __cascaded_biquad_init_ (incl. non-delayed rts) Memory Usage __cascaded_biquad_ 10 words instructions in PM 4*(sections) coefficients in PM 2*(sections) delay line storage in DM __cascaded_biquad_init 5 words instructions in PM 2*(sections) delay line storage in DM */ .segment/pm pm_code; .global __cascaded_biquad_, __cascaded_biquad_init_; .extern coefs, dline; __cascaded_biquad_init_: /* *** call this once to set up initial conditions *** */ F2=0; LCNTR=R0, DO clear UNTIL LCE; /*for each section, do:*/ dm(I0,1)=F2; /*clear w`` storage*/ clear: dm(I0,1)=F2; /*clear w` storage*/ RTS; __cascaded_biquad_: /* *** call this for every sample to be filtered *** */ /*w` = w(n-1), w`` = w(n-2)*/ B1=B0; /*NEXT = "for next biquad section"*/ F12=F12-F12, F2=dm(I0,M1), F4=pm(I8,M8); /*F12=0, rd w``, rd a2*/ LCNTR=R0, DO quads UNTIL LCE; /*for each section, do:*/ F12=F2*F4, F8=F8+F12, F3=dm(I0,M1), F4=pm(I8,M8); /*w``a2, 1st=x+0,else=y, rd w`, rd a1*/ F12=F3*F4, F8=F8+F12, dm(I1,M1)=F3, F4=pm(I8,M8); /*w`a1, x+w``a2, wr new w`, rd b2*/ F12=F2*F4, F8=F8+F12, F2=dm(I0,M1), F4=pm(I8,M8); /*w``b2, new w, rd NEXT w``, rd b1*/ quads: F12=F3*F4, F8=F8+F12, dm(I1,M1)=F8, F4=pm(I8,M8); /*w`b1, new w+(w``b2), wr new w, rd NEXT a2*/ RTS (DB), F8=F8+F12; /*calc last y after dropping out of loop*/ NOP; NOP; .endseg;