/******************************************************************************
* FILE PURPOSE: Test Driver for tx+rx
*******************************************************************************
*
* FILE NAME: test_tx_rx.c
*
* DESCRIPTION: This file contains test driver for tx+rx
*       
*
* HISTORY:
* 02/25/2009          S.Yim   initial revision.
*
* LIST OF FUNCTIONS:
*
* Copyright (c) 2008 Texas Instruments Inc.  All rights reserved.
******************************************************************************/
#include "DSP28x_Project.h"
#include "phy_tx.h"
#include "prime_phy.h"
#include "hal_afe.h"
#include "f28335.h"
#include <phy.h>
#include <phy_rx.h>

/* Test Sweep all ppdu payload len */
#define PHY_TX_TEST_SWEEP_PPDU_LEN   0                    

/* Default phy cfg */
#define PHY_TX_TEST_DEFAULT_PPDU_LEN  40
#define PHY_TX_TEST_DEFAULT_LEVEL     3                   // max -6 dB 
#define PHY_TX_TEST_DEFAULT_MOD       PRIME_PRCL_DBPSK_F  // bpsk + fec
#define PHY_TX_TEST_DEFAULT_TIME      0                   // immediate start

/* Defines */
#define PHY_TX_TEST_PPDU_LENGTH 2268 
#define PHY_TX_TEST_BUF_SIZE    1200 
#define PHY_TX_TEST_HDR_SIZE      4  //16*4=64bits enought for MAC_H (54)

/***********************************************************************/
/* Data                                                                */
/***********************************************************************/
/* Define data buffers */
int16 hdrBuf[PHY_TX_TEST_HDR_SIZE];
int16 ppduBuf[PHY_TX_TEST_BUF_SIZE];
PHY_tx_ppdu_t PHY_tx_ppdu_s;

volatile Uint16 txSymbDone;            // TX symbol done flag
volatile UINT16 afeReadyFlag;

interrupt void PHY_tx_cpuTimer0_isr(void);
interrupt void PHY_tx_dintch2_isr(void);
interrupt void PHY_rx_dintch1_isr(void);

#ifdef FLASH
/***********************************************************************/
/* Set up for flash                                                    */
/***********************************************************************/
/* Following symbols should be referred to linker file */
extern Uint16 secureRamFuncs_loadstart, secureRamFuncs_loadend, secureRamFuncs_runstart;
extern Uint16 isrRamFuncs_loadstart, isrRamFuncs_loadend, isrRamFuncs_runstart;
extern Uint16 phyRamFuncs_loadstart, phyRamFuncs_loadend, phyRamFuncs_runstart;  

void config_flash(void)
{
  /* Copy time critical code and Flash setup code to RAM */
  memcpy(&secureRamFuncs_runstart,
         &secureRamFuncs_loadstart,
         &secureRamFuncs_loadend - &secureRamFuncs_loadstart);

  memcpy(&isrRamFuncs_runstart,
         &isrRamFuncs_loadstart,
         &isrRamFuncs_loadend - &isrRamFuncs_loadstart);

  memcpy(&phyRamFuncs_runstart,
         &phyRamFuncs_loadstart,
         &phyRamFuncs_loadend - &phyRamFuncs_loadstart);
  
  // Call Flash Initialization to setup flash waitstates
  // This function must reside in RAM
  // InitFlash code in CSL.lib
  InitFlash();  // Call the flash wrapper init function
}
#endif

void cb_tx(PHY_ev_t eventID, PHY_cbData_t *data_p);
void cb_sync(PHY_ev_t eventID, PHY_cbData_t *data_p);
void cb_ppdu(PHY_ev_t ev, PHY_cbData_t *data_p);

/***********************************************************************/
/* PHY TX callback                                                     */
/***********************************************************************/
Uint16 cb_ev=0;
int txppdu_cnt = 0;

void cb_tx(PHY_ev_t eventID, PHY_cbData_t *data_p)
{
  cb_ev = eventID;

  txppdu_cnt++;

  /* flash led every 8 pkt for testing */
  if ((txppdu_cnt & 0x7) == 0)
    GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1;    
}

/***********************************************************************/
/* Call back for PHY_rxPpduStart                                           */
/***********************************************************************/
int rxppdu_cnt = 0, rxppdu_done = 0;
void cb_ppdu(PHY_ev_t ev, PHY_cbData_t *data_p)
{
  if (data_p->status == PHY_STAT_SUCCESS)
  {
    /* ok to read data */
    rxppdu_cnt++;

    /* release */
    PHY_rxPpduRelease((PHY_rxPpdu_t *)(data_p->cbParms.rxPpdu.ppduInfoAddr));

    /* flash led every 8 pkt for testing */
    if ((rxppdu_cnt & 0x7) == 0)
      GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;   
    
    rxppdu_done = 1;

  }

}

/***********************************************************************/
/* Call back for PHY_rxStart                                           */
/***********************************************************************/
void cb_sync(PHY_ev_t eventID, PHY_cbData_t *data_p)
{
  if (data_p->status == PHY_STAT_SUCCESS)
    {
      /* Start PPDU then */
      PHY_rxPpduStart(cb_ppdu);
    }
}

/***********************************************************************/
/* Main                                                                */
/***********************************************************************/
UINT32 txstart_cnt=0;
const char *ver_p;
void main(void)
{
  Uint16 idx, i; //maxLen;
  Uint16 *buf_p;
  PHY_txGetData_t phyGetData;
  HAL_afe_prfParms_t afePrfParms;

  afeReadyFlag = 0;

  /* F28335 Initialize */
  F28335_init();

#ifdef FLASH
  /* Configure for flash */
  config_flash();
#endif

  /* ISR functions */
  /* For PHY TX, using CPU timer0 & DMA channel 2 intterrupts */
  EALLOW;
  PieVectTable.TINT0 = &PHY_tx_cpuTimer0_isr;
#ifndef F2806X
  PieVectTable.DINTCH2 = &PHY_tx_dintch2_isr;
  PieVectTable.DINTCH1 = &PHY_rx_dintch1_isr;
#else
  PieVectTable.DINT_CH2 = &PHY_tx_dintch2_isr;
  PieVectTable.DINT_CH1 = &PHY_rx_dintch1_isr;
#endif
  EDIS;

  /* LED set up */
  EALLOW; // below registers are "protected", allow access.
    
  //GPIO-34 - PIN FUNCTION = LED3 (for Release 1.1 and up F2833x controlCARDs)
  GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0;  // 0=GPIO,  1=ECAP1,  2=Resv,  3=Resv
  GpioCtrlRegs.GPBDIR.bit.GPIO34  = 1;          // 1=OUTput,  0=INput 

  //  GPIO-31 - PIN FUNCTION = LED2 (for Release 1.1 and up F2833x controlCARDs)
  GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 0;  // 0=GPIO,  1=CANTX-A,  2=XA17,  3=Resv
  GpioCtrlRegs.GPADIR.bit.GPIO31  = 1;          // 1=OUTput,  0=INput 
  
  EDIS; // Disable register access

  ver_p = PHY_getLibVersion();

  /* init AFE HAL driver*/
  /* HAL profile (tx/rx sampling and PWM frequencies */
  afePrfParms.rx_fs_kHz = HAL_AFE_KHZ_250;
  afePrfParms.tx_fs_kHz = HAL_AFE_KHZ_500;
  afePrfParms.tx_pwm_kHz = HAL_AFE_KHZ_1000;

  HAL_afeInit(&afePrfParms);

  /* init_PHY */
  PHY_txInit();
  PHY_rxInit();

  EnableInterrupts();

  /* Initialize TX PPDU data buffer */
  PHY_tx_ppdu_s.length = PHY_TX_TEST_DEFAULT_PPDU_LEN;
  PHY_tx_ppdu_s.level  = PHY_TX_TEST_DEFAULT_LEVEL;
  PHY_tx_ppdu_s.mcs    = PHY_TX_TEST_DEFAULT_MOD;
  PHY_tx_ppdu_s.txTime = PHY_TX_TEST_DEFAULT_TIME;

  PHY_tx_ppdu_s.ppduHdr_p = (Uint16 *)&hdrBuf[0];
  PHY_tx_ppdu_s.ppduPld_p = (Uint16 *)&ppduBuf[0];

  /* Fill the ppduBuf with ramp data*/
  buf_p = (Uint16 *)ppduBuf;
  for (idx = 0; idx < (PHY_TX_TEST_BUF_SIZE); idx++)
    {
      *buf_p++ = ((((idx & 127) << 1) + 1) << 8) | ((idx & 127) << 1);
    }

  buf_p = (Uint16 *)hdrBuf;
  for (i = 0; i < PHY_TX_TEST_HDR_SIZE; i++)
    {
      *buf_p++ = ((((i & 127) << 1) + 1) << 8) | ((i & 127) << 1);
    }
 
  /* Start PHY Rx */
  PHY_rxStart(0xFFFF, cb_sync);
  
  /* Start TX for the first time */
  PHY_txPpdu(&PHY_tx_ppdu_s, cb_tx);
  
  /* run state machine */
  while(1)
  {
    // wait for either tx or rx has something
    while((afeReadyFlag==0) && (txSymbDone == 0));
     
    if (afeReadyFlag == 1)
    {
      /* Clear AFE ready flag */
      afeReadyFlag = 0;
        
      /* Run PHY Rx */
      PHY_rxSmRun();

      /* Check if RX PPDU done */
      if (rxppdu_done == 1)
      {
        rxppdu_done = 0;

        /* Get the current absolute time */
        PHY_txGet(PHY_TIMER, &phyGetData);

        /* Start 5 symbols later */
        PHY_tx_ppdu_s.txTime = (phyGetData.currTime - 224*5) & 0xFFFFF;


	txstart_cnt++;
        PHY_txPpdu(&PHY_tx_ppdu_s, cb_tx);
      }
    }
    
    if (txSymbDone == 1)
    {
      /* Clear the symbol done flag */
      txSymbDone = 0;
        
      /* State transition */
      PHY_txSmRun();
        
      if(cb_ev == PHY_EV_TX_PPDU_DONE)
      {
        cb_ev = 0;
      }
    }
  }
}

/***********************************************************************/
/* ISR for CPU timer 0                                                 */
/***********************************************************************/
#ifdef FLASH
#pragma CODE_SECTION(PHY_tx_cpuTimer0_isr, "isrRamFuncs");
#endif
interrupt void PHY_tx_cpuTimer0_isr(void)
{
  txSymbDone = 1; 
  HAL_cpuTint0Func();
}

/***********************************************************************/
/* ISR for DMA channel 2                                               */
/***********************************************************************/
#ifdef FLASH
#pragma CODE_SECTION(PHY_tx_dintch2_isr, "isrRamFuncs");
#endif
interrupt void PHY_tx_dintch2_isr(void)
{
  txSymbDone = 1; 
  HAL_afeTxDmaCh2IntFunc();
}

/***********************************************************************/
/* Rx AFE ISR                                                          */
/***********************************************************************/
#ifdef FLASH
#pragma CODE_SECTION(PHY_rx_dintch1_isr, "isrRamFuncs");
#endif

interrupt void PHY_rx_dintch1_isr(void)
{
  /* Set ready flag */
  afeReadyFlag = 1;

  /* Call HAL AFE function for dma handling */
  HAL_afeRxDmaCh1IntFunc();
}





