{ SELMS.ASM performs the following sign-error LMS algorithm implemented with a transversal FIR filter structure ***************************************************************** * 1) y(n)= w.u ( . = dot_product) , y(n)= FIR filter output * * where w= [w0(n) w1(n) ... wN-1(n)]= filter weights * * and u= [u(n) u(n-1) ... u(n-N+1)]= input samples in delay line* * n= time index, N= number of filter weights (taps) * * 2) e(n)= d(n)-y(n), e(n)= error signal & d(n)= desired output * * 3) wi(n+1)= wi(n)+STEPSIZE*sgn[e(n)]*u(n-i), 0 == 0 and -1 if e(n) < 0 * ***************************************************************** Written by: Wassim G. Najm , Analog Devices, DSP division, April 2 1991 Calling parameters (inputs): f0= u(n)= input sample f1= d(n)= desired output Altered registers: f0, f1, f2, f4, f7, f8, f12, f13 Computation cycles: selms_alg: 3N+8 per iteration, selms_init: 12+N Results (outputs): f13= y(n)= filter output f1= e(n)= filter error signal i8 -> Program Memory Data buffer of the filter weights Memory usage: pm code: 29 words, pm data= N words, dm data= N words } #define TAPS 5 #define STEPSIZE 0.005 .GLOBAL selms_init; .GLOBAL selms_alg; .SEGMENT/DM dm_data; .VAR deline_data[TAPS]; .ENDSEG; .SEGMENT/PM pm_data; .VAR weights[TAPS]; .ENDSEG; .SEGMENT/PM pm_code; selms_init: b0=deline_data; m0=-1; l0=TAPS; {circular delay line buffer} b8=weights; b9=b8; m8=1; l8=TAPS; {circular weight buffer} l9=l8; f7=STEPSIZE; f0=0.0; lcntr=TAPS, do clear_bufs until lce; clear_bufs: dm(i0,m0)=f0, pm(i8,m8)=f0; {clear delay line & weights} rts; selms_alg: dm(i0,m0)=f0, f4=pm(i8,m8); {store u(n) in delay line,f4= w0(n)} f8=f0*f4, f0=dm(i0,m0), f4=pm(i8,m8); {f8= u(n)*w0(n)} {f0= u(n-1), f4= w1(n)} f12=f0*f4, f0=dm(i0,m0), f4=pm(i8,m8); {f12= u(n-1)*w1(n), f0= u(n-2), f4= w2(n)} lcntr=TAPS-3, do macs until lce; macs: f12=f0*f4, f8=f8+f12, f0=dm(i0,m0), f4=pm(i8,m8); {f12= u(n-i)*wi(n), f8= sum of prod, f0= u(n-i-1), f4= wi+1(n)} f12=f0*f4, f8=f8+f12; {f12=u(n-N+1)*wN-1(n)} f13=f8+f12, f2=f7; {f13= y(n), f2= step-size} f1=f1-f13, f4=dm(i0,m0); {f1= e(n), f4= u(n)} if lt f2=-f7; {if e(n) < 0 then f2= -step-size} f0=f2*f4, f12=pm(i8,m8); {f0= f2*u(n), f12= w0(n)} lcntr=TAPS-1, do update_weights until lce; f8=f0+f12, f4=dm(i0,m0), f12=pm(i8,m8); {f8= wi(n+1), f4= u(n-i-1), f12= wi+1(n)} update_weights: f0=f2*f4, pm(i9,m8)=f8; {store wi(n+1)} rts(db); f8=f0+f12, f0=dm(i0,1); {f8= wN-1(n+1)} {i0 -> u(n+1) location in delay line} pm(i9,m8)=f8; {store wN-1(n+1)} .ENDSEG;