📄 dtmfgai.txt
字号:
*************************************************************
* 程序名称:DTMF双音频检测 *
*************************************************************
.mmregs
.include "globals.inc" ;全局标号
.include "tables.inc" ;变量表
.text
*******************************************************************
* 子程序:initoscis *
* 输入:指向结构DTMFENCOBJ的指针 *
* 输出:无 *
* 描述:初始化数字正弦振荡器状态 *
* 它将指定状态集的状态复制到通道对应的振荡器状态缓冲区中 *
*******************************************************************
_initoscis:
NOP
PSHM ST0
PSHM ST1
PSHM AR1
PSHM AR6
PSHM AR7
NOP
;(A)=指向结构DTMFENCOBJ
;*SP(6)=数字
STLM A,AR6 ;AR6用作指向结构元素的指针
;*AR6(0)=指向数据
;*AR6(1)=指向振荡器状态
LD #0,ASM ;ASM=0
STM #OSCIS,AR2 ;AR2指向振荡器状态表
LD *AR6(1),A
STLM A,AR3 ;AR3指向通道振荡器状态表
LD *AR2+,16,A ;装入第一个值
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
*******************************************************************
* 子程序:dtmftone *
* 输入:指向结构DTMFENCOBJ的指针 *
* 输出:无 *
* 描述:计算DTMF双音频的102个采样值 *
* 子程序根据指针值取出数字,并将其送入堆栈进行编码 *
*******************************************************************
_dtmftone:
NOP
PSHM ST0
PSHM ST1
PSHM AR1
PSHM AR6
PSHM AR7
NOP
FRAME #-2 ;----局部变量----
;*SP(0)=衰减值
;----参数--------
;(A)=指向结构DTMFENCOBJ
;*SP(8)=数字
STLM A,AR6 ;AR6用作指针指向结构元素
;*AR6(0)=指向数据
;*AR6(1)=指向振荡器
;*AR6(2)=音频衰减值
SSBX FRCT ;设置分数模式
;----数字解包,指针指向振荡器抽头系数----
LD *SP(8),A
STLM A,AR0 ;AR0为映射表的偏移量
STM #KEYS,AR2 ;AR2指向数字映射表首地址
NOP
MAR *AR2+0 ;AR2指向映射表中对应的数字
LD *AR2,A ;数字装入A
LD A,B ;(A)->(B)
AND #0F00h,A ;取行部分
SFTL A,-8 ;(A)右移8位
STLM A,AR2 ;AR2包含行音频的系数表偏移量
SFTL A,1 ;(A)<<1
STLM A,AR4 ;AR4包含行音频振荡器表偏移量
AND #000Fh,B ;取列部分
ADD #4,B ;B+4=列音频的系数表偏移量
STLM B,AR3 ;AR3包含列音频的系数表偏移量
SFTL B,1 ;(B)<<1
STM #COEFFS,AR0 ;AR0指向系数表
STLM B,AR5 ;AR5包含列音频振荡器表偏移量
MAR *AR2+0 ;AR2指向行音频系数
MAR *AR3+0 ;AR3指向列音频系数
LD *AR6(1),A ;装入指向数据的指针
STLM A,AR0 ;AR0指向振荡器表
LD *AR6(2),B ;载入衰减值
STL B,*SP(0) ;存储到局部变量区
MAR *AR4+0 ;AR4指向行音频振荡器
MAR *AR5+0 ;AR5指向列音频振荡器
MAR *AR4+ ;AR4指向行音频y(n-2)
MAR *AR5+ ;AR5指向列音频y(n-2)
;----产生DTMF音频------------------------
LD *AR6(0),A
STLM A,AR1 ;AR1指向数据
STM #(N-1),BRC
RPTB oscil-1 ;for(n=0;n<N;n++){
LD #0,A ;----产生行音频采样值----
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)=2coef*y(n-1)-y(n-2)
DELAY *AR4 ;y(n-1)->y(n-2)
STH A,*AR4 ;(A) ->y(n-1)
LD #0,A ;----产生列音频采样值----
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)=2coef*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+tol-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
*******************************************************************
* 子程序:gaincntrl *
* 输入:指向结构DTMFENCOBJ的指针 *
* 输出:无 *
* 描述:定标数据块,确保执行goertzel算法时无溢出 *
* 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(ain_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 ;----局部变量----
;*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)
;----变量初始化----------------------
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
;----计算信号能量--------------------
LD *SP(9),A
STLM A,AR2 ;AR2指向数据缓冲区
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/(N/64) (32bit)
OR *SP(3),A
SUB A,B ;(B)=gain_pow-gain_lim
BC gain2,BLEQ ;if(gain_pow>gain_lim
;{
;----计算gain_amp=sqrt(gain_pow)-----
ST #4000h,*SP(4) ;初始化gain_amp
ST #4000h,*SP(8) ;初始化gain_delta
MVMM SP,AR2
MAR *+AR2(8) ;AR2指向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
;----计算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
;----计算gain_lev/gain_amp-----------------
LD *SP(5),16,A ;(AH)=gain_lev
RPT #(16-1)
SUBC *SP(4),A ;计算(gain_lev/gain_amp)
AND #0FFFFh,A ;保留商(AL),屏蔽余数
SFTA A,15 ;左移商到累加器高位
STH A,*SP(6) ;(AH)->gain_scale
;----用(gain_lev/gain_amp)定标数据---------
LD *SP(9),A
STLM A,AR2 ;AR2指向数据
MVMM SP,AR3
MAR *+AR3(6) ;AR3指向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
*******************************************************************
* 子程序:goetzel *
* 输入:指向结构DTMFENCOBJ的指针 *
* 输出:无 *
* 描述:该程序对102个数据计算差分方程 *
* 因为有增益控制保护可能的溢出,故程序不检查溢出 *
* 由于二次谐波在子程序dtmfchecks()中计算,故这里只计算基频(8个) *
* 子程序同样计算8个基频的能量模板 *
* 随后复位滤波器抽头系数为0,准备下一次计算 *
*******************************************************************
_goertzel:
NOP
PSHM ST0
PSHM ST1
PSHM AR1
PSHM AR6
PSHM AR7
;----参数-----------
;(A)=指向DTMFDECOBJ
RSBX OVA
SSBX FRCT
STLM A,AR5 ;AR5指向结构DTMFDECOBJ
;*AR5(0)=ptr to data
;*AR5(1)=ptr to taps
;*AR5(2)=ptr to energy template
;*AR5(3)=digiptr
;*AR5(4)=digitlast
;*AR5(5)=detectstat
;*AR5(6)=err_flags
;---------------------------------------------------
; Goertzel滤波器计算
; vk(n)=2coef*vk(n-1)-vk(n-2)+x(n)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -