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

📄 dtmf_dec.asm

📁 DSP c54** 实现的DTMF产生和解码 汇编原代码 包括了goerztel算法详细讲解
💻 ASM
📖 第 1 页 / 共 2 页
字号:
**************************************************************
*   (C) COPYRIGHT TEXAS INSTRUMENTS, INC. 1996               *
**************************************************************
*   Program Name:     DTMF tone decoder                      *
*   File Name:        dtmf_dec.asm                           *
*   File Description: This file contains the code            *
*                     for a DTMF tone detector               *
*                     (TMS320C54x EVM version)               *
*   Author:   Gunter Schmer                                  *
*   Date:     06/06/96                                       *
*   Revision: 1.0                                            *
*   Latest working date: 06/06/96                            *
**************************************************************

	.title	"dtmf decoder"
	.mmregs

***************************************
***   Constants
***************************************
N	.set	205		;max count for DFT loops (1. Harmonics)
				;max count for DFT loops (2. Harm.) is 204
DAC_OFS	.set	000h		;DAC offset

THR_SIG	.set	1000h		;threshold for max signal
THR_TWI	.set	1000h		;threshold for max twist
THR_REL	.set	0800h		;threshold for energy difference of proximity peaks
THR_2nd	.set	0800h		;threshold for energy difference of 2. Harmonics 
THR_PAU	.set	0200h		;threshold for pause energy

GAIN_THR .set	0100h		;gain control threshold
GAIN_CON .set	5A82h		;gain control constant = (1/2)sqrt(2)


***************************************
***   Variables
***************************************
        .bss    aic_conf,1	;AIC configuration word
	.bss	rcv,1		;RECEIVE loaction
	.bss	tra,1		;TRANSMIT location
	.bss	COUNT,1		;count value for DFT loops
	.bss	DTMF_STAT,1	;status of detector: 1 - enabled, ready for detection
				;		     0 - disabled, waiting for pause
	.bss	DIGIT_PTR,1	;pointer to DIGITS
	.bss	DIGIT_ROW,1	;row number of digit
	.bss	DIGIT_COL,1	;column number of digit
	.bss	MAX_ROW_1st,1	;maximum row energy (1.Harm)
	.bss	MAX_COL_1st,1	;maximum column energy (1.Harm)
	.bss	MAX_ROW_2nd,1	;maximum row energy (2.Harm)
	.bss	MAX_COL_2nd,1	;maximum column energy (2.Harm)

	.bss	GAIN_VAR,1	;variable for gain control
	.bss	GAIN_AMP,1	;avg. peak amplitude
	.bss	GAIN_FCT,1	;gain control factor
	.bss	GAIN_PTR,1	;pointer to gain control buffer

***************************************
***   Tables
***************************************


*******************************************************
* The following table holds the coefficients for      *
* the 16 Goertzel filters, computed as follows        *
*                                                     *
*       .word    cos(2pi*k/N)*32768	;coefficient  *
*                                                     *
* with  N = 205  (1st Harmonics)                      *
*       N = 201  (2nd Harmonics)                      *
*       k = 18, 20, 22, 24, 31, 34, 38, 42  (1. Harm) *
*       k = 35, 39, 43, 47, 61, 67, 74, 82  (2. Harm) *
*                                                     *
*******************************************************
        .sect   "tbl_coef"
COEF1st	.word	27906		; 1st Harmonics
	.word	26802
	.word	25597
	.word	24295
	.word	19057
	.word	16529
	.word	12945
	.word	9166

COEF2nd	.word	15036		; 2nd Harmonics
	.word	11287
	.word	7363
	.word	3323
	.word	-10805
	.word	-16384
	.word	-22153
	.word	-27440

*******************************************************
* The following table holds the taps for the          *
* 16 Goertzel filters with initial conditions         *
*                                                     *
*******************************************************
	.sect	"tbl_taps"
TAPS2nd	.word	0		;v15(n-1)   ;2nd Harmonics
	.word	0		;v15(n-2)
	.word	0		;v14(n-1)
	.word	0		;v14(n-2)
	.word	0		;v13(n-1)
	.word	0		;v13(n-2)
	.word	0		;v12(n-1)
	.word	0		;v12(n-2)
	.word	0		;v11(n-1)
	.word	0		;v11(n-2)
	.word	0		;v10(n-1)
	.word	0		;v10(n-2)
	.word	0		;v9(n-1)
	.word	0		;v9(n-2)
	.word	0		;v8(n-1)
END2nd	.word	0		;v8(n-2)

TAPS1st	.word	0		;v7(n-1)  ;1st Harmonics
	.word	0		;v7(n-2)
	.word	0		;v6(n-1)
	.word	0		;v6(n-2)
	.word	0		;v5(n-1)
	.word	0		;v5(n-2)
	.word	0		;v4(n-1)
	.word	0		;v4(n-2)
	.word	0		;v3(n-1)
	.word	0		;v3(n-2)
	.word	0		;v2(n-1)
	.word	0		;v2(n-2)
	.word	0		;v1(n-1)
	.word	0		;v1(n-2)
	.word	0		;v0(n-1)
END1st	.word	0		;v0(n-2)

**********************************************
* The foll table holds the computed energies *
**********************************************
	.sect	"tbl_ener"
ENERGY	.word	0		;E[0]     (1. Harmonics)
	.word	0		;E[1]
	.word	0		;E[2]
	.word	0		;E[3]
	.word	0		;E[4]
	.word	0		;E[5]
	.word	0		;E[6]
	.word	0		;E[7]

	.word	0		;E[8]     (2. Harmonics)
	.word	0		;E[9]
	.word	0		;E[10]
	.word	0		;E[11]
	.word	0		;E[12]
	.word	0		;E[13]
	.word	0		;E[14]
	.word	0		;E[15]

*****************************************************************
* Digit mapping table                                           *
*   Low byte : row number                                       *
*   High byte: column number                                    * 
*****************************************************************
	.sect	"tbl_keys"
KEYS	.word	0301h		; '0'  
	.word	0000h		; '1'
	.word	0001h		; '2'
	.word	0002h		; '3'
	.word	0100h		; '4'
	.word	0101h		; '5'
	.word	0102h		; '6'
	.word	0200h		; '7'
	.word	0201h		; '8'
	.word	0202h		; '9'
	.word	0003h		; 'A'
	.word	0103h		; 'B'
	.word	0203h		; 'C'
	.word	0302h		; 'D'
	.word	0300h		; 'E' = '*'
	.word	0302h		; 'F' = '#'

BUFFER	.word	0		;current digit
	.word	0		;last digit
	.word	0		;2nd to last digit


****************************************************************
* Input Buffer for gain limiting                               *
****************************************************************
GAIN_BUF .usect "gain_buf",20h


****************************************************************
* Output Buffer for actual detected digits                     *
****************************************************************
DIGITS	.usect "dgts_buf",20h




******************************************
*       Stack setup
*****************************************
BOS     .usect  "stack",20h	; setup stack
TOS     .usect  "stack",1	; Top of stack at reset


******************************************
*       Interrupt Vectors
******************************************
V_TBL	.sect   "vectors"

RESET	bd      START		; reset vector
        stm     #TOS,SP		; Setup stack

	.space	19*4*16

RINT0	retf			; 0xFFD0
	nop
	nop
	nop

XINT0	retf			; 0xFFD4
	nop
	nop
	nop

RINT1	bd    	RINT1_ISR	; 0xFFD8
	pshm    ST0             ; Save status registers on stack
	pshm    ST1

XINT1	retf			; 0xFFDC
	nop
	nop
	nop


******************************************
*       CODE STARTS HERE
******************************************
       .text
START
	ssbx	INTM		;global interrupt disable
	ld	#0,DP		;initialize data pointer


;------------ Initialize Hardware ------------------------------------

	call	hwinit		;hardware initialization subroutine


;------------ Initialize Software ------------------------------------

        ssbx    SXM		;data sign ext. before usage
        rsbx    OVM		;no saturation of accu if overflow
	ssbx	FRCT		;fractional mode bit, left shift of
				;  multiplier to compensate for extra 
				;  sign bit

	ld	#0,A
	stm	#GAIN_BUF,AR2
	rpt	#(32-1)
	 stl	A,*AR2+		;initialize GAIN_BUF buffer
	stm	#DIGITS,AR2
	rpt	#(32-1)
	 stl	A,*AR2+		;initialize DIGITS buffer

	stm	#0040h,IMR	;enable RINT1 interrupt
	stm	#0c80h,IFR	;clear all pending serial port or timer interrupts
	rsbx	INTM		;global interrupt enable

	mvmd	DRR1,rcv
	mvdm	tra,DXR1


******************************************
*       Main Program
******************************************

Main
	ld	#aic_conf,DP	;DP to variables
	st	#N,COUNT	;initialize counter
	st	#1,DTMF_STAT	;initialize DTMF status to detector enabled
	st	#DIGITS,DIGIT_PTR  ;initialize pointer to DIGITS
	st	#GAIN_BUF,GAIN_PTR ;initialize pointer to gain buffer
	st	#GAIN_CON,GAIN_VAR

next	idle	1
	stm	#07fffh,BK
	ld	rcv,A
	sub	#0044h,A
	stl	A,rcv

	stm	#00f8h,IFR	;clear pending interrupts
	call	tasks		;actual processing following RINT interrupt
	nop
	b	next

done	b	done



	
********************************************************
* SUBROUTINE: tasks
*
* Input:  none
* Output: none
* Uses:
*
* Description:
*  If (COUNT >= 0)
*      do Goertzel filters
*  else
*      restore COUNT with N=205
*      do dtmf_checks to validate digit
*
********************************************************
tasks:	ld	COUNT,A
	sub	#01h,A
	stl	A,COUNT		;decrement counter by one
	bc	task1,alt
task0	call	gaincntrl
	ld	COUNT,A
	call	goertzel	;if(COUNT >= 0) do goertzel
	b	task2
task1	call	gaincntrl
	calld	dtmf_checks	;if(COUNT < 0) do dtmf_checks
	 st	#N,COUNT	;  restore COUNT
	nop
task2	ret


*******************************************************************
* SUBROUTINE: gaincntrl
*
* Input: none
* Output: none
* Uses:
*
* Description:
* Control gain of the input sample x(n)
* On a 32 samples length circular buffer of input samples
* the average peak amplitude GAIN_AMP is computed. The current
* input sample is then attenuated using the foll formulas:
*
* GAIN_CON = (1/2)SQRT(2)
* GAIN_AMP(n) = GAIN_CON*(1/16)*[abs(x(n))+abs(x(n+1))+...+abs(x(n+31))]
*
* if( GAIN_AMP > GAIN_THR )
*       y(n) = (GAIN_THR/GAIN_AMP) * x(n)
* else
*       y(n) = x(n)
*
*******************************************************************
gaincntrl:
	mvdm	GAIN_PTR,AR2	;load pointer to gain buffer
	stm	#001fh,BK	;load buffer modulo
	ld	rcv,A		;current sample --> (A)
	ld	*AR2,B		;oldest sample --> (B)
	stl	B,rcv		;store oldest sample (to be gain controlled) into rcv
	stl	A,*AR2+%	;store current sample into gain buffer
	mvmd	AR2,GAIN_PTR	;store updated pointer to gain buffer

	ld	#0,B		;clear B
	stm	#(32-1),BRC	
	rptb	gain1-1		;for(k=0;k<32;k++)   {
	 ld	*AR2+%,A
	 abs	A		;  (A)=abs(x(n+k))
	 add	A,B		;  (B)=(B)+(A)
gain1				;}
				;  (B) now contains accumulated absolute values

	sfta	B,12,A		;(AH)=(1/16)*(BL)
	mpya	GAIN_VAR	;(BH)=(1/2)SQRT(2)*(AH)
	sth	B,GAIN_AMP	;(BH) --> GAIN_AMP
	
	sub	#GAIN_THR,16,B,A ;(AH)=(BH)-GAIN_THR
	bc	gain2,aleq	;
	ld	#GAIN_THR,16,A	;if( GAIN_AMP > GAIN_THR )
	rpt	#(16-1)
	 subc	GAIN_AMP,A	;  compute (GAIN_THR/GAIN_AMP)
	and	#0ffffh,A	;  retain quotient (AL), mask remainder
	sfta	A,15		;  shift quotient into high accu
	sth	A,GAIN_FCT	;  store quotient
	mpya	rcv		;  (B)=(GAIN_THR/GAIN_AMP)*x(n)
	sth	B,rcv		;  store attenuated sample
gain2				;else
	nop			;  do not change sample
	ret


*************************************************************************************
* SUBROUTINE: goertzel 
*
* Input:  A (current counter value)
* Output: none
* Uses:
*
* Description:
* vk(n) = 2*coef*vk(n-1) - vk(n-2) + x(n)
*
* Coefficients are in pmem in order starting with location COEF1st
* COEF1st .word	xxxx	;coef1
*	 .word	yyyy	;coef2
*	 ....
*
* Data vk(n-1), vk(n-2) is ordered as follows in dmem
*	v15(n-1)
*	v15(n-2)
*	v14(n-1)
*	v14(n-2)
*	....
*	v0(n-1)
*	v0(n-2)  <--AR2
*
* FRCT = 1 , OVLY = 1
* A holds current COUNT
*     A is reduced by #4 to prevent more than 201 iterations for 2. Harm
*
**************************************************************************************
goertzel:
	sub	#04h,A
	bc	goer1,alt	;if (A < 0) 
				;    do only 1.st Harm.
				;else
				;    do 1. and 2. Harm.

				;do 2.Harm. for 201 samples
goer2	stm	#END2nd,AR2	;  AR2 points to end of tap block
	stm	#COEF2nd,AR3	;  AR3 points to Coefficients
	stm	#(8-1),BRC	; 
	rptb	goer21-1	;  for(k=8;k<16;k++)  do 8 filters as follows
	 ld	rcv,15,A	;  { (A) = (1/2)x(n)

⌨️ 快捷键说明

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