www.pudn.com > DTMF_ENC.rar > DTMF_ENC.ASM


************************************************************** 
*   (C) COPYRIGHT TEXAS INSTRUMENTS, INC. 1996               * 
************************************************************** 
*   Program Name:     DTMF tone generator                    * 
*   File Name:        dtmf_enc.asm                           * 
*   File Description: This file contains the code for a      * 
*                     DTMF tone generator                    * 
*                     (TMS320C54x EVM version)               * 
*                                                            * 
*   Author:   Gunter Schmer                                  * 
*   Date:     06/06/96                                       * 
*   Revision: 1.0                                            * 
*   Latest working date:  06/06/96                           * 
************************************************************** 
 
	.title	"dtmf encoder" 
	.mmregs 
 
*************************************** 
***   Constants 
*************************************** 
TIME_SH	.set	03ffh	;short duration (128 msec) 
TIME_LG	.set	03ffh	;long duration  (128 msec) 
DAC_OFS	.set	000h	;DAC offset 
 
*************************************** 
***   Variables 
*************************************** 
        .bss    aic_conf,1 
	.bss	rcv,1		;receive variable 
	.bss	tra,1		;transmit variable 
	.bss	DIGIT,1		;current digit 
	.bss	DIGIT_PTR,1	;points to current digit in PHNBR table 
	.bss	TIMER,1		;timer counter 
	.bss	T1_OFS,1	;offset for tone 1 (row tone) 
	.bss	T2_OFS,1	;offset for tone 2 (column tone) 
	.bss	TASK,1		;holds the nbr of the task that is to be executed 
 
 
*************************************** 
***   Tables 
*************************************** 
 
******************************************************* 
* The following table assembles the coefficients and  * 
* initial conditions for the difference equations of  * 
* the digital sinusoidal oscillators.                 * 
*                                                     * 
* In general:                                         * 
*   DEQ:    y(n) = 2*cos(2pi*f/fs)*y(n-1) - y(n-2)    * 
*   I.C.:   y(-1) = 0                                 * 
*           y(-2) = -A*sin(2pi*f/fs)                  * 
*   where   A  = desired amplitude of sine wave       * 
*           f  = desired frequency of sine wave       * 
*           fs = sampling frequency                   * 
*                                                     * 
* Example:                                            * 
*       .word    cos(2pi*f/fs)*32768	;coefficient  * 
*       .word    0			;y(-1)        * 
*       .word    -A*sin(2pi*f/fs)*32768	;y(-2)        * 
*                                                     * 
******************************************************* 
        .sect   "tbl_tone" 
TONES   .word    27978          ; row 1      coef 
        .word        0          ;            y(n-1) 
        .word     -533          ;            y(n-2) 
 
        .word    26956          ; row 2      coef 
        .word        0          ;            y(n-1) 
        .word     -582		;            y(n-2) 
 
        .word    25701          ; row 3      coef 
        .word        0          ;            y(n-1) 
        .word     -635		;            y(n-2) 
 
        .word    24219          ; row 4      coef 
        .word        0          ;            y(n-1) 
        .word     -689		;            y(n-2) 
 
        .word    19073          ; column 1   coef 
        .word        0          ;            y(n-1) 
        .word     -833		;            y(n-2) 
 
        .word    16325          ; column 2   coef 
        .word        0          ;            y(n-1) 
        .word     -888		;            y(n-2) 
 
        .word    13085          ; column 3   coef 
        .word        0          ;            y(n-1) 
        .word     -938		;            y(n-2) 
 
        .word     9314          ; column 4   coef 
        .word        0          ;            y(n-1) 
        .word     -981		;            y(n-2) 
 
 
***************************************************************** 
* The following table contains offsets into the                 * 
* tone table tbl_tone.                                          * 
* The offset for the row-tone is the (upper byte) of each word  * 
* The offset for the column-tone is the (lower byte + #12)      * 
*                                                               * 
***************************************************************** 
	.sect	"tbl_keys" 
KEYS	.word	0903h		; '0'  example: 0903h --> 3.row, 1.column (*3) 
	.word	0000h		; '1' 
	.word	0003h		; '2' 
	.word	0006h		; '3' 
	.word	0300h		; '4' 
	.word	0303h		; '5' 
	.word	0306h		; '6' 
	.word	0600h		; '7' 
	.word	0603h		; '8' 
	.word	0606h		; '9' 
	.word	0009h		; 'A' 
	.word	0309h		; 'B' 
	.word	0609h		; 'C' 
	.word	0906h		; 'D' 
	.word	0900h		; 'E' = '*' 
	.word	0906h		; 'F' = '#' 
 
 
**************************************************************** 
* The following table contains the phone number to be          * 
* encoded. The format is as follows                            * 
*                                                              * 
* PH_NBR   .word   4,2,7,E,F,A,3,-1                            * 
*                                                              * 
* is the foll nbr: 4 2 7 * # A 3   (-1 terminates the encoding)* 
**************************************************************** 
	.sect	"tbl_phnr" 
PH_NBR	.word	1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,-1	;Phone Number 
 
 
 
****************************************** 
*       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 
 
	stm	#0040h,IMR	;enable RINT1 interrupt 
	stm	#00c8h,IFR	;clear all pending serial port or timer interrupts 
	rsbx	INTM		;global interrupt enable 
 
	mvmd	DRR1,rcv	;dummy read 
	mvdm	tra,DXR1	;dummy write 
 
	b	Main 
 
****************************************** 
*       Main Program 
****************************************** 
 
Main 
	ld	#aic_conf,DP	;DP to variables 
	st	#PH_NBR,DIGIT_PTR  ;initialize pointer to PHNBR table 
	st	#0,TASK		;initialize beginning task 
	st	#0,TIMER	;initialize timer to zero 
 
next	idle	1 
	call	tasks		;actual processing following RINT interrupt 
	nop 
	b	next 
 
done	b	done 
 
 
************************************************************ 
* Task Scheduler:       
* Run this task scheduler section at the beginning of 
* each RINT_ISR process 
* 
*  
************************************************************ 
tasks	cmpm	TASK,#00h 
	bc	task1,NTC	;if(TASK!=0) branch to task1 
				;  else branch to task0  
 
task0	cmpm	TIMER,#00h 
	bc	task01,NTC	;branch if timer not zero 
	mvdm	DIGIT_PTR,AR1	; AR1 points to digit in PHNBR table 
	st	#01h,TASK	; TASK of next RINT_ISR is task1 
	st	#TIME_LG,TIMER	; set timer to long duration 
	ld	*AR1+,A		; load A with digit 
	bc	done,alt	; done if digit is -1 ! 
	mvmd	AR1,DIGIT_PTR	; save new pointer to digit in PHNBR table 
	call	unpack		; unpack digit: A --> T1_OFS, T2_OFS 
	b	task02 
task01	ld	TIMER,A 
	sub	#1,A 
	stl	A,TIMER		;decrement timer 
task02	call	quiet 
	b	task3		;branch to task3 
 
 
task1	cmpm	TIMER,#00h 
	bc	task11,NTC	;branch if timer not zero 
	st	#00h,TASK	; TASK of next RINT_ISR is task0 
	st	#TIME_SH,TIMER	; set timer to short duration 
	b	task12 
task11	ld	TIMER,A 
	sub	#1,A 
	stl	A,TIMER		;decrement timer 
task12	mvdm	T1_OFS,AR2	;AR2 is offset for row-tone 
	mvdm	T2_OFS,AR3	;AR3 is offset for column-tone 
	call	tone 
 
task3	ret 
 
	 
 
 
***************************************************************** 
* SUBROUTINE:  unpack                                           * 
* Description: Maps the key value (in A) into two offsets for   * 
*              two tones and writes results into variables      * 
*              T1_OFS, T2_OFS                                   * 
* Uses:        AR2                                              * 
* Input:       A                                                * 
* Output:      none                                             * 
***************************************************************** 
unpack	stlm	A,AR2		;AR2 keys-map offset for unpacking 
	ld	#DIGIT,DP	;DP to variables 
	nop			;pipeline conflict(1) + latency(1) with AR2 
	ld	*AR2(KEYS),A	;load A with keys-map value 
	ld	*AR2(KEYS),B	;load B with keys-map value 
	and	#0f00h,A	;mask out the row portion 
	and	#000fh,B	;mask out the column portion 
	sftl	A,-8		;right shift A by 8 
	add	#12,B		;add 4*3 words offset to point into column portion 
	stl	A,T1_OFS	;store tone 1 offset (row tone) 
	stl	B,T2_OFS	;store tone 2 offset (column tone) 
	ret 
 
 
***************************************************************** 
* SUBROUTINE:  tone                                             * 
* Description: Generates the dual tone samples for DTMF         * 
*              using offsets T1_OFS, T2_OFS                     * 
* Uses:        AR2, AR3                                         * 
* Input:       none                                             * 
* Output:      none                                             * 
***************************************************************** 
tone	ld	#0,B			;clear B  ----ROW TONE---- 
	sub	*AR2(TONES+2),15,B	; (B) = -(1/2)y(n-2), in high accumulator 
	ltd	*AR2(TONES+1)		; load (T) with y(n-1) and y(n-1) --> y(n-2) 
	mpy	*AR2(TONES),A  		; (A) = coef*y(n-1) 
	add	A,B		    	; (B) = coef*y(n-1) - (1/2)y(n-2) 
	sth	B,1,*AR2(TONES+1)	; 2*(B) --> y(n-1) 
	ld	#0,B			;clear B  ----COLUMN TONE---- 
	; b	tone1			; test only one oscillator 
	sub	*AR3(TONES+2),15,B	; (B) = -(1/2)y(n-2), in high accumulator 
	ltd	*AR3(TONES+1)		; load (T) with y(n-1) and y(n-1) --> y(n-2) 
	mpy	*AR3(TONES),A  		; (A) = coef*y(n-1) 
	add	A,B		    	; (B) = coef*y(n-1) - (1/2)y(n-2) 
	sth	B,1,*AR3(TONES+1)	; 2*(B) --> y(n-1) 
 
tone1	add	*AR2(TONES+1),15,B	; add two tone samples 
	add	#DAC_OFS,B		; add DAC offset 
	sth	B,tra			; write to transmit variable 
	ret 
 
 
***************************************************************** 
* SUBROUTINE:  quiet                                            * 
* Description: Generates a pause of specified duration          * 
*                                                               * 
* Uses:        AR2, AR3                                         * 
* Input:       TIME_SH                                          * 
* Output:      none                                             * 
***************************************************************** 
quiet	ld	#0,B		; clear B 
	add	#DAC_OFS,B	; add DAC offset 
	sth	B,tra		; write to transmit variable 
	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     #0080h,IMR	; allow TINT1 interrupt 
	stm     #00c8h,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)	 0dB (analog input) 
				;		-6dB (analog output) 
	 
	ssbx	INTM		; global interrupt disable 
	stm     #0h, DXR1 
 
	ret 
 
;------------ END OF H/W INITIALIZATION SUBROUTINE--------------------- 
 
 
        .end