📄 tonegen1.asm
字号:
;
; (C) Copyright 1997 White Mountain DSP, Inc. All rights reserved.
; Use of copyright notice is precationary and does not imply publication.
;
; ======== ToneGen.asm ========
;
; Without any audio input to the AIC, this program will generate a
; Sine wave output using a second-order digital sinusoidal
; oscillator algorithm. The algorithm will calculate the sine wave
; data and send it to the AIC using the transmit interrupt of the
; synchronous serial port.
;
.title "Sine Wave Generator"
* .include "Dsp_vect.h"
.include Dsp_init.h
.mmregs
EN_XINT .set 010h
EN_TXRXINT .set 020h
; enable the XINT interrupts
CLR_XINT .set 02fh
; mark the interrupt as serviced
SSPCFG1 .set 04000h ; settings for the SSPCR (in reset)
SSPCFG2 .set 04C30h ; settings for the SSPCR (out of reset)
; Tx interrupt fires when Tx FIFO (4-deep) empty
.data ; starting address for this section is
; 300h in Data Space
cinfo .word 0 ; cinfo variable
data2aic .word 0 ; data to be sent to AIC
;
; ======== COEFFS ========
; The table that follows supplies the coefficients and intial
; conditions for the difference equation of the digital sinusoidal
; oscillator.
;
; The basic formulas for a second-order digital sinusoidal oscillator
; are:
; Difference Equation: y(n) = coeff*y(n-1) - y(n-2)
; Initial Conditions: y(-1) = 0
; y(-2) = -A*sin(w0)
; where
; coeff = 2*cos(w0)
; w0 = 2pi*f/fs
; and
; A = desired amplitude of sine wave
; f = desired frequency of sine wave
; fs = sampling frequency
;
; For more on Digital Sinusoidal Oscillators see:
;
; Proakis, J., Manolakis, D. (1988) Introduction to Digital Signal
; Processing, pp. 373-376, MacMillan, New York.
;
;
; Due to the algorithm used to generate the sine wave data the formulas
; for the coefficient and the intial conditions change slightly. They
; become:
; coeff = cos(w0)*32768
; y(-2) = -A*sin(w0)*32768
;
; The format of the sections that follow are:
; .word coeff ;where coeff = cos(w0)*32768
; .word y(-1) ;where y(-1) = 0
; .word y(-2) ;where y(-2) = -A*sin(w0)*32768
;
; Each section starts with a comment stating which values were used
; for A, f, and fs, followed by the three calculated values of coeff
; y(-1) and y(-2). It is important to note that only one section can
; be used (un-commented) at a time.
;
; There are 2 limitations to this application:
;
; 1) Due to the fact that we are using only a second-order
; oscillator the frequency observed on the output of the
; AIC will not match exactly with the value of f that was
; used to calculate the coefficients. If more precision is
; required, a higher order oscillator may be used.
;
; 2) The default state of the AIC at power-up is for a sampling
; rate of 16kHz and a low-pass filter on the output with its
; -3dB point located at 7.2kHz. Therefore as f increases
; towards the -3dB point of the filter the amplitude of the
; generated sine wave will decrease. If increased bandwidth
; is desired then the AIC can be setup to increase the sampling
; rate and the frequency at which the -3dB point occurs in the
; filter. See the TLC320AC02C Data Manual (SLAS084B) for further
; information.
;
; NOTE:
; It is extemely important that when the Interrupt Mask register is setup
; that the TXRXINT interrupt (for the Async Serial Port) be enabled in
; addition to any interrupts being used by the user's program. If the
; TXRXINT is not enabled then the monitor program will not function properly.
; Just uncomment a set of COEFFS to use them in your calculations.
; Default COEFFS are for a 1kHz sine wave
;COEFFS ; for f = 500Hz, A = .25, fs = 16000
; .word 32138
; .word 0
; .word -1598
;COEFFS ; for f = 1kHz, A = .25, fs = 16000
; .word 30274
; .word 0
; .word -3135
;COEFFS ; for f = 1.5kHz, A = .25 fs = 16000
; .word 27246
; .word 0
; .word -4551
;COEFFS ; for f = 2kHz, A = .25 fs = 16000
; .word 23170
; .word 0
; .word -5793
COEFFS ; for f = 2.5kHz, A = .25 fs = 16000
.word 18205
.word 0
.word -6811
;COEFFS ; for f = 3kHz, A = .25 fs = 16000
; .word 12540
; .word 0
; .word -7568
;COEFFS ; for f = 3.5kHz, A = .25 fs = 16000
; .word 6393
; .word 0
; .word -8035
;COEFFS ; for f = 4kHz, A = .25 fs = 16000
; .word 0
; .word 0
; .word -8192
;COEFFS ; for f = 4.5kHz, A = .25 fs = 16000
; .word -6393
; .word 0
; .word -8035
;COEFFS ; for f = 5kHz, A = .25 fs = 16000
; .word -12540
; .word 0
; .word -7568
;COEFFS ; for f = 5.5kHz, A = .25 fs = 16000
; .word -18205
; .word 0
; .word -6811
;COEFFS ; for f = 6kHz, A = .25 fs = 16000
; .word -23170
; .word 0
; .word -5793
;COEFFS ; for f = 6.5kHz, A = .25 fs = 16000
; .word -27246
; .word 0
; .word -4551
;COEFFS ; for f = 7kHz, A = .25 fs = 16000
; .word -30274
; .word 0
; .word -3135
;COEFFS ; for f = 7.5kHz, A = .25 fs = 16000
; .word -32138
; .word 0
; .word -1598
;
; ======== vectors ========
;
; This is the interrupt vector table that tells the DSP where
; the various ISRs are located that will be serviced during the
; programs execution. Since we will be servicing the
; synchronous serial port TRANSMIT interrupt in this program, we
; place a branch instruction at location 0Ah that points to the
; xmitIsr function. All other interrupt vectors branch to the
; the reset vector at location 0 which will effectively restart
; the monitor.
;
.sect "vectors"
b start
b 0000h ;02; restart the monitor
b 0000h ;04; restart the monitor
b 0000h ;06; restart the monitor
b 0000h ;08; restart the monitor
b xmitIsr ;0a; restart the monitor
b 0000h ;0c; restart the monitor
.space 2*16 ;0e; Reserved Space
b 0000h ;10; restart the monitor
b 0000h ;12; restart the monitor
b 0000h ;14; restart the monitor
b 0000h ;16; restart the monitor
b 0000h ;18; restart the monitor
b 0000h ;1a; restart the monitor
b 0000h ;1c; restart the monitor
b 0000h ;1e; restart the monitor
b 0000h ;20; restart the monitor
b 0000h ;22; restart the monitor
b 0000h ;24; restart the monitor
.space 2*16 ;26; Reserved Space
b 0000h ;28; restart the monitor
b 0000h ;2a; restart the monitor
b 0000h ;2c; restart the monitor
b 0000h ;2e; restart the monitor
b 0000h ;30; restart the monitor
b 0000h ;32; restart the monitor
b 0000h ;34; restart the monitor
b 0000h ;36; restart the monitor
b 0000h ;38; restart the monitor
b 0000h ;3a; restart the monitor
b 0000h ;3c; restart the monitor
b 0000h ;3e; restart the monitor
;
; ======== start ========
;
; This is the main entry point for the program and is responsible
; for configuring the DSP before allowing the SSP interrupts
; to be serviced.
;
.text
start: setc intm ; INTM = 1, disable global interrupts
clrc cnf ; CNF = 0, map DARAM to data space (0x200-0x2ff)
setc sxm ; SXM = 1, use sign extension mode
clrc ovm ; OVM = 0, results overflow normally in accumulator
spm 1 ; set ALU to handle fractional multiplication
ldp #06h ; use the DARAM block with Direct Addressing
splk #0000h, data2aic ; data2aic = 0
; set all wait-states to zero
splk #0000h, cinfo ; cinfo = 0
; out cinfo, WSGR ; Set all wait states to zero
; setup the Sync Serial Port
splk #SSPCFG1, cinfo ; place the ssp into reset and set it
; out cinfo, SSPCR ; up for continuous mode operation.
splk #SSPCFG2, cinfo
; out cinfo, SSPCR ; take the ssp out of reset
; reset the AIC so any old settings get wiped out
; in cinfo, IOSR ; read IOSR
lacl cinfo ; acc = cinfo
and #0fff7h ; make IO3 = 0
sacl cinfo ; store acc to cinfo
; out cinfo, IOSR ; write to IOSR, put AIC in reset
; in cinfo, IOSR ; read IOSR
lacl cinfo ; acc = cinfo
or #08h ; make IO3 = 1
sacl cinfo ; store acc to cinfo
; out cinfo, IOSR ; write to IOSR, take AIC out of reset
; unmask required interrupts
ldp #0h ; set data page pointer
splk #EN_XINT | EN_TXRXINT, IMR ; enable the XINT interrupts
; also enable the TXRXINT (Async Serial Port)
; interrupt (required by the monitor)
clrc intm ; enable global interrupts
;loop: idle ; enter loop and allow DSP to process
; b loop ; XINT interrupts
; ======== xmitIsr ========
;
; This is the interrupt service routine called when the transmit
; FIFO of the F206 is empty (something needs to be sent). It
; will write data to the transmit FIFO which will send it back out to the
; TLC320AC02C audio codec. Also this is the routine that will generate
; the actual sine wave data.
;
lar ar3, #900h
xmitIsr:
ldp #06h ; set data page pointer
; start calculating sine wave data
lar ar0, #(COEFFS+2) ; ar0 = COEFFS+2
lar ar2, #0000h ; ar2 = 0
mar *, ar2 ; ARP = ar2
lacc #0 ; acc = 0
mar *0+ ; ar2 += ar0
sub *-, 15 ; ah = -(1/2)*y(n-2)
dmov * ; y(n-2) = y(n-1)
lt *- ; TREG = y(n-1)
mpy *+ ; PREG = coeff*y(n-1)
apac ; ah = coeff*y(n-1) - (1/2)*y(n-2)
sfl ; ah = 2*coeff*y(n-1) - (1/2)*y(n-2)
sach *,ar3 ; y(n-1) = ah
sach *+
sach data2aic ; data2aic = y(n)
; sine wave calculation complete
lacl data2aic ; acc = data2aic
and #0fffch ; need to keep control bits set to 0
sacl data2aic ; store acc to data2aic
; out data2aic, SDTR ; send the sine wave data to the AIC
ldp #0h ; set data page pointer
clrc intm ; re-enable global interrupts
splk #CLR_XINT, IFR ; mark the interrupt as serviced
lar ar0,#1000h
cmpr 01 ;AR(arp)<ar0? Y:TC=1
bcnd xmitIsr,TC
loop: nop ; enter loop and allow DSP to process
b loop ; XINT interrupts
ret ; return to caller
.end ; signify end of program
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -