;************************************************************************* ;* DSP56302EVM Core Utility * ;*-----------------------------------------------------------------------* ;* Jake Janovetz * ;* * ;* This work is based on code written for the DSPCARD4 by the Alef Null * ;* group. I apologize, but I've lost track of modifications. * ;* * ;*-----------------------------------------------------------------------* ;* * ;* This file should be included in any file that uses the 56302EVM. It * ;* contains code to initialize the board and setup the CODEC. It also * ;* contains the interrupt vectors for handling CODEC I/O. After * ;* startup, this code jumps to 'main' which must be included in the * ;* user's code. See "THRU.ASM" as an example of how to use this file. * ;* * ;* The user must also define "SAMPLERATE" as the sampling rate to * ;* initialize the CODEC. Valid rates are: 8, 9.6, 16, 27.42857, 32, * ;* 48 kHz. * ;* * ;************************************************************************* nolist include 'equ302.inc' list MONO equ $000000 ; used in initcodec STEREO equ $000400 ; used in initcodec HEADOUT equ $8000 ; used in setdts LINEOUT equ $4000 ; used in setdts SPKROUT equ $0040 ; used in setdts LINEIN equ $0000 ; used in setdts MICIN equ $1000 ; used in setdts topdata equ $1b00 ; Address for private storage buflen equ 16 ; Sample buffer length (in samples) ;************************************************************************* ; initcodec (MACRO) ;************************************************************************* ; Remark - high pass filter enabled ; Macro that calls 'initcs' through the jump table ; - Calls an OS routine that initializes the CODEC for operation ; - 'fs' determines the sampling rate (from below) ; - 'aural' determines whether the CODEC samples in stereo or mono ; ; Bit (TimeSlot 2) XTAL1 XTAL2 ; 5 4 3 24.5786MHz 16.9344MHz ; ; 0 0 0 8 kHz 5.5125 kHz ; 0 0 1 16 kHz 11.024 kHz ; 0 1 0 27.42857kHz 18.9 kHz ; 0 1 1 32 kHz 22.05 kHz ; 1 0 0 N/A 37.8 kHz ; 1 0 1 N/A 44.1 kHz ; 1 1 0 48 kHz 33.075 kHz ; 1 1 1 9.6 kHz 6.615 kHz ; initcodec macro fs,aural ; Place XTAL number in TimeSlot 3 ; Also set CS4215 to generate FSYNC and FS if (fs==8)|(fs==9.6)|(fs==16)|(fs==27.42857)|(fs==32)|(fs==48) move #>$220000,x1 else if (fs==5.5125)|(fs==11.025)|(fs==18.9)|(fs==22.05)|(fs==37.8)|(fs==44.1)|(fs==33.075)|(fs==6.615) move #>$120000,x1 else fail "Sample rate: fs kHz not supported" endif endif ; Place Data Conversion Frequency Selection in TimeSlot 2 ; if (fs==8)|(fs==5.5125) move #>(aural|$108000),x0 else if (fs==16)|(fs==11.025) move #>(aural|$108800),x0 else if (fs==27.42857)|(fs==18.9) move #>(aural|$109000),x0 else if (fs==32)|(fs==22.05) move #>(aural|$109800),x0 else if (fs==37.8) move #>(aural|$10a000),x0 else if (fs==44.1) move #>(aural|$10a800),x0 else if (fs==48)|(fs==33.075) move #>(aural|$10b000),x0 else if (fs==9.6)|(fs==6.615) move #>(aural|$10b800),x0 endif endif endif endif endif endif endif endif clr a x0,y:csconf ; Move control information to move x1,y:csconf+1 ; CS control block buffer move a,y:csconf+2 ; Clear timeslots 5-8 move x0,y:csconf+3 ; THIS IS A BUG, BUT SEEMS TO ; WORK. I DON'T UNDERSTAND. jsr initcs endm ;************************************************************************* ; setdts (MACRO) ;************************************************************************* ; Macro to fill an output circular buffer with Data Time Slot ; information for the CS4215 CODEC ; ; reg = User program's circular buffer register ; buflen = Length of circular buffer ; clear = 1 if output data is to be cleared, 0 to leave it unchanged ; output = Any combination of: HEADOUT, LINEOUT, or SPKROUT or'ed ; input = Either LINEIN or MICIN ; gainl = Gain on Left input (0-22.5dB) ; gainr = Gain on Right input (0-22.5dB) ; attnl = Attenuation on Left output (0-94.5dB) ; attnr = Attenuation on Right output (0-94.5dB) ; setdts macro reg,buflen,cler,input,gainl,gainr,output,attnl,attnr move #>(output|(@cvi(attnl/1.5)<<8)|@cvi(attnr/1.5))<<8,x0 clr a #>(input|(@cvi(gainl/1.5)<<8)|@cvi(gainr/1.5)|$f0)<<8,x1 move (reg)+ do #buflen,_setdts1 if cler move a,y:(reg)+ move a,y:(reg)+ else move (reg)+ move (reg)+ endif move x0,y:(reg)+ move x1,y:(reg)+ _setdts1 move (reg)- endm ;************************************************************************* ; waitdata (MACRO) ;************************************************************************* ; Macro to wait 'length' number of samples to come in from the CODEC ; ; reg = User program's circular buffer register ; buflen = Length of circular buffer ; length = Number of samples to wait for ; waitdata macro reg,buflen,length _waitloop wait move r7,a move reg,x0 sub x0,a #>length*4,x0 jpl <_nowrap move #>buflen*4,x1 add x1,a _nowrap cmp x0,a jlo <_waitloop endm ; Interrupts to respond to: ; ESSI Tx - Transmit interrupt used for CODEC communication (does receive too) ; ESSI Te - SSI transmit with error - does nothing but acknowledge error ; ESSI interface interrupts org p:I_SI0TD ; Trap SSI transmit interrupts: movep y:(r7)+,x:M_TX00 ; - Transmit from y:(r7) movep x:M_RX0,x:(r7) ; - Receive to x:(r7) org p:I_SI0TDE ; Trap SSI transmit (error): movep x:M_SSISR0,x:M_TX00 ; - Clear TUE in SSI:tx to ack error org p:$200 start ; movep #$040003,x:M_PCTL movec #0,sp move #0,omr move #bufr+2,r7 move #buflen*4-1,m7 move #bufr,r3 ; Sample buffer space start address move #buflen*4-1,m3 ; and length setdts r3,buflen,1,MICIN,0,0,LINEOUT|HEADOUT,0,0 initcodec SAMPLERATE,STEREO jmp main ;************************************************************************* ; initcs ;************************************************************************* ; This subroutine initializes the CODEC. It should be called only once. ; It will typically be called from within the 'initcodec' macro. ; ; Configuration of Port C (ESSI) ; = Port C RXD = bit 0 (unused) ; = Port C TXD = bit 1 (unused) ; CS D/C = Port C SCLK = bit 2 (GPIO) ; = Port C SC0 = bit 3 (unused) ; CS RESET = Port C SC1 = bit 4 (GPIO) ;Frame Sync = Port C SC2 = bit 5 ; CS SCLK = Port C SCK = bit 6 ; CS SDOUT = Port C SRD = bit 7 ; CS SDIN = Port C STD = bit 8 ;************************************************************************* initcs ori #$03,mr movep #>$000000,x:M_PCRC ; Turn OFF ESSI0 for now movep #>$000003,x:M_PRRC ; SC00,SC01 are GPIO (output) movep #>$000000,x:M_PDRC ; D/_C low and RESET low ; Wait about 50ms after RESET goes low. ; (4000*1000 * 1 clock cycles per NOP / 66MHz = 0.060 seconds) do #2000,_d2 do #1000,_d1 nop _d1 nop _d2 ; Now, bring CODEC out of RESET. movep #>$000001,x:M_PDRC ; RESET high ; Setup ESSI port to SEND clock and frame sync movep #>$10380f,x:M_CRA0 ; 16-bit words, Enable prescalar ; Left align, 16 words per frame movep #>$033130,x:M_CRB0 ; Generate SCLK and FS for CS4215 movep #>$00003c,x:M_PCRC ; Enable ESSI0 ; Now, send control blocks until CLB goes low signifying proper transition ; to Data Mode move #csconf,r0 move #3,m0 _wakeup jsr outblk move x:temp+2,x0 jset #18,x0,_wakeup ; Set CLB=1 bset #18,y:csconf+0 do #20,_clbwait jsr outblk nop _clbwait move #-1,m0 ; Reconfigure ESSI to _RECEIVE_ clock and FrameSync movep #>$000000,x:M_PCRC ; Turn OFF ESSI0 while reprogramming movep #>$10380f,x:M_CRA0 ; 16-bit words, Enable prescalar ; Left align, 4 words per frame movep #>$033100,x:M_CRB0 ; Let CS4215 generate SCLK and FS movep #>$00003c,x:M_PCRC ; Enable ESSI0 movep #>$000003,x:M_PDRC ; D/_C high (data mode on CS4215) _waitsyn jclr #M_TDE,x:M_SSISR0,_waitsyn jset #M_TFS,x:M_SSISR0,_frmsync movep x:M_RX0,x:M_TSR0 jmp _waitsyn _frmsync do #4-1,_flshrm jclr #M_TDE,x:M_SSISR0,* movep y:(r7)+,x:M_TX00 movep x:M_RX0,x:(r7) _flshrm ; Enable ESSI0 transmit interrupts movep #>$00000a,x:M_IPRP ; Set ESSI0 IPL to 2, HI to 2. movep #>$473100,x:M_CRB0 ; Enable ESSI0 Interrupts andi #$fc,mr ; Enable interrupts in general rts ; outblk ; ; Outputs one 64 bit block to the CODEC ; - r0 must contain the address of the buffers (y:transmit, x:receive) ; - m0 must contain the modulous of that buffer (ie size-1) ; outblk do #4,_l1 ; Send out four words to the jclr #M_TDE,x:M_SSISR0,* ; CODEC. This is the actual movep x:M_RX0,x:(r0) ; data time slot. It also reads movep y:(r0)+,x:M_TX00 ; data to the receive buffer. _l1 rts ;************************************************************************* ;***************** OPERATING SYSTEM DATA STORAGE ************************* ;************************************************************************* ;* Here, we reserve space for two things. Both of these will reside in * ;* high memory space. This space CANNOT be used by the user. The user * ;* is free to use any memory from x:$0000 - x:topdata-1 and likewise in * ;* y memory. * ;* * ;* One is the sample buffer. Samples are received and transmitted on * ;* interrupts to and from this buffer. * ;* * ;* The second thing we allocate space for is a temporary buffer for data * ;* coming in and going out of the SSI from/to the CODEC during * ;* initialization. * ;************************************************************************* org x:topdata bufr dsm buflen*4 temp dsm 4 org y:topdata dsm buflen*4 csconf dsm 4