///////////////////////////////////////////////////////////////////////
// Filename: ISRs.c
//
// Synopsis: Interrupt service routines for McBSP transmit and receive
//
// Original by:  Michael G. Morrow, 3/17/2004
//
// Changes by:	Mark A. Yoder
//
// Date of Last Revision: 12-Apr-2004
//
// Copyright (c): 2001-2004 by Michael G. Morrow.  All rights reserved.
///////////////////////////////////////////////////////////////////////

#include <bsl.h>
#include <rtdx.h>
#include "DSK_Support.h"
#include "c6711cfg.h"
#include "math.h"
#include "frames.h" 

#include "../fixDA.h"

RTDX_outputChannel ochan = RTDX_OUTPUT_INITIAL_STATE;	// Declare rtdx channel
RTDX_inputChannel  ichan = RTDX_INPUT_INITIAL_STATE;

void FIRfilter(float *inbuf, float *outbuf, float *coeff, int buffSize,
				int Norder);

#pragma DATA_SECTION (buffer, "SDRAM"); // allocate buffers in SDRAM 
short buffer[NUM_BUFFERS][BUFFER_LENGTH];
// there are 3 buffers in use at all times, one being filled from the McBSP,
// one being operated on, and one being emptied to the McBSP
// ready_index --> buffer ready for processing
volatile short buffer_ready = 0, over_run = 0, ready_index = 0;

void ZeroBuffers() 
////////////////////////////////////////////////////////////////////////
// Purpose:   Sets all buffer locations to 0 
//
// Input:     None
//
// Returns:   Nothing
//
// Calls:     Nothing
//
// Notes:     None
///////////////////////////////////////////////////////////////////////
{
    int i = NUM_BUFFERS * BUFFER_LENGTH;
    short *p = (short *)buffer;

    while(i--)
        *p++ = 0;
        
   	RTDX_enableOutput(&ochan);
   	RTDX_enableInput(&ichan);
}

float rVol = 1.0;
float lVol = 1.0;	
	
int	desiredAveMag = 2000;
int	zeroThreshold = 500;
	
void ProcessBuffer()
///////////////////////////////////////////////////////////////////////
// Purpose:   Processes the data in buffer[ready_index] and stores
//  		  the results back into the buffer 
//            Data is packed into the buffer, alternating right/left
//
// Input:     None
//
// Returns:   Nothing
//
// Calls:     Nothing
//
// Notes:     None
///////////////////////////////////////////////////////////////////////
{
	short *pBuf = buffer[ready_index];
//	static float Left[BUFFER_COUNT], Right[BUFFER_COUNT];
//	float *pL = Left, *pR = Right;
	int i;
	int sum=0;
	int aveMagOfFrame;
	int status, count;
	static	int input;

/*
	for(i = 0;i < BUFFER_COUNT;i++) { // extract data to float buffers
	   *pR++ = rVol * *pBuf++;
 	   *pL++ = lVol * *pBuf++;
	}
*/

	STS_set(&stsProcess, CLK_gethtime());	// Time how long the processing takes.

	for(i=0; i<BUFFER_LENGTH; i+=2) {
		sum += _abs(buffer[ready_index][i]);
	}
	STS_delta(&stsProcess, CLK_gethtime());	// Stop the clock.
	
	STS_set(&stsProcess2, CLK_gethtime());	// Time how long the processing takes.
	aveMagOfFrame = sum/BUFFER_COUNT;
//	LOG_printf(&logTrace, "Ave = %d", aveMagOfFrame);
	status = RTDX_write(&ochan, &aveMagOfFrame, sizeof(aveMagOfFrame));
	
	if(aveMagOfFrame > zeroThreshold) 
		for(i=0; i<BUFFER_LENGTH; i+=2) {		// Just do the right channel
			buffer[ready_index][i] = buffer[ready_index][i] * desiredAveMag
										/ aveMagOfFrame;
		}
	else
		for(i=0; i<BUFFER_LENGTH; i+=2) {
			buffer[ready_index][i] = 0;
		}
		

	// Sends a -1 to tell Excel it's done.
	if(DIP_get(DIP_3) == 0) {
		aveMagOfFrame = -1;
		status = RTDX_write(&ochan, &aveMagOfFrame, sizeof(aveMagOfFrame));
	}
	
	// Read data from Excel.  Note:  input must be declared static.
	if(!RTDX_channelBusy(&ichan)) {
		RTDX_readNB(&ichan, &input, sizeof(input));
		LOG_printf(&logTrace, "input=%d", input);
	
		if(input > 0)
			LED_on(LED_3);
		else
			LED_off(LED_3);
	}
	
	STS_delta(&stsProcess2, CLK_gethtime());	// Stop the clock.

/*
 	pBuf = buffer[ready_index];
	pL = Left;
	pR = Right;

	for(i = 0;i < BUFFER_COUNT;i++) { // pack into buffer without bounding
		*pBuf++ = *pR++;
		*pBuf++ = *pL++;
	}
*/

/* Original pack into buffer.	
	for(i = 0;i < BUFFER_COUNT;i++) { // pack into buffer after bounding
		*pBuf++ = _spint(*pR++ * 65536) >> 16;
		*pBuf++ = _spint(*pL++ * 65536) >> 16;
	}
*/	
 	pBuf = buffer[ready_index];
	if(CodecType == TLC320AD535) { // mask off LSB to prevent codec reprogramming
		for(i = 0;i < BUFFER_COUNT;i++) {
	 	   *(unsigned int *)pBuf &= 0xfffffffe; 
		   pBuf += 2;
		}
	}
	
	    buffer_ready = 0; // mark buffer as ready for processing
}

///////////////////////////////////////////////////////////////////////
// Purpose:   Access function for buffer overrun flag 
//
// Input:     None
//
// Returns:   Non-zero if a buffer overrun has occurred
//
// Calls:     Nothing
//
// Notes:     None
///////////////////////////////////////////////////////////////////////
int IsOverRun()
{
    return over_run;
}
 
void EDMA_ISR()
///////////////////////////////////////////////////////////////////////
// Purpose:   EDMA interrupt service routine.  Invoked on every buffer 
//            completion 
//
// Input:     None
//
// Returns:   Nothing
//
// Calls:     Nothing
//
// Notes:     None
///////////////////////////////////////////////////////////////////////
{	
	LED_toggle(LED_2);

	EDMA_intClear(15); // clear McBSP TCC event
		
    if(++ready_index >= NUM_BUFFERS) // update buffer index
        ready_index = 0;
    if(buffer_ready == 1) // set a flag if buffer isn't processed in time 
        over_run = 1;
    buffer_ready = 1; // mark buffer as ready for processing

    SWI_post(&processBufferSwi); // post SWI to process buffer
}