/**************************************************************************
 *
 * Title: Functions to Read and Write ESCI data
 *
 * Filename: eSCI_library.c
 *
 *
 * First used on: MPC5554
 *
 * Compiler:
 *
 * Creation date:		02/21/06
 * $Author: Jyotsna Chitri
 *
 * Copyright Freescale Semiconductor Inc
 * 2006 All Rights Reserved
 *
 * Notes :
 * <RELEVANT information only - leave blank if none>
 *
 *
 * Revision History :
 *  $Date: 2006/09/13 20:16:20 $
 *
 *
 *************************************************************************/

#include "RAppID_Blockset.h"

circ_buff_t tx_buffers[num_sci_modules];
vuint32_t tx_in_progress_flags[num_sci_modules];
uint32_t buffer_overflow;

/*********************************************************************************
   Function Name :esci_check_transmit_flag_fnc()
   
   Description:To Poll for the status of the TDRE flag
   
   Inputs: SCI module Name
   
   Outputs: Boolean TDRE flag status
   
 **********************************************************************************/
uint8_t esci_check_transmit_flag_fnc(uint8_t sci_mod)
{
  uint8_t flag_status = 0;
  if(sci_mod == 1)
  {
    if (ESCI_A.SR.B.TDRE != 0)          /* Check for TDRE flag */
    flag_status = 1;
  }
  else if (sci_mod == 2)
  {
    if (ESCI_B.SR.B.TDRE != 0)          /* Check for TDRE flag */
    flag_status = 1;
  }
  return(flag_status);
}

/*********************************************************************************
   Function Name :esci_check_receive_flag_fnc()
   
   Description:To Poll for the status of the RDRF flag
   
   Inputs: SCI module Name
   
   Outputs: Boolean RDRF flag status
   
 **********************************************************************************/
uint8_t esci_check_receive_flag_fnc(uint8_t sci_mod)
{
  uint8_t flag_status = 0;
  if(sci_mod == 1)
  {
    if (ESCI_A.SR.B.RDRF != 0)          /* Check for RDRF flag */
    flag_status = 1;
  }
  else if (sci_mod == 2)
  {
    if (ESCI_B.SR.B.RDRF != 0)          /* Check for RDRF flag */
    flag_status = 1;
  }
  return(flag_status);
}

/*********************************************************************************
   Function Name :esci_clear_transmit_flag_fnc()
   
   Description:To Clear the TDRE Transmit flag
   
   Inputs: SCI module Name
   
   Outputs: None
   
 **********************************************************************************/
void esci_clear_transmit_flag_fnc(uint8_t sci_mod)
{
  if(sci_mod == 1)
  {
    if (ESCI_A.SR.B.TDRE)
    ESCI_A.SR.R = 0x80000000;           /* Clear TDRE flag */
  }
  else if (sci_mod == 2)
  {
    if (ESCI_B.SR.B.TDRE)
    ESCI_B.SR.R = 0x80000000;           /* Clear TDRE flag */
  }
}

/*********************************************************************************
   Function Name :esci_clear_receive_flag_fnc()
   
   Description:To Clear the RDRF receive flag
   
   Inputs: SCI module Name
   
   Outputs: None
   
 **********************************************************************************/
void esci_clear_receive_flag_fnc(uint8_t sci_mod)
{
  if(sci_mod == 1)
  {
    if (ESCI_A.SR.B.RDRF != 0)
    ESCI_A.SR.R = 0x20000000;           /* Clear RDRF flag */
  }
  else if (sci_mod == 2)
  {
    if (ESCI_B.SR.B.RDRF != 0)
    ESCI_B.SR.R = 0x20000000;           /* Clear RDRF flag */
  }
}

/*********************************************************************************
   Function Name :esci_transmit_fnc()
   
   Description:To Transmit the data over eSCI
   
   Inputs: SCI module, Data
   
   Outputs:None
   
 **********************************************************************************/
void esci_transmit_fnc(uint8_t sci_mod,uint16_t data )
{
  if(sci_mod == 1)
  {
    if(ESCI_A.CR1.R & 0x1000)
    ESCI_A.DR.R = ((data&0x100)<<6) | (data & 0xFF);
    else
    ESCI_A.DR.R = (data & 0xFF);        /* Transmit Input Data */
  }
  else if (sci_mod == 2)
  {
    if(ESCI_B.CR1.R & 0x1000)
    ESCI_B.DR.R = ((data&0x100)<<6) | (data & 0xFF);
    else
    ESCI_B.DR.R = (data & 0xFF);        /* Transmit Input Data */
  }
}

/*********************************************************************************
   Function Name :esci_receive_fnc()
   
   Description:To Receive the data over eSCI
   
   Inputs: SCI module
   
   Outputs:Data Received
   
 **********************************************************************************/
uint16_t esci_receive_fnc(uint8_t sci_mod )
{
  uint16_t receive_data = 0;
  if(sci_mod == 1)
  {
    receive_data = ESCI_A.DR.R;         /* Receive Input Data */
    if(ESCI_A.CR1.R & 0x1000)
    receive_data = ((receive_data>>7)&0x100) | (receive_data & 0xFF);
    else
    receive_data &= 0xFF;
  }
  else if (sci_mod == 2)
  {
    receive_data = ESCI_B.DR.R;         /* Receive Input Data */
    if(ESCI_B.CR1.R & 0x1000)
    receive_data = ((receive_data>>7)&0x100) | (receive_data & 0xFF);
    else
    receive_data &= 0xFF;
  }

  return(receive_data);
}

/*********************************************************************************
   Function Name :esci_dma_data_update_fcn()
   
   Description:To Update the data to be transmitted over eSCI using DMA
   
   Inputs: SCI module, data buffer length, data buffer address
   
   Outputs:None
   
 **********************************************************************************/
void esci_dma_data_update_fcn(uint8_t sci_mod,int buff_len,uint32_t data_buf){

  if(sci_mod == 0)
  {

    EDMA.TCD[18].SADDR = (vuint32_t) data_buf; /* Source Address             */
    EDMA.TCD[18].DADDR = (vuint32_t) ESCIA_DR_L; /* Destination Address        */
    EDMA.TCD[18].BITER = buff_len;      /* Current "minor" iteration count */
    EDMA.TCD[18].CITER = buff_len;      /* Current "major" iteration count */
    EDMA.TCD[18].D_REQ = 0x01;          /* Disable the DMA channel when Done */
    EDMA.ERQRL.B.ERQ18 = 0x1;           /* Channel Enable Register */
    EDMA.CIRQR.R = 18;                  /* Clear the interrupt */
  }
  else if (sci_mod == 1)
  {
    EDMA.TCD[34].SADDR = (vuint32_t) data_buf; /* Source Address             */
    EDMA.TCD[34].DADDR = (vuint32_t) ESCIB_DR_L; /* Destination Address        */
    EDMA.TCD[34].BITER = buff_len;      /* Current "minor" iteration count */
    EDMA.TCD[34].CITER = buff_len;      /* Current "major" iteration count */
    EDMA.TCD[34].D_REQ = 0x01;          /* Disable the DMA channel when Done */
    // EDMA.ERQRH.B.ERQ34 = 0x1;           /* Channel Enable Register */   PWM Update for MPC5553
    EDMA.CIRQR.R = 34;
  }
}

/*********************************************************************************
   Function Name :esci_transmit_dma_fcn()
   
   Description:To send the buffer over eSCI using DMA
   
   Inputs: SCI module, data length, Data
   
   Outputs:None
   
 **********************************************************************************/

void esci_transmit_dma_fcn(sci_mod_t mod_num, uint32_t buff_len, const uint8_t
 *pData)
{
  uint32_t buff_start_addr, num_items;

  /* Make sure data added to buffer */
  if (!add_items(&tx_buffers[mod_num], pData, buff_len))
  {
    /* If no transmission in progress, set up DMA transfer from tail until
       head or end of buffer */
    if (!tx_in_progress_flags[mod_num])
    {
      tx_in_progress_flags[mod_num] = 1;

      buff_start_addr = get_data_start_address(&tx_buffers[mod_num]);
      num_items = get_num_items_to_send(&tx_buffers[mod_num]);

      /* This should never happen since we check that items were added to buffer
         by looking at the return value of add_items(). */
      if (num_items > 0)
      {
        esci_dma_data_update_fcn(mod_num,num_items,buff_start_addr);
      }
    }
  }
  else                                  /* buffer overflow */
  {
    buffer_overflow++;
  }
}

/*********************************************************************************
   Function Name :esci_dma_9bit_data_update_fcn()
   
   Description:To Update the data to be transmitted over eSCI using DMA
   
   Inputs: SCI module, data buffer length, data buffer address
   
   Outputs:None
   
 **********************************************************************************/
void esci_dma_9bit_data_update_fcn(uint8_t sci_mod,int buff_len,uint32_t
 data_buf){

  if(sci_mod == 0)
  {

    EDMA.TCD[18].SADDR = (vuint32_t) data_buf; /* Source Address             */
    EDMA.TCD[18].DADDR = (vuint32_t) ESCIA_DR_U; /* Destination Address        */
    EDMA.TCD[18].BITER = buff_len/2;    /* Current "minor" iteration count */
    EDMA.TCD[18].CITER = buff_len/2;    /* Current "major" iteration count */
    EDMA.TCD[18].D_REQ = 0x01;          /* Disable the DMA channel when Done */
    EDMA.ERQRL.B.ERQ18 = 0x1;           /* Channel Enable Register */
    EDMA.CIRQR.R = 18;                  /* Clear the interrupt */
  }
  else if (sci_mod == 1)
  {
    EDMA.TCD[34].SADDR = (vuint32_t) data_buf; /* Source Address             */
    EDMA.TCD[34].DADDR = (vuint32_t) ESCIB_DR_U; /* Destination Address        */
    EDMA.TCD[34].BITER = buff_len/2;    /* Current "minor" iteration count */
    EDMA.TCD[34].CITER = buff_len/2;    /* Current "major" iteration count */
    EDMA.TCD[34].D_REQ = 0x01;          /* Disable the DMA channel when Done */
    // EDMA.ERQRH.B.ERQ34 = 0x1;           /* Channel Enable Register */  PWM Update for MPC5553
    EDMA.CIRQR.R = 34;
  }
}

/*********************************************************************************
   Function Name :esci_transmit_9bit_dma_fcn()
   
   Description:To send the buffer over eSCI using DMA for  9 bit data format
   
   Inputs: SCI module, data length, Data
   
   Outputs:None
   
 **********************************************************************************/

void esci_transmit_9bit_dma_fcn(sci_mod_t mod_num, uint32_t buff_len, const
 uint8_t *pData)
{
  uint32_t buff_start_addr, num_items;

  /* Make sure data added to buffer */
  if (!add_items(&tx_buffers[mod_num], pData, buff_len))
  {
    /* If no transmission in progress, set up DMA transfer from tail until
       head or end of buffer */
    if (!tx_in_progress_flags[mod_num])
    {
      tx_in_progress_flags[mod_num] = 1;

      buff_start_addr = get_data_start_address(&tx_buffers[mod_num]);
      num_items = get_num_items_to_send(&tx_buffers[mod_num]);

      /* Check if multiples of 2 for 2 bytes */
      if (num_items %2 == 0)
      {
        esci_dma_9bit_data_update_fcn(mod_num,num_items,buff_start_addr);
      }

      else
      {
        num_items = num_items - (num_items%2);
        if(num_items > 1)               /*Send data in multiples of 2 and drop the last byte */
        esci_dma_9bit_data_update_fcn(mod_num,num_items,buff_start_addr);
      }
    }
  }

  else                                  /* buffer overflow */
  {
    buffer_overflow++;
  }
}

/*********************************************************************************
   Function Name :clear_dma_esci_interrupt_flag_fnc()
   
   Description:To Clear the interrupt flag for the DMA channel
   
   Inputs: SCI module Name
   
   Outputs: None
   
 **********************************************************************************/
void clear_dma_esci_interrupt_flag_fnc(uint8_t sci_mod)
{
  if(sci_mod == 1)
  {
    EDMA.CIRQR.R = 18;                  /* Clear the interrupt */
  }
  else if (sci_mod == 2)
  {
    EDMA.CIRQR.R = 34;                  /* Clear the interrupt */
  }
}
/*********************************************************************************
   Function Name :esci_check_9bit_fnc()
   
   Description:To check if 9 bit data format is selected for the sci module
   
   Inputs: SCI module Name
   
   Outputs: Boolean flag status if 9 bit is selected
   
 **********************************************************************************/
uint8_t esci_check_9bit_fnc(uint8_t sci_mod)
{
  uint8_t flag_status = 0;

  if(sci_mod == 0)
  {
    if(ESCI_A.CR1.R & 0x1000)
    {
      flag_status = 1;
    }
  }
  else if (sci_mod == 1)
  {
    if(ESCI_B.CR1.R & 0x1000)
    {
      flag_status = 1;
    }
  }
  return(flag_status);
}

/*********************************************************************************
   Function Name :esci_package_to_transmit_fnc()
   
   Description:To package the data and to transmit the data over eSCI using DMA
   
   Inputs: SCI module, Data
   
   Outputs:None
   
 **********************************************************************************/
void esci_package_to_transmit_fnc(uint8_t sci_mod,uint16_t data )
{
  uint8_t bytes[2];

  if(esci_check_9bit_fnc(sci_mod))
  {

    bytes[0] = (((data & 0x100)<<6)>>8);
    bytes[1] = (data & 0xFF);
    esci_transmit_9bit_dma_fcn( sci_mod, 2, bytes);
  }
  else
  {
    bytes[0] = (data & 0xFF);
    esci_transmit_dma_fcn( sci_mod, 1, bytes);
  }
}
