📄 dtmf_dec.asm
字号:
**************************************************************
* (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 + -