;************************************************************************* ;* DSP56002EVM 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 EVM56002. 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 'equ002.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 $3f00 ; Address for private storage buflen equ 40 ; 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 ; NOTE: This code is commented out because the 56002EVMs do not ; have both crystals installed (like Jake's awesome board does) 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 a,y:csconf+3 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: ; SSI Tx - Transmit interrupt used for CODEC communication (does receive too) ; SSI Te - SSI transmit with error - does nothing but acknowledge error ; SSI interface interrupts org p:i_ssitd ; Trap SSI transmit interrupts: movep y:(r7)+,x:m_tx ; - Transmit from y:(r7) movep x:m_rx,x:(r7) ; - Receive to x:(r7) org p:i_ssitde ; Trap SSI transmit (error): movep x:m_sr,x:m_tx ; - Clear TUE in SSI:tx to ack error org p:$0 jmp start org p:$40 start movep #$3e000f,x:m_pll ; Set PLL to 4MHz * 16 = 64MHz ; Disable CKOUT to minimize RFI movep #$0001,x:m_bcr ori #$3,mr ; Disable interrupts 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 ; OK, here is where we are finished with initialization code and ; we can jump out and process our samples. 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 (SSI) ; = 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 movep #$0000,x:m_pcc ; Turn OFF SSI for now movep #$0014,x:m_pcddr ; GPIO pins are outputs movep #$0000,x:m_pcd ; D/_C low and RESET low ; Wait about 50ms after RESET goes low. ; (1000*1000 * 2 clock cycles per NOP / 40MHz = 0.050 seconds) do #1000,_d2 do #1000,_d1 nop _d1 nop _d2 ; Now, bring CODEC out of RESET. bset #4,x:m_pcd ; RESET high ; Setup SSI port to SEND clock and frame sync movep #$4f05,x:m_cra ; 16-bit word, 4 words per frame movep #$3b30,x:m_crb ; generate SCLK and FS for CS4215 movep #$01e0,x:m_pcc ; Port C: SSI=ON, SCI=OFF ; 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 SSI to _RECEIVE_ clock and FrameSync movep #$0000,x:m_pcc ; Turn off SSI while reprogramming movep #$4305,x:m_cra ; 16-bit, 4 frames movep #$3b00,x:m_crb ; RECEIVE SCLK and FS movep #$01e0,x:m_pcc ; TXD,RXD,SC2,SCK,SRD,STD bset #2,x:m_pcd ; D/_C high (data mode on CS4215) _waitsyn jclr #m_tde,x:m_sr,_waitsyn jset #m_tfs,x:m_sr,_frmsync movep x:m_rx,x:m_tsr jmp _waitsyn _frmsync do #4-1,_flshrm jclr #m_tde,x:m_sr,* movep y:(r7)+,x:m_tx movep x:m_rx,x:(r7) _flshrm ; Enable SSI transmit interrupts movep #$3000,x:m_ipr ; Set interrupt priority level movep #$7b00,x:m_crb ; Enable SSI interrupts andi #$fc,mr ; Enable interrupts in general rts ; outblk ; ; Outputs one 256 bit block to the CODEC (and fills the other time ; slots with nothing) ; - 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_sr,* ; CODEC. This is the actual movep x:m_rx,x:(r0) ; data time slot. It also reads movep y:(r0)+,x:m_tx ; data to the receive buffer. _l1 do #16-4,_l2 ; Send nothing to remaining jclr #m_tde,x:m_sr,* ; timeslots. movep a1,x:m_tsr _l2 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