{_________________________________________________________________________ R2FIREZ.ASM ADSP-21020 Radix-2 FIR Filter - EZ-Lab Example This routine performs N-tap FIR filtering using a radix-2 implementation, where N must be even. The FIR filter is broken down into three subfilters resulting in about a 25% speed improvement at the cost of a 50% greater memory requirement. For a more complete discussion see: [1] Meyer, Reng, Schwarz : Convolution Algorithms on DSP Processors Proc. ICASSP 1991 Toronto [2] Mou, Duhamel : Fast FIR Filtering: Algorithms and Implementations Signal Processing 13 (1987) pp. 377-384 This routine should be called each time a new sample is available to be fed into the filter. Filter coefficients reside in program memory and can be generated from direct FIR filter coeff using the program D2R2FIR. This program creates the coeff tables H0, H1 and H0+H1 and stores them consecutively in a file where H0 = h(0), h(2), h(4), ... and H1 = h(1), h(3), h(5), ... . Author: Karl Schwarz, Universitaet Erlangen Nuernberg Revision: 11-JUN-91, Ronnin Yee, Analog Devices, DSP div., (617) 461-3672 Calling Information: f2 = x(n-1) in floating point f11 = x(n) in floating point where x is the incoming sample stream and n is the current sample Results: f9 = y(n-1) in floating point f10 = y(n) in floating point where y is the outgoing, filtered sample stream and n is the current sample Altered Registers: f0,f1,f2,f3,f4,f8,f11,f12,f13,f14, i0,i1,i2,i3,i8,i9,i10,l0,l1,l2,l8,l9,l10, m0,m1,m2,m8 Benchmarks: radix-2 FIR, 3/4*N + 7 cycles/sample 3/4*N + 15.5 cycles/sample with pointer initialization/restoration Memory Usage: pm code = 32, pm data = 1.5N words, dm data = 1.5N + 1 words Assembler Preprocessor Variables: N = number of taps = degree + 1 = even _________________________________________________________________________} #include "def21020.h" #define N 32 .SEGMENT/PM pm_sram; .VAR coeff[3*N/2] = "coeff.dat"; .ENDSEG; .SEGMENT/DM dm_sram; .VAR a_smpl[N/2]; {a= x(n-1), x(n-3), ... ; b= x(n-2), x(n-4),...} .VAR bma_smpl[N/2]; { c= x(n), x(n-2), ... } .VAR amc_smpl[N/2]; { bma_smpl= b - a; amc_smpl= a - c } .VAR x_old = 0; { x(n-2) sample} .ENDSEG; { These are the 2111 hip port addresses } .SEGMENT/DM hip_regs; .PORT hdr0; {in left audio} .PORT hdr1; {in right audio} .PORT hdr2; {out left audio} .PORT hdr3; {out right audio} .PORT hdr4; {2111 status} .PORT hdr5; {2111 commands} .ENDSEG; .SEGMENT/PM rst_svc; pmwait=0x0021; {pgsz=0,pmwtstates=0,softw.wtstates only} dmwait=0x008421;{pgsz=0,dmwtstates=0,softw.wtstates only} jump main; nop; nop; .ENDSEG; .SEGMENT/PM tmzh_svc; nop; .ENDSEG; .SEGMENT/PM irq3_svc; jump hip_rnt; nop; nop; .ENDSEG; .SEGMENT/PM irq2_svc; nop; .ENDSEG; .SEGMENT/PM pm_sram; main: imask=IRQ3I; {irq3 enable} mode1=IRPTEN; {enable global interrupt} r15=0x0; {odd/even sample count} {r2fir Initialization } b0= a_smpl; { a } b1= bma_smpl; { b-a } b2= amc_smpl; { a-c } b3= x_old; { x(n-2) sample} b8= coeff+N; { h0+h1 } b9= coeff+N/2; { h1 } b10=coeff; { h0 } m0=1; m1=-1; m2=0; m8=1; l0=N/2; l1=N/2; l2=N/2; l8=N/2; l9=N/2; l10=N/2; {sit around and let the service routine do all the work} idle; jump (pc,-1); nop; nop; hip_rnt: i6=hdr0; {incoming audio sample port} i7=hdr2; {outgoing audio sample port} m7=0; r15= pass r15, r5=dm(i6,m7); {read data} if ne jump dofilter; r15=r15+1; rti (db); r9=fix f9; f2=float r5, dm(i7,m7)=r9; {write y(n-1) to hdr2} dofilter: call r2fir (db); r10=fix f10; f11=float r5, dm(i7,m7)=r10; {write y(n) to hdr2} rti (db); r15=r15-r15; nop; {radix-2 fir filter} r2fir: { f2 = input; = x(n-1) } { f11 = input; = x(n) } { f8 = x(n-2) = old value from f11 } r14=r14-r14, f8=dm(i3,m2); {zeros out f14} f13=pass f2, dm(i0,m0)=f2, f4=pm(i8,m8); f12=f2*f4, f3=f8-f13, f0=dm(i0,m0), f4=pm(i9,m8); f13=f3*f4, f1=f11-f13, dm(i1,m0)=f3, f4=pm(i10,m8); f8=f1*f4, dm(i2,m0)=f1, f4=pm(i8,m8); LCNTR=N/2-2, do fir_l until LCE; f8=f0*f4, f14=f8+f14, f0=dm(i1,m0), f4=pm(i9,m8); f8=f0*f4, f12=f8+f12, f0=dm(i2,m0), f4=pm(i10,m8); fir_l: f8=f0*f4, f13=f8+f13, f0=dm(i0,m0), f4=pm(i8,m8); f8=f0*f4, f14=f8+f14, f0=dm(i1,m2), f4=pm(i9,m8); f8=f0*f4, f12=f8+f12, f0=dm(i2,m2), f4=pm(i10,m8); f8=f0*f4, f13=f8+f13, f0=dm(i0,m1); rts (db), f14=f8+f14; f9=f12+f13, dm(i3,m2)=f11; {x(n-2) = x(n)} f10=f12+f14; { output = f9 = y(n-1) } { output = f10 = y(n) } {end of routine} .ENDSEG;