

#include "board.h"


#include <stdio.h>
#include <string.h>
#include <math.h>

#include "mp2enc.h"
#include "mp2_dec.h"

/******************************************************************************
**                          FUNCTION DEFINITIONS
******************************************************************************/

// encoder bitrate in kbps 
int bitrate             = 192   ;   // first bitrate, encode some frames

// number of blank bytes at end of output frame , used for DAB ancillary   data 
int num_blank_bytes     = 0      ;
// audio Mode | 0 stereo, 1 J-stereo, 2 dual Channel, 3 Mono 
int audioMode           = 1      ;   
int modeExt             = 3      ;   
int sample_rate         = 48000  ; 
int channel_num         = 2      ;
unsigned char enc_output_buf[4096];

#define TRACE_LEN 16 
// unsigned int opt_old_trace [TRACE_LEN];
// unsigned int opt_new_trace [TRACE_LEN];
// unsigned int tx_link [TRACE_LEN];
// unsigned int tx_src [TRACE_LEN];



/*
** The main function. Application starts here.
*/
#define NUM_SAMPLES_PER_AUDIO_CH (NUM_SAMPLES_PER_AUDIO_BUF/2)


short enc_input_buf[2][1152];
short dec_out[2][1152]; 

// conver input audio int to float
// input is a signed short val with 2MSByte 0x0000
// convert to float (-1, 1)
float AuIn2Float(unsigned int in_val_i){
  float scale = 1.0/32767;
  float out_f = 0;
  short temp = 0;
  temp = in_val_i & 0xffff;
  out_f = scale * temp; 
  return out_f;
}

// conver float to output audio int 
// float val should be  (-1, 1)
// output is a signed short val with 2MSByte 0x0000
unsigned int Float2AuOut(float in_val_f){
  float scale = 32767;
  unsigned int out_i = 0;
  short temp_s = 0;
  int temp_i = 0;
  temp_s = in_val_f *scale; 
  temp_i =  temp_s;
  out_i = temp_i & 0xffff; 
  return out_i;
}

/*
** Setup the timer for 64 bit mode
*/
static void TimerSetUp64Bit(void)
{
    /* Configuration of Timer */
    TimerConfigure(SOC_TMR_2_REGS, TMR_CFG_64BIT_CLK_INT);

    /* Set the 64 bit timer period */
    TimerPeriodSet(SOC_TMR_2_REGS, TMR_TIMER12, TMR_PERIOD_LSB32);
    TimerPeriodSet(SOC_TMR_2_REGS, TMR_TIMER34, TMR_PERIOD_MSB32);
}

#define TIME_TRACE_LEN (256*3)
unsigned int time_trace[TIME_TRACE_LEN];

void wr_circular_trace_buf(unsigned int val, unsigned int *p_buf, unsigned int buf_len){
  static unsigned int idx = 0;
  p_buf[idx]  = val;
  idx ++;
  if(idx == buf_len) {idx = 0;}
}

void test_malloc(unsigned int buf_len){
  unsigned int * ptr = NULL;
  unsigned int i, val;
  ptr = (unsigned int *) malloc(buf_len * sizeof(unsigned int));
  if(ptr == NULL){
	  printf("malloc failed\n");
	  return;
  }
  else{
	  printf("malloc OK.\n");
  }

  val = 0xAA55AA55;
  for(i = 0; i < buf_len; i ++){
    ptr[i] = val;
  }
  for(i = 0; i < buf_len; i ++){
    unsigned int read = ptr[i];
    if(read != val){
      printf("Data check error, address:0x%x, write:0x%x, read:0x%x\n", i, val, read );
    }
  }
  printf("Data check PASS.\n");
  free(ptr);

}

void enable_all_INT(){
  IntEnable(C674X_MASK_INT4);
  IntEnable(C674X_MASK_INT5);
  IntEnable(C674X_MASK_INT6);
}
void disable_all_INT(){
  IntDisable(C674X_MASK_INT4);
  IntDisable(C674X_MASK_INT5);
  IntDisable(C674X_MASK_INT6);
}

int main(void)
{
  unsigned int rx_cnt = 0;

  unsigned int time_frame1 = 0;
  unsigned int * src_ptr = NULL;
  unsigned int * dst_ptr = NULL;
  int i = 0, ErrNum = 0;
  h_mp2enc_t hEncoder = NULL; 
  h_mp2_frm_dec_t h_dec  = NULL;

  int enc_out_bytes_num = 0;


  init_tx_buf();
  
  // board_init();
  disable_all_INT();
  test_malloc(0x400);
  enable_all_INT();
  while(1);

  // setup timer and enable it start working
  TimerSetUp64Bit();
  TimerEnable(SOC_TMR_2_REGS, TMR_TIMER12, TMR_ENABLE_CONT);

  // open encoder
  ErrNum = mp2_enc_open(&hEncoder, sample_rate, channel_num, audioMode, modeExt, bitrate);
 // init frame decoder
  mp2_frame_dec_init(&h_dec);

  if(ErrNum){ while(1); }   // open error cause strap

  while(1) {
    unsigned int time_cnt1, time_cnt2, time_enc, time_dec;
    unsigned int enc_load = 0, dec_load = 0; 
    unsigned int addr = 0;
    if(is_rx_new()){
      unsigned int time_frame_len = 0;
      time_frame1 = TimerCounterGet(SOC_TMR_2_REGS,  TMR_TIMER12); 

      
      // must disable counter before set its value
      TimerDisable(SOC_TMR_2_REGS, TMR_TIMER12);
      TimerCounterSet(SOC_TMR_2_REGS,  TMR_TIMER12, 0); 
      TimerEnable(SOC_TMR_2_REGS, TMR_TIMER12, TMR_ENABLE_CONT);

      // get frame time length
      time_frame_len = time_frame1;
      wr_circular_trace_buf(time_frame_len, &time_trace[0], TIME_TRACE_LEN);

      // clear counter
      TimerCounterSet(SOC_TMR_2_REGS, TMR_TIMER_BOTH, 0); 
      time_cnt1 = TimerCounterGet(SOC_TMR_2_REGS,  TMR_TIMER12); 



      addr = get_new_rx_buf();
      src_ptr = (unsigned int *) addr;
      
      addr = get_rdy_tx_buf();
      dst_ptr = (unsigned int *)addr;
      for(i = 0; i < NUM_SAMPLES_PER_AUDIO_CH; i ++){
        enc_input_buf[0][i] = 0xffff & src_ptr[i*2];
        enc_input_buf[1][i] = 0xffff & src_ptr[i*2+1];
      }// for(i)
     
      // time trace point, encoder run
      time_cnt1 =  TimerCounterGet(SOC_TMR_2_REGS,  TMR_TIMER12); 
      // frame Encoder run
      mp2_enc_run(hEncoder, enc_input_buf, enc_output_buf, num_blank_bytes, &enc_out_bytes_num); 
      // time trace point, encoder done
      time_cnt2  =  TimerCounterGet(SOC_TMR_2_REGS,  TMR_TIMER12); 
      time_enc = time_cnt2 - time_cnt1;
      
      
      // time trace point, decoder run
      time_cnt1 =  TimerCounterGet(SOC_TMR_2_REGS,  TMR_TIMER12); 
      // frame Decoder run
      mp2_fram_dec_run( enc_output_buf, enc_out_bytes_num, dec_out, channel_num, h_dec);
      // time trace point, decoder done
      time_cnt2  =  TimerCounterGet(SOC_TMR_2_REGS,  TMR_TIMER12); 
      time_dec = time_cnt2 - time_cnt1;
      enc_load = (100.0*time_enc) / time_frame_len;
      dec_load = (100.0*time_dec) / time_frame_len;
      wr_circular_trace_buf(time_enc, &time_trace[0], TIME_TRACE_LEN );
      wr_circular_trace_buf(time_dec, &time_trace[0], TIME_TRACE_LEN );
      
      // copy decoder PCM to DMA buffer
      for(i = 0; i < NUM_SAMPLES_PER_AUDIO_CH; i ++){
        int val0, val1;
        // expand short to int
        val0 =  dec_out[0][i];  
        val1 =  dec_out[1][i];
        dst_ptr[i*2    ] = val0; 
        dst_ptr[i*2 + 1] = val1;
      }// for(i)
      
      rx_cnt ++;
    }// if(is_rx_new())
  }// while(1)
} // main(void)

/***************************** End Of File ***********************************/


