/*****************************************************************************
Copyright(c) 2005 Analog Devices, Inc.  All Rights Reserved. This software is 
proprietary and confidential to Analog Devices, Inc. and its licensors.
******************************************************************************

$RCSfile: audio_codec.c,v $
$Revision: 1.2 $
$Date: 2008/03/25 05:40:34 $

Project:	Audio Player
Title:		
Author(s):	
Revised by: 

Description:
		This file contains functions to setup and configure the audio codec 
		Depending on macro set at Project-option Preprocessor definition,
		following audio related functions are provided:
		Macro CODEC_AD1938 for AD1938A codec on the Audio Extender card or
		Macro CODEC_AD1854 for AD1854 DAC and AD1871 ADC on board BF537 EZKIT or
		Macro CODEC_AD1836 AD1836 on board BF533 EZKIT

References:
	AD1938A Preliminary Technical Data
	ADSP-BF537 Hardware reference
	ADSP-BF537 EZ-Kit Lite Schematic
	AD1836 Preliminary Technical Data
	ADSP-BF533 Hardware reference
	ADSP-BF533 EZ-Kit Lite Schematic
	

References:
			None

******************************************************************************
Tab Setting:			4

Target Processor:		ADSP-BF5xx
Target Tools Revision:	ADSP VisualDSP++ v4.0
******************************************************************************


Revision 1.2  2006/05/10 05:04:11  dwu
Fixed a circular buffer bug.
Added code to measure USB read times.

Revision 1.1.1.1  2006/05/09 04:01:29  dwu
USB based audio demonstration




*****************************************************************************/

#include "system.h"
#include "codec.h"
#include "adac_buffer.h"
#include "SDK-ezkitutilities.h"
#include <adi_ssl_Init.h>
#include <drivers/sport/adi_sport.h> 

#include <audio_codec.h>
#include "adi_id3_parser.h"
#include "adi_mp3_dec.h"
//#include "adi_wma_dec.h"
#include "adi_heaacv2_decoder.h"




#include <stdio.h>					// stdio header
#include <string.h>					// string header
#include <stdlib.h>
#include <math.h>
#include <cycle_count.h> 			// for basic cycle counting


/*****************************************************************************
	User defines
 *****************************************************************************/


// =========================================================
//	FIFO buffers
// =========================================================
#pragma align 4
section("adac_buffers") static short fifo_buffer[FIFO_BUFFER_SIZE*NUM_FIFO_BUFFERS];
//section("adac_buffers") static short fifo_buffer[2000];

#if defined (CODEC_AD1938)
#include <drivers/codec/adi_ad1938_ii.h>	// AD1938A device driver includes
#define		AD1938_SPI_CS_DEVICE_A		5	// PF5
static ADI_DEV_DEVICE_HANDLE AD1938DriverHandler;
#elif defined(CODEC_AD1836)
#include <drivers/codec/adi_ad1836a_ii.h>	// AD1836A device driver includes
#define		AD1836_SPI_CS_DEVICE_A		4	// PF4
static ADI_DEV_DEVICE_HANDLE AD1836DriverHandler;
#elif defined(CODEC_AD1854)
#include <drivers/adc/adi_ad1871.h>	// AD1871 device driver includes
#include <drivers/dac/adi_ad1854.h>	// AD1854 device driver includes
// handle to the ad1871 driver
static ADI_DEV_DEVICE_HANDLE AD1871DriverHandler;
// handle to the ad1854 driver
static ADI_DEV_DEVICE_HANDLE AD1854DriverHandler;
#endif


#if defined(__ADSPBF533__)
// Macros specific to BF533 Ez-Kit
// address of flash A port A output data register
#define pFlashA_PortA_Out   ((volatile unsigned char *)0x20270004)  
// address of flash A port A direction register
#define pFlashA_PortA_Dir   ((volatile unsigned char *)0x20270006)  
#endif

#define		SPORT_DEV_NUMBER		0	// SPORT 0 for audio


	
// one-dimensional buffer for processing data
static ADI_DEV_1D_BUFFER adc_Buffer1;
static ADI_DEV_1D_BUFFER dac_Buffer1;
static ADI_DEV_1D_BUFFER adc_Buffer2;
static ADI_DEV_1D_BUFFER dac_Buffer2;

section("adac_buffers") volatile u16 iADCdata1[(CHANNEL_NUMBER * ADAC_BUFFER_SIZE)]; 
section("adac_buffers") volatile u16 iDACdata1[(CHANNEL_NUMBER * ADAC_BUFFER_SIZE)];
section("adac_buffers") volatile u16 iADCdata2[(CHANNEL_NUMBER * ADAC_BUFFER_SIZE)]; 
section("adac_buffers") volatile u16 iDACdata2[(CHANNEL_NUMBER * ADAC_BUFFER_SIZE)];


//section("dac_buffers") char testbuf[1000]; 


// DMA Stream Handels
ADI_DMA_STREAM_HANDLE		MDMA_Handle;

// MDMA 2D transfer data type
ADI_DMA_2D_TRANSFER			MDMA_Src;
ADI_DMA_2D_TRANSFER			MDMA_Dest;


/* Functions prototype */
static void ClientCallback( void *AppHandle, u32 Event, void *pArg);




// Decoder main function
// does all the file handling
// CRUNCH use generic decode function 
int do_decode(void)
{
	char  current_input_file_name[MAX_FILE_NAME_LEN];
	char  output_file_name[MAX_FILE_NAME_LEN];
	static char current_path[MAX_PATH_NAME_LEN];

	FILE *fp_dir;			// file pointer to list file

	int next_file;
	char key;

	int return_code = CODEC_SUCCESS;
	
	printf("Blackfin(r) Audio Kit\n");
	printf("(c) 2007 Analog Devices Inc.\n");
  	printf("\n");

  	// Open list file
  	strcpy(current_path, ROOT_DIR);
	fp_dir = fopen( strcat(strcat(current_path, AUDIO_DIR), AUDIO_LIST_FILE), "r" );
 	if (fp_dir == NULL)
	{
		fprintf( fperr, "Error: could not read directory file\n" );
		return CODEC_FILE_ERROR;
	}

	// start decoding
	printf("Reading list of audio files from %s\n\n", AUDIO_LIST_FILE);
	
	//printf("  Press button SW4 to skip file...\n\n");
	// Get Next File name from directory file
	next_file = fscanf(fp_dir, "%s", current_input_file_name);
	
	
	while(next_file != EOF)
	{
	  	// User routine initialization
	  	usr_init(fifo_buffer, FIFO_BUFFER_SIZE, NUM_FIFO_BUFFERS); 	  	
		

		// build the next input file name in tempstring
		strcpy(current_path, ROOT_DIR);
		strcat(strcat(current_path, AUDIO_DIR), current_input_file_name);

        printf("\nExtension:  %s\n", strchr(current_path,'.'));
    
		
        if((strcmp(strchr(current_input_file_name,'.'),".aac") ==0) | (strcmp(strchr(current_input_file_name,'.'),".AAC") ==0) )
            {
            AAC_Decode(current_path);
            }
        else if((strcmp(strchr(current_input_file_name,'.'),".adif") ==0) | (strcmp(strchr(current_input_file_name,'.'),".ADIF") ==0) )
            {
            AAC_Decode(current_path);

            }
        else if((strcmp(strchr(current_input_file_name,'.'),".mp3") ==0) |(strcmp(strchr(current_input_file_name,'.'),".MP3") ==0) )
            {
            	MP3_Decode_File(current_path);
            //AAC_Decode(current_path);

            }

               
        else
            printf("Invalid Extension\n");  

	
		// Get Next File name from directory file
		next_file = fscanf(fp_dir, "%s", current_input_file_name);
		if(!next_file) next_file = EOF;
		
	}

	if(!return_code)
		printf("\nReached end of list\n");

	// close the list file
	fclose( fp_dir );

	return CODEC_SUCCESS;
}


/*********************************************************************

	Function:		ClientCallback

	Description:	
	Each type of callback event has it's own unique ID so we can use a single 
	callback function for all callback events.  The switch statement tells us
	which event has occurred.

	Note that in the device driver model, in order to generate a callback for 
	buffer completion, the CallbackParameter of the buffer must be set to a 
	non-NULL value.
	
	In this example, we'll get a callback when the SPORT has completed 
	processing of the DAC buffer chains. If loopback is enabled the device 
	driver will automatically reuse the buffer chains. If loopback is not 
	used, the callback function must requeue the chain that just finished in 
	order to keep the device driver saturated with data.  

*********************************************************************/
static void ClientCallback(
	void 	*AppHandle,
	u32  	Event,
	void 	*pArg)
{
    
    ADI_DEV_1D_BUFFER *pBuf = pArg;
	switch (Event)
	{
		// CASE (DMA buffer processed)
		case ADI_DEV_EVENT_BUFFER_PROCESSED:
		
		    // DAC processing			
			DACUserISR(pArg,ADAC_BUFFER_SIZE);
	
			break;
		
		// CASE (an error)
		case ADI_DEV_EVENT_DMA_ERROR_INTERRUPT:
	    printf("DMA error\n");
		
			break;
		
		default:

            // on occurance of other events turn on all LEDs & wait to attend the error
            ezTurnOnAllLEDs();            
            while(1);
	}
}


/*********************************************************************
*
*	Function:	install_audiodriver
*
*********************************************************************/
//section("sdram0_bank3_nocache")
void install_audiodriver()
{
    u32 ResponseCount;          // response counter

    int i;
    
    	/**************** Buffer Preparation ****************/
	// Create two buffer chains for ADC data.		
	// Make the CallbackParameter point to the first buffer chain and the second buffer chain.
	/**************** Setup Audio buffers ****************/		    	
	adc_Buffer1.Data = (void*)iADCdata1;
	adc_Buffer1.ElementCount = (CHANNEL_NUMBER * ADAC_BUFFER_SIZE);
	adc_Buffer1.ElementWidth = 2;
	adc_Buffer1.CallbackParameter = NULL;
	adc_Buffer1.pNext = &adc_Buffer2;

	adc_Buffer2.Data = (void*)iADCdata2;
	adc_Buffer2.ElementCount = (CHANNEL_NUMBER * ADAC_BUFFER_SIZE);
	adc_Buffer2.ElementWidth = 2;
	adc_Buffer2.CallbackParameter = NULL;
	adc_Buffer2.pNext = NULL;
	

	dac_Buffer1.Data = (void*)iDACdata1;
	dac_Buffer1.ElementCount = (CHANNEL_NUMBER * ADAC_BUFFER_SIZE);
	dac_Buffer1.ElementWidth = 2;
	dac_Buffer1.CallbackParameter = &dac_Buffer1;
	dac_Buffer1.pNext = &dac_Buffer2;

	dac_Buffer2.Data = (void*)iDACdata2;
	dac_Buffer2.ElementCount = (CHANNEL_NUMBER * ADAC_BUFFER_SIZE);
	dac_Buffer2.ElementWidth = 2;
	dac_Buffer2.CallbackParameter = &dac_Buffer2;
	dac_Buffer2.pNext = NULL;	
    		
    
#if defined (CODEC_AD1938)

    // Open the AD1938 driver 
    if(adi_dev_Open(	adi_dev_ManagerHandle,            // Dev manager Handle
                        &ADIAD1938IIEntryPoint, 		// Device Entry point
                        0,                              // Device number
                        NULL,                           // No client handle
                        &AD1938DriverHandler,                  // Device manager handle address
                        ADI_DEV_DIRECTION_BIDIRECTIONAL,// Data Direction
                        adi_dma_ManagerHandle,               // Handle to DMA Manager
                        DCBManagerHandle,               // Handle to callback manager
                        ClientCallback) != ADI_DEV_RESULT_SUCCESS)

	    printf("adi_dev_Open failed\n");

    /**************** SPORT Configuration Settings ****************/	
    if(adi_dev_Control( AD1938DriverHandler, ADI_AD1938_CMD_SET_SPORT_DEVICE_NUMBER, (void*)SPORT_DEV_NUMBER )!= ADI_DEV_RESULT_SUCCESS)	
		    printf("adi_dev_Control failed to set SPORT device number\n");
			    
    /**************** AD1938 Configuration Settings ****************/
    ADI_DEV_ACCESS_REGISTER 	ConfigAD1938_DevA[]	= 
  				{	
					{ AD1938_DAC2L_VOL_CTRL,	0x00	},	// No Attenuation (DAC 2L)
					{ AD1938_DAC2R_VOL_CTRL,	0x00	},	// No Attenuation (DAC 2R)
					{ AD1938_DAC3L_VOL_CTRL,	0x00	},	// No Attenuation (DAC 3L)
					{ AD1938_DAC3R_VOL_CTRL,	0x00	},	// No Attenuation (DAC 3R)
					{ AD1938_DAC4L_VOL_CTRL,	0x00	},	// No Attenuation (DAC 4L)
					{ AD1938_DAC4R_VOL_CTRL,	0x00	},	// No Attenuation (DAC 4R)
					{ AD1938_DAC_CHNL_MUTE,		0x00	},	// Unmute all DAC channels
					{ AD1938_DAC1L_VOL_CTRL,	0x00	},	// No Attenuation (DAC 1L)
					{ AD1938_DAC1R_VOL_CTRL,	0x00	},	// No Attenuation (DAC 1R)
// ADC/DAC control register configurations
// DAC Control register 0 - set DAC serial format, No SDATA delay, Sample rate, DAC normal operation
					{ AD1938_DAC_CTRL0,			0x48	}, 
// DAC Control register 1 - left low, set BCLKs per frame (channel count), Latch in mid cycle, other fields - dont care for Aux mode					
					{ AD1938_DAC_CTRL1,			0x84		},
// DAC Control register 2 - Non-inverted output, Word width, Flat De-emphasis,Unmute DACs
//					{ AD1938_DAC_CTRL2,			0x18		},
					
//					{ AD1938_DAC_CTRL2,			0x1A		},// 44kHz curve
					{ AD1938_DAC_CTRL2,			0x1C		},// 48kHz curve
					
// ADC Control register 0 - Sample rate,Unmute all channels, HPF off, ADC Power down
					{ AD1938_ADC_CTRL0,			0x3E },
// ADC Control register 1 - Latch in mid cycle, Serial format, no SDATA delay, Word width
					{ AD1938_ADC_CTRL1,			0x43	},
// ADC Control register 2 - internally generated BCLK, BCLK Master, BCLKs per frame, LRCLK master, LRCLK left low, BCLK Drive out on falling edge, LRCLK is Pulse
					{ AD1938_ADC_CTRL2,			0x6D	},

					{ AD1938_PLL_CLK_CTRL0,		0x9C	},	// Internal MCLK enabled,MCLK as PLL input, MCLK_O off,INPUT 256, normal
					{ AD1938_PLL_CLK_CTRL1,		0x04	},	// PLL as ADC & DAC clock source, Onchip Voltage Reference disabled		
					
					{ ADI_DEV_REGEND,			0    }	// Register access delimiter (indicates end of register access) 					
				};		
													
    // Set AD1938 Device A SPI chipselect
    if(adi_dev_Control( AD1938DriverHandler, ADI_AD1938_CMD_SET_SPI_CS, (void*)AD1938_SPI_CS_DEVICE_A )!= ADI_DEV_RESULT_SUCCESS)	
		    printf("adi_dev_Control failed to set SPI Chipselect for Device A\n");
    
    // Configure AD1938 Device A
    if(adi_dev_Control(AD1938DriverHandler, ADI_DEV_CMD_REGISTER_TABLE_WRITE, (void *)ConfigAD1938_DevA)!= ADI_DEV_RESULT_SUCCESS)	
		    printf("adi_dev_Control failed to configure ADV1938\n");
		
    // read AD1938 registers	    
	//Read1938AReg(AD1938DriverHandler);	    
	
    // set dataflow method
    if(adi_dev_Control(AD1938DriverHandler, ADI_DEV_CMD_SET_DATAFLOW_METHOD, (void *)ADI_DEV_MODE_CHAINED_LOOPBACK )!=ADI_DEV_RESULT_SUCCESS)
    printf("adi_dev_Control failed to set dataflow method\n");
    
    // enable streaming mode
   if(adi_dev_Control(AD1938DriverHandler, ADI_DEV_CMD_SET_STREAMING,(void *)TRUE )!=ADI_DEV_RESULT_SUCCESS)
    printf("enable streaming mode failed\n");

    // submit buffers to the driver
    if(adi_dev_Read (AD1938DriverHandler, ADI_DEV_1D, (ADI_DEV_BUFFER *)&adc_Buffer1)!=ADI_DEV_RESULT_SUCCESS)
        printf("adi_dev_Read failed\n");
        
    if(adi_dev_Write (AD1938DriverHandler, ADI_DEV_1D, (ADI_DEV_BUFFER *)&dac_Buffer1)!=ADI_DEV_RESULT_SUCCESS)
        printf("adi_dev_Write failed\n");


    // Enable data flow
    ezErrorCheck(adi_dev_Control(AD1938DriverHandler, ADI_DEV_CMD_SET_DATAFLOW, (void*)TRUE));

      
	// configure MDMA stream
   	//ConfigureMDMA();
   	
#elif defined(CODEC_AD1854)  
       // AD1854 on EzKit BF537 must be pulled out of reset    
	adi_flag_SetDirection(ADI_FLAG_PF12,ADI_FLAG_DIRECTION_OUTPUT);
	adi_flag_Set(ADI_FLAG_PF12);


    // Open the AD1871 driver 
    if(adi_dev_Open(	adi_dev_ManagerHandle,            // Dev manager Handle
                        &ADI_AD1871_EntryPoint, 		// Device Entry point
                        0,                              // Device number
                        NULL,                           // No client handle
                        &AD1871DriverHandler,                  // Device manager handle address
                        ADI_DEV_DIRECTION_INBOUND,// Data Direction
                        adi_dma_ManagerHandle,               // Handle to DMA Manager
                        DCBManagerHandle,               // Handle to callback manager
                        ClientCallback) != ADI_DEV_RESULT_SUCCESS)

	    printf("adi_dev_Open 1871 failed\n");

	//configure SPORT interface.		    	    
	ADI_DEV_CMD_VALUE_PAIR sport_I2S_RxConfig[] = 
	{
		{ 	ADI_SPORT_CMD_SET_RCR1,     (void *)(RFSR | RCKFE)},
		{ 	ADI_SPORT_CMD_SET_RCR2,	   	(void *)(15 | RSFSE)},
		{ 	ADI_DEV_CMD_END, 			(void*)NULL						},
	};	
		
	if(adi_dev_Control( AD1871DriverHandler, ADI_DEV_CMD_TABLE, (void *)sport_I2S_RxConfig )!= ADI_DEV_RESULT_SUCCESS)
	  printf("AD1871 SportConfig failed\n");

	// set dataflow method
    if(adi_dev_Control(AD1871DriverHandler, ADI_DEV_CMD_SET_DATAFLOW_METHOD, (void *)ADI_DEV_MODE_CHAINED_LOOPBACK )!=ADI_DEV_RESULT_SUCCESS)
    printf("adi_dev_Control failed to set dataflow method\n");
    
    // enable streaming mode
   if(adi_dev_Control(AD1871DriverHandler, ADI_DEV_CMD_SET_STREAMING,(void *)TRUE )!=ADI_DEV_RESULT_SUCCESS)
    printf("enable streaming mode failed\n");

   if(adi_dev_Read (AD1871DriverHandler, ADI_DEV_1D, (ADI_DEV_BUFFER *)&adc_Buffer1)!=ADI_DEV_RESULT_SUCCESS)
    printf("adi_dev_Read failed\n");

		    
		    
    // Open the AD1854 driver 
    if(adi_dev_Open(	adi_dev_ManagerHandle,            // Dev manager Handle
                        &ADI_AD1854_EntryPoint, 		// Device Entry point
                        0,                              // Device number
                        NULL,                           // No client handle
                        &AD1854DriverHandler,                  // Device manager handle address
                        ADI_DEV_DIRECTION_OUTBOUND,// Data Direction
                        adi_dma_ManagerHandle,               // Handle to DMA Manager
                        DCBManagerHandle,               // Handle to callback manager
                        ClientCallback) != ADI_DEV_RESULT_SUCCESS)

	    printf("adi_dev_Open 1854 failed\n");
	
		//configure SPORT interface.		    	    
	ADI_DEV_CMD_VALUE_PAIR sport_I2S_TxConfig[] = 
	{	

		{ 	ADI_SPORT_CMD_SET_TCR1,     (void *)(TFSR | TCKFE)},
		{ 	ADI_SPORT_CMD_SET_TCR2,	   	(void *)(15 | TSFSE)},
		{ 	ADI_DEV_CMD_END, 			(void*)NULL						},
	};	
		
	if(adi_dev_Control( AD1854DriverHandler, ADI_DEV_CMD_TABLE, (void *)sport_I2S_TxConfig )!= ADI_DEV_RESULT_SUCCESS)
	  printf("AD1854 SportConfig failed\n");
	
	// set dataflow method
    if(adi_dev_Control(AD1854DriverHandler, ADI_DEV_CMD_SET_DATAFLOW_METHOD, (void *)ADI_DEV_MODE_CHAINED_LOOPBACK )!=ADI_DEV_RESULT_SUCCESS)
    printf("adi_dev_Control failed to set dataflow method\n");
    
    // enable streaming mode
   if(adi_dev_Control(AD1854DriverHandler, ADI_DEV_CMD_SET_STREAMING,(void *)TRUE )!=ADI_DEV_RESULT_SUCCESS)
    printf("enable streaming mode failed\n");

    
   if(adi_dev_Write(AD1854DriverHandler, ADI_DEV_1D, (ADI_DEV_BUFFER *)&dac_Buffer1)!=ADI_DEV_RESULT_SUCCESS)
    printf("adi_dev_Write failed\n");

	
    // Enable audio data flow
    ezErrorCheck(adi_dev_Control(AD1871DriverHandler, ADI_DEV_CMD_SET_DATAFLOW, (void*)TRUE));

    ezErrorCheck(adi_dev_Control(AD1854DriverHandler, ADI_DEV_CMD_SET_DATAFLOW, (void*)TRUE));
    
#elif defined(CODEC_AD1836)
   
    // Pull AD1836A from reset mode
    // Set PortA pin 0 as output
    *pFlashA_PortA_Dir = 0x01;
   //write to Port A to reset AD1836
   *pFlashA_PortA_Out = 0x00; 
   //wait at least 5 ns in reset
    asm("nop; nop; nop;"); 
  //write to Port A to enable AD1836
   *pFlashA_PortA_Out = 0x01; 
      
    // Open the AD1836 driver 
    if(adi_dev_Open(	adi_dev_ManagerHandle,            // Dev manager Handle
                        &ADIAD1836AEntryPoint, 		// Device Entry point
                        0,                              // Device number
                        NULL,                           // No client handle
                        &AD1836DriverHandler,                  // Device manager handle address
                        ADI_DEV_DIRECTION_BIDIRECTIONAL,// Data Direction
                        adi_dma_ManagerHandle,               // Handle to DMA Manager
                        DCBManagerHandle,               // Handle to callback manager
                        ClientCallback) != ADI_DEV_RESULT_SUCCESS)

	    printf("adi_dev_Open failed\n");

	/**************** SPORT Configuration Settings ****************/	
	if(adi_dev_Control( AD1836DriverHandler, ADI_AD1836A_CMD_SET_SPORT_DEVICE_NUMBER, (void*)SPORT_DEV_NUMBER )!= ADI_DEV_RESULT_SUCCESS)	
		    printf("adi_dev_Control failed to set SPORT device number\n");
		    

	// Set SPORT Operating Mode (I2S)
	if(adi_dev_Control( AD1836DriverHandler, ADI_AD1836A_CMD_SET_SPORT_OPERATION_MODE, (void*)ADI_AD1836A_SET_I2S_MODE )!= ADI_DEV_RESULT_SUCCESS)
		    printf("adi_dev_Control failed to set SPORT operation mode\n");

		    
/**************** AD1836A Configuration Settings ****************/
// AD1836A Subaddress Register values
ADI_DEV_ACCESS_REGISTER ConfigAD1836A[] =
{
	{AD1836A_DAC_CTRL_1,0x010}, // No De-emphasis,I2S,16bits,normal,3*48KHz
    {AD1836A_DAC_CTRL_2,0x000},	// Un-mute all DAC channels
    {AD1836A_DAC_1L_VOL,0x3FF}, // DAC 1L Max Volume
    {AD1836A_DAC_1R_VOL,0x3FF}, // DAC 1R Max Volume
    {AD1836A_DAC_2L_VOL,0x3FF},	// DAC 2L Max Volume
    {AD1836A_DAC_2R_VOL,0x3FF},	// DAC 2R Max Volume
    {AD1836A_DAC_3L_VOL,0x000},	// DAC 3L Max Volume
    {AD1836A_DAC_3R_VOL,0x000},	// DAC 3R Max Volume
    {AD1836A_ADC_CTRL_1,0x000},	// DC,Normal Mode,48KHz,0dB gain
    {AD1836A_ADC_CTRL_2,0x020}, // Slave,I2S,16 bits, all ADC un-mute
    {AD1836A_ADC_CTRL_3,0x000},	// 256*fs,Differential PGA,Direct,I/P 0
  	{ADI_DEV_REGEND,   0x0000}
};				
	
	
	// Set AD1836 Device A SPI chipselect
	if(adi_dev_Control( AD1836DriverHandler, ADI_AD1836A_CMD_SET_SPI_CS, (void*)AD1836_SPI_CS_DEVICE_A )!= ADI_DEV_RESULT_SUCCESS)	
	printf("adi_dev_Control failed to set SPI Chipselect for Device A\n");
    
	// Configure AD1836 Device A
    if(adi_dev_Control(AD1836DriverHandler, ADI_DEV_CMD_REGISTER_TABLE_WRITE, (void *)ConfigAD1836A)!= ADI_DEV_RESULT_SUCCESS)	
	printf("adi_dev_Control failed to configure ADV1836\n");
		    	
	// set dataflow method
    if(adi_dev_Control(AD1836DriverHandler, ADI_DEV_CMD_SET_DATAFLOW_METHOD, (void *)ADI_DEV_MODE_CHAINED_LOOPBACK )!=ADI_DEV_RESULT_SUCCESS)
    printf("adi_dev_Control failed to set dataflow method\n");
    
       // Disable transmit secondary SPORT channel.		    	    
	ADI_DEV_CMD_VALUE_PAIR sport_I2S_Config[] = 
	{
		{ 	ADI_SPORT_CMD_SET_TCR2,    	(void *)(15| TSFSE)},
		{ 	ADI_DEV_CMD_END, 			(void*)NULL						},
	};	
		
   if(adi_dev_Control( AD1836DriverHandler, ADI_DEV_CMD_TABLE, (void *)sport_I2S_Config)!=ADI_DEV_RESULT_SUCCESS)
       printf("disable secondary SPORT failed\n");
 
    
    // enable streaming mode
   if(adi_dev_Control(AD1836DriverHandler, ADI_DEV_CMD_SET_STREAMING,(void *)TRUE )!=ADI_DEV_RESULT_SUCCESS)
    printf("enable streaming mode failed\n");

    
    if(adi_dev_Read (AD1836DriverHandler, ADI_DEV_1D, (ADI_DEV_BUFFER *)&adc_Buffer1)!= ADI_DEV_RESULT_SUCCESS)
    printf("adi_dec_Read failed\n");

	if(adi_dev_Write(AD1836DriverHandler, ADI_DEV_1D, (ADI_DEV_BUFFER *)&dac_Buffer1)!= ADI_DEV_RESULT_SUCCESS)
    printf("adi_dec_Write failed\n");

	
	// Enable data flow
	if(adi_dev_Control(AD1836DriverHandler, ADI_DEV_CMD_SET_DATAFLOW, (void*)TRUE)!= ADI_DEV_RESULT_SUCCESS)
    printf("ADI_DEV_CMD_SET_DATAFLOW failed\n");
    
	
#endif
}

/*********************************************************************
*
*	Function:	Copy I2S data from FIFO to DAC buffer in TDM format
*
*********************************************************************/
#if defined (CODEC_AD1938)
void CopyFifoToDACbuf(char *pSrc, char *pDest,unsigned long num_of_bytes)
{
    	int res,i;
    	
    	u16 *pLSrc, *pRSrc, *pLDest, *pRDest;

   	
    	num_of_bytes = num_of_bytes/4;
    	
    	
    	
    	pLSrc = (u16*)pSrc;
    	pRSrc = (u16*)pSrc + 1;
    	
    	pLDest = (u16*)pDest;
     	pRDest = (u16*)pDest + 2;
   	
    	for(i=0; i<num_of_bytes; i++)
    	{
    		*(pLDest +(i*16)) = *(pLSrc +(i*2));	
    	    *(pRDest +(i*16)) = *(pRSrc +(i*2));	
	
    	}	
    
}


/**********************************************************************
* read AD1938A registers 
**********************************************************************/
void Read1938AReg(ADI_DEV_DEVICE_HANDLE DevHandler)	
{
    	u32 Result = 0, i;


    
    ADI_DEV_ACCESS_REGISTER Regs[] = 
	{{ AD1938_PLL_CLK_CTRL0, 	0 },		// Register address to access, corresponding register data
     { AD1938_PLL_CLK_CTRL1, 	0 },
     { AD1938_DAC_CTRL0, 	0 },
     { AD1938_DAC_CTRL1, 	0 },
     { AD1938_DAC_CTRL2, 	0 },
     { AD1938_ADC_CTRL0, 	0 },
     { AD1938_ADC_CTRL1, 	0 },
     { AD1938_ADC_CTRL2, 	0 },
     { ADI_DEV_REGEND,	0 }};	// Register access delimiter (indicates end of register access)

//To read list of registers in DevRegs
    Result =  adi_dev_Control(DevHandler, ADI_DEV_CMD_REGISTER_TABLE_READ, (void *)&Regs);    
    if (Result != 0) printf("CMD_SELECTIVE_REGISTER_READ failed(error:%x)\n",Result);
    else {
    	// print the values	
		printf("1938A: ");
		for (i=0; i<8; i++){
		printf("0x%02X ",Regs[i].Data);
		}
		printf("\n");

    }

}
#endif

