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

📄 dtmfsub.asm

📁 运行环境:CCS2.1
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	 sth	B,*AR4+		; store result E[k] into energy data block
goer4				;}


;------------------------------------------------------------------------
; Initialize Filter Taps to zero for next round
;
;------------------------------------------------------------------------
	ld	*AR5(1),A
	stlm	A,AR2		;AR2 points to beginning of filter taps
	ld	#0,A
	rpt	#(20-1)		;for(i=0;i<20;i++)
	 stl	A,*AR2+		;   initialize filter taps for next round

goer5	popm	AR7
	popm	AR6
	popm	AR1
	popm	ST1
	popm	ST0
	ret




**************************************************************************
* SUBROUTINE: dtmf_checks             (approx 1544 cycles)
*
* Input:  ptr to DTMFDECOBJ
* Output: none
* Uses:
*
* Description:
*  - maximum search
*  - DTMF status check
*  - signal strength check
*  - twist check
*  - relative peak check
*  - 2nd harmonic check
*	conditional computation of 2nd harmonics energies
*  - digit validation
*
**************************************************************************

_dtmfchecks:
	nop
	pshm	ST0
	pshm	ST1
	pshm	AR1
	pshm	AR6
	pshm	AR7
	nop
	frame	#0		;---- local variables -----
				; none
				;---- arguments -----------
				; (A)    = ptr to dtmfchannel struct
	ssbx	FRCT
	stlm	A,AR5		;AR5 is used as ptr to dtmfchannel struct
				; *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


;------------------------------------------------------------------------
; Alternative Maximum search
; result: AR3 points to max row energy ROWMAX
;         AR4 points to max col energy COLMAX
;------------------------------------------------------------------------
max_search:
	ld	*AR5(2),A
	stlm	A,AR2		;AR2 points to ENERGY table (row energies)
	mvmm	AR2,AR3		;AR3 points to ENERGY table
	stm	#(4-1),BRC
	rptb	max1-1		;for(k=0;k<4;k++)
	ld	*AR3,A		;   (A)=oldmax
	sub	*AR2,A		;   (A)=oldmax-E[k]
	bc	max11,AGT	;   if(oldmax < E[k])
	mvmm	AR2,AR3		;      AR3 points to newmax
max11	mar	*AR2+		;   increment pointer
max1				;result: AR3 points to ROWMAX
				;        AR2 points to column energies

	mvmm	AR2,AR4		;AR4 points to ENERGY table (column energies)
	stm	#(4-1),BRC
	rptb	max2-1		;for(k=0;k<4;k++)
	ld	*AR4,A		;   (A)=oldmax
	sub	*AR2,A		;   (A)=oldmax-E[k]
	bc	max21,AGT	;   if(oldmax < E[k])
	mvmm	AR2,AR4		;      AR4 points to newmax
max21	mar	*AR2+		;   increment pointer
max2				;result: AR4 points to COLMAX
				;        AR2 points to column energies


;----------------------------------------------------------------------
; DTMF Status Check:
;   if(detectstat == 0) 
;      if( max(ROWMAX,COLMAX) < THR_PAU )
;         detectstat = 1, detector enabled
;      terminate all checks
;   else
;      continue
;
; AR3 points to ROWMAX
; AR4 points to COLMAX
;----------------------------------------------------------------------
stat_check
	andm	#0080h,*AR5(6)	;clear error flags, except OVA
	bitf	*AR5(5),#0001h	;

	bc	stat1,NTC	;if(detectstat == 1)
	ld	*AR5(5),A	;   load detectstat
	and	#0F00h,A	;   mask out duration bits
	sftl	A,1		;   shift duration bits
	andm	#0001h,*AR5(5)	;   retain only detect status bit
	or	*AR5(5),A	;   or in duration bits
	stl	A,*AR5(5)	;   write back to detectstat
	b	sig_check	;   continue with sig_check

stat1	ld	*AR3,A		;else
	ld	*AR4,B		;
	max	A		;  (A)=max(ROWMAX,COLMAX)
	sub	#THR_PAU,A	;  (A)=max(ROWMAX,COLMAX) - THR_PAU
	bc	stat2,ageq	;  if((A)<0)
	st	#0001h,*AR5(5)	;     detectstat = 1
stat2	b	ende		;  terminate all checks


;----------------------------------------------------------------------
; Signal strength check:
;    if(ROWMAX+COLMAX > THR_SIG)  continue
;    else  terminate all checks
;
; AR3 points to ROWMAX
; AR4 points to COLMAX
;----------------------------------------------------------------------
sig_check:
	ld	*AR3,A
	add	*AR4,A		;(A) = ROWMAX+COLMAX
	sub	#THR_SIG1,A,B	;
	bc	ende,BLEQ	;if(ROWMAX+COLMAX <= THR_SIG1) 
				;    signal is not possible tone
				;    terminate checks
	sub	#THR_SIG2,A,B	;
	bc	err_sig,BLEQ	;if(ROWMAX+COLMAX <= THR_SIG2)
				;    signal is possible tone
				;    however does not meet THR_SIG2
				;    branch to err_sig
	b	twist_check

err_sig:			;**** record signal strength error ****
	orm	#0001h,*AR5(6)	; set signal strength error flag (b0)
	b	ende		; terminate checks


;----------------------------------------------------------------------
; Twist check:
;    if(ROWMAX > COLMAX)   
;       check reverse twist:
;       if((COLMAX/ROWMAX) > THR_REVTWI)   continue
;       else terminate all checks
;    else                  
;       check standard twist:
;       if((ROWMAX/COLMAX) > THR_STDTWI)   continue
;       else  terminate all check
;
; AR3 points to ROWMAX
; AR4 points to COLMAX
;----------------------------------------------------------------------
twist_check:
	ld	*AR3,A
	sub	*AR4,A
	bc	twist2,ALEQ	;if(ROWMAX > COLMAX)

twist1	ld	*AR4,16,A	;   (AH)=COLMAX
	rpt	#(16-1)		;
	 subc	*AR3,A		;   compute (COLMAX/ROWMAX)
	and	#0ffffh,A	;   retain quotient (AL), mask remainder
	sfta	A,15		;   shift quotient into AH
	sub	#THR_REVTWI,16,A;
	bc	err_revtwi,ALEQ	;   if((COLMAX/ROWMAX) <= THR_REVTWI)
				;      branch to err_revtwi
	b	rel_check	
				;else
twist2	ld	*AR3,16,A	;   (AH)=ROWMAX
	rpt	#(16-1)		;
	 subc	*AR4,A		;   compute (ROWMAX/COLMAX)
	and	#0ffffh,A	;   retain quotient (AL), mask remainder
	sfta	A,15		;   shift quotient into AH
	sub	#THR_STDTWI,16,A;
	bc	err_stdtwi,ALEQ	;   if((COLMAX/ROWMAX) <= THR_STDTWI)
				;      branch to err_stdtwi
	b	rel_check

err_revtwi:			;**** record reverse twist error ****
	orm	#0002h,*AR5(6)	; set reverse twist error flag (b1)
	b	ende		; terminate checks

err_stdtwi:			;**** record standard twist error ****
	orm	#0004h,*AR5(6)	; set standard twist error flag (b2)
	b	ende		; terminate checks


;----------------------------------------------------------------------
; Relative peak check:
;    
;    find rel row peak --> RELPEAK
;    if(RELPEAK/ROWMAX < THR_ROWREL)  continue
;    else terminate all checks
;
;    find rel col peak --> RELPEAK
;    if(RELPEAK/COLMAX < THR_ROWREL)  continue
;    else terminate all checks
;
; AR3 points to ROWMAX
; AR4 points to COLMAX
;----------------------------------------------------------------------
rel_check:			;------ relative row peak ratio check -------
	ld	*AR5(2),A	;
	stlm	A,AR0		;AR0 points to ENERGY table (row frequencies)
	ld	#0,B		;(BH)=0
	stm	#(4-1),BRC	;
	rptb	rel12-1		;for(k=0;k<4;k++)
	 ld	*AR0,16,A	;  (AH)=E[k]
	 cmpr	0,AR3		; 
	 bc	rel11,TC	;  if(AR0==AR3)
	 max	B		;    (B)=newmax=max(oldmax,E[k])
rel11	 mar	*AR0+		;
	
rel12	rpt	#(16-1)		;
	 subc	*AR3,B		;compute (RELPEAK/ROWMAX)
	and	#0ffffh,B	;retain quotient (BL), mask remainder
	sfta	B,15		;shift quotient into BH
	sub	#THR_ROWREL,16,B;
	bc	err_rowrel,BGEQ	;if((RELPEAK/ROWMAX) >= THR_ROWREL)
				;      branch to err_rowrel

				;------ relative column peak ratio check ----
rel2	ld	#0,B		;(BH)=0
	stm	#(4-1),BRC	;
	rptb	rel22-1		;for(k=4;k<8;k++)
	 ld	*AR0,16,A	;  (AH)=E[k]
	 cmpr	0,AR4		; 
	 bc	rel21,TC	;  if(AR0==AR4)
	 max	B		;    (B)=newmax=max(oldmax,E[k])
rel21	 mar	*AR0+		;
		
rel22	rpt	#(16-1)		;
	 subc	*AR4,B		;compute (RELPEAK/COLMAX)
	and	#0ffffh,B	;retain quotient (BL), mask remainder
	sfta	B,15		;shift quotient into BH
	sub	#THR_COLREL,16,B;
	bc	err_colrel,BGEQ	;if((RELPEAK/COLMAX) >= THR_COLREL)
				;      branch to err_colrel
	b	sec_check

err_rowrel:			;**** record row's rel peak error ****
	orm	#0008h,*AR5(6)	; set row's rel peak error flag (b3)
	b	ende		; terminate checks

err_colrel			;**** record col's rel peak error ****
	orm	#0010h,*AR5(6)	; set col's rel peak error flag (b4)
	b	ende		; terminate checks


;----------------------------------------------------------------------
; Second Harmonics check
;    if( (ROW2nd/ROWMAX) < THR_ROW2nd )  continue
;    else terminate all checks
;
;    if( (COL2nd/COLMAX) < THR_COL2nd )  continue
;    else terminate all checks
;
; AR3 points to ROWMAX
; AR4 points to COLMAX
;----------------------------------------------------------------------
sec_check:
	mvmm	AR3,AR6		;backup AR3
	mvmm	AR4,AR7		;backup AR4

	;=========== 2nd harmonics check for rows ===========
				;----- define ptr to coeff tbl (AR3) -----
	ld	*AR5(2),A	;load pointer to coeffs from struct
	stlm	A,AR0		;AR0 points to energy template
	nop
	nop			;pipeline latencies
	mar	*AR3-0		;AR3 contains displacement in energy template
	mvmm	AR3,AR1		;save displacement in AR1
	stm	#COEF2nd,AR0	;AR0 points to 2nd harm coefficients
	mar	*AR3+0		;AR3 points to desired coefficient

				;----- define ptr to taps array (AR4) -----
	ld	*AR5(1),A	;load pointer to taps from struct
	add	#3,A		;
	stlm	A,AR4		;AR4 points to row's 2nd harm tap

				;----- define ptr to energy (AR1) ------
	ld	*AR5(2),A	;
	add	#8,A		;
	stlm	A,AR1		;AR1 points to row's 2nd harm in energy template

				;----- compute goertzel filter -----
	ld	#0,ASM		;ASM=0
	ld	*AR5(0),A	;
	stlm	A,AR2		;AR2 points to data
	stm	#(N-1),BRC	;
	ld	*AR2+,16,A	;(AH) = x(n)
	rptb	sec1-1		;for(n=0;n<N;n++)	{
	 sub	*AR4-,16,A,B	;   (B) = -vk(n-2) + x(n)
	 mac	*AR4,*AR3,B	;   (B) = coef*vk(n-1) - vk(n-2) + x(n)
	 mac	*AR4,*AR3,B	;   (B) = 2*coef*vk(n-1) - vk(n-2) + x(n)
	 delay	*AR4		;   vk(n-1) ---> vk(n-2)
	 st	B,*AR4+		;   (B)     ---> vk(n-1)
	|| ld	*AR2+,A		;   (AH) = x(n)
sec1				;}
				;----- compute energy --------------
	ld	*AR4,16,A	; (A) = vk(N-1), A(32:16) loaded
	mpya	*AR4-		; (B) = vk(N-1)*vk(N-1), (T) = vk(N-1)
	mpy	*AR4,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	*AR4,T		; (T) = vk(N)
	mac	*AR4,B		; (B) = vk(N)*vk(N) - 2*coef*vk(N)*vk(N-1) + vk(N-1)*vk(N-1)
	sth	B,*AR1		; store result E[k] into energy template

				;----- check threshold condition ------
	ld	*AR1,16,A	;(AH)=ROW2nd
	sub	*AR6,16,A,B	;(BH)=ROW2nd-ROWMAX
	bc	err_row2nd,BGEQ	;if(ROW2nd<ROWMAX)
	rpt	#(16-1)		;
	 subc	*AR6,A		;   compute (ROW2nd/ROWMAX)
	and	#0ffffh,A	;   retain quotient (AL), mask remainder
	sfta	A,15		;   shift quotient into AH
	sub	#THR_ROW2nd,16,A;
	bc	err_row2nd,AGEQ	;   if((ROW2nd/ROWMAX) >= THR_ROW2nd)
				;      branch to err_row2nd



	;=========== 2nd harmonics check for columns ===========
				;----- define ptr to coeff tbl (AR3) -----
	mvmm	AR7,AR3		;AR3 points to COLMAX
	ld	*AR5(2),A	;load pointer to coeffs from struct
	stlm	A,AR0		;AR0 points to energy template
	nop
	nop			;pipeline latencies
	mar	*AR3-0		;AR3 contains displacement in energy template
	mvmm	AR3,AR1		;save displacement in AR1
	stm	#COEF2nd,AR0	;AR0 points to 2nd harm coefficients
	mar	*AR3+0		;AR3 points to desired coefficient

				;----- define ptr to taps array (AR4) -----
	ld	*AR5(1),A	;load pointer to taps from struct
	add	#1,A		;
	stlm	A,AR4		;AR4 points to column's 2nd harm tap

				;----- define ptr to energy (AR1) ------
	ld	*AR5(2),A	;
	add	#9,A		;
	stlm	A,AR1		;AR1 points to column's 2nd harm in energy template

				;----- compute goertzel filter -----
	ld	#0,ASM		;ASM=0
	ld	*AR5(0),A	;
	stlm	A,AR2		;AR2 points to data
	stm	#(N-1),BRC	;
	ld	*AR2+,16,A	;(AH) = x(n)
	rptb	sec2-1		;for(n=0;n<N;n++)	{
	 sub	*AR4-,16,A,B	;   (B) = -vk(n-2) + x(n)
	 mac	*AR4,*AR3,B	;   (B) = coef*vk(n-1) - vk(n-2) + x(n)
	 mac	*AR4,*AR3,B	;   (B) = 2*coef*vk(n-1) - vk(n-2) + x(n)
	 delay	*AR4		;   vk(n-1) ---> vk(n-2)
	 st	B,*AR4+		;   (B)     ---> vk(n-1)
	|| ld	*AR2+,A		;   (AH) = x(n)
sec2				;}
				;----- compute energy --------------
	ld	*AR4,16,A	; (A) = vk(N-1), A(32:16) loaded
	mpya	*AR4-		; (B) = vk(N-1)*vk(N-1), (T) = vk(N-1)
	mpy	*AR4,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	*AR4,T		; (T) = vk(N)
	mac	*AR4,B		; (B) = vk(N)*vk(N) - 2*coef*vk(N)*vk(N-1) + vk(N-1)*vk(N-1)
	sth	B,*AR1		; store result E[k] into energy template

				;----- check threshold condition ------
	ld	*AR1,16,A	;(AH)=COL2nd
	sub	*AR7,16,A,B	;(BH)=COL2nd-COLMAX
	bc	err_col2nd,BGEQ	;if(COL2nd<COLMAX)
	rpt	#(16-1)		;
	 subc	*AR7,A		;   compute (COL2nd/COLMAX)
	and	#0ffffh,A	;   retain quotient (AL), mask remainder
	sfta	A,15		;   shift quotient into AH
	sub	#THR_COL2nd,16,A;
	bc	err_col2nd,AGEQ	;   if((COL2nd/COLMAX) >= THR_COL2nd)
				;      branch to err_col2nd

	mvmm	AR6,AR3		;restore AR3
	mvmm	AR7,AR4		;restore AR4

	b	digit_map

err_row2nd:			;**** record row's 2nd harm error ****
	orm	#0020h,*AR5(6)	; set row's 2nd harm error flag (b5)
	b	ende		; terminate checks

err_col2nd:			;**** record col's 2nd harm error ****
	orm	#0040h,*AR5(6)	; set col's 2nd harm error flag (b6)
	b	ende		; terminate checks


;----------------------------------------------------------------------
; Map detected tone pair to digit
; 
; AR3 points to ROWMAX
; AR4 points to COLMAX
;----------------------------------------------------------------------
digit_map:
;---------- find row and col numbers ----------------------------
	ld	*AR5(2),A
	stlm	A,AR0		;load offset
	nop
	nop
	mar	*AR3-0		;AR3 contains row#
	mar	*+AR0(4)
	mar	*AR4-0		;AR4 contains col#
	
;---------- map row and column numbers to actual digit -------------
	ld	*(AR3),8,A	;load row nbr in upper byte of AL
	add	*(AR4),A	;load column nbr in lower byte of AL
	stm	#KEYS,AR2	;AR2 points to key mapping table
	stm	#0,AR3		;AR3 is used as counter
	stm	#(16-1),BRC
	rptb	digit3-1	;for(k=0;k<16;k++)   {
	 sub	*AR2+,A,B
	 bc	digit31,bneq	;   if(A == KEYS[k])  insert delay
	  b	digit4		;       branch to ende
digit31	 mar	*AR3+		;  increment counter
digit3				;}

				
;------------------------------------------------------------------------
; Validate digit from previous digit
;
;------------------------------------------------------------------------
digit4	nop			;now AR3 contains decoded digit
	ld	*AR5(3),A	;
	stlm	A,AR4		;AR4 used as digitptr

	orm	#0100h,*AR5(5)	;set bit "duration counter"
	ldm	AR3,A		;load current digit
	sub	*AR5(4),A,B	;compare with last digit
	bc	digit5,bneq	;if current digit and last digit are the same
	stl	A,*AR4+		;   store VALID DIGIT into DIGITS
	ldm	AR4,A		;
	stl	A,*AR5(3)	;   update pointer
	st	#0,*AR5(5)	;   disable detector and wait for pause
	st	#-1,*AR5(4)	;   reset last digit
	b	ende		;else
digit5	ldm	AR3,A		;   store decoded digit
	stl	A,*AR5(4)	;   into digitlast

ende	bitf	*AR5(5),#0400h	;test "duration counter"
	bc	end1,NTC	;if(bit set)
	st	#0,*AR5(5)	;   disable detector and wait for pause
	st	#-1,*AR5(4)	;   reset last digit

end1	frame	#0
	popm	AR7
	popm	AR6
	popm	AR1
	popm	ST1
	popm	ST0
	nop
	ret


⌨️ 快捷键说明

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