📄 ndlms.asm
字号:
;***********************************************************
; Version 2.20.01
;***********************************************************
;********************************************************************************
; Function: ndlms
; Description: ndlms fir filter
;
; Copyright Texas instruments Inc, 1998
;------------------------------------------------------------------------------
; Revision History:
; 0.00 , J. Nikolic-Popovic, 7/15/98 - Original code
; 1.00, A. Aboagye, 8/31/98 - Changed calling conventions
; 2.00 - Li Yuan, 4/09/02. fixed overflow flag setup at the end of code.
;--------------------------------------------------------------------------------
; Registers modified:
; a, b,
; ar1, ar2, ar3, ar4, ar5, ar6, ar7
; brc, sp, st1(sxm, frct, asm)
;
;********************************************************************************
.mmregs
.if __far_mode
offset .set 1
.else
offset .set 0
.endif
; local variables
.asg (0), mu_error ; 2*mu*error(i) variable
.asg (1), inv_abs_power ; inverse absolute power
.asg (2), abs_power ; absolute power (long-aligned)
.asg (4), save_st1
.asg (5), save_st0
.asg (6), save_ar7
.asg (7), save_ar6 ; stack description
.asg (8), save_ar1
.asg (9), ret_addr
; arguments
; x in A
.asg (10 + offset), arg_h
.asg (11 + offset), arg_y
.asg (12 + offset), arg_d
.asg (13 + offset), arg_des
.asg (14 + offset), arg_nh
.asg (15 + offset), arg_n
.asg (16 + offset), arg_l_tau
.asg (17 + offset), arg_cutoff
.asg (18 + offset), arg_gain
.asg (19 + offset), arg_norm_d
; register usage
.asg ar1, ar_count
.asg ar2, ar_d
.asg ar3, ar_h
.asg ar7, ar_des
.asg ar4, ar_norm_d
.asg ar6, ar_y
.asg ar5, ar_x
;============================================================================
.global _ndlms
_ndlms:
; Preserve registers
;-------------------
pshm ar1
pshm ar6
pshm ar7
PSHM ST0 ; 1 cycle
PSHM ST1 ; 1 cycle
RSBX OVA ; 1 cycle
RSBX OVB ; 1 cycle
; Preserve space for local variables
; ----------------------------------
frame -4 ; local vars:
; mu_error
; inverse_absy
; abs_power ( 2 locations)
; OJO: may need to clear OVA flag
; Set math and overflow modes
;---------------------------
ssbx sxm ; sign extension on
ld #0,ASM ; clear ASM (used by st||mpy)
st #0, *sp(mu_error) ; clear error OJO : make argument
; Get arguments
;---------------
stlm a, ar_x ; pointer to x
ld #0, a
dst a,*sp(abs_power) ; store abolute power as a local variable
mvdk *sp(arg_h),*(ar_h) ; pointer to h
mvdk *sp(arg_y),*(ar_y) ; pointer to y
mvdk *sp(arg_norm_d),*(ar_norm_d) ; pointer to normalized delay buffer
mvdk *sp(arg_d),*(ar_d) ; de-referencing
mvdk *sp(arg_des),*(ar_des) ; for circ addr
mvdk *sp(arg_n), *(ar_count) ; sample counter
mar *ar_count- ; ar_count= nsamples-1
ld *sp(arg_nh),a ; a = nh
; Initialize registers
; --------------------
stlm a,bk ; bk = circular buffer size = nh
sub #02,a ;
stl a, *sp(arg_nh)
; Loop through remaining (n-1) samples
;-------------------------------------
next_sample:
; Update power estimate
;-------------------------------------
ld *ar_x, 0,b
abs b
ld *sp(arg_l_tau),t
ld *sp(arg_l_tau),asm
dld *sp(abs_power),a ; double presicion load
sub *sp(abs_power),TS ,a ; a - ABSY *2^LTAU
add b,ASM,a ; a + ABSY0*2^LTAU
add *sp(arg_cutoff),TS,A ; a + CUTOFF*2^LTAU
dst a,*sp(abs_power) ; double precision store.
ld #1, 16, b
rpt #14
subc *sp(abs_power), b
stl b,*sp(inv_abs_power) ; inv_abs_power = 1 / abs_power
ld #0,asm ; clear asm for st||mpy
; Continue
;-------------------------------------
ssbx frct
stm #1,AR0
mvdk *sp(arg_nh),brc
ld *sp(mu_error), t ; t = 2 * mu * error (i)
sub b,b ; b = 0
; Update delay buffer
; -------------------
mvdd *ar_x, *ar_d+0% ; new sample --> dbuffer x(i)
; Loop through (nh-1) taps: compute filter and adapt at = time
; ------------------------------------------------------------
rptbd nlms_end -1
mpy *ar_norm_d+0%,a ; a = mu_error * n_x(i-N)
; point to n_x(i-N+1)
lms *ar_h, *ar_d+0% ; b = b + h(1) * x(i-N+1)
; a = a + h(1)
nlms_beg
st a, *ar_h+0%; ; update h(1)
; point to h(2)
|| mpy *ar_norm_d+0%,a ; a = mu_error * n_x(i-N+1)
; point to n_x(i-N+2)
lms *ar_h, *ar_d+0% ; b = b + h(2) * x(i-N+2)
; a = a + h(2)
nlms_end
sth a, *ar_h+0% ; update last coef
; Write output sample
; -------------------
sth b, *ar_y+
; Compute new error
; ----------------
sub *ar_des+,16,b,a ;
neg a ; ah = error(i)=des(i)-y(i)
mpya *sp(inv_abs_power) ; (Q.0 * Q.15) << 1 = Q.16
sfta b,15
sat b ; b is in Q.31 now
ld *sp(arg_gain),t
norm b ; b = b << arg_gain
sth b,*sp(mu_error)
; Update normalized delay buffer
; ------------------------------
ld *ar_x+,16,a
mpya *sp(inv_abs_power) ; (Q.0 * Q.15) << 1 = Q.16
sfta b,15
sat b ; b is in Q.31 now
sth b, *ar_norm_d+0%
rsbx frct
banz next_sample, *ar_count-
; Return
;-------
.asg ar_h, ar_temp1 ; ar_h not used any more
.asg ar_x, ar_temp2 ; ar_x not used any more
mvdk *sp(arg_d), *(ar_temp1)
mvkd *(ar_d), *ar_temp1 ; update new ar_d
; Return overflow flag
; --------------------
ld #0,a
xc 1,AOV
ld #1,a
; Adjust stack pointer and restore registers
; ------------------------------------------
frame +4 ; adjust for local vars
POPM ST1
POPM ST0
popm ar7
popm ar6
popm ar1
.if __far_mode
fretd ; 4 cycles
.else
retd ; 3 cycles
.endif
nop
nop
;end of file. please do not remove. it is left here to ensure that no lines of code are removed by any editor
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -