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

📄 dtmfsub.asm

📁 运行环境:CCS2.1
💻 ASM
📖 第 1 页 / 共 2 页
字号:
**************************************************************
*   (C) COPYRIGHT TEXAS INSTRUMENTS, INC. 1996               *
**************************************************************
*   Program Name:     DTMF tone decoder                      *
*   File Name:        dtmfsub.asm                            *
*   File Description: This file contains the ASM-subroutines *
*                     used for a DTMF tone detector          *
*                     (TMS320C54x EVM version)               *
*   Author:   Gunter Schmer                                  *
*   Date:     03/24/97                                       *
*   Revision: 3.0                                            *
*   Latest working date: 03/24/97                            *
**************************************************************

	.mmregs
	.include  "globals.inc"		;global labels
	.include  "tables.inc"		;various tables


	.text


***********************************************************************
* SUBROUTINE: initoscis         (approx. 1600 cycles)
*
* Input:  ptr to DTMFENCOBJ
* Output: none
* Uses:
*
* Description:
* This subroutine initializes the digital sinusoidal oscillator
* states. It uses a generic set of states and copies them into
* the channel specific osci state buffer.
*
***********************************************************************
_initoscis
	nop
	pshm	ST0
	pshm	ST1
	pshm	AR1
	pshm	AR6
	pshm	AR7
	nop
				;---- local variables -----
				; none
				;---- arguments -----------
				; (A)    = ptr to DTMFENCOBJ
				; *SP(6) = digit

	stlm	A,AR6		;AR6 is used as pointer to struct elements
				; *AR6(0) = ptr to data
				; *AR6(1) = ptr to oscis

	ld	#0,ASM		;ASM=0
	stm	#OSCIS,AR2	;AR2 points to generic osci states
	ld	*AR6(1),A
	stlm	A,AR3		;AR3 points to channel osci states
	ld	*AR2+,16,A	;load first value
	rpt	#(16-1)		;for(k=0;k<16;k++)	{
	   st	A,*AR3+		;   store (AH)
	|| ld	*AR2+,A		;   load (AH)
				;}

	popm	AR7
	popm	AR6
	popm	AR1
	popm	ST1
	popm	ST0
	ret


***********************************************************************
* SUBROUTINE: dtmftone         (approx. 1600 cycles)
*
* Input:  ptr to DTMFENCOBJ
* Output: none
* Uses:
*
* Description:
* This subroutine computes 102 samples of DTMF tones. The routine
* expects a ptr to a encoder object in the accu A and the digit to
* be encoded on the stack.
*
***********************************************************************
_dtmftone
	nop
	pshm	ST0
	pshm	ST1
	pshm	AR1
	pshm	AR6
	pshm	AR7
	nop
	frame	#-2		;---- local variables -----
				; *SP(0) = attenuation
				;---- arguments -----------
				; (A)    = ptr to DTMFENCOBJ
				; *SP(8) = digit

	stlm	A,AR6		;AR6 is used as pointer to struct elements
				; *AR6(0) = ptr to data
				; *AR6(1) = ptr to oscis
				; *AR6(2) = attenuation of tone
	ssbx	FRCT		;set fractional mode

	;---- unpack digit and find pointers to oscillator taps ----
	ld	*SP(8),A
	stlm	A,AR0		;AR0 is offset within mapping table
	stm	#KEYS,AR2	;AR2 points to mapping table
	nop
	mar	*AR2+0		;AR2 points to mapping table value
	ld	*AR2,A		;load mapping table value
	ld	A,B		; in (A) and (B)

	and	#0f00h,A	;mask out the row portion
	sftl	A,-8		;right shift (A) by 8
	stlm	A,AR2		;AR2 contains coef-table offset for row-tone
	sftl	A,1		;left shift (A) by 1
	stlm	A,AR4		;AR4 contains oscis-table offset for row-tone

	and	#000fh,B	;mask out the column portion
	add	#4,B		;add 4 to offset to point into column portion
	stlm	B,AR3		;AR3 contains coef-table offset for col-tone
	sftl	B,1		;left shift (B) by 1
	stm	#COEFFS,AR0	;AR0 points to coef-table
	stlm	B,AR5		;AR5 contains oscis-table offset for col-tone

	mar	*AR2+0		;AR2 points to row-tone coefficient
	mar	*AR3+0		;AR3 points to col-tone coefficient
	ld	*AR6(1),A	;load ptr to data
	stlm	A,AR0		;AR0 points to oscis-table
	ld	*AR6(2),B	;load attenuation
	stl	B,*SP(0)	;store in local variable
	mar	*AR4+0		;AR4 points to row-tone osci
	mar	*AR5+0		;AR5 points to col-tone osci
	mar	*AR4+		;AR4 points to row-tone y(n-2)
	mar	*AR5+		;AR5 points to col-tone y(n-2)

	;---- generate DTMF tones ----------------------------------
	ld	*AR6(0),A
	stlm	A,AR1		;AR1 points to data
	stm	#(N-1),BRC

	rptb	osci1-1		;for(n=0;n<N;n++)   {
	 ld	#0,A		;   ---- generate row-tone sample ----- 
	 sub	*AR4-,16,A	;   (A) = -y(n-2)
	 mac	*AR4,*AR2,A	;   (A) = coef*y(n-1) - y(n-2)
	 mac	*AR4,*AR2,A	;   (A) = 2*coef*y(n-1) - y(n-2)
	 delay	*AR4		;   y(n-1) ---> y(n-2)
	 sth	A,*AR4		;   (A)    ---> y(n-1)
	 ld	#0,A		;   ---- generate col-tone sample ----- 
	 sub	*AR5-,16,A	;   (A) = -y(n-2)
	 mac	*AR5,*AR3,A	;   (A) = coef*y(n-1) - y(n-2)
	 mac	*AR5,*AR3,A	;   (A) = 2*coef*y(n-1) - y(n-2)
	 delay	*AR5		;   y(n-1) ---> y(n-2)
	 sth	A,*AR5+		;   (A)    ---> y(n-1)
	 add	*AR4+,16,A	;   (A) = row-tone + col-tone
	 mpya	*SP(0)		;   (A) = attn*(AH)
	 sth	B,*AR1+		;   (A)    ---> x(n)
osci1

	frame	#2
	nop
	popm	AR7
	popm	AR6
	popm	AR1
	popm	ST1
	popm	ST0
	ret




*******************************************************************
* SUBROUTINE: gaincntrl (approx. 575 cycles)
*
* Input: ptr to DTMFDECOBJ
* Output: none
* Uses:
*
* Description: Scales a block of input data in order to ensure 
*              no overflow when running the goertzel routine
*              approx. 6 cycles   per sample (negligable)
*
*              gain_power = (1/64) * SUM{0,N-1}[x(n)*x(n)]
*                         = (1/64) * N * signalpower
*
*              gain_lim   = (1/64) * (1/N)
*                         = minimum signalpower (-..dB)
*
*              gain_const = 0.5*sqrt(2)*sqrt(64/N)
*              gain_amp   = gain_const * sqrt(gain_power)
*              gain_lev   = 1/N
*              gain_scale = gain_lev/gain_amp
*
*              x(n) = x(n) * gain_scale
*
* FRCT=1, SXM=1
*******************************************************************
_gaincntrl:
	nop
	pshm	ST0
	pshm	ST1
	pshm	AR1
	pshm	AR6
	pshm	AR7
	nop
	frame	#-10		;---- local variables -----
				; *SP(0) = gain_pow (HI)
				; *SP(1) = gain_pow (LO)
				; *SP(2) = gain_lim (HI)
				; *SP(3) = gain_lim (LO)
				; *SP(4) = gain_amp
				; *SP(5) = gain_lev
				; *SP(6) = gain_scale
				; *SP(7) = gain_const
				; *SP(8) = gain_delta
				; *SP(9) = ptr to data
				;---- arguments -----------
				; (A)    = ptr to DTMFDECOBJ
	stlm	A,AR5
	nop
	nop
	nop
	ld	*AR5,A
	stl	A,*SP(9)

	;---- value initializations --------------------------
	ld	#0005h,16,A		;(A)  = 00050000h
	or	#0505h,A		;(A)  = 00050505h = 1/(64*N) (Q31)
	sth	A,*SP(2)		;(A)  --> gain_lim  (32bit)
	stl	A,*SP(3)
	ld	#00E3h,A		;(AL) = 00E3h = (0.5*sqrt(2))/N
	stl	A,*SP(5)		;(AL) --> gain_lev  (16bit)
	ld	#6564h,A		;(AL) = 6564h = sqrt(64/102)
	stl	A,*SP(7)		;(AL) --> gain_const
	ld	#4000h,A		;(AL) = 4000h = 0.5
	stl	A,*SP(8)		;(AL) --> gain_delta
	
	ssbx	FRCT
	;---- compute signal power ---------------------------
	ld	*SP(9),A
	stlm	A,AR2			;AR2 points to data buffer
	rptz	B,#(N-1)		;for(n=0;n<N-1;n++)
	 squra	*AR2+,B			;  (B)=(B)+x(n)*x(n)
	sfta	B,-6			;(B)=(1/64)*(B)
	sth	B,*SP(0)		;(B) --> gain_pow   (32bit)
	stl	B,*SP(1)		;        gain_pow = (N/64)*sigpower
	ld	*SP(2),16,A		;(A) = gain_lim = 1/(64*N)  (32bit)
	or	*SP(3),A
	sub	A,B			;(B) = gain_pow - gain_lim


	bc	gain2,BLEQ		;if(gain_pow > gain_lim)
					;{
	;---- compute gain_amp = sqrt(gain_pow) -------------
	st	#4000h,*SP(4)		;   initialize gain_amp estimate
	st	#4000h,*SP(8)		;   initialize gain_delta to 0.5
	mvmm	SP,AR2
	mar	*+AR2(8)		;   AR2 points to gain_delta
	stm	#(sqrt_iterations-1),BRC

	rptbd	sqrtloopend-1
	squr	*SP(4),A		;   (A) = yold*yold
	dsub	*SP(0),A		;   (A) = yold*yold - x
sqrtloop
	bcd	sqrt1,AGT
	ld	*SP(4),16,B		;   (B) = yold
	sub	*AR2,15,B		;   (B) = yold - (1/2)*delta
					;   if(y needs to be larger)
	add	*AR2,16,B		;     (B) = yold + (1/2)*delta
sqrt1	sth	B,*SP(4)		;   (BH) --> ynew
	ld	*AR2,15,A		;   (AH) = (1/2)delta
	sth	A,*AR2			;   (AH) --> delta new
	squr	*SP(4),A			
	dsub	*SP(0),A		;   (A) = yold*yold - x
sqrtloopend	

	;---- compute gain_amp = sqrt(64/N)*gain_amp --------
	ld	*SP(7),T		;   (T) = gain_const
	mpy	*SP(4),A		;   (A)=sqrt(64/102)*gain_amp
	sth	A,*SP(4)		;   (AH) --> gain_amp

	;---- compute gain_lev/gain_amp ---------------------
	ld	*SP(5),16,A		;   (AH) = gain_lev
	rpt	#(16-1)
	 subc	*SP(4),A		;   compute (gain_lev/gain_amp)
	and	#0ffffh,A		;   retain quotient (AL), mask remainder
	sfta	A,15			;   shift quotient into high accu
	sth	A,*SP(6)		;   (AH) --> gain_scale

	;---- scale data with (gain_lev/gain_amp) ---------
	ld	*SP(9),A		;
	stlm	A,AR2			;   AR2 points to data
	mvmm	SP,AR3			;
	mar	*+AR3(6)		;   AR3 points to gain_scale
	stm	#(N-1),BRC		;
	rptb	gain1-1			;   for(n=0;n<N;n++)
	mpy	*AR2,*AR3,A		;      (A) = x(n)*(gain_lev/gain_amp)
	sth	A,*AR2+			;      (AH) --> x(n)
gain1					;}
	
gain2	frame	#10
	nop
	popm	AR7
	popm	AR6
	popm	AR1
	popm	ST1
	popm	ST0
	ret


***********************************************************************
* SUBROUTINE: goertzel         (w/o OV check approx. 4637 cycles)
*
* Input:  ptr to DTMFDECOBJ
* Output: none
* Uses:
*
* Description:
* This new version of the subroutine operates on a block of data
* 102 samples long and computes the following difference equation
* It does thereby not check for overflow and assumes a prescaling 
* gain control function to protect from possible overflow.
* Since 2nd harmonic frequencies are computed conditionally in
* subroutine dtmfchecks(), this routine now only computes the
* fundamental frequency information (8 freqs)
* This routine also computes the energy template for the 8 fundamental
* frequencies. It thereafter sets the filter taps to zero for the next
* round.
*
*
***********************************************************************
_goertzel:
	nop
	pshm	ST0
	pshm	ST1
	pshm	AR1
	pshm	AR6
	pshm	AR7
				;---- local variables -----
				; none
				;---- arguments -----------
				; (A)    = ptr to DTMFDECOBJ

	rsbx	OVA		;clear overflow bit for A
	ssbx	FRCT		;set fractional mode
	stlm	A,AR5		;AR5 is used as pointer to struct elements
				; *AR5(0) = ptr to data
				; *AR5(1) = ptr to taps
				; *AR5(2) = ptr to energy template
				; *AR5(3) = digitptr
				; *AR5(4) = digitlast
				; *AR5(5) = detectstat
				; *AR5(6) = err_flags

;---------------------------------------------------------------------
; Goertzel filter computation
;
; vk(n) = 2*coef*vk(n-1) - vk(n-2) + x(n)
;
; Coefficients are in order starting with location COEF1st
; COEF1st .word	xxxx	;coef1
;	  .word	yyyy	;coef2
;	  ....
;
; Data vk(n-1), vk(n-2) is ordered as follows
;	v9(n-1)
;	v9(n-2)  column's second harm
;	v8(n-1)
;	v8(n-2)  row's 2nd harm
;
;	v7(n-1)
;	v7(n-2)
;	....
;	v0(n-1)
;	v0(n-2)  <--AR2
;
; FRCT=1, SXM=1
;
;---------------------------------------------------------------------
	ld	*AR5,A		;
	stlm	A,AR1		;AR1 points to data buffer
	ld	*AR5(1),A	;
	add	#19,A		;
	stlm	A,AR6		;AR6 points to end of taps block
	stm	#(N-1),BRC
	
goer1	rptb	goer2-1		;for(n=0;n<N;n++)     {

	mvmm	AR6,AR2		;   AR2 points to end of taps block
	stm	#COEF1st,AR3	;   AR3 points to Coefficients
	ld	*AR1+,16,A	;   (A) = x(n)
				;   ------ filter k=0 -----------------
	sub	*AR2-,16,A,B	;   (B) = -vk(n-2) + x(n)
	mac	*AR2,*AR3,B	;   (B) = coef*vk(n-1) - vk(n-2) +x(n)
	mac	*AR2,*AR3+,B	;   (B) = 2*coef*vk(n-1) - vk(n-2) +x(n)
	delay	*AR2		;   vk(n-1) ---> vk(n-2)
	sth	B,*AR2-		;   (B)     ---> vk(n-1)
				;   ------ filter k=1 -----------------
	sub	*AR2-,16,A,B	;   (B) = -vk(n-2) + x(n)
	mac	*AR2,*AR3,B	;   (B) = coef*vk(n-1) - vk(n-2) +x(n)
	mac	*AR2,*AR3+,B	;   (B) = 2*coef*vk(n-1) - vk(n-2) +x(n)
	delay	*AR2		;   vk(n-1) ---> vk(n-2)
	sth	B,*AR2-		;   (B)     ---> vk(n-1)
				;   ------ filter k=2 -----------------
	sub	*AR2-,16,A,B	;   (B) = -vk(n-2) + x(n)
	mac	*AR2,*AR3,B	;   (B) = coef*vk(n-1) - vk(n-2) +x(n)
	mac	*AR2,*AR3+,B	;   (B) = 2*coef*vk(n-1) - vk(n-2) +x(n)
	delay	*AR2		;   vk(n-1) ---> vk(n-2)
	sth	B,*AR2-		;   (B)     ---> vk(n-1)
				;   ------ filter k=3 -----------------
	sub	*AR2-,16,A,B	;   (B) = -vk(n-2) + x(n)
	mac	*AR2,*AR3,B	;   (B) = coef*vk(n-1) - vk(n-2) +x(n)
	mac	*AR2,*AR3+,B	;   (B) = 2*coef*vk(n-1) - vk(n-2) +x(n)
	delay	*AR2		;   vk(n-1) ---> vk(n-2)
	sth	B,*AR2-		;   (B)     ---> vk(n-1)
				;   ------ filter k=4 -----------------
	sub	*AR2-,16,A,B	;   (B) = -vk(n-2) + x(n)
	mac	*AR2,*AR3,B	;   (B) = coef*vk(n-1) - vk(n-2) +x(n)
	mac	*AR2,*AR3+,B	;   (B) = 2*coef*vk(n-1) - vk(n-2) +x(n)
	delay	*AR2		;   vk(n-1) ---> vk(n-2)
	sth	B,*AR2-		;   (B)     ---> vk(n-1)
				;   ------ filter k=5 -----------------
	sub	*AR2-,16,A,B	;   (B) = -vk(n-2) + x(n)
	mac	*AR2,*AR3,B	;   (B) = coef*vk(n-1) - vk(n-2) +x(n)
	mac	*AR2,*AR3+,B	;   (B) = 2*coef*vk(n-1) - vk(n-2) +x(n)
	delay	*AR2		;   vk(n-1) ---> vk(n-2)
	sth	B,*AR2-		;   (B)     ---> vk(n-1)
				;   ------ filter k=6 -----------------
	sub	*AR2-,16,A,B	;   (B) = -vk(n-2) + x(n)
	mac	*AR2,*AR3,B	;   (B) = coef*vk(n-1) - vk(n-2) +x(n)
	mac	*AR2,*AR3+,B	;   (B) = 2*coef*vk(n-1) - vk(n-2) +x(n)
	delay	*AR2		;   vk(n-1) ---> vk(n-2)
	sth	B,*AR2-		;   (B)     ---> vk(n-1)
				;   ------ filter k=7 -----------------
	sub	*AR2-,16,A,B	;   (B) = -vk(n-2) + x(n)
	mac	*AR2,*AR3,B	;   (B) = coef*vk(n-1) - vk(n-2) +x(n)
	mac	*AR2,*AR3+,B	;   (B) = 2*coef*vk(n-1) - vk(n-2) +x(n)
	delay	*AR2		;   vk(n-1) ---> vk(n-2)
	sth	B,*AR2-		;   (B)     ---> vk(n-1)
goer2				;}

;-------------------------------------------------------------------------
; Energy computation for fundamental frequencies (8 freqs)
;
;  y(N)y*(N) = vk(N)*vk(N) - 2*coef*vk(N)*vk(N-1) + vk(N-1)*vk(N-1)
;
; Coefficients are in pmem in order starting with location COEF1st
; COEF1st .word	xxxx	;coef0  <--AR3
; 	  .word	yyyy	;coef1
;	  ....
;
; Data vk(n-1), vk(n-2) is ordered
;	v9(n-1)
;	v9(n-2)   2nd harm column
;	v8(n-1)
;	v8(n-2)   2nd harm row
;	v7(n-1)
;	v7(n-2)
;	....
;	v0(n-1)
;	v0(n-2)  <--AR2
;
; FRCT=1, SXM=1
;
;-------------------------------------------------------------------------
goer3	ld	*AR5(1),A
	add	#19,A
	stlm	A,AR2		;AR2 points to end of filter taps block
	stm	#COEF1st,AR3	;AR3 points to beg of coefficient table
	ld	*AR5(2),A
	stlm	A,AR4		;AR4 points to energy template
	stm	#(8-1),BRC

	rptb	goer4-1		;for(k=0;k<8;k++)   {
	 ld	*AR2,16,A	; (A) = vk(N-1), A(32:16) loaded
	 mpya	*AR2-		; (B) = vk(N-1)*vk(N-1), (T) = vk(N-1)
	 mpy	*AR2,A		; (A) = vk(N)*vk(N-1)
	 ld	*AR3+,T		; (T) = coef
	 mpya	A		; (A) = coef*vk(N)*vk(N-1)
	 sub	A,1,B		; (B) = -2*coef*vk(N)*vk(N-1) + vk(N-1)*vk(N-1)
	 ld	*AR2,T		; (T) = vk(N)
	 mac	*AR2-,B		; (B) = vk(N)*vk(N) - 2*coef*vk(N)*vk(N-1) + vk(N-1)*vk(N-1)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -