;************************************************************************** ;** DUAL-TONE MODULATED FREQUENCY GENERATOR FOR THE 'C50 ** ;** (DTMF) ** ;************************************************************************** ;** Texas Instruments, Inc. ** ;** App. by: Gerald Capwell ** ;** Date: Nov 18th, 1994 ** ;************************************************************************* ; ;The code below was written using the 'C5x DSK Debugger and 'C5x DSK board. ;Code is loaded into the DSK using the 'C5x debugger interface or the DSK ;Loader. Upon execution, the DSK output will generate a 2-tone (DTMF) ;frequency corresponding to the telephone keypad digits found at the label ;'NUMBR'. Digits 1-9 are generated using 1-9. Digits *,0,# are generated ;using '0ah', '0bh' and '0ch' repectively. See the keypad below: ; ; Column ; 1 2 3 ; ; +-----------------------+ ; 1 | 1 | 2 | 3 | ; | | | | ; +-------+-------+-------+ ; 2 | 4 | 5 | 6 | ; R | | | | ; O +-------+-------+-------+ ; W 3 | 7 | 8 | 9 | ; | | | | ; +-------+-------+-------+ ; 4 | * _| 0 _| # _| ; | |a| |b| |c| ; +-----------------------+ ; ;Each number to be dialed must be followed by a comma. The phone number must ;end with a '-1'. One second delays can be inserted between digits for a ;pausing effect. Here is an example phone number: ; ; NUMBR .word 1,7,1,3,2,7,4,2,3,2,3,0,0,1,0bh,2,3,-1 ; \___________________/ \ / \_______/ \/ ; | | | Stop word ; Phone number Two | ; (1-713-274-2323) second | ; pause | ; password, ; etc. ; (1023) ; ; .mmregs .ds 0f00h ; Note: 1. Master clock = 10.000 MHz ; 2. The transmit and receive sections are in synchronous mode. ; Tone generation is synced on the receive interrupt. ; ; ; ** These words must be on a boundary. Do not insert anything before these ROWS .word 00000h ; Offset cos(x) (Coefficient) .word 00000h ; sin(x) .word 00000h ; Y(n-1) .word 07ae1h ; row 1 cos(x) (Coefficient) .word 011ebh ; sin(x) .word 00000h ; Y(n-1) .word 079c2h ; row 2 cos(x) (Coefficient) .word 013bch ; sin(x) .word 00000h ; Y(n-1) .word 07860h ; row 3 cos(x) (Coefficient) .word 015c2h ; sin(x) .word 00000h ; Y(n-1) .word 076b8h ; row 4 cos(x) (Coefficient) .word 017ech ; sin(x) .word 00000h ; Y(n-1) COLS .word 00000h ; Offset .word 00000h .word 00000h .word 0698bh ; cos(x) (Coefficient) .word 02435h ; column 3 sin(x) .word 00000h ; Y(n-1) .word 06d86h ; cos(x) (Coefficient) .word 0211fh ; column 2 sin(x) .word 00000h ; Y(n-1) .word 070cdh ; cos(x) (Coefficient) .word 01e3fh ; column 1 sin(x) .word 00000h ; Y(n-1) ;--------------------------------------------------------- TA .word 18 ; RA .word 18 ; ; TB .word 18 ; Conversion frequency = 7716hz RB .word 18 ; AIC_CTR .word 08h ; xmit and rcv are synchronous TIME .word 0d60h ; pulse duration TIMER .word 00000h .ds 1000h NUMBR .word 02h,07h,06h,05h,04h,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1 ;*************************************************************** ; Set up the ISR vector * ;*************************************************************** .ps 080ah ; rint: B RECEIVE ;0A; Serial port receive interrupt RINT. xint: B TRANSMIT ;0C; Serial port transmit interrupt XINT. ; ;***************************************************************** ; TMS32C05X INITIALIZATION * ; * ;***************************************************************** .ps 0a00h .entry SETC INTM ; Disable interrupts LDP #0 ; Set data page pointer OPL #0834h,PMST ; OR the status register LACC #0 SAMM CWSR ; Set software wait state to 0 SAMM PDWSR ; ; Reset AIC by writing to PA2 (address >52) to DSK SPLK #022h,IMR ; Using XINT syn TX & RX CALL AICINIT ; initialize AIC and enable interrupts ; CLRC OVM ; OVM = 0 normal accumulator overflow SPM 0 ; PM = 0 no shift when transferring to ALU LAR AR0,#NUMBR ; Phone number pointer NEXTNUM LDP #0 SPLK #03h,INDX ; set index register to 3 SPLK #02h,IMR ; disable receive interrupt LAR AR1,#ROWS ; init column pointer LAR AR2,#COLS ; init row pointer CALL UNPACK ; decipher row and column for each digit CALL PAUSESH ; pause between digits LACC #02h ; SAMM INDX ; set index register to 2 ADD #10h SAMM IMR ; set rcv interrupt CLRC INTM ; enable interrupts WAIT LACL TIMER ; check timer BCND NEXTNUM,EQ ; If timer is zero get another digit B WAIT END CLRC INTM ; enable interrupts B END ; done. ;------- end of main program ----------; ; ;-------------------------- RECIEVER ISR ---------------------------------- ; RECEIVE: CLRC INTM ; enable interrupts LDP #TIMER MAR *,AR1 ; AR1 is current AR register (ROWS) ZAP ; ACC => 0 EXAR ; ACCB => 0 LAMM AR1 ; Load address in AR1 (COSx) CALL GENR8R EXAR ; load ACCB with ACC (value of first tone) MAR *,AR2 LAMM AR2 ; Load address in AR2 (COSx) CALL GENR8R ADDB ; Add the ACCB (value of second tone) RPT #16 ; move to low word (reduce amplitude also) SFR AND #0FFFCh,0 ; bit 0 & 1 have to be 0 for AIC SAMM DXR ; send it to AIC thru serial port LACL TIMER ; Load timer value SUB #01h ; Decrement timer SACL TIMER ; Save the timer. LAMM DRR ; get junk to enable next interrupt RETE ;------------------------- Tone Generator -------------------------------- GENR8R: MAR *0+ ; Increment pointer. Points to Y(n-1)) SAMM BMAR ; save address of COSX to BMAR MPY #0 ; clear P register (TREG0 x 0 -> P) LACC *-,15 ; load ACChi with Y(n-1) NEG ; -ACC ==> ACC MADD * ; coeff*sinx=P and ACC= -y(n-1) APAC ; coeff*sinx - y(n-1) APAC ; 2(coeff*sinx)- y1 SACH *-,1 ; shift one & store ACC_hi ->new sinx value RET ;---------------------------- end of ISR ------------------------ UNPACK: MAR *,AR0 LDP #TIMER SPLK #0,TIMER ; reset timer value = 0 LACC *+,0,AR1 ; get digit BCND PAUSELG,EQ ; Zero then pause ; BCND END,LT ; Negative then end BCND REPETE,LT NEXTR: SUB #0003h ; subtract three from digit MAR *0+ ; increment row pointer by three BCND NEXTR,GT ; subtract again MAR *,AR2 ; init column pointer NEXTC: MAR *0+ ; increment column pointer ADD #01h ; add 1 BCND NEXTC,LEQ ; increment column pointer until ACC=0 LACL TIME ; Load time value SACL TIMER ; Reset timer for pulse duration RET REPETE: LAR AR0,#NUMBR B PAUSELG ;----------------------------- Pause generator ---------------------- PAUSESH LACC #06h,15 ; .1 apprx. second pause (50ns cycle) B LOOP PAUSELG LACC #0cah,15 ; load ACC with value to decrement ADD #0b9ah,4 ; 1 second pause (50ns cycle) LOOP SUB #01h ; 1 cycle BCND LOOP,GT ; +2 cycles = 3 cycles total RET ; ;-------------------------------------------------------------------- ;-------------------------- Transmit ISR -------------------------- ; ;transmit interrupt is disabled ; TRANSMIT: RETE ;---------------------------- end of ISR ------------------------ ; ;***************************************************************** ; DESCRIPTION: This routine initializes the 'C50 serial port * ; and the TLC320C40's (AIC) TA,RA,TB,RB and * ; control registers * ;***************************************************************** ; AICINIT: SPLK #20h,TCR ; To generate 10 MHz from Tout SPLK #01h,PRD ; for AIC master clock MAR *,AR0 LACC #0008h ; Non continuous mode SACL SPC ; FSX as input LACC #00c8h ; 16 bit words SACL SPC LACC #080h ; Pulse AIC reset by setting it low SACH DXR SACL GREG LAR AR0,#0FFFFh RPT #10000 ; and taking it high after 10000 cycles LACC *,0,AR0 ; (.5ms at 50ns) SACH GREG ;------------------------ LDP #TA ; SETC SXM ; LACC TA,9 ; Initialize TA and RA register ADD RA,2 ; CALL AIC_2ND ; ;------------------------ LDP #TB LACC TB,9 ; Initialize TB and RB register ADD RB,2 ; ADD #02h ; CALL AIC_2ND ; ;------------------------ LDP #AIC_CTR LACC AIC_CTR,2 ; Initialize control register ADD #03h ; CALL AIC_2ND ; RET ; AIC_2ND: LDP #0 ; Data page point is 0 (MM regs) SACH DXR ; send ACChi 00 CLRC INTM ; enable interrupts IDLE ; wait for interrupt ADD #6h,15 ; 0000 0000 0000 0011 XXXX XXXX XXXX XXXX b SACH DXR ; send ACChi to initiate secondary protocol IDLE ; wait for interrupt SACL DXR ; send the T register data IDLE ; wait for interrupt LACL #0 ; clear ACClo SACL DXR ; send another to make sure 1st word got sent IDLE ; wait for interrupt SETC INTM RET ; .end