	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


