/*************************************************\
 *  BSL and CSL patches (written by the TTO)
 *************************************************
 This file contains the following functions:
	void AD535_HWI_write(int handle, int out_data)
	int AD535_HWI_read(int handle)
	void MCBSP_setfree(int port)
	int AD535_checkif_readReady()
	int AD535_checkif_writeReady()
\*************************************************/

/***************
  Include Files
 ***************/
#include "C:\ti\c6000\dsk6x11\include\c6x11dsk.h"
#include <c6x.h>
#include <csl.h>
#include <csl_mcbsp.h>
#include <bsl.h>
#include <bsl_ad535.h>

#ifndef BSL_PATCH
#define BSL_PATCH
/***********************************************\
 * This is a new routine that is being added to
 * the BSL library. Unlike the AD535_read API 
 * it doesn't use polling to establish that
 * the McBSP is ready for another sample. Rather,
 * it requires the McBSP to already be ready.
 * In other words, the AD535_HWI_read routine
 * is for use within an Interrupt Service Routine.
 * The fact that you arrived at a McBSP transmit
 * ISR signifies that the McBSP is ready with 
 * another sample.
 *
 * Currently, the handle is not used, which is
 * why that prototype has been commented out. 
 * This routine writes directly to the McBSP 
 * out register. In other words, in 
 * this patch we're "cheating". This will be
 * fixed once it is officially added to the BSL.
\***********************************************/
short AD535_HWI_read(AD535_Handle handle)
{
	int readInput;
	MCBSP_Handle h;
	
	h = AD535_getMcbspHandle(handle);
	
	//readInput = *(unsigned volatile int *)McBSP0_DRR;
	readInput = MCBSP_read(h);

	return ((short)readInput);
}

/***********************************************\
 * See comments for AD535_HWI_read, above.
 *
 * Notice that the LSB of the output data is 
 * masked off. The LSB is used to signal a 
 * command to the AD535 codec. A LSB = 1 
 * signifies the next value ia a command. 
 * Commands are used to change the input/output
 * gains and such.
 * 
 * If you were to examine the BSL code which 
 * initializes the codec, you would find this 
 * bit used often.
 * 
 * When outputing sound, though, we want to mask
 * off this control bit. Hence, the AND'ing
 * operation included in this routine.
\***********************************************/
void AD535_HWI_write(AD535_Handle handle, short out_data)
{
	MCBSP_Handle h;
	
	h = AD535_getMcbspHandle(handle);

	out_data &= 0xFFFE;

    MCBSP_write(h,(int)out_data);
}

/***************************************************\
 *  When writing to the AD535 codec, the LSB of the 
 *  16-bit data output sample is used to initiate
 *  a command to the codec. That is, if the LSB
 *  is 1, then the next 16-bit value written to
 *  the codec will be a codec command (as opposed
 *  to data to be converted by the DAC).
 *
 *  The codec commands are used to set its 
 *  control registers. These registers are used
 *  for setting the input and output gains, 
 *  among other things.
 *
 *  When the DSP is halted during emulation for
 *  breakpoints and such, the McBSP normally also
 *  halted. Unfortunately, this means the data
 *  stream from the McBSP to the codec is halted.
 *  Since the McBSP0 data transmit line (DX0) is
 *  not being driven, it is allowed to float.
 *  While this is nice feature in production, it
 *  isn't desirable during development. In the 
 *  case of the DSK, the DX0 pin will often float
 *  to 1. If it floats to 1 when the AD535 is
 *  expecting the LSB command bit, the codec will
 *  often cease to function as expected. Usually, 
 *  the only way to recover from this is to close
 *  the debugger (CCS) and remove power-cycle the
 *  DSK.
 *
 *  The McBSP contains a yet-to-be documented FREE
 *  bit (bit 25). The next revision of the 'C6000
 *  Peripherals Guide should describe this bit.
 *  OR'ing the McBSP SPCR (serial port control
 *  register) with 0x200_0000 sets the FREE bit.
\***************************************************/
void MCBSP_setfree(int port)
{
	switch (port) {
		case 0:
			*(unsigned volatile int *)McBSP0_SPCR |= 0x2000000;
			break;
		case 1:
			*(unsigned volatile int *)McBSP1_SPCR |= 0x2000000;
			break;
		/* case 2:  // 'C6711 doesn't contain a 3rd McBSP
			*(unsigned volatile int *)McBSP2_SPCR |= 0x2000000;
			break;  */
		/* default: */
	}
}

/***********************************************\
 * Possible additions to BSL?
\***********************************************/
int AD535_checkif_readReady()
{
	int RRDYval = -1;

	RRDYval = *(unsigned volatile int *)McBSP0_SPCR;

	/**********************************************\
	 *	Extract RRDY bit (bit 1) from McBSP SPCR.
	 *
	 *   int _extu( int input, int csta, int cstb);
	 *      csta =   31 - MSB = 31 - 1 = 30
	 *      cstb = csta + LSB = 30 + 1 = 31
	\**********************************************/
		RRDYval = _extu(RRDYval,30,31);

	return (RRDYval);
}

int AD535_checkif_writeReady()
{
	int XRDYval = -1;

	XRDYval = *(unsigned volatile int *)McBSP0_SPCR;
	/**********************************************\
	 *	Extract XRDY bit (bit 17) from McBSP SPCR.
	 *
	 *   int _extu( int input, int csta, int cstb);
	 *      csta =   31 - MSB = 31 - 17 = 14
	 *      cstb = csta + LSB = 14 + 17 = 31
	\**********************************************/
		XRDYval = _extu(XRDYval,14,31);

	return (XRDYval);
}

#endif