📄 dtmf_enc.txt
字号:
**************************************************************
* (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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -