#include <stdio.h>
#include <stdlib.h>

#include <mcbsp.h>      // mcbsp devlib
#include <common.h>
#include <mcbspdrv.h>   // mcbsp driver
#include <board.h>      // EVM library
#include <codec.h>      // codec library
#include <mathf.h>

#include "typedef.h"
#include "interf_enc.h"
#include "interf_dec.h"

#undef	WITHOUT_CODEC

void AsyncTxCallback(Mcbsp_dev dev,int status);
void AsyncRxCallback(Mcbsp_dev dev,int status);
int enc(int, short *, unsigned char *);
void dec(unsigned char *, short *);

int status;
int play_state;
int cap_state;

int *enstate, *destate;

#define Frame_len (80)
#define Frame_2ch_len (160)

short in_pcm[160];     		// Pointer to new speech data    
unsigned char serial[32];	// Output bitstream buffer
short out_pcm[160];
  
static void led_blink( int count, int ms_period )
{
    int     i;
    for (i=0;i<count;i++)
    {
        evm_led_enable(0); evm_led_enable(1); delay_msec(ms_period/2);
        evm_led_disable(0); evm_led_disable(1); delay_msec(ms_period/2);
    }
}

int main()
{
  Mcbsp_dev dev;
  Mcbsp_config   mcbspConfig;
  int           numBytes=Frame_2ch_len*2;
  int           sampleRate=8000;
  int           i;
  short         Txbuffer1[Frame_2ch_len],Txbuffer2[Frame_2ch_len],Rxbuffer1[Frame_2ch_len],Rxbuffer2[Frame_2ch_len];

  evm_init();
  mcbsp_drv_init();
  dev= mcbsp_open(0);
  
  memset(&mcbspConfig,0,sizeof(mcbspConfig));

  mcbspConfig.loopback              = FALSE;

  mcbspConfig.tx.update             = TRUE;
  mcbspConfig.tx.clock_polarity     = CLKX_POL_RISING;
  mcbspConfig.tx.frame_sync_polarity= FSYNC_POL_HIGH; 
  mcbspConfig.tx.clock_mode         = CLK_MODE_EXT;
  mcbspConfig.tx.frame_sync_mode    = FSYNC_MODE_EXT;
  mcbspConfig.tx.phase_mode         = SINGLE_PHASE;
  mcbspConfig.tx.frame_length1      = 0;
  mcbspConfig.tx.word_length1       = WORD_LENGTH_32;
  mcbspConfig.tx.frame_ignore       = FRAME_IGNORE;
  mcbspConfig.tx.data_delay         = DATA_DELAY0;

  mcbspConfig.rx.update             = TRUE;            
  mcbspConfig.rx.clock_polarity     = CLKR_POL_FALLING;
  mcbspConfig.rx.frame_sync_polarity= FSYNC_POL_HIGH;
  mcbspConfig.rx.clock_mode         = CLK_MODE_EXT;
  mcbspConfig.tx.frame_sync_mode    = FSYNC_MODE_EXT;
  mcbspConfig.rx.phase_mode         = SINGLE_PHASE;
  mcbspConfig.rx.frame_length1      = 0;
  mcbspConfig.rx.word_length1       = WORD_LENGTH_32;
  mcbspConfig.rx.frame_ignore       = FRAME_IGNORE;
  mcbspConfig.rx.data_delay         = DATA_DELAY0;

  if(mcbsp_config(dev,&mcbspConfig)==ERROR)
	exit(0);

  /****************************************************************************/
  /* configure CODEC                                                          */
  /****************************************************************************/
  if(codec_init()==ERROR)
	exit(0);

  codec_change_sample_rate(sampleRate, TRUE);

  /* A/D 0.0 dB gain, turn on 20dB mic gain, sel (L/R)MIC as inputs       */
  if(codec_adc_control(LEFT,0.0,TRUE,MIC_SEL)==ERROR)
  	exit(0);
  if(codec_adc_control(RIGHT,0.0,TRUE,MIC_SEL)==ERROR)
  	exit(0);
    
  /* D/A 0.0 dB atten, do not mute DAC outputs                                */
  if(codec_dac_control(LEFT, 0.0, FALSE)==ERROR)
 	exit(0);
  if(codec_dac_control(RIGHT, 0.0, FALSE)==ERROR)
	exit(0);

  evm_led_enable(1);
  evm_led_enable(0);

  //delay_msec(200);
  led_blink( 3, 100 );
  
  play_state=1;
  cap_state=1;

   // init encoder
   enstate = Encoder_Interface_init(0);
   // init decoder
   destate = Decoder_Interface_init();
												
  status = mcbsp_cont_async_receive(dev,(unsigned char *)Rxbuffer1,(unsigned char *)Rxbuffer2,
                                    numBytes,FALSE,NULL,AsyncRxCallback ); 
  delay_msec(3);
  status = mcbsp_cont_async_send(dev,(unsigned char *)Txbuffer1,(unsigned char *)Txbuffer2,
                                    numBytes,FALSE,NULL,AsyncTxCallback );
  while(1)
  {
  	while(cap_state==1)
  	{
  	}
	for(i=0;i<Frame_len;i++)	//從雙聲道資料中把某一聲道取出來
	{
		in_pcm[i]=Rxbuffer1[2*i];
	}
 		
  	while(cap_state==-1)
  	{
  	}
	for(i=0;i<Frame_len;i++)	//從雙聲道資料中把某一聲道取出來
	{
		in_pcm[80+i]=Rxbuffer2[2*i];
	}
	
#ifdef	WITHOUT_CODEC
	for(i=0;i<160;i++)
		out_pcm[i] = in_pcm[i];
#else
    enc(MR122, in_pcm, serial);
	dec(serial, out_pcm);
#endif
	
	while(play_state==-1)
  	{
  	}
	for(i=0;i<Frame_len;i++)	//把單聲道資料擴展放到雙聲道buffer
	{	
		Txbuffer1[2*i]=out_pcm[i];
		Txbuffer1[2*i+1]=out_pcm[i];
		Txbuffer2[2*i]=out_pcm[80+i];
		Txbuffer2[2*i+1]=out_pcm[80+i];
	}
  }
}

void AsyncTxCallback(Mcbsp_dev dev, int status)
{
  play_state=-play_state;
  return;
}

void AsyncRxCallback(Mcbsp_dev dev, int status)
{
  cap_state=-cap_state;
  return;
}            

