{ SSLMS.ASM performs the following sign-sign 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)]*sgn[u(n-i)], 0 == 0 and -1 if x < 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, f9, f12, f13 Computation cycles: sslms_alg: 4N+7 per iteration, sslms_init: 13+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= 31 words, pm data= N words, dm data= N words } #define TAPS 5 #define STEPSIZE 0.005 .GLOBAL sslms_init, sslms_alg; .SEGMENT/DM dm_data; .VAR deline_data[TAPS]; .ENDSEG; .SEGMENT/PM pm_data; .VAR weights[TAPS]; .ENDSEG; .SEGMENT/PM pm_code; sslms_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; f2=1.0; 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; sslms_alg: dm(i0,m0)=f0, f4=pm(i8,m8); {f4=w0(n), store u(n) in delay line} 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, f8=dm(i0,m0), f12=pm(i8,m8); {f13= y(n), f12= w0(n)} f1=f1-f13, f9=f7; {f1= e(n), f8= u(n), f9= STEPSIZE} f0=f1*f8, f4=dm(i0,m0); {f0= u(n)*e(n) to set multiplier flags for sign of product, f4=u(n-1)} lcntr=TAPS-1, do update_weights until lce; if ms f9=-f7; {if u(n)*e(n)<0 then f9=-STEPSIZE} f9=f2*f7, f8=f9+f12, f12=pm(i8,m8); {restore f9 to STEPSIZE} {f8= wi-1(n+1), f12= wi(n)} update_weights: f0=f1*f4, f4=dm(i0,m0), pm(i9,m8)=f8; {store wi-1(n+1)} {set multiplier flags, f4= u(n-i-1)} if ms f9=-f7; rts(db); f8=f9+f12, f0=dm(i0,2); {i0 -> u(n+1) location in delay line} {f8= wN-1(n+1)} pm(i9,m8)=f8; {store wN-1(n+1)} .ENDSEG;