///////////////////////////////////////////////////////////////////////
// Filename: ISRs.c
//
// Synopsis: Interrupt service routines for McBSP transmit and receive
//
// Authors:  Michael G. Morrow
//
// Date of Last Revision: 3/17/2004
//
// Copyright (c): 2001-2004 by Michael G. Morrow.  All rights reserved.
///////////////////////////////////////////////////////////////////////

#include "DSK_Support.h"
#include "c6711cfg.h"
#include "math.h"
#include "frames.h" 

#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;
}

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;


//    float temp;

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

	pL = Left; // reinitialize pointers
	pR = Right;  
	      
/* gain 
   for(i=0;i < BUFFER_COUNT;i++){ 
		*pL++ *= 16.0;
		*pR++ *= 16.0;
   }  
	pL = Left; // reinitialize pointers
	pR = Right;        
*/
  
/* zero out left channel 
   for(i=0;i < BUFFER_COUNT;i++){ 
		*pL = 0.0;
        pL++;
   }  */

 
/* zero out right channel 
   for(i=0;i < BUFFER_COUNT;i++){ 
		*pR = 0.0;
        pR++;
   }    
*/

/* echo on right channel  
   for(i=0;i < BUFFER_COUNT-4;i++){ 
		*pR = *pR + (0.9 * pR[2]) + (0.45 * pR[4]);
        pR++;
   }              
*/ 
  
/* addition and subtraction 
   for(i=0;i < BUFFER_COUNT;i++){ 
      temp = *pL;        
      *pL = temp + *pR; // left = L+R
      *pR = temp - *pR; // right = L-R 
      pL++;
      pR++;
    }   */
             
                   
/* add a sinusoid    
   for(i=0;i < BUFFER_COUNT;i++){ 
      *pL = *pL + 4000*sinf(0.5*i);
      pL++;
    }    
*/                       

/* AM modulation 
    for(i=0;i < BUFFER_COUNT;i++){
      *pR = *pL * *pR * (1/32768.0); // right = L*R 
      *pL = *pL + *pR; // left = L*(1+R) 
      pL++;
      pR++;
    } 
*/

 	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; // signal we are done
}

///////////////////////////////////////////////////////////////////////
// Purpose:   Access function for buffer ready flag 
//
// Input:     None
//
// Returns:   Non-zero when a buffer is ready for processing
//
// Calls:     Nothing
//
// Notes:     None
///////////////////////////////////////////////////////////////////////
int IsBufferReady()
{
    return buffer_ready;
 }

///////////////////////////////////////////////////////////////////////
// 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;
}
 
interrupt void EDMA_ISR()
///////////////////////////////////////////////////////////////////////
// Purpose:   EDMA interrupt service routine.  Invoked on every buffer 
//            completion 
//
// Input:     None
//
// Returns:   Nothing
//
// Calls:     Nothing
//
// Notes:     None
///////////////////////////////////////////////////////////////////////
{
	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
}