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

📄 dtmf_dec.asm

📁 dtmf 源码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	 sub	*AR2-,15,A	;    (A) = -(1/2)vk(n-2) + (1/2)x(n)
	 ltd	*AR2		;    vk(n-1) --> vk(n-2)
	 mac	*AR2,*AR3+,A	;    (A) = coef*vk(n-1) - (1/2)vk(n-2) + (1/2)x(n)
	 sfta	A,1		;    (A) = 2*coef*vk(n-1) - vk(n-2) + x(n)
	 bc	novf2,anov	;   <--- check on OVERFLOW
	  st	#-1,COUNT	;    if(OV set)  {  COUNT = -1
	  b	goer3		;                   branch unconditionally to goer3 }	
novf2	 sth	A,*AR2-		;    (A) --> vk(n-1)
goer21				;  }

				;do 1.Harm. for 205 samples
goer1	stm	#END1st,AR2	;  AR2 points to end of tap block
	stm	#COEF1st,AR3	;  AR3 points to Coefficients
	stm	#(8-1),BRC	;  
	rptb	goer11-1	;  for(k=0;k<8;k++)  do 8 filters as follows
	 ld	rcv,15,A	;  { (A) = (1/2)x(n)
	 sub	*AR2-,15,A	;    (A) = -(1/2)vk(n-2) + (1/2)x(n)
	 ltd	*AR2		;    vk(n-1) --> vk(n-2)
	 mac	*AR2,*AR3+,A	;    (A) = coef*vk(n-1) - (1/2)vk(n-2) + (1/2)x(n)
	 sfta	A,1		;    (A) = 2*coef*vk(n-1) - vk(n-2) + x(n)
	 bc	novf1,anov	;   <--- check on OVERFLOW
	  st	#-1,COUNT	;    if(OV set)  {  COUNT = -1
	  b	goer3		;                   branch unconditionally to goer3 }	
novf1	 sth	A,*AR2-		;    (A) --> vk(n-1)
goer11				;  }

goer3	ret




**************************************************************************
* SUBROUTINE: dtmf_checks
*
* Input:  none
* Output: A (status if valid digit)
* Uses:
*
* Description:
* (Subroutine is done if COUNT < 0
*  It is only done once every 205 samples since COUNT is restored to 205)
*
*  - energy computation
*  - initialize filter taps to zero
*  - maximum search
*  - DTMF status check
*  - signal strength check
*  - twist check
*  - relative peak check
*  - 2nd harmonic check
*  - digit check (same as second to last, same as last?)
*
**************************************************************************

dtmf_checks:
	nop


;-------------------------------------------------------------------------
; Energy computation
;
;  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 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
; AR2: points to v1(N-1)
; AR3: points to COEF1st
;
;-------------------------------------------------------------------------
energy	stm	#END1st,AR2	;AR2 points to end of filter taps block
	stm	#COEF1st,AR3	;AR3 points to beg of coefficient table
	stm	#ENERGY,AR4	;AR4 points to block of energies
	stm	#(16-1),BRC

	rptb	ener1-1		;for(k=0;k<16;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)
	 sth	B,*AR4+		; store result E[k] into energy data block
ener1				;}


;------------------------------------------------------------------------
; Initialize Filter Taps to zero for next round
;
;------------------------------------------------------------------------
	stm	#TAPS2nd,AR2	;AR2 points to beginning of filter taps
	rpt	#(32-1)		;for(i=0;i<32;i++)
	 st	#0,*AR2+	;   initialize filter taps for next round

	nop

;------------------------------------------------------------------------
; Maximum search
; Searches row-energies and column-energies for their maxima
; Distinguishes between 1.Harm and 2.Harm
;
; MAX_ROW_1st: Maximum spectral energy in row tone band (1.Harmonics)
; MAX_COL_1st: Maximum spectral energy in column tone band (1.Harmonics)
; MAX_ROW_2nd: Maximum spectral energy in row tone band (2.Harmonics)
; MAX_COL_2nd: Maximum spectral energy in column tone band (2.Harmonics)
; 
;------------------------------------------------------------------------
max_search:
	stm	#ENERGY,AR2	;AR2 points to energy table (row energies)
	stm	#(4-1),BRC
	ld	#0,B		;clear B
	rptb	max1-1		;for(k=0;k<4;k++)    {
	 ld	*AR2+,A		;  load A with next energy value E[k]
	 max	B		;  max(A,B) --> B
max1				;}
	stl	B,MAX_ROW_1st	;save result
	stm	#(4-1),BRC
	ld	#0,B		;clear B
	rptb	max2-1		;for(k=4;k<8;k++)    {
	 ld	*AR2+,A		;  load A with next energy value E[k]
	 max	B		;  max(A,B) --> B
max2				;}
	stl	B,MAX_COL_1st	;save result
	stm	#(4-1),BRC
	ld	#0,B		;clear B
	rptb	max3-1		;for(k=8;k<12;k++)    {
	 ld	*AR2+,A		;  load A with next energy value E[k]
	 max	B		;  max(A,B) --> B
max3				;}
	stl	B,MAX_ROW_2nd	;save result
	stm	#(4-1),BRC
	ld	#0,B		;clear B
	rptb	max4-1		;for(k=12;k<16;k++)    {
	 ld	*AR2+,A		;  load A with next energy value E[k]
	 max	B		;  max(A,B) --> B
max4				;}
	stl	B,MAX_COL_2nd	;save result


;----------------------------------------------------------------------
; DTMF Status Check:
;   if(DTMF_STAT == 0) 
;      if( max(MAX_ROW_1st,MAX_COL_1st) < THR_PAU )
;         DTMF_STAT = 1, detector enabled
;      terminate all checks
;   else
;      continue
;
;----------------------------------------------------------------------
stat_check
	bitf	DTMF_STAT,#0001h	;
	bc	sig_check,tc		;if(DTMF_STAT == 1) continue with sig_check
	ld	MAX_ROW_1st,A		;
	ld	MAX_COL_1st,B		;else
	max	A			;  (A)=max(MAX_ROW_1st,MAX_COL_1st)
	sub	#THR_PAU,A		;  (A)=max(MAX_ROW_1st,MAX_COL_1st) - THR_PAU
	bc	stat1,ageq		;  if((A)<0)
	st	#0001h,DTMF_STAT	;     DTMF_STAT = 1
stat1	b	ende			;  terminate all checks



;----------------------------------------------------------------------
; Signal strength check:
;    if(MAX_ROW_1st > THR_SIG)
;      else  terminate all checks
;    if(MAX_COL_1st > THR_SIG)
;      else  terminate all checks
;
;----------------------------------------------------------------------
sig_check:
	ld	MAX_ROW_1st,A	
	sub	#THR_SIG,A
	bc	ende,alt	;if(MAX_ROW_1st < THR_SIG) branch to ende
	ld	MAX_COL_1st,A	
	sub	#THR_SIG,A
	bc	ende,alt	;if(MAX_COL_1st < THR_SIG) branch to ende


;----------------------------------------------------------------------
; Twist check:
;    if( abs(MAX_ROW_1st-MAX_COL_1st) < THR_TWI )
;      else  terminate all check
;
;----------------------------------------------------------------------
twist_check:
	ld	MAX_ROW_1st,A
	sub	MAX_COL_1st,A
	abs	A
	sub	#THR_TWI,A
	bc	ende,agt	;if(abs(MAX_ROW_1st-MAX_COL1st) > THR_TWI) branch to ende
	

;----------------------------------------------------------------------
; Relative peak check:
;    if( min(MAX_ROW_1st-E[0,1,2,3]) > THR_REL )
;      else terminate all checks
;    if( min(MAX_COL_1st-E[4,5,6,7]) > THR_REL )
;      else terminate all checks
;
;----------------------------------------------------------------------
rel_check:
	stm	#ENERGY,AR2
	ld	#07fffh,B
	stm	#(4-1),BRC
	rptb	rel1-1		;for(k=0;k<4;k++)
	 ld	MAX_ROW_1st,A	; (A)=MAX_ROW_1st
	 sub	*AR2+,A		; (A)=MAX_ROW_1st-E[k]
	 bc	rel11,aeq	; if(identical) don't use value for min
	 min	B		; (B)=min((B),MAX_ROW_1st-E[k])
rel11	 nop
rel1	sub	#THR_REL,B
	bc	ende,blt	;if(min(MAX_ROW_1st-E[k]) < THR_REL)  branch to ende

	ld	#07fffh,B
	stm	#(4-1),BRC
	rptb	rel2-1		;for(k=4;k<8;k++)
	 ld	MAX_COL_1st,A	; (A)=MAX_COL_1st
	 sub	*AR2+,A		; (A)=MAX_COL_1st-E[k]
	 bc	rel21,aeq	; if(identical) don't use value for min
	 min	B		; (B)=min((B),MAX_COL_1st-E[k])
rel21	 nop
rel2	sub	#THR_REL,B
	bc	ende,blt	;if(min(MAX_ROW_1st-E[k]) < THR_REL)  branch to ende


;----------------------------------------------------------------------
; Second Harmonics check
;    if( (MAX_ROW_1st-MAX_ROW_2nd) > THR_2nd )
;      else terminate all checks
;    if( (MAX_COL_1st-MAX_COL_2nd) > THR_2nd )
;      else terminate all checks
;
;----------------------------------------------------------------------
sec_check:
	ld	MAX_ROW_1st,A
	sub	MAX_ROW_2nd,A
	bc	ende,alt	;if( (MAX_ROW_1st-MAX_ROW_2nd) < THR_2nd ) branch to ende
	ld	MAX_COL_1st,A
	sub	MAX_COL_2nd,A
	bc	ende,alt	;if( (MAX_COL_1st-MAX_COL_2nd) < THR_2nd ) branch to ende


;----------------------------------------------------------------------
; Map detected tone pair to digit
;    
;----------------------------------------------------------------------
digit_map:

;---------- find row number corresponding to peak ------------
	stm	#ENERGY,AR2	;AR2 points to energy table
	ld	MAX_ROW_1st,A	;load A with max row energy value
	stm	#0,AR3		;AR3 is used as counter
	stm	#(4-1),BRC
	rptb	digit1-1	;for(k=0;k<4;k++)   {
	 sub	*AR2+,A,B	;  ---- do for row energies ----
	 bc	digit11,bneq
	  mvmd	AR3,DIGIT_ROW	;  if(MAX_ROW_1st == E[k])  save row nbr
digit11	 mar	*AR3+		;  increment counter
digit1				;}

;---------- find column number corresponding to peak ------------
	ld	MAX_COL_1st,A	;load A with max column energy value
	stm	#0,AR3		;AR3 is used as counter
	stm	#(4-1),BRC
	rptb	digit2-1	;for(k=4;k<8;k++)   {
	 sub	*AR2+,A,B	;  ---- do for column energies ----
	 bc	digit21,bneq
	  mvmd	AR3,DIGIT_COL	;  if(MAX_COL_1st == E[k])  save column nbr
digit21	 mar	*AR3+		;  increment counter
digit2				;}

;---------- map row and column numbers to actual digit -------------
	stm	#KEYS,AR2	;AR2 points to key mapping table
	stm	#0,AR3		;AR3 is used as counter
	stm	#BUFFER+1,AR4	;AR4 points to digit buffer +1
	ld	DIGIT_ROW,8,A	;load row nbr in upper byte of AL
	add	DIGIT_COL,A	;load column nbr in lower byte of AL
	stm	#(16-1),BRC
	rptb	digit3-1	;for(k=0;k<16;k++)   {
	 sub	*AR2+,A,B
	 bc	digit31,bneq
	  ltd	*AR4-		;   if(A == KEYS[k])  insert delay
	  ltd	*AR4		;       insert delay
	  mvmd	AR3,BUFFER	;       save decoded digit into buffer 
	  b	digit4		;       branch to ende
digit31	 mar	*AR3+		;  increment counter
digit3				;}

;------------------------------------------------------------------------
; Validate digits from previous digits
;
;------------------------------------------------------------------------
digit4
	stm	#BUFFER,AR2
	mvdm	DIGIT_PTR,AR3
	ld	*AR2+,A		;load current digit
	sub	*AR2,A,B	;compare with last digit
	bc	ende,bneq	;if current digit and last digit are the same
	 stl	A,*AR3+		;   store VALID DIGIT into DIGITS
	 mvmd	AR3,DIGIT_PTR	;   update pointer
	 st	#0,DTMF_STAT	;   disable detector and wait for pause
	



ende	ret




******************************************
* Interrupt Service Routines
******************************************
RINT1_ISR:
	ld	#rcv,DP
	mvmd	DRR1,rcv
	andm	#0fffch,tra
	mvdm	tra,DXR1

	popm	ST1
	popm	ST0
	rete



*****************************************************************
* SUBROUTINE: hwinit                                            *
* Description: Initializes Processor                            *
*                          Serial Port 1                        *
*                          AIC                                  *
* Input: none                                                   *
* Output: none                                                  *
*****************************************************************

hwinit:

;----------- Initialize Processor ---------------------------

	stm	#0ffe0h,PMST	;configure on-chip RAM in OVLY mode
	stm	#02000h,SWWSR	;I/O:    2 wait states
				;memory: 0 wait states
	stm	#0000h,BSCR	;no bank switching


;----------- Initialize Serial Port 1 -----------------------

	stm     #10h, TCR       ; turn off timer
	stm     #0c008h, SPC1   ; reset serial port 1
				;     =0 (b0) : reserved, always zero
				; DBL =0 (b1) : loopback mode disabled
				; FO  =0 (b2) : 16-bit word operation
				; FSM =1 (b3) : frame sync control
				; MCM =0 (b4) : external CLKX
				; TXM =0 (b5) : external FSK
				; XRST=0 (b6) : Xmit reset
				; RRST=0 (b7) : Recv reset
	stm     #0c0c8h, SPC1   ; take serial port 1 out of reset
				; XRST=0 (b6) : Xmit reset
				; RRST=0 (b7) : Recv reset


;----------- Initialize AIC ----------------------------------

	ld      #aic_conf,DP    ; reset AIC
	portr   0014h, aic_conf	; (EVM: Port 14h used as target control register
	andm    #7fffh, aic_conf;       B15 of port 14h is AICRST/  )
	portw   aic_conf,0014h

	rpt	#40		; keep low for 2usec
	nop

	ld      #aic_conf,DP    ; take AIC out of reset
	portr   0014h,aic_conf
	orm     #8000h,aic_conf
	portw   aic_conf,0014h


	stm     #80h, IMR       ; allow TINT1 interrupt
	stm     #0c8h, IFR      ; clear pending serial port 1 and timer interrupts
	rsbx	INTM		; global interrupt enable
	stm     #0h, DXR1       ; dummy Xmit for synchronization

	stm     #3h, DXR1       ; request secondary Xmit mode to send control word
	idle	1		; wait for TINT1 interrupt
        stm     #0124h, DXR1    ; CONVERSION RATE:   sample rate      DXR1 value
	idle	1		; (Reg1)		16 kHz		0112h
				;			 8 kHz		0124h
				;			 4 kHz		0148h         
	stm     #3h,DXR1
	idle	1
	stm     #0212h,DXR1	; PRESCALER:	FCLK = 288 kHz
	idle	1		; (Reg2)
	
	stm     #3h,DXR1
	idle	1
	stm     #0300h,DXR1     ; PHASE ADJUSTMENTS: none  
	idle	1		; (Reg3)

	stm     #3h, DXR1 
	idle	1
	stm     #0426h, DXR1    ; OUTPUT GAINS:	-8dB (monitor)
	idle	1		; (Reg4)	-6dB (analog input)
				;		-6dB (analog output)
	
	ssbx	INTM		; global interrupt disable
	stm     #0h, DXR1

	ret

;------------ END OF H/W INITIALIZATION SUBROUTINE---------------------


        .end

⌨️ 快捷键说明

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