

#include "board.h"


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




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


/*
** 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*5)
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;}
}


#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)
float trace_buf_L[NUM_SAMPLES_PER_AUDIO_CH*4];
float trace_buf_R[NUM_SAMPLES_PER_AUDIO_CH*4];

#pragma DATA_SECTION(proc_buf_L, "PROC_BUF");
float proc_buf_L[NUM_SAMPLES_PER_AUDIO_CH];
float * proc_buf_R = NULL;

// 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;
}

void timer_init(){
  TimerSetUp64Bit();
  TimerDisable(SOC_TMR_2_REGS, TMR_TIMER12);
  TimerCounterSet(SOC_TMR_2_REGS,  TMR_TIMER12, 0); 
}
// start timer with zero value
void time_start_zero(){
  // must disable counter before set its value
  // setup timer and enable it start working
  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);
}

int main(void)
{
  unsigned int rx_cnt = 0;
  unsigned int tx_cnt = 0;
  unsigned int * src_ptr = NULL;
  unsigned int * dst_ptr = NULL;
  int i = 0;
  PSC_All_On();
  // init cpu core and DDR2 mem 
  // gel_cpu_ddr_init();

  memset(trace_buf_L, 0, sizeof(unsigned int) * NUM_SAMPLES_PER_AUDIO_CH*4);
  memset(trace_buf_R, 0, sizeof(unsigned int) * NUM_SAMPLES_PER_AUDIO_CH*4);

  init_tx_buf();
  
  proc_buf_R = NULL;
  proc_buf_R = (float *) malloc(NUM_SAMPLES_PER_AUDIO_CH * sizeof(float)); 
  while(proc_buf_R == NULL){ ; } // malloc failed then loop here 

  board_init();
  timer_init();

  while(1) {
    unsigned int time_cnt1, time_cnt2, time_cnt3, time_cnt4, time_cnt5; 
    unsigned int time_L_in, time_L_out, time_R_in, time_R_out;
    int n_buf = NUM_SAMPLES_PER_AUDIO_BUF;
    int size_buf = AUDIO_BUF_SIZE;
    unsigned int addr = 0;
    if(is_rx_new()){
      unsigned int time_frame_len = 0;

      int n_ch = NUM_SAMPLES_PER_AUDIO_CH;
      int start_frame = 1;

      // get frame time length
      time_frame_len = TimerCounterGet(SOC_TMR_2_REGS,  TMR_TIMER12); 
      //  start timer with zeros value
      time_start_zero();




      addr = get_new_rx_buf();
      src_ptr = (unsigned int *) addr;
      
      addr = get_rdy_tx_buf();
      dst_ptr = (unsigned int *)addr;
      /* Copy the trace buffer */
      if((rx_cnt >= start_frame)&&(rx_cnt < 4+start_frame)){
        int offset = (rx_cnt-start_frame)*n_ch;
        for(i = 0; i < n_ch; i ++){
          trace_buf_L[offset + i] = src_ptr[i*2]; 
          trace_buf_R[offset + i] = src_ptr[i*2+1]; 
        }
      }
      // copy input data to proc buf, perform proc, then output  
      
      // time trace point, left ch input to proc buf
      time_cnt1 =  TimerCounterGet(SOC_TMR_2_REGS,  TMR_TIMER12); 
      // copy to left proc buf
      for(i = 0 ; i < NUM_SAMPLES_PER_AUDIO_CH; i ++) { 
        proc_buf_L[i] = AuIn2Float(src_ptr[i*2]);
        proc_buf_L[i] = proc_buf_L[i] * 0.95;
      }

      time_cnt2  =  TimerCounterGet(SOC_TMR_2_REGS,  TMR_TIMER12); 

      // copy to right proc buf
      for(i = 0 ; i < NUM_SAMPLES_PER_AUDIO_CH; i ++) { 
        proc_buf_R[i] = AuIn2Float(src_ptr[i*2+1]);
        proc_buf_R[i] = proc_buf_R[i] * 0.95;
      }

      time_cnt3  =  TimerCounterGet(SOC_TMR_2_REGS,  TMR_TIMER12); 

      // left channel scale and output 
      for(i = 0 ; i < NUM_SAMPLES_PER_AUDIO_CH; i ++){
        float temp_L; temp_L = proc_buf_L[i] * 0.9; 
        // proc_buf_L[i] = temp_L; // write to proc buf
        dst_ptr[i*2]   = Float2AuOut(temp_L); 
      }

      time_cnt4  =  TimerCounterGet(SOC_TMR_2_REGS,  TMR_TIMER12); 

      // right channel scale and output 
      for(i = 0 ; i < NUM_SAMPLES_PER_AUDIO_CH; i ++){
        float temp_R; temp_R = proc_buf_R[i] * 0.9; 
        // proc_buf_R[i] = temp_R; // write to proc buf
        dst_ptr[i*2+1] = Float2AuOut(temp_R); 
      }
      time_cnt5  =  TimerCounterGet(SOC_TMR_2_REGS,  TMR_TIMER12); 
      

      time_L_in  = time_cnt2 - time_cnt1;
      time_R_in  = time_cnt3 - time_cnt2;
      time_L_out = time_cnt4 - time_cnt3;
      time_R_out = time_cnt5 - time_cnt4;
      // write to trace buffer
      wr_circular_trace_buf(time_frame_len, &time_trace[0], TIME_TRACE_LEN);
      wr_circular_trace_buf(time_L_in , &time_trace[0], TIME_TRACE_LEN );
      wr_circular_trace_buf(time_R_in , &time_trace[0], TIME_TRACE_LEN );
      wr_circular_trace_buf(time_L_out, &time_trace[0], TIME_TRACE_LEN );
      wr_circular_trace_buf(time_R_out, &time_trace[0], TIME_TRACE_LEN );


      rx_cnt ++;
    }
  }
}

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





