⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nblms.asm

📁 CCS3.3自带的TI 5400系列DSP的dsplib文件。文档说明可以在TI公司网站上下载。
💻 ASM
字号:
;***********************************************************
; Version 2.20.01                                           
;***********************************************************
;****************************************************************
;  Function:	nblms
;  Description: nblms fir filter
;
;  Copyright Texas instruments Inc, 1998
;---------------------------------------------------------------
; Revision History:
;  0.0	J. Nikolic-Popovic. 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 vars
	
	.asg	(0), error			; 
	.asg	(1), inv_abs_power		; inverse absolute power		
	.asg	(2), nh				; number of coefficients
	.asg	(3), mod_bsize_cnt		; block counter
						; (points to block to be updated)
	.asg	(4), bsize_2			; blocksize-2
	.asg	(5), y0_ptr			; pointer to the latest sample
	.asg	(6), abs_power			; absolute power (long aligned)

	.asg	(10), save_ar7
	.asg	(11), save_ar6			; stack description
	.asg	(12), save_ar1
	.asg	(13), ret_addr

	; arguments
						; x in A
	.asg	(14 + offset), arg_h
	.asg	(15 + offset), arg_y
	.asg	(16 + offset), arg_d
	.asg	(17 + offset), arg_des
	.asg	(18 + offset), arg_nb
	.asg	(19 + offset), arg_n
	.asg	(20 + offset), arg_bsize
	.asg	(21 + offset), arg_norm_e
*	.asg	(22 + offset), arg_p_abs_power	
	.asg	(22 + offset), arg_l_tau
	.asg	(23 + offset), arg_cutoff
	.asg	(24 + offset), arg_gain

	; register usage

	.asg	ar1, ar_count
	.asg	ar2, ar_d
	.asg	ar3, ar_h
	.asg	ar7, ar_des
	.asg	ar4, ar_norm_e
	.asg	ar6, ar_y
	.asg	ar5, ar_x
;============================================================================
	.global _nblms

_nblms:

; 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	-8				; local var
						; error 
						; inverse_absy
						; nh ( number of taps)
						; modulo(blocksize) counter
						; blocksize-2				
						; y0_ptr
						; abs_power

						; OJO: may need to clear OVA flag
; Set math and overflow modes
;---------------------------
	ssbx	sxm				; sign extension on

; Get arguments and Initialize registers
;---------------------------------------
	stlm	a, ar_x 			; pointer to x
	mvdk	*sp(arg_y),*(ar_y)		; pointer to y

	mvdk	*sp(arg_d),*(ar_d)		; de-referencing
	ld	*ar_d,a				; pointer to d
	stl	a,*sp(y0_ptr)			; initialize the local variable
	mvdk	*ar_d,*(ar_d)		

	mvdk	*sp(arg_des),*(ar_des)		; 
	mvdk	*sp(arg_n), *(ar_count) 	; sample counter
	mar	*ar_count-			; ar_count= nsamples-1

	ld	*sp(arg_nb),T			; calculate number of coefficients	
	mpy	*sp(arg_bsize),a		; and store it as a local variable
	sub	#02,a,b				; 
	stl	b, *sp(nh)			; 
	add	*sp(arg_bsize),a
	stlm	a,bk				; bk = circular buffer size = nh+blocksize

	ld	*sp(arg_nb),b
	sub	#1,b
	stl	b,*sp(arg_nb)			; store (number of blocks -1)

	ld	*sp(arg_bsize),a
	sub	#2,a
	stl	a,*sp(bsize_2)			; store (blocksize - 2 )

	ld	*sp(arg_gain),a
	add	#15,a
	stl	a,*sp(arg_gain)			; store gain+15
	
	ld	#0h, a
	dst	a,*sp(abs_power)		; store abolute power as a local variable

	ld	#0,b
	stl	b,*sp(mod_bsize_cnt)		; initialize block couter to zero
	ssbx	frct


; Loop through remaining (n-1) samples
;-------------------------------------

next_sample:

	stm     #0ffffh,AR0             	; initialize to -1		
	mvdd	*ar_x, *ar_d			; new sample --> dbuffer 

	; Adaptive Fir
	;-------------

adaptive_fir:

	mvdk	*sp(arg_h),*(ar_h)		; pointer to h

	ld      #0,b
	rpt     *sp(nh)				; repeat nh-1 times
	mac     *ar_d+0%,*ar_h+,b
	macr    *ar_d+0%,*ar_h,b		; add rounding offset.
						; Q0 * Q15 = Q15, shift by one = Q16
 	; Write output sample
	; -------------------
	sth	b, *ar_y+			; save in Q0	


	; Compute new error
	; -----------------

	sub	*ar_des+,16,b,a			; 
	neg	a				; ah = error(i)=des(i)-y(i)
	sth	a,*sp(error)


	; Update power estimate
	;----------------------

update_power_estimate:

	ld	*ar_x+, 0,b			; point to next entry in the input buffer
	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	


	; Update normalized error buffer
	;------------------------------- 

	mvdk	*sp(arg_norm_e),ar_norm_e
	ld	*ar_norm_e,a
	add	*sp(bsize_2),a
	stlm	a,ar_norm_e			; point to end of the buffer
	rpt	*sp(bsize_2)			; rpt blocksize-2 times	
	delay	*ar_norm_e-
	ld	*sp(error), T
	mpy	*sp(inv_abs_power), a		; Q0 * Q15 << 1  = Q16
	sfta	a, 15				; Q31				
	sat	a
	sth	a, *+ar_norm_e			

	; Update taps
	;------------

update_taps:

	ld	*sp(arg_nb),a
	stlm	a, BRC			

						; set up the pointer to the reference buffer:
	ld	*sp(y0_ptr), A
	sub	*sp(mod_bsize_cnt),A
	stlm	A,ar_d				; pointer into delay buffer

	ld	*sp(arg_h),a
	add	*sp(mod_bsize_cnt), a				
	sub	*sp(arg_bsize), a		
	stlm	a, ar_h				; pointer to the block of coefficients 
						; to be updated

	mvdk	*sp(arg_norm_e),*(ar_norm_e)	; de-referencing

	rptbd	$block_end-1
	mvdk	*ar_norm_e,*(ar_norm_e)		; pointer to d

	stm     #0ffffh,AR0             	
	ld	#0,a
	rpt	*sp(bsize_2)			; actually, it should
						; be blocksize-2!
	mac	*ar_d+0%, *ar_norm_e+, A	; Q0*Q15 = Q15, shifted by one = Q16
	macr	*ar_d+0%, *ar_norm_e, A		; Q0*Q15 = Q15, shifter by one = Q16

	mpya	*sp(inv_abs_power)		; Q0*Q15 = Q15, shifted by one = Q16
						; (in B)	

	mvdk	*sp(arg_bsize),*(AR0)		; index

	mar	*ar_h+0
	ld	*ar_h, 16, A			
		
	ld	*sp(arg_gain),ASM
	add	b, ASM,a			; a = a + b << ASM
						; ak(i+1) = ak(i) + b<<(15+GAIN)
						; the 15 is to transform B 
						; from Q16 to Q31

	sth	a, *ar_h
						; reset the pointer to delay buffer
	mvdk	*sp(arg_norm_e),*(ar_norm_e)	; de-referencing
	mvdk	*ar_norm_e,*(ar_norm_e)		; pointer to d

$block_end

	; Update block counter (modulo blocksize)
	;---------------------------------------- 

update_counter:

  	ld	*sp(mod_bsize_cnt), a		; counter -> a
	add	#1, a				; a +1 -> a
	sub	*sp(arg_bsize),a,b
	mvdk	*sp(y0_ptr),*(ar_d)		; update y0_ptr 
	xc	1,beq				; reset counter if it
						; it has reached max.	
	ld	#0,a
	STL	a, *sp(mod_bsize_cnt)		; a -> counter


	mar	*ar_d+%				; increment pointer into ref. buffer
	mvkd	*(ar_d),*sp(y0_ptr)		; remember location of y(0)

	banz	next_sample, *ar_count-

; Return
;-------
	.asg	ar_h, ar_temp			; ar_h not used any more

	mvdk	*sp(arg_d), *(ar_temp)
	mvkd	*(ar_d), *ar_temp		; update new ar_d

	; Return overflow flag
	; --------------------
	ld	#0,a
	xc	1,AOV
	ld	#1,a


	; Adjust stack pointer and restore registers
	; ------------------------------------------

	frame	+8				; 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 + -