page 132,60 ;**************************************************************************** ; The program for Digital Processing of Transcranial Doppler Signal ; with DSP56002EVM module ; written by Wojciech Zabolotny (wzab@ipe.pw.edu.pl) ; This is a free software, however some parts use the code ; which is copyrighted by Motorola . ;****************************************************************************** ;**************************************************************************** ; All information about DSP56002 features has been obtained from the books ; "DSP 56002 Digital Signal Processor User's Manual" and ; "DSP56000 Digital Signal Processor Family Manual" included with ; the DSP56002EVM (also available in the Internet at: ; http://www.mot.com/pub/SPS/DSP/LIBRARY/56000/FM_REV0/COMPLETE.PDF ; http://www.mot.com/pub/SPS/DSP/LIBRARY/56002/UM_REV1/COMPLETE.PDF ) ; ; The SSI and codec initialization routines are based on "ada_init.asm" ; and "txrx_isr.asm" ; copyrighted by MOTOROLA 1995, Semiconductor Products Sector, ; Digital Signal Processing Division ; which can be found in the evm27.zip file, available in the Internet ; at: http://www.mot.com/pub/SPS/DSP/software/dr_bub/evm27.zip ;**************************************************************************** ;Two following macros are used in subroutines. They move the return address ;from the hardware stack to the software stack, to avoid the stack overflow ; ejsr MACRO move ssh,x:(r7)+ ENDM erts MACRO move x:-(r7),ssh nop rts ENDM ;Miscelaneous on-chip hardware addresses PLL equ $FFFD BCR EQU $FFFE ;Bus control register IPR EQU $FFFF ;Interrupt priority register ;Addresses associated with port C PCC EQU $FFE1 ;Port C control register PCDDR EQU $FFE3 ;Port C data direction register PCD EQU $FFE5 ;Port C data register PCC_CW EQU $01EB ;Configuration of port C ;Addresses associated with Serial Communication Interface (SCI) SCR EQU $FFF0 ;SCI interface control register SCCR EQU $FFF2 ;SCI clock control register SRX EQU $FFF4 ;SCI receive register STX EQU $FFF4 ;SCI transmit register SSR equ $FFF1 ;SCI status register ;Addresses associated with Synchronous Serial Interface (SSI) CRA equ $FFEC ;SSI control register A [R/W] CRB equ $FFED ;SSI control register B [R/W] TSR equ $FFEE ;SSI time slot register [W] SSISR equ $FFEE ;SSI status register [R] RX equ $FFEF ;SSI receive data register [R] TX equ $FFEF ;SSI transmit data register [W] ;Definitions associated with TIMER TCSR EQU $FFDE TCR EQU $FFDF org x:$0 org xh:$2800 ; Buffers SCI_TX_BUF_LEN equ 512 SCI_TX_BUF dsm SCI_TX_BUF_LEN SSI_TX_BUF dsm 4 SSI_RX_BUF dsm 4 SCI_TX_PTR ds 1 SCI_SND_PTR ds 1 SSI_RX_PTR ds 1 SSI_TX_PTR ds 1 CDC_RX_PTR ds 1 CDC_RCV_PTR ds 1 ;Bit flags definitions USER_FLAGS1 ds 1 UF1_SCI_STOPPED equ 0 UF1_CDC_RECEIVE equ 1 UF1_CDC_OVERRUN equ 2 ANALYSIS_BUF equ 0 ANALYSIS_LEN equ 256 LOG2_AN_LEN equ 8 org lh:$3000 CDC_BUF_LEN equ 1024 CDC_BUF dsm CDC_BUF_LEN TMP_AN_BUF dsm ANALYSIS_LEN ; Definitions of codec control words ; The information about the meaning of particular control words ; can be found in CS4215 data sheet, available in the Internet ; at http://www.cirrus.com/ftp/pubs/4215.pdf ; ; +Must be "001" ; | +MLB (Microphone Level) 0: 0.288Vpp 1: 2.88Vpp ; | | /OLB (Output Level) 0: Line 2.8 Phone 4.0 Speaker 8.0 Vpp ; | ||\1: Line 2.0 Phone 2.0 Speaker 4.0 Vpp ; | ||+CLB (Control Latch Bit) should be "0" ; | ||| +Must be "00" (reserved) ; | ||| |+HPF (High Pass Filter) 0: disabled 1:enabled ; | ||| ||+Must be "0" (reserved) ; | ||| ||| +DFR2-0 (Data Conversion Frequency Selection) ; | ||| ||| | +ST (Stereo Bit) ; | ||| ||| | | +DF1-0 (Data Format Selection) ; / \|||/\||/ \|/\++++++++ Not transmitted (should be "0") CDC_CW12 equ %001100000011110000000000 ;DFR2-0: (for xtal 24576kHz - used in EVM) ;000: 8kHz,001: 16kHz, 010: 27.42857kHz , 011: 32kHz ;100: Not used, 101: Not used, 110: 48kHz, 111: 9.6 kHz ; ;DF1-0: 00: 16 bit signed integer (linear) 01: 8-bit u-Law ; 10: 8-bit A-Law 11: 8-bit unsigned integer (linear) ; ; +ITS (Immediate Three-State) ; | +MCK2-0 (Clock Source Select) 000:SCLK (requires: BSEL=2,XCLK=0) ; | | 001:XTAL1 (not available in EVM) 010:XTAL2 ; | | 011:CLKIN (requires CLKIN=256xFs) 100:CLKIN (Fs set by DFR) ; | | +BSEL1-0 (Select Bit Rate) 00:64 01:128 10:256 bits/frame 11:reserved ; | | | +XCLK(Transmit clock) 0:SLAVE 1:MASTER ; | | | |+XEN (Transmitter enable) 0:Enable 1:Disable ; | | | || +TEST (should be zero) ; | | | || /\ + ENL (Enable Loopback Testing) 0:Disable 1:Enable ; | | | || / \ |+DAD (Loopback Mode) 0:D-D Loopback 1: D-A-D Loopback ; |/ \/\||/ \||++++++++ Not transmitted (should be "0") CDC_CW34 equ %101000100000000000000000 CDC_CW56 equ $000000 CDC_CW78 equ $000000 ; +HE (Headphone Output Enable) 1:Enabled 0:Muted ; |+LE (Line Output Enable) 1:Enabled 0:Muted ; || +LO5-0 (Left Channel Output Attenuation Setting) ; || | 0:No attenuation 111111:-94.5 dB step: 1.5dB ; || | +ADI (A/D Data Invalid) 0:valid 1:invalid (calibration) ; || | |+SE (Speaker Enable) 1:Enabled 0:Muted ; || /\ || RO5-0 (Right Channel Output Attenuation (like LO) ; || / \ || / \ ; ||/ \||/ \++++++++ Not transmitted (should be "0") CDC_OUT EQU %110000000000000000000000 ; ; +PIO10 (Parallel Output bits) ; | +OVR (Overrange) ; | |+IS (Input Select) 0:line (not available in EVM) 1:Microphone ; | || +LG3-0 (Left Channel Input Gain Setting) step:1.5dB ; | || | 0:0dB 1111:22.5dB ; | || | +MA3-0 (Monitor Path Attenuation) step:6dB ; | || | | 0:0dB 1111:muted ; | || /\ /\ RG3-0 (Right Channel Input Gain Setting) (like LG3-0) ; /\||/ \/ \/ \++++++++ Not transmited (should be "0") CDC_IN EQU %000100001111000000000000 org xh: MESSAGE dupc znak,'Dopiszmy tu coś jeszcze To jest komunikat z karty EVM56002' dc "znak" endm dc 10 END_MSG dc 'a' MSG_LEN equ END_MSG-MESSAGE org p:0 ;RESET Vector jmp START ; SSI interface interrupt routines org p:$000C jsr SSI_RX_ISR ;SSI RX jsr SSI_RX_ISR ;SSI RX w/Exception jsr SSI_TX_ISR ;SSI TX jsr SSI_TX_ISR ;SSI TX w/Exception ;SCI RECEIVE INTERRUPT VECTOR org p:$00014 nop nop ;SCI TRANSMIT INTERRUPT VECTOR org p:$00018 jsr SCI_Snd_Int nop org p:$40 org p: include "process.asm" ;Serial asynchronous interface service routines SCI_Snd_Int ;Interrupt after sending the byte ;First save the used registers to the stack move x0,x:(r7)+ ; Save x0 to the stack. move a0,x:(r7)+ ; Save a0 to the stack. move a1,x:(r7)+ ; Save a1 to the stack. move a2,x:(r7)+ ; Save a2 to the stack. ;check if there is anything to send move x:SCI_TX_PTR,x0 ; Load the pointer move x:SCI_SND_PTR,a cmp x0,a jeq SCI_Snd_l1 ; Nothing to send move r0,x:(r7)+ ; Save r0 to the stack. move m0,x:(r7)+ ; Save m0 to the stack. move #(SCI_TX_BUF_LEN-1),m0 ; Circular buffer. move x0,r0 nop movep x:(r0)+,x:STX ; SCI transfer data register. move r0,x:SCI_TX_PTR ; Update tx buffer pointer. move x:-(r7),m0 ; Restore m0 move x:-(r7),r0 ; Restore r0 SCI_Snd_l2 move x:-(r7),a2 ; Restore a2. move x:-(r7),a1 ; Restore a1. move x:-(r7),a0 ; Restore a0. move x:-(r7),x0 ; Restore x0. rti SCI_Snd_l1 bclr #UF1_SCI_STOPPED,x:USER_FLAGS1 jmp SCI_Snd_l2 ;Procedure for sending byte through the serial interface ;INPUT: r1 - byte to send ;USES: x0,b,r0,m0 ;OUTPUT: carry set - buffer overflow ; carry clear - sent correct SCI_Snd ; We save the byte to the send buffer ; First check if there is place in the buffer ori #$03,MR ; Block the interrupts to avoid ; the interference with interrupt routine move x:SCI_SND_PTR,r0 move #(SCI_TX_BUF_LEN-1),m0 move x:SCI_TX_PTR,b move (r0)+ ;r0 points to the position of the next byte move r0,x0 cmp x0,b jeq SCI_Snd_no_place ; Buffer is full move r1,x:(r0) ;Write data to the buffer move r0,x:SCI_SND_PTR ;Update the pointer ; Now we have to check if it is necessary to resume the transmission. ; If during the last interrupt buffer was empty, it is necessary ; to send the byte. ; We are sure, that there is a new byte in the buffer, so there ; is no need for checking... btst #UF1_SCI_STOPPED,x:USER_FLAGS1 jcs SCI_Snd_return move x:SCI_TX_PTR,r0 ; The SCI_TX_PTR is already in "B" register ; but there is small chance, that the ; SCI_Snd_Int was executed after this value ; was read (Keep in mind, that ORI #3,MR ; works after 4 instructions...) bset #UF1_SCI_STOPPED,x:USER_FLAGS1 movep x:(r0)+,x:STX move r0,x:SCI_TX_PTR SCI_Snd_return ; Switch on the interrupts andi #$fc,MR ; Clear the carry flag andi #$fe,CCR rts SCI_Snd_no_place ;No place in the buffer, set the CARRY flag and return ; Switch on the interrupts andi #$fc,MR ori #$01,CCR rts ;SSI Interrupt routines SSI_RX_ISR move r0,x:(r7)+ ; Save r0 to the stack. move m0,x:(r7)+ ; Save m0 to the stack. move #3,m0 ; Modulo 4 buffer. move x:SSI_RX_PTR,r0 ; Load the pointer to the rx buffer. jclr #3,x:SSISR,SSI_RX_ISR_next ; If not fr. syc, jump to receive data. move #SSI_RX_BUF,r0 ; If frame sync, reset base pointer. ; Check if the data reception is on btst #UF1_CDC_RECEIVE,x:USER_FLAGS1 jcc SSI_RX_ISR_next ; The previous data set is ready, copy it to the CDC_BUF buffer move r1,x:(r7)+ ; Save r1 to the stack move m1,x:(r7)+ ; Save m1 to the stack move x1,x:(r7)+ ; Save x1 to the stack. move a0,x:(r7)+ ; Save a0 to the stack. move a1,x:(r7)+ ; Save a1 to the stack. move a2,x:(r7)+ ; Save a2 to the stack. ; Check if there is place for the sample move x:CDC_RX_PTR,r1 move #(CDC_BUF_LEN-1),m1 nop move (r1)+ move x:CDC_RCV_PTR,a move r1,x1 cmp x1,a jeq SSI_RX_ISR_Overrun move x:SSI_RX_BUF,x1 move x1,x:(r1) move x:SSI_RX_BUF+1,x1 move x1,y:(r1) move r1,x:CDC_RX_PTR SSI_RX_ISR_Return move x:-(r7),a2 ; Restore a2 move x:-(r7),a1 ; Restore a1 move x:-(r7),a0 ; Restore a0 move x:-(r7),x1 ; Restore x1 move x:-(r7),m1 ; Restore m1 move x:-(r7),r1 ; Restore r1 SSI_RX_ISR_next movep x:RX,x:(r0)+ ; Read out received data to buffer. move r0,x:SSI_RX_PTR ; Update rx buffer pointer. move x:-(r7),m0 ; Restore m0. move x:-(r7),r0 ; Restore r0. rti SSI_RX_ISR_Overrun bset #UF1_CDC_OVERRUN,x:USER_FLAGS1 bclr #UF1_CDC_RECEIVE,x:USER_FLAGS1 jmp SSI_RX_ISR_Return ;-------------------------------------------------------------------- ; SSI Transmit ISR ; This Interrupt Service Routine is the destination of the SSI TX ; vector located at p:$0010. In many cases the SSI TX w/Exception ; vector will also jump here. ; R7 should point to the first free location on the stack (in X:memory). ; The data is taken from a 1 frame (4 word) buffer and sync. ; is verified/restored every frame. ;-------------------------------------------------------------------- SSI_TX_ISR move r0,x:(r7)+ ; Save r0 to the stack. move m0,x:(r7)+ ; Save m0 to the stack. move #3,m0 ; Modulus 4 buffer. move x:SSI_TX_PTR,r0 ; Load the pointer to the tx buffer. jclr #2,x:SSISR,SSI_TX_ISR_next ; If not frame sync, jump to transmit data. move #SSI_TX_BUF+1,r0 ; If frame sync, reset pointer. nop SSI_TX_ISR_next movep x:(r0)+,x:TX ; SSI transfer data register. move r0,x:SSI_TX_PTR ; Update tx buffer pointer. move x:-(r7),m0 ; Restore m0. move x:-(r7),r0 ; Restore r0. rti START movep #$0,x:PCC ;Switch off (?) the PCC movep #$26100a,x:PLL ;set PLL for MPY of 11x ;movep #$261009,x:PLL ;set PLL for MPY of 10x movep #$0000,x:BCR ;zero wait states in all ext. memory ori #3,mr ;disable interrupts movep #$C000,x:IPR ;Set interrupt priority to 2 movec #0,sp ;clear hardware stack pointer move #0,omr ;mode 0: enable int. P:RAM, rst=0000 move #$1000,r7 ; initialize stack pointer move #-1,m7 ; linear addressing move #0,x0 move x0,x:USER_FLAGS1 ;Initialization of the asynchronous serial interface movep #$1202,x:SCR movep #$0005,X:SCCR ;115200 baud/s move #SCI_TX_BUF,r0 move r0,x:SCI_TX_PTR move r0,x:SCI_SND_PTR bclr #UF1_SCI_STOPPED,x:USER_FLAGS1 ;Initialization of the synchronous serial interface movep #$4303,x:CRA ; 40MHz/16 = 2.5MHz SCLK, WL=16 bits, 4W/F movep #$FB30,x:CRB ; RIE,TIE,RE,TE, NTWK, SYN, FSR/RSR->bit movep #$14,x:PCDDR ; setup pc2 and pc4 as outputs movep #$0,x:PCD ; D/C~ and RESET~ = 0 ==> control mode ;----reset delay for codec ---- do #500,_delay_loop rep #2200 ; 100 us delay nop _delay_loop bset #4,x:PCD ; RESET~ = 1 movep #$f000,x:IPR ; set interrupt priority level movep #PCC_CW,X:PCC ;Set the port C ;Copy the control mode data to the TX buffer move #CDC_CW12,x0 move x0,x:SSI_TX_BUF move #CDC_CW34,x0 move x0,x:SSI_TX_BUF+1 move #CDC_CW56,x0 move x0,x:SSI_TX_BUF+2 move #CDC_CW78,x0 move x0,x:SSI_TX_BUF+3 ;Fill the receive buffer with zeros move #0,x0 move x0,x:SSI_RX_BUF move x0,x:SSI_RX_BUF+1 move x0,x:SSI_RX_BUF+2 move x0,x:SSI_RX_BUF+3 ;Prepare the buffer pointers move #SSI_TX_BUF,x0 move x0,x:SSI_TX_PTR move #SSI_RX_BUF,x0 move x0,x:SSI_RX_PTR move #CDC_BUF,x0 move x0,x:CDC_RX_PTR move x0,x:CDC_RCV_PTR ;Initialization of the codec (based on "ada_init.asm" code) movep #PCC_CW,X:PCC ;Set the port C andi #$fc,mr ;Switch the interrupts on ; ; CLB == 0 in TX Buffer, wait for CLB == 1 in RX Buffer ; jclr #3,x:SSISR,* ; wait until rx frame bit==1 jset #3,x:SSISR,* ; wait until rx frame bit==0 jclr #3,x:SSISR,* ; wait until rx frame bit==1 CDC_IN_l1 move x:SSI_RX_BUF,x0 jset #18,x0,CDC_IN_l1 ; loop until CLB set ; ; CLB == 1 in RX Buffer, send 4 frames and then disable SSI ; bset #18,x:SSI_TX_BUF ;set CLB do #4,_init_loopB ; Delay as 4 full frames to pass jclr #2,x:SSISR,* ; wait until tx frame bit==1 jset #2,x:SSISR,* ; wait until tx frame bit==0 _init_loopB movep #0,x:PCC ;reset SSI port (disable SSI...) ; ; now CLB should be 1 -- re-program fsync and sclk direction to input ; ; movep #$4303,x:CRA ; 16bits,4 word/frame, /2/4/2=2.5 MHz movep #$FB00,x:CRB ; rcv,xmt & int ena,netwk,syn,sclk==inp,msb 1st movep #$14,x:PCD ; D/C~ pin = 1 ==> data mode ;Prepare the SSI_TX buffer for data mode move #$0,x1 move x1,x:SSI_TX_BUF move x1,x:SSI_TX_BUF+1 move #CDC_OUT,x1 move x1,x:SSI_TX_BUF+2 move #CDC_IN,x1 move x1,x:SSI_TX_BUF+3 movep #PCC_CW,x:PCC ; turn on ssi port (enable SSI now...) ;The initialization is completed ;Now the main program starts do #10,loopwz1 move x:MESSAGE,r1 jsr SCI_Snd nop loopwz1 bset #UF1_CDC_RECEIVE,x:USER_FLAGS1 MainLoop ;We check if there is a new data block ready for analysis ;Calculate amount of data available in the buffer move x:CDC_RX_PTR,a move x:CDC_RCV_PTR,x0 sub x0,a jge MainLoop_correct move #>CDC_BUF_LEN,x0 add x0,a ;Correct the negative result MainLoop_correct ;The accumulator contains the number of available samples move #>ANALYSIS_LEN,x0 cmp x0,a jlt MainLoop ;Wait for sufficient amount of samples ;There is enough samples, so run the processing routine jsr ProcessData jmp MainLoop