/******************************************************************************\
*           Copyright (C) 2000 Texas Instruments Incorporated.
*                           All Rights Reserved
*------------------------------------------------------------------------------
* FILENAME...... bsl_ad535.c
* DATE CREATED.. Thu 06/15/2000 
* LAST MODIFIED. Thu 06/15/2000 
*
\******************************************************************************/
#define _AD535_MOD_
#define _BOARD_MOD_ 

/****************************************\
* include files
\****************************************/

#include <csl_mcbsp.h>                    
#include "bsl_ad535.h"

#if (AD535_SUPPORT)
/******************************************************************************\
*                         L O C A L   S E C T I O N
\******************************************************************************/

/****************************************\
* AD535 static macro declarations
\****************************************/

/****************************************\
* AD535 static typedef declarations
\****************************************/

/****************************************\
* AD535 static function declarations
\****************************************/

static inline Uint32 readCodec(AD535_Handle hAD535);
static inline void writeCodec(AD535_Handle hAD535, Uint32 val);
static void writeData(AD535_Handle hAD535, Uint32 *valVector, Uint32 length);

/****************************************\
* AD535 static variable definitions
\****************************************/

/****************************************\
* AD535 static function definitions
\****************************************/
/*----------------------------------------------------------------------------*/

Uint32 readCodec(AD535_Handle hAD535){
  while(!MCBSP_rrdy(_AD535_HMCBSP(hAD535))); 
  return( MCBSP_read(_AD535_HMCBSP(hAD535)) );
}
/*----------------------------------------------------------------------------*/

void writeCodec(AD535_Handle hAD535, Uint32 val){
  MCBSP_write(_AD535_HMCBSP(hAD535),val);
  while(!MCBSP_xrdy(_AD535_HMCBSP(hAD535)));
  MCBSP_write(_AD535_HMCBSP(hAD535),0);
}
/*----------------------------------------------------------------------------*/
void writeData(AD535_Handle hAD535, Uint32 *valVector, Uint32 length){
  Uint32 i = 0;
  for (i=0; i<length; i++) {
    readCodec(hAD535);
    writeCodec(hAD535, valVector[i]);
  }
}
/*----------------------------------------------------------------------------*/

/******************************************************************************\
*                        G L O B A L   S E C T I O N
\******************************************************************************/

/****************************************\
* AD535 global variable definitions
\****************************************/
/* local codec on 6711 DSK */
#if (BOARD_6711DSK | BOARD_6211DSK)
  AD535_Id local_id = {{0}, {FALSE, INV}};
#endif

  AD535_Id *AD535_localId = &local_id;
/****************************************\
* AD535 global function definitions
\****************************************/
/*----------------------------------------------------------------------------*/

void _AD535_init(){

  MCBSP_Handle hMcbsp;
  static int initialized = 0;

  if (!initialized) {
    /* Open the Mcbsp_handle */
    hMcbsp = MCBSP_open(local_id.Id.mcbsp_no, MCBSP_OPEN_RESET);
    
    /* configure McBSP for 16-bit signed communication */
    MCBSP_configArgs(hMcbsp,
                  0x00012001,
                  0x00010040,
                  0x00010040,
                  MCBSP_SRGR_DEFAULT,
                  MCBSP_MCR_DEFAULT,
                  MCBSP_RCER_DEFAULT,
                  MCBSP_XCER_DEFAULT,
                  MCBSP_PCR_DEFAULT
                 );

    /* Software Reset */

    while(!MCBSP_xrdy(hMcbsp));
    MCBSP_write(hMcbsp,0);
 
    while(!MCBSP_rrdy(hMcbsp));
    MCBSP_write(hMcbsp,1);

    while(!MCBSP_xrdy(hMcbsp));
    MCBSP_write(hMcbsp,0x0380);
    
    while(!MCBSP_xrdy(hMcbsp));
    MCBSP_write(hMcbsp,0);
 
    MCBSP_close(hMcbsp);

  _BOARD_init();
  initialized = 1;
  }
}
/*----------------------------------------------------------------------------*/

void AD535_close(AD535_Handle hAD535){

#define VECTOR_SIZE   4
  Uint32 writeVector[VECTOR_SIZE] = {0,
                                     1,
                                     0x0380,            /* set reset bit in control register 3 */
                                     0
                                    };
  /* Reset the codec before closing */
  _AD535_ASSERT_HANDLE(hAD535);

  writeData(hAD535, writeVector, VECTOR_SIZE);
    
  _AD535_ALLOCATED(hAD535) = FALSE;  
  MCBSP_close(_AD535_HMCBSP(hAD535));

#undef VECTOR_SIZE
}
/*----------------------------------------------------------------------------*/

void AD535_config(AD535_Handle hAD535, AD535_Config *config){

#define VECTOR_SIZE 8
  Uint32 inGain, outGain;
  Uint32 writeVector[VECTOR_SIZE]; 

  _AD535_ASSERT_HANDLE(hAD535);
  inGain = 0;
  outGain = 0;
  
  /* check if in_gain and out_gain are within range */        
  if ((config->in_gain <= 12.0) && (config->in_gain >= -36.0))
    inGain = (Uint32) ((config->in_gain / 1.5) + 25);
  
  if ((config->out_gain <= 12.0) && (config->out_gain >= -36.0))
    outGain = (Uint32) ((config->out_gain / 1.5) + 25.0);

  writeVector[0] = 0;
  writeVector[1] = 1;
  writeVector[2] = (0x0306 + (Uint32)config->lb_mode);
  writeVector[3] = 1;
  writeVector[4] = (0x0400 + (Uint32)config->mic_gain + inGain);
  writeVector[5] = 1;
  writeVector[6] = (0x0502 + (outGain<<2) );
  writeVector[7] = 0;

  writeData(hAD535, writeVector, VECTOR_SIZE);

#undef VECTOR_SIZE
}
/*----------------------------------------------------------------------------*/

void AD535_inGain(AD535_Handle hAD535, float inGain){

#define VECTOR_SIZE 3
  Uint32 oldCtrlRegVal, gain;
  Uint32 writeVector[VECTOR_SIZE]; 

  if ((inGain <= 12.0) && (inGain >= -36.0)){
    gain = (Uint32) ((inGain / 1.5) + 25.0);
  }
  _AD535_ASSERT_HANDLE(hAD535);

  writeVector[0] = 0;
  writeVector[1] = 1;
  writeVector[2] = 0x02400;
  writeData(hAD535, writeVector, VECTOR_SIZE);

  oldCtrlRegVal = readCodec(hAD535);
  while (0xFFFFFF00 & oldCtrlRegVal)
    oldCtrlRegVal = readCodec(hAD535);

  writeVector[0] = 1;
  writeVector[1] = ( 0x00FF & ((~0x003F &  oldCtrlRegVal) + gain) ) + 0x0400;
  writeVector[2] = 0;
  writeData(hAD535, writeVector, VECTOR_SIZE);

#undef VECTOR_SIZE                  
}
/*----------------------------------------------------------------------------*/

void AD535_micGain(AD535_Handle hAD535, AD535_MicGain micGain){

#define VECTOR_SIZE 3
  Uint32 oldCtrlRegVal; 
  Uint32 writeVector[VECTOR_SIZE]; 

  _AD535_ASSERT_HANDLE(hAD535);

  writeVector[0] = 0;
  writeVector[1] = 1;
  writeVector[2] = 0x02400;
  writeData(hAD535, writeVector, VECTOR_SIZE);

  oldCtrlRegVal = readCodec(hAD535);
  while (0xFFFFFF00 & oldCtrlRegVal)
    oldCtrlRegVal = readCodec(hAD535);

  writeVector[0] = 1;
  writeVector[1] = (0x00FF & (((~0x40) &  oldCtrlRegVal) + (Uint32)micGain ))
                        + 0x0400;
  writeVector[2] = 0;
  writeData(hAD535, writeVector, VECTOR_SIZE);

#undef VECTOR_SIZE
}
/*----------------------------------------------------------------------------*/

void AD535_modifyReg(AD535_Handle hAD535, AD535_Reg ad535Register, Uint32 val, Uint32 mask){

#define VECTOR_SIZE 3
  Uint32 oldCtrlRegVal, write_val;
  short regShifted, lower_byte_mask;
  Uint32 writeVector[VECTOR_SIZE]; 

  regShifted = (short) (ad535Register<<8);
  if (ad535Register == AD535_REG_CTRL5) lower_byte_mask = 0x00FE;
  else lower_byte_mask = 0x00FF;

  _AD535_ASSERT_HANDLE(hAD535);

  writeVector[0] = 0;
  writeVector[1] = 1;
  writeVector[2] = (Uint32)regShifted + 0x2000;
  writeData(hAD535, writeVector, VECTOR_SIZE);

  oldCtrlRegVal = readCodec(hAD535);
  while (0xFFFFFF00 & oldCtrlRegVal)
    oldCtrlRegVal = readCodec(hAD535);
  write_val =(((Uint32)lower_byte_mask & (((~mask) & oldCtrlRegVal) + (mask & val)))
                                + (Uint32)regShifted);
  writeVector[0] = 1;
  writeVector[1] = write_val;
  writeVector[2] = 0;
  writeData(hAD535, writeVector, VECTOR_SIZE);

#undef VECTOR_SIZE    
}
/*----------------------------------------------------------------------------*/

AD535_Handle AD535_open(AD535_Id *myId){

  AD535_Handle hCodec;
 
  if ( !(_AD535_ALLOCATED(myId)) ) {  
    _AD535_HMCBSP(myId) = MCBSP_open(_AD535_MCBSP_NO(myId), MCBSP_OPEN_RESET);  /* Open the Mcbsp_handle */
    
    if ( _AD535_HMCBSP(myId) ==  INV)  {
      hCodec = (AD535_Handle)INV ;
      _AD535_ALLOCATED(myId)  = FALSE;
    }
    else {
      _AD535_ALLOCATED(myId) = TRUE;
      /* configure McBSP for 16-bit signed communication */
      MCBSP_configArgs(_AD535_HMCBSP(myId),
                  0x00012001,
                  0x00010040,
                  0x00010040,
                  MCBSP_SRGR_DEFAULT,
                  MCBSP_MCR_DEFAULT,
                  MCBSP_RCER_DEFAULT,
                  MCBSP_XCER_DEFAULT,
                  MCBSP_PCR_DEFAULT
                 );
      hCodec = myId;
    }
  } 
  else { 
    hCodec = INV ;
  }
 
  return hCodec;
}
/*----------------------------------------------------------------------------*/

void AD535_outGain(AD535_Handle hAD535, float outGain){

#define VECTOR_SIZE 3
  Uint32 oldCtrlRegVal, gain, write_val; 
  Uint32 writeVector[VECTOR_SIZE]; 

  if ((outGain <= 12.0) && (outGain >= -36.0)){
    gain = (Uint32) ((outGain / 1.5) + 25.0);
  }
  _AD535_ASSERT_HANDLE(hAD535);

  writeVector[0] = 0;
  writeVector[1] = 1;
  writeVector[2] = 0x02530;
  writeData(hAD535, writeVector, VECTOR_SIZE);

  oldCtrlRegVal = readCodec(hAD535);  
  while (0xFFFFFF00 & oldCtrlRegVal)
    oldCtrlRegVal = readCodec(hAD535);
  write_val = ((0x00FE & ( ((~0x00FC) &  oldCtrlRegVal) + (gain<<2) )) + 0x0500);

  writeVector[0] = 1;
  writeVector[1] = write_val;
  writeVector[2] = 0;
  writeData(hAD535, writeVector, VECTOR_SIZE);

#undef VECTOR_SIZE    
}
/*----------------------------------------------------------------------------*/

void AD535_powerDown(AD535_Handle hAD535){

#define VECTOR_SIZE 4
  Uint32 writeVector[VECTOR_SIZE]; 

  _AD535_ASSERT_HANDLE(hAD535);

  writeVector[0] = 0;
  writeVector[1] = 1;
  writeVector[2] = 0x0340;
  writeVector[3] = 0;
  writeData(hAD535, writeVector, VECTOR_SIZE);

#undef VECTOR_SIZE    
}
/*----------------------------------------------------------------------------*/

Uint32 AD535_readReg(AD535_Handle hAD535, AD535_Reg ad535Register){

#define VECTOR_SIZE 3
  Uint32 retVal;
  Uint32 regShifted;
  Uint32 writeVector[VECTOR_SIZE]; 

  regShifted = (Uint32) (ad535Register<<8);

  _AD535_ASSERT_HANDLE(hAD535);

  writeVector[0] = 0;
  writeVector[1] = 1;
  writeVector[2] = ( regShifted + 0x2000 );
  writeData(hAD535, writeVector, VECTOR_SIZE);

  retVal = readCodec(hAD535);
  while (0xFFFFFF00 & retVal)
    retVal = readCodec(hAD535);

  return(retVal);  

#undef VECTOR_SIZE    
}
/*----------------------------------------------------------------------------*/
 
void AD535_reset(AD535_Handle hAD535){

#define VECTOR_SIZE 4
  Uint32 writeVector[VECTOR_SIZE]; 

  _AD535_ASSERT_HANDLE(hAD535);

  writeVector[0] = 0;
  writeVector[1] = 1;
  writeVector[2] = 0x0380;
  writeVector[3] = 0;
  writeData(hAD535, writeVector, VECTOR_SIZE);

#undef VECTOR_SIZE    
}
/*----------------------------------------------------------------------------*/

void AD535_writeReg(AD535_Handle hAD535, AD535_Reg ad535Register, Uint32 val){
                  
#define VECTOR_SIZE 4
  short regShifted, lower_byte_mask;
  Uint32 writeVector[VECTOR_SIZE]; 

  regShifted = (short) (ad535Register<<8);
  if (ad535Register == AD535_REG_CTRL5) lower_byte_mask = 0x00FE;
  else lower_byte_mask = 0x00FF;
                                                                   
  _AD535_ASSERT_HANDLE(hAD535);

  writeVector[0] = 0;
  writeVector[1] = 1;
  writeVector[2] = ((Uint32)lower_byte_mask & val) + (Uint32)regShifted;
  writeVector[3] = 0;
  writeData(hAD535, writeVector, VECTOR_SIZE);

#undef VECTOR_SIZE    
}
/*----------------------------------------------------------------------------*/
#endif /* AD535_SUPPORT */
/******************************************************************************\
* End of bsl_ad535.c
\******************************************************************************/