/** @file sci.c 
*   @brief SCI Driver Inmplmentation File
*   @date 15.March.2013
*   @version 03.05.00
*
*   (c) Texas Instruments 2009-2013, All rights reserved.
*/

/* USER CODE BEGIN (0) */
/* USER CODE END */

#include "hw_sci.h"
#include "sys_common.h"
#include "bl_config.h"

/* USER CODE BEGIN (1) */
/* USER CODE END */
/** @struct g_sciTransfer
*   @brief Interrupt mode globals
*
*/
static struct g_sciTransfer
{
    uint32   mode;
    uint32   length;
    uint8    * data;
} g_sciTransfer_t[2U];


/** @fn void sciInit(void)
*   @brief Initializes the SCI Driver
*
*   This function initializes the SCI module.
*/
void sciInit(void)
{
/* USER CODE BEGIN (2) */
/* USER CODE END */
    /** @b initialize @b SCI */
    unsigned f;
    double   vclk = VCLK_FREQ * 1000000;

    /** - bring SCI out of reset */
    sciREG1->GCR0 = 1U;

    /** - Disable all interrupts */
    sciREG1->CLRINT    = 0xFFFFFFFFU;
    sciREG1->CLRINTLVL = 0xFFFFFFFFU;

    /** - global control 1 */
    sciREG1->GCR1 = (1U << 25U)  /* enable transmit */
                  | (1U << 24U)  /* enable receive */
                  | (1U << 5U)   /* internal clock (device has no clock pin) */
                  | ((2U-1U) << 4U)  /* number of stop bits */
                  | (0U << 3U)  /* even parity, otherwise odd */
                  | (0U << 2U)  /* enable parity */
                  | (1U << 1U);  /* asynchronous timing mode */

    /** - set baudrate */
    f = sciREG1->GCR1 & 2 ? 16 : 1;
    sciREG1->BRS = ((unsigned)((vclk /(f*UART_BAUDRATE) + 0.5)) - 1) & 0x00FFFFFF;

    //sciREG1->BRS = 520U;  /* baudrate */

    /** - set baudrate */
    //sciREG1->BAUD = 260;  /* baudrate --- 19200 from 80MHz VCLK*/

    /** - tranmision length */
    sciREG1->FORMAT = 8U - 1U;  /* length */

    /** - set SCI pins functional mode */
    sciREG1->FUN = (1U << 2U)  /* tx pin */
                 | (1U << 1U)  /* rx pin */
                 | (0U);  /* clk pin */

    /** - set SCI pins default output value */
    sciREG1->DOUT = (0U << 2U)  /* tx pin */
                  | (0U << 1U)  /* rx pin */
                  | (0U);  /* clk pin */

    /** - set SCI pins output direction */
    sciREG1->DIR = (0U << 2U)  /* tx pin */
                 | (0U << 1U)  /* rx pin */
                 | (0U);  /* clk pin */

    /** - set SCI pins open drain enable */
    sciREG1->ODR = (0U << 2U)  /* tx pin */
                 | (0U << 1U)  /* rx pin */
                 | (0U);  /* clk pin */

    /** - set SCI pins pullup/pulldown enable */
    sciREG1->PD = (0U << 2U)  /* tx pin */
                | (0U << 1U)  /* rx pin */
                | (0U);  /* clk pin */

    /** - set SCI pins pullup/pulldown select */
    sciREG1->PSL = (1U << 2U)  /* tx pin */
                 | (1U << 1U)  /* rx pin */
                 | (1U);  /* clk pin */

    /** - set interrupt level */
    sciREG1->SETINTLVL = (0U << 26U)  /* Framing error */
                       | (0U << 25U)  /* Overrun error */
                       | (0U << 24U)  /* Pariry error */
                       | (0U << 9U)  /* Receive */
                       | (0U << 8U)  /* Transmit */
                       | (0U << 1U)  /* Wakeup */
                       | (0U);  /* Break detect */

    /** - set interrupt enable */
    sciREG1->SETINT = (0U << 26U)  /* Framing error */
                    | (0U << 25U)  /* Overrun error */
                    | (0U << 24U)  /* Pariry error */
                    | (0U << 9U)  /* Receive */
                    | (0U << 1U)  /* Wakeup */
                    | (0U);  /* Break detect */

    /** - inialise global transfer variables */
    g_sciTransfer_t[0U].mode   = 0U << 8U;
    g_sciTransfer_t[0U].length = 0U;

    /** - Finaly start SCI1 */
    sciREG1->GCR1 |= (1U << 7U);


    /** @b intalise @b SCI2 */

    /** - bring SCI out of reset */
    sciREG2->GCR0 = 1U;

    /** - Disable all interrupts */
    sciREG2->CLRINT    = 0xFFFFFFFFU;
    sciREG2->CLRINTLVL = 0xFFFFFFFFU;

    /** - global control 1 */
    sciREG2->GCR1 = (1U << 25U)  /* enable transmit */
                  | (1U << 24U)  /* enable receive */
                  | (1U << 5U)   /* internal clock (device has no clock pin) */
                  | ((2U-1U) << 4U)  /* number of stop bits */
                  | (0U << 3U)  /* even parity, otherwise odd */
                  | (0U << 2U)  /* enable parity */
                  | (1U << 1U);  /* asynchronous timing mode */

    /** - set baudrate */
    sciREG2->BRS = 520U;  /* baudrate */

    /** - tranmision length */
    sciREG2->FORMAT = 8U - 1U;  /* length */

    /** - set SCI pins functional mode */
    sciREG2->FUN = (1U << 2U)  /* tx pin */
                 | (1U << 1U)  /* rx pin */
                 | (0U);  /* clk pin */

    /** - set SCI pins default output value */
    sciREG2->DOUT = (0U << 2U)  /* tx pin */
                  | (0U << 1U)  /* rx pin */
                  | (0U);  /* clk pin */

    /** - set SCI pins output direction */
    sciREG2->DIR = (0U << 2U)  /* tx pin */
                 | (0U << 1U)  /* rx pin */
                 | (0U);  /* clk pin */

    /** - set SCI pins open drain enable */
    sciREG2->ODR = (0U << 2U)  /* tx pin */
                 | (0U << 1U)  /* rx pin */
                 | (0U);  /* clk pin */

    /** - set SCI pins pullup/pulldown enable */
    sciREG2->PD = (0U << 2U)  /* tx pin */
                | (0U << 1U)  /* rx pin */
                | (0U);  /* clk pin */

    /** - set SCI pins pullup/pulldown select */
    sciREG2->PSL = (1U << 2U)  /* tx pin */
                 | (1U << 1U)  /* rx pin */
                 | (1U);  /* clk pin */

    /** - set interrupt level */
    sciREG2->SETINTLVL = (0U << 26U)  /* Framing error */
                       | (0U << 25U)  /* Overrun error */
                       | (0U << 24U)  /* Pariry error */
                       | (0U << 9U)  /* Receive */
                       | (0U << 8U)  /* Transmit */
                       | (0U << 1U)  /* Wakeup */
                       | (0U);  /* Break detect */

    /** - set interrupt enable */
    sciREG2->SETINT = (0U << 26U)  /* Framing error */
                    | (0U << 25U)  /* Overrun error */
                    | (0U << 24U)  /* Parity error */
                    | (0U << 9U)  /* Receive */
                    | (0U << 1U)  /* Wakeup */
                    | (0U);  /* Break detect */

    /** - inialise global transfer variables */
    g_sciTransfer_t[1U].mode   = 0U << 8U;
    g_sciTransfer_t[1U].length = 0U;

    /** - Finaly start SCI2 */
    sciREG2->GCR1 |= (1U << 7U);

/* USER CODE BEGIN (3) */
/* USER CODE END */
}

/** @fn void sciSetBaudrate(sciBASE_t *sci, uint32 baud)
*   @brief Change baudrate at runtime.
*   @param[in] sci  - sci module base address
*   @param[in] baud - baudrate in Hz
*
*   Change the SCI baudrate at runtime.
*/
void sciSetBaudrate(sciBASE_t *sci, uint32 baud)
{
    unsigned long   vclk = 80.000 * 1000000.0;
    uint32 f    = ((sci->GCR1 & 2U) == 2U) ? 16U : 1U;

/* USER CODE BEGIN (6) */
/* USER CODE END */

	/*SAFETYMCUSW 96 S MR:6.1 <REVIEWED> "Calculations including int and float cannot be avoided" */
    sci->BRS = ((uint32)((vclk /(f*baud) + 0.5)) - 1U) & 0x00FFFFFFU;

/* USER CODE BEGIN (7) */
/* USER CODE END */
}



/** @fn void sciSendByte(sciBASE_t *sci, uint8 byte)
*   @brief Send Byte
*   @param[in] sci  - sci module base address
*   @param[in] byte - byte to transfer
*
*   Sends a single byte in polling mode, will wait in the
*   routine until the transmit buffer is empty before sending
*   the byte.  Use sciIsTxReady to check for Tx buffer empty
*   before calling sciSendByte to avoid waiting.
*/
void sciSendByte(sciBASE_t *sci, uint8 byte)
{
/* USER CODE BEGIN (9) */
/* USER CODE END */

    while ((sci->FLR & SCI_TX_INT) == 0U) 
    { 
	} /* Wait */
    sci->TD = byte;

/* USER CODE BEGIN (10) */
/* USER CODE END */
}


/** @fn void sciSend(sciBASE_t *sci, uint32 length, uint8 * data)
*   @brief Send Data
*   @param[in] sci    - sci module base address
*   @param[in] length - number of data words to transfer
*   @param[in] data   - pointer to data to send
*
*   Send a block of data pointed to by 'data' and 'length' bytes
*   long.  If interrupts have been enabled the data is sent using
*   interrupt mode, otherwise polling mode is used.  In interrupt
*   mode transmission of the first byte is started and the routine
*   returns immediately, sciSend must not be called again until the
*   transfer is complete, when the sciNotification callback will
*   be called.  In polling mode, sciSend will not return  until 
*   the transfer is complete.
*
*   @note if data word is less than 8 bits, then the data must be left
*         aligned in the data byte.
*/
void sciSend(sciBASE_t *sci, uint32 length, uint8 * data)
{
    uint32 index = sci == sciREG1 ? 0U : 1U;

    if ((g_sciTransfer_t[index].mode & SCI_TX_INT) != 0U)
    {
        /* we are in interrupt mode */
        
        g_sciTransfer_t[index].length = length;
        g_sciTransfer_t[index].data   = data;

        /* start transmit by sending first byte */        
        sci->TD     = *g_sciTransfer_t[index].data++ ;
        sci->SETINT = SCI_TX_INT;
    }
    else
    {
        /* send the data */
        while (length-- > 0U)
        {
            while ((sci->FLR & SCI_TX_INT) == 0U)
            { 
	        } /* Wait */
            sci->TD = *data++;
        }
    }

/* USER CODE BEGIN (11) */
/* USER CODE END */
}


/** @fn uint32 sciReceiveByte(sciBASE_t *sci)
*   @brief Receive Byte
*   @param[in] sci - sci module base address
*
*   @return Received byte
*
*    Receives a single byte in polling mode.  If there is
*    not a byte in the receive buffer the routine will wait
*    until one is received.   Use sciIsRxReady to check to
*    see if the buffer is full to avoid waiting.
*/
uint32 sciReceiveByte(sciBASE_t *sci)
{
/* USER CODE BEGIN (14) */
/* USER CODE END */

    while ((sci->FLR & SCI_RX_INT) == 0U) 
    { 
	} /* Wait */

    return (sci->RD & 0x000000FFU);
}


/** @fn void sciReceive(sciBASE_t *sci, uint32 length, uint8 * data)
*   @brief Receive Data
*   @param[in] sci    - sci module base address
*   @param[in] length - number of data words to transfer
*   @param[in] data   - pointer to data buffer
*
*   Receive a block of 'length' bytes long and place it into the 
*   data buffer pointed to by 'data'.  If interrupts have been 
*   enabled the data is received using interrupt mode, otherwise
*   polling mode is used.  In interrupt mode receive is setup and
*   the routine returns immediately, sciReceive must not be called 
*   again until the transfer is complete, when the sciNotification 
*   callback will be called.  In polling mode, sciReceive will not
*   return  until the transfer is complete.
*/
void sciReceive(sciBASE_t *sci, uint32 length, uint8 * data)
{
/* USER CODE BEGIN (15) */
/* USER CODE END */

    if ((sci->SETINT & SCI_RX_INT) == SCI_RX_INT)
    {
        /* we are in interrupt mode */
        uint32 index = sci == sciREG1 ? 0U : 1U;
        
        /* clear error flags */
        sci->FLR = SCI_FE_INT | SCI_OE_INT | SCI_PE_INT;

        g_sciTransfer_t[index].length = length;
        g_sciTransfer_t[index].data   = data;
    }
    else
    {   
        while (length-- > 0U)
        {
            while ((sci->FLR & SCI_RX_INT) == 0U) 
		    { 
	        } /* Wait */
            *data++ = (uint8)(sci->RD & 0x000000FFU);
        }
    }
/* USER CODE BEGIN (16) */
/* USER CODE END */
}



void UART_send32BitData(sciBASE_t *sci, uint32 data)
{
	uint8 c_get ;
  	volatile int i = 0;
  	for( i = 8 ; i > 0 ; i-- )
  	{
 		c_get = (data >> 28) & 15 ;
		if( c_get > 9 )
			c_get += 7 ;
		c_get += 48 ;

		while ((sci->FLR & SCI_TX_INT) == 0) { /* wait */ };
		sci->TD = c_get;
		data = data << 4 ;
	}
}

/**
  * @brief  Print a string on the HyperTerminal
  * @param  s: The string to be printed
  * @retval None
  */
void UART_putString(sciBASE_t *sci, char *s)
{
  while (*s != '\0')
  {
    UART_putChar(sci, *s);
    s++;
  }
}


/**
  * @brief  Print a character on the HyperTerminal
  * @param  c: The character to be printed
  * @retval None
  */
void UART_putChar(sciBASE_t *sci, char c)
{
	  while (!(sci->FLR & 0x800));
	  sci->TD = c;
  {
  }
}



asm(" nop");

