Listing for MemOutput.asm
nolist
include 'DSPInit.asm'
;-----------------------------------------------------------------------------------
;Memory Map :
;- See how the C compiler organizes the data and variables
; and we will hand code the asm file generated
;
;- We will use the pre-defined sine table in ROM of the DSP56000
; which resides in Y:256 to Y:511 and
; we need the set Data Rom Enable, DE = 1, in the Operating Mode Register (OMR)
;-----------------------------------------------------------------------------------
ProgramStart EQU $0040
WAVE_TABLE_START EQU $0001
WAVE_TABLE_END EQU $0002
WAVE_TABLE_SIZE EQU $0003
WAVE_TABLE_INC EQU $0004
CYCLES EQU $0005
DELAY EQU $0006
AMPLIFICATION EQU $0007
ENVELOPE_TABLE_START EQU $0021
ENVELOPE_TABLE_END EQU $0022
ENVELOPE_TABLE_SIZE EQU $0023
ENVELOPE_TABLE_INC EQU $0024
;-----------------------------------------------------------------------------------
;Host Command Jump Table
;This is where we assign the interrupt vectors to the labels (addresses)
;of the various subroutines
;-----------------------------------------------------------------------------------
ORG P:Reset
JMP ProgramStart
ORG P:SSITxInt
JSR TxInterrupt
ORG P:SSITxEx
JSR SSIException
ORG P:HostCmdInt0
JSR hcOutputWave
ORG P:HostCmdInt13
JSR RxDataInterrupt
;-----------------------------------------------------------------------------------
;Main Program
;-----------------------------------------------------------------------------------
ORG P:ProgramStart
MOVEP #$0000,X:M_BCR ;no wait states
BCLR #M_HF3,X:M_HCR ;HF3 = 0 ie handshake to Mac indicating now not in play mode
;This is where we usually set up various constants in memory, initialize pointers, etc...
;that stay the same between running of the algorithm. REMEMBER that if you request a card
;that has your algorithm already loaded into it, code that lives here WILL NOT BE RUN again
;because the driver will just say heres your card and it's already loaded so don't put
;stuff here that changes after or while you run your algorithm. Put stuff like that in a
;host command called initialize or at the start of your generic do it host command. See
;the filter module in DSPWorkshop for an example.
;NOTE: The following lines set up the various on chip and on card hardware. Generally you should
;just cut and paste from here and/or DSPWorkshop to get things the way you want them. The order
;is important so don't change it unless you know what your doing. See the white binder for
;more info on all the card control logic and chapter 11 in the red book for the SSI etc...
;The I/O-interrupts on the 56k are quite complicated so mess with these initial 'magic' bit settings
;at your own risk and only after consulting the white binder and the red book.
MOVE #>$001377,X0 ;standard STEREO_ON_CARD_PLAYBACK (see white book)
MOVEM X0,P:CTL_LATCH ;set I/O control latch (see white book for details)
MOVEP #$2400,X:M_IPR ;set ssi ipl = 1, host port ipl = 0
MOVEP #$4006,X:M_CRA ;prescale = 1,const = 6,wl = 16 bits ie 44.1kHz
;sets SSI's on chip baud rate - see chap 11 in red book
BTST #4,X:M_SR ;read SSI SR to clear TUE bit so we don't get intrrupted??
MOVEP #0,X:M_TX ;send out zero sample, in conjunction with last line clrs TUE
MOVEP #$531E,X:M_CRB ;RIE = disable,RE = disable, TIE = enable,TE = enable
;SCKD = 0(ext clk),OF1 =1(stereo),OF0 = 0(ext clk)
MOVEP #$0005,X:M_PCDDR ;always!! set to this value so PAL's on card don't get
;conflicting pin directions on expansion port
MOVEP #$0001,X:M_PCD ;Oncard clock source,enable expansion port transmit
;it's a good idea to always enable the expansion port
;transmit so that someone using external DAC,I/O boxes etc...
;can get hold of the data your program generates
;The following three lines must be in this order and next to each other.
MOVEP #$01F8,X:M_PCC ;set port c to SSI mode, disable SCI
BSET #M_HCIE,X:M_HCR ;enable host command data interrupts
ANDI #$FC,MR ;enable interrupts ie set interrupt level to 0
;remember, reseting and loading code into the card
;starts you our at level 3 so you can set up the I/O
;stuff.
ORI #$FF,OMR ;set to mode 0 and set DE = 1 to use ROM table
ANDI #$0C,OMR ;
WtHost WAIT ;wait for mac/host to say start
JMP WtHost
;-----------------------------------------------------------------------------------
;
;-----------------------------------------------------------------------------------
hcOutputWave
BSET #M_HF3,X:M_HCR ;set HF3 to 1 to let host know code is running
BCLR #M_OF0,X:M_CRB ;OF0 = 0 external clock, OF0 = 1 internal clock
BCLR #M_OF1,X:M_CRB
BCLR #M_SCD0,X:M_CRB ;SCD0,SCD1,SCD2 must be set to 1
BSET #M_SCD1,X:M_CRB ;
BSET #M_SCD2,X:M_CRB ;
BCLR #M_SCKD,X:M_CRB ;SCKD = 0 external clock, SCKD = 1 internal clock
BSET #M_FSL,X:M_CRB
BSET #M_SYN,X:M_CRB
BCLR #M_GCK,X:M_CRB
BCLR #M_MOD,X:M_CRB
BSET #M_STE,X:M_CRB
BCLR #M_SRE,X:M_CRB
; BCLR #M_STIE,X:M_CRB
BCLR #M_SRIE,X:M_CRB
nolist
;Start of algorithm
MOVE X:WAVE_TABLE_INC,N0
MOVE X:ENVELOPE_TABLE_START,R1
MOVE X:ENVELOPE_TABLE_INC,N1
BSET #M_STIE,X:M_CRB ;switch DAC on
DO X:CYCLES,_EndCycle
MOVE X:(R1)+N1,X1
MOVE X:WAVE_TABLE_START,R0
DO X:WAVE_TABLE_SIZE,_EndSize
MOVE Y:(R0)+N0,X0
MPY X1,X0,A
DO X:DELAY,_EndDelay
MOVE A0,Y:OUTPUT
_EndDelay
NOP
_EndSize
NOP ;needed because addresses between "end of do loops" cannot be less than 2
_EndCycle
BCLR #M_STIE,X:M_CRB ;switch DAC off
BCLR #M_HF3,X:M_HCR ;clear HF3 to let host know end of code running
RTI
nolist
;-------------------------------------------------------------------------------------
;SSI transmit data
;-------------------------------------------------------------------------------------
TxInterrupt
JSET #M_HF3,X:M_HCR,Playing ;see if we think we are playing
MOVEP #0,X:M_TX ;play a zero
RTI
Playing
MOVEP Y:OUTPUT,X:M_TX ;send the sample to SSI port (DAC)
JCLR #1,X:M_PCD,Done ;if we just played a right sample
Done RTI
;-------------------------------------------------------------------------------------
;Handle a SSI transmit interrupt with underrun exception - tell Mac via HREQ interrupts
;-------------------------------------------------------------------------------------
SSIException
BTST #4,X:M_SR ;read SSI SR to clear TUE bit
MOVEP Y:OUTPUT,X:M_TX ;transmit data to DAC (also needed to clear TUE)
RTI
;-------------------------------------------------------------------------------------
;Interrupt to receive data from host to specific locations of X or Y memory
;-------------------------------------------------------------------------------------
RxDataInterrupt
LoopRxa JCLR #M_HRDF,X:M_HSR,LoopRxa ;wait till MAC has sent the address over
MOVEP X:M_HRX,X0 ;read the xySelect into X0
LoopRxb JCLR #M_HRDF,X:M_HSR,LoopRxb ;wait till MAC has sent the address over
MOVEP X:M_HRX,R0 ;read the xyAddress into R0
LoopRxc JCLR #M_HRDF,X:M_HSR,LoopRxc ;wait till MAC has sent the value over
MOVEP X:M_HRX,Y0 ;read the xyValue into Y0
CLR B
ADD X0,B
JNE RxY
RxX MOVE Y0,X:(R0) ;put value into specified location in X memory
RTI
RxY MOVE Y0,Y:(R0) ;put value into specified location in Y memory
RTI
END