/******************************************************************************
*@file  : spl_uart.c
*@brief : UART SPL module driver
******************************************************************************/

#include "spl_uart.h"

UART_TypeDef *g_DebugUart = NULL;   //printf UARTx
  
/**
  * @brief  Deinitializes the UARTx peripheral registers to their default reset values.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @retval None
  */
void UART_DeInit(UART_TypeDef* UARTx)
{
  /* Check the parameters */
  assert_param(IS_UART_ALL_PERIPH(UARTx));

  if (UARTx == UART1)
  {
    __RCC_UART1_RESET();     
  }
  else if (UARTx == UART2)
  {
    __RCC_UART2_RESET();     
  }
  else if (UARTx == UART3)
  {   
    __RCC_UART3_RESET();
  }    
  else if (UARTx == UART4)
  {
    __RCC_UART4_RESET();
  }
}

/**
  * @brief  Initializes the UARTx peripheral according to the specified
  *         parameters in the UART_InitStruct .
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART UART peripheral.
  * @param  UART_InitStruct: pointer to a UART_InitTypeDef structure that contains
  *         the configuration information for the specified UART peripheral.
  * @retval None
  */
void UART_Init(UART_TypeDef* UARTx, UART_InitTypeDef* UART_InitStruct)
{
    uint32_t ibaud, fbaud;
    uint64_t tmp;
    uint32_t pclk = 0x00;    
    RCC_ClocksTypeDef RCC_ClocksStatus;

    /* Check the parameters */
    assert_param(IS_UART_ALL_PERIPH(UARTx));
    assert_param(IS_UART_WORDLENGTH(UART_InitStruct->WordLength));
    assert_param(IS_UART_STOPBITS(UART_InitStruct->StopBits));
    assert_param(IS_UART_PARITY(UART_InitStruct->Parity));
    assert_param(IS_UART_MODE(UART_InitStruct->Mode));
    assert_param(IS_UART_HARDWARE_FLOW_CONTROL(UART_InitStruct->HwFlowCtl));
    
    /* Set the UART Communication parameters */
    UARTx->CR3 = UART_InitStruct->WordLength | UART_CR3_FEN | UART_InitStruct->StopBits | UART_InitStruct->Parity;
    UARTx->CR1 = UART_InitStruct->HwFlowCtl | UART_InitStruct->Mode;
    
    if (UART_InitStruct->Mode == UART_MODE_HALF_DUPLEX) 
    {
        SET_BIT(UARTx->CR2, UART_CR2_HDSEL);
    }

    /*---------------------------- UART BRR Configuration -----------------------*/
    /* Configure the UART Baud Rate */
    RCC_GetClocksFreq(&RCC_ClocksStatus);

    if ((UARTx == UART1))
    {
        pclk = RCC_ClocksStatus.PCLK2_Frequency;
    }
    else
    {
        pclk = RCC_ClocksStatus.PCLK1_Frequency;
    }

    /* Integral part */
    ibaud = pclk / (UART_InitStruct->BaudRate * 16);

    /* Fractional part */
    tmp = pclk % (UART_InitStruct->BaudRate * 16);
    tmp = (tmp * 1000000) / (UART_InitStruct->BaudRate * 16);
    fbaud     = (tmp * 64 + 500000) / 1000000;

    if (fbaud >= 64) 
    {
        MODIFY_REG(UARTx->BRR, UART_BRR_IBAUD_Msk, ((ibaud + 1) << UART_BRR_IBAUD_Pos));
        MODIFY_REG(UARTx->BRR, UART_BRR_FBAUD_Msk, (0 << UART_BRR_FBAUD_Pos));
    }
    else 
    {
        MODIFY_REG(UARTx->BRR, UART_BRR_IBAUD_Msk, (ibaud << UART_BRR_IBAUD_Pos));
        MODIFY_REG(UARTx->BRR, UART_BRR_FBAUD_Msk, (fbaud << UART_BRR_FBAUD_Pos));
    }
}

/**
  * @brief  Fills each UART_InitStruct member with its default value.
  * @param  UART_InitStruct: pointer to a UART_InitTypeDef structure which will
  *         be initialized.
  * @retval None
  */
void UART_StructInit(UART_InitTypeDef* UART_InitStruct)
{
  /* UART_InitStruct members default value */
  UART_InitStruct->BaudRate     = 9600;
  UART_InitStruct->WordLength   = UART_WORDLENGTH_8B;
  UART_InitStruct->StopBits     = UART_STOPBITS_1;
  UART_InitStruct->Parity       = UART_PARITY_NONE ;
  UART_InitStruct->Mode         = UART_MODE_RX | UART_MODE_TX;
  UART_InitStruct->HwFlowCtl    = UART_HWCONTROL_NONE;  
}

/**
  * @brief  Enables or disables the specified UART FIFO(TXFIFO and RXFIFO).
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  NewState: new state of the UARTx peripheral.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void UART_FIFOCmd(UART_TypeDef* UARTx, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_UART_ALL_PERIPH(UARTx));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  
  if (NewState != DISABLE)
  {
    /* Enable the selected UART by setting the UE bit in the CR1 register */
    UARTx->CR3 |= (UART_CR3_FEN);
  }
  else
  {
    /* Disable the selected UART by clearing the UE bit in the CR1 register */
    UARTx->CR3 &= ~(UART_CR3_FEN);
  }
}

/**
  * @brief  Set the specified UART FIFO level for triggering interrupt(TXFIFO and RXFIFO).
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  TXFIFO_Level: Specify the TX FIFO level for triggering TXI.
  *           TXFIFO_Level can be one of the following values:
  *             @arg   UART_TX_FIFO_1_16: TXI happen when 0 data   in TXFIFO
  *             @arg   UART_TX_FIFO_1_8:  TXI happen when 2 datas  in TXFIFO
  *             @arg   UART_TX_FIFO_1_4:  TXI happen when 4 datas  in TXFIFO
  *             @arg   UART_TX_FIFO_1_2:  TXI happen when 8 datas  in TXFIFO
  *             @arg   UART_TX_FIFO_3_4:  TXI happen when 12 datas in TXFIFO
  *             @arg   UART_TX_FIFO_7_8:  TXI happen when 14 datas in TXFIFO
  * @note  TXI happened only at the point when the data quantity in TXFIFO changes to one of the values above.
 
  * @param  RXFIFO_Leve: Specify the RX FIFO level for triggering RXI
  *           RXFIFO_Level can be one of the following values:
  *             @arg   UART_RX_FIFO_1_16: RXI happen when 1 data   in RXFIFO
  *             @arg   UART_RX_FIFO_1_8:  RXI happen when 2 datas  in RXFIFO
  *             @arg   UART_RX_FIFO_1_4:  RXI happen when 4 datas  in RXFIFO
  *             @arg   UART_RX_FIFO_1_2:  RXI happen when 8 datas  in RXFIFO
  *             @arg   UART_RX_FIFO_3_4:  RXI happen when 12 datas in RXFIFO
  *             @arg   UART_RX_FIFO_7_8:  RXI happen when 14 datas in RXFIFO
  * @note  RXI happened only at the point when the data quantity in RXFIFO changes to one of the values above.

  * @retval None
  */
void UART_FIFO_Level_Set(UART_TypeDef* UARTx, uint32_t TXFIFO_Level, uint32_t RXFIFO_Level)
{
  /* Check the parameters */
    assert_param(IS_UART_ALL_PERIPH(UARTx));
    assert_param(IS_UART_TX_FIFO_LEVEL(TXFIFO_Level));
    assert_param(IS_UART_RX_FIFO_LEVEL(RXFIFO_Level));
  
    UARTx->CR3 &= ~(UART_CR3_RXIFLSEL | UART_CR3_TXIFLSEL);
  
    UARTx->CR3 |= TXFIFO_Level | RXFIFO_Level;
}

/**
  * @brief  Set the specified UART TX FIFO level for triggering TXI.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  TXFIFO_Level: Specify the TX FIFO level for triggering TXI.
  *           TXFIFO_Level can be one of the following values:
  *             @arg   UART_TX_FIFO_1_16: TXI happen when 0 data   left in TXFIFO
  *             @arg   UART_TX_FIFO_1_8:  TXI happen when 2 datas  left in TXFIFO
  *             @arg   UART_TX_FIFO_1_4:  TXI happen when 4 datas  left in TXFIFO
  *             @arg   UART_TX_FIFO_1_2:  TXI happen when 8 datas  left in TXFIFO
  *             @arg   UART_TX_FIFO_3_4:  TXI happen when 12 datas left in TXFIFO
  *             @arg   UART_TX_FIFO_7_8:  TXI happen when 14 datas left in TXFIFO
  * @note  TXI happened only at the point when the data quantity in TXFIFO changes to one of the values above.
  *
  * @retval None
  */
void UART_TX_FIFO_Level_Set(UART_TypeDef* UARTx, uint32_t TXFIFO_Level)
{
  /* Check the parameters */
    assert_param(IS_UART_ALL_PERIPH(UARTx));
    assert_param(IS_UART_TX_FIFO_LEVEL(TXFIFO_Level));
  
    UARTx->CR3 &= ~(UART_CR3_TXIFLSEL);
  
    UARTx->CR3 |= TXFIFO_Level;
}

/**
  * @brief  Set the specified UART RX FIFO level for triggering RXI.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  RXFIFO_Leve: Specify the RX FIFO level for triggering RXI
  *           RXFIFO_Level can be one of the following values:
  *             @arg   UART_RX_FIFO_1_16: RXI happen when 1 data   in RXFIFO
  *             @arg   UART_RX_FIFO_1_8:  RXI happen when 2 datas  in RXFIFO
  *             @arg   UART_RX_FIFO_1_4:  RXI happen when 4 datas  in RXFIFO
  *             @arg   UART_RX_FIFO_1_2:  RXI happen when 8 datas  in RXFIFO
  *             @arg   UART_RX_FIFO_3_4:  RXI happen when 12 datas in RXFIFO
  *             @arg   UART_RX_FIFO_7_8:  RXI happen when 14 datas in RXFIFO
  * @note  RXI happened only at the point when the data quantity in RXFIFO changes to one of the values above.

  * @retval None
  */
void UART_RX_FIFO_Level_Set(UART_TypeDef* UARTx, uint32_t RXFIFO_Level)
{
  /* Check the parameters */
    assert_param(IS_UART_ALL_PERIPH(UARTx));
    assert_param(IS_UART_RX_FIFO_LEVEL(RXFIFO_Level));
  
    UARTx->CR3 &= ~(UART_CR3_RXIFLSEL);
  
    UARTx->CR3 |= RXFIFO_Level;
}

/**
  * @brief  Enables or disables the specified UART peripheral.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  NewState: new state of the UARTx peripheral.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void UART_Cmd(UART_TypeDef* UARTx, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_UART_ALL_PERIPH(UARTx));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  
  if (NewState != DISABLE)
  {
    /* Enable the selected UART by setting the UARTEN bit in the CR1 register */
    UARTx->CR1 |= UART_CR1_UARTEN;
  }
  else
  {
    /* Disable the selected UART by clearing the UARTEN bit in the CR1 register */
    UARTx->CR1 &= ~(UART_CR1_UARTEN);
  }
}

/**
  * @brief  Sets the system clock prescaler.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  UART_Prescaler: specifies the prescaler clock. 
  * @note   The function is used for IrDA mode and 7816 Master mode.   
  * @retval None
  */
void UART_SetPrescaler(UART_TypeDef* UARTx, uint8_t UART_Prescaler)
{ 
  /* Check the parameters */
  assert_param(IS_UART_ALL_PERIPH(UARTx));
  
  /* Clear the UART prescaler */
  UARTx->GTPR &= UART_GTPR_PSC;
  /* Set the UART prescaler */
  UARTx->GTPR |= UART_Prescaler;
}

/**
  * @brief  Transmits single data through the UARTx peripheral.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  Data: the data to transmit.
  * @retval None
  */
void UART_SendData(UART_TypeDef* UARTx, uint16_t Data)
{
  /* Check the parameters */
  assert_param(IS_UART_ALL_PERIPH(UARTx));
  assert_param(IS_UART_DATA(Data)); 
    
  /* Transmit Data */
  UARTx->DR = (Data & (uint16_t)0x01FF);
}

/**
  * @brief  Returns the most recent received data by the UARTx peripheral.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @retval The received data.
  */
uint16_t UART_ReceiveData(UART_TypeDef* UARTx)
{
  /* Check the parameters */
  assert_param(IS_UART_ALL_PERIPH(UARTx));
  
  /* Receive Data */
  return (uint16_t)(UARTx->DR & (uint16_t)0x01FF);
}


/**
  * @brief  Sets the address of the UART node.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  UART_Address: Indicates the address of the UART node.
  * @retval None
  */
void UART_SetAddress(UART_TypeDef* UARTx, uint8_t UART_Address)
{
  /* Check the parameters */
  assert_param(IS_UART_ALL_PERIPH(UARTx));
  assert_param(IS_UART_ADDRESS(UART_Address)); 
    
  /* Clear the UART address */
  UARTx->CR2 &= ~UART_CR2_ADDR;
  /* Set the UART address node */
  UARTx->CR2 |= UART_Address;
}

/**
  * @brief  Determines if the UART is in mute mode or not.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  NewState: new state of the UART mute mode.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void UART_ReceiverWakeUpCmd(UART_TypeDef* UARTx, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_UART_ALL_PERIPH(UARTx));
  assert_param(IS_FUNCTIONAL_STATE(NewState)); 
  
  if (NewState != DISABLE)
  {
    /* Enable the UART mute mode  by setting the RWU bit in the CR1 register */
    UARTx->CR2 |= UART_CR2_RWU;
  }
  else
  {
    /* Disable the UART mute mode by clearing the RWU bit in the CR1 register */
    UARTx->CR2 &= ~(UART_CR2_RWU);
  }
}

/**
  * @brief  Selects the UART WakeUp method.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  UART_WakeUp: specifies the UART wakeup method.
  *          This parameter can be one of the following values:
  *            @arg UART_WakeUp_IdleLine: WakeUp by an idle line detection
  *            @arg UART_WakeUp_AddressMark: WakeUp by an address mark
  * @retval None
  */
void UART_WakeUpConfig(UART_TypeDef* UARTx, uint16_t UART_WakeUp)
{
  /* Check the parameters */
  assert_param(IS_UART_ALL_PERIPH(UARTx));
  assert_param(IS_UART_WAKEUP(UART_WakeUp));
  
  UARTx->CR2 &= ~UART_CR2_WAKE;
  UARTx->CR2 |= UART_WakeUp;
}


/*
  * @brief  Transmits break characters.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @retval None
  */
void UART_SendBreak(UART_TypeDef* UARTx)
{
  /* Check the parameters */
  assert_param(IS_UART_ALL_PERIPH(UARTx));
  
  /* Send break characters */
  UARTx->CR3 |= UART_CR3_BRK;
}


/**
  * @brief  Enables or disables the UART's Half Duplex communication.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  NewState: new state of the UART Communication.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void UART_HalfDuplexCmd(UART_TypeDef* UARTx, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_UART_ALL_PERIPH(UARTx));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  
  if (NewState != DISABLE)
  {
    /* Enable the Half-Duplex mode by setting the HDSEL bit in the CR3 register */
    UARTx->CR2 |= UART_CR2_HDSEL;
  }
  else
  {
    /* Disable the Half-Duplex mode by clearing the HDSEL bit in the CR3 register */
    UARTx->CR2 &= ~(UART_CR2_HDSEL);
  }
}


/**
  * @brief  Sets the specified UART guard time.
  * @param  UARTx: where x can be 1, 2, 3 or 6 to select the UART or 
  *         UART peripheral.
  * @param  UART_GuardTime: specifies the guard time.   
  * @retval None
  */
void UART_SetGuardTime(UART_TypeDef* UARTx, uint8_t UART_GuardTime)
{    
  /* Clear the UART Guard time */
  UARTx->GTPR &= UART_GTPR_GT_Msk;
  /* Set the UART guard time */
  UARTx->GTPR |= (uint16_t)((UART_GuardTime & 0xF) << UART_GTPR_GT_Pos);
}

/**
  * @brief  Enables or disables the UART's 7816 Master mode.
  * @param  UARTx: where x can be 1, 2, 3 or 6 to select the UART peripheral.
  * @param  NewState: new state of the 7816 Master mode.
  *          This parameter can be: ENABLE or DISABLE.      
  * @retval None
  */
void UART_SmartCardCmd(UART_TypeDef* UARTx, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));
    
  if (NewState != DISABLE)
  {
    /* Enable the 7816 Master mode by setting the SCEN bit in the CR2 register */
    UARTx->CR2 |= UART_CR2_SCEN;
  }
  else
  {
    /* Disable the 7816 Master mode by clearing the SCEN bit in the CR2 register */
    UARTx->CR2 &= ~(UART_CR2_SCEN);
  }
}

/**
  * @brief  Enables or disables NACK transmission.
  * @param  UARTx: where x can be 1, 2, 3 or 6 to select the UART peripheral.
  * @param  NewState: new state of the NACK transmission.
  *          This parameter can be: ENABLE or DISABLE.  
  * @retval None
  */
void UART_SmartCardNACKCmd(UART_TypeDef* UARTx, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));
    
  if (NewState != DISABLE)
  {
    /* Enable the NACK transmission by setting the NACK bit in the CR2 register */
    UARTx->CR2 |= UART_CR2_NACK;
  }
  else
  {
    /* Disable the NACK transmission by clearing the NACK bit in the CR2 register */
    UARTx->CR2 &= ~(UART_CR2_NACK);
  }
}


/**
  * @brief  Configures the UART's IrDA interface.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  UART_IrDAMode: specifies the IrDA mode.
  *          This parameter can be one of the following values:
  *            @arg UART_IrDAMode_LowPower
  *            @arg UART_IrDAMode_Normal
  * @retval None
  */
void UART_IrDAConfig(UART_TypeDef* UARTx, uint32_t UART_IrDAMode)
{
  /* Check the parameters */
  assert_param(IS_UART_ALL_PERIPH(UARTx));
  assert_param(IS_UART_IRDA_MODE(UART_IrDAMode));
    
  UARTx->CR1 &= ~UART_CR1_SIRLP;
  UARTx->CR1 |= UART_IrDAMode;
}

/**
  * @brief  Enables or disables the UART's IrDA interface.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  NewState: new state of the IrDA mode.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void UART_IrDACmd(UART_TypeDef* UARTx, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_UART_ALL_PERIPH(UARTx));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
    
  if (NewState != DISABLE)
  {
    /* Enable the IrDA mode by setting the SIREN bit in the CR1 register */
    UARTx->CR1 |= UART_CR1_SIREN;
  }
  else
  {
    /* Disable the IrDA mode by clearing the SIREN bit in the CR1 register */
    UARTx->CR1 &= ~(UART_CR1_SIREN);
  }
}

  
/**
  * @brief  Enables or disables the UART's DMA interface.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  UART_DMAReq: specifies the DMA request.
  *          This parameter can be any combination of the following values:
  *            @arg UART_DMAReq_Tx: UART DMA transmit request
  *            @arg UART_DMAReq_Rx: UART DMA receive request
  * @param  NewState: new state of the DMA Request sources.
  *          This parameter can be: ENABLE or DISABLE.   
  * @retval None
  */
void UART_DMACmd(UART_TypeDef* UARTx, uint32_t UART_DMAReq, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_UART_ALL_PERIPH(UARTx));
  assert_param(IS_UART_DMAREQ(UART_DMAReq));  
  assert_param(IS_FUNCTIONAL_STATE(NewState)); 

  if (NewState != DISABLE)
  {
    /* Enable the DMA transfer for selected requests by setting the TXDMAE and/or
       RXDMAE bits in the UART CR1 register */
    UARTx->CR1 |= UART_DMAReq;
  }
  else
  {
    /* Disable the DMA transfer for selected requests by setting the TXDMAE and/or
       RXDMAE bits in the UART CR1 register */
    UARTx->CR1 &= ~UART_DMAReq;
  }
}



/**
  * @brief  Enables or disables the specified UART interrupts.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  UART_IT: specifies the UART interrupt sources to be enabled or disabled.
  *          This parameter can be one of the following values:
  *            @arg UART_IT_ABRI:   Auto baud rate adaption interrupt
  *            @arg UART_IT_IDLEI:  Idle line detection interrupt
  *            @arg UART_IT_BCNTI:  Bit count completed interrupt
  *            @arg UART_IT_LBDI:   LIN Break detection interrupt
  *            @arg UART_IT_OEI:    Overrun Error interrupt
  *            @arg UART_IT_BEI:    Break Error interrupt
  *            @arg UART_IT_PEI:    Parity Error interrupt
  *            @arg UART_IT_FEI:    Frame Error interrupt
  * @param  NewState: new state of the specified UARTx interrupts.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void UART_ITConfig(UART_TypeDef* UARTx, uint32_t UART_IT, FunctionalState NewState)
{
    /* Check the parameters */
    assert_param(IS_UART_ALL_PERIPH(UARTx));
    assert_param(IS_UART_CONFIG_IT(UART_IT));
    assert_param(IS_FUNCTIONAL_STATE(NewState));
    
    if (NewState != DISABLE)
        UARTx->IE |= UART_IT;
    else UARTx->IE &= ~UART_IT;
}

/**
  * @brief  Checks whether the specified UART flag(UART_FR register) is set or not.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART or UART peripheral.
  * @param  UART_FLAG: specifies the flag to check.
  *          This parameter can be one of the following values:
  *            @arg UART_FR_BUSY: Busy for sending flag
  *            @arg UART_FR_CTS:  CTS Input status flag
  *            @arg UART_FR_TXFE: TXFIFO Empty flag
  *            @arg UART_FR_RXFF: RXFIFO Full flag
  *            @arg UART_FR_TXFF: TXFIFO Full flag
  *            @arg UART_FR_RXFE: RXFIFO Empty flag
  *            @arg UART_FR_OE:   OverRun Error flag
  *            @arg UART_FR_BE:   Noise Error flag
  *            @arg UART_FR_PE:   Parity Error flag
  *            @arg UART_FR_FE:   Frame Error flag
  * @retval The new state of UART_FLAG (SET or RESET).
  */
FlagStatus UART_GetFlagStatus(UART_TypeDef* UARTx, uint32_t UART_FLAG)
{
//    FlagStatus bitstatus = RESET;
    /* Check the parameters */
    assert_param(IS_UART_ALL_PERIPH(UARTx));
    assert_param(IS_UART_FLAG(UART_FLAG));

    return ((UARTx->FR & UART_FLAG) == UART_FLAG)? SET : RESET;
}

/**
  * @brief  Checks whether the specified UART interrupt has occurred or not.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  UART_IT: specifies the UART interrupt source to check.
  *          This parameter can be one of the following values:
  *            @arg UART_ISR_ABRI:  Auto baud rate adaption interrupt.
  *            @arg UART_ISR_IDLEI: Idle line detection interrupt.
  *            @arg UART_ISR_BCNTI: Bit count completed interrupt. 
  *            @arg UART_ISR_LBDI:  LIN Break detection interrupt
  *            @arg UART_ISR_OEI:   Overrun Error interrupt.
  *            @arg UART_ISR_BEI:   Break Error interrupt.
  *            @arg UART_ISR_PEI:   Parity Error interrupt.
  *            @arg UART_ISR_FEI:   Frame Error interrupt.
  *            @arg UART_ISR_TXI:   Transmit interrupt.
  *            @arg UART_ISR_RXI:   Receive interrupt.
  * @retval The new state of UART_IT (SET or RESET).
  */
ITStatus UART_GetITStatus(UART_TypeDef* UARTx, uint32_t UART_IT)
{
//    FlagStatus bitstatus = RESET;
    uint32_t iesets;
    uint32_t isrflags;
    /* Check the parameters */
    assert_param(IS_UART_ALL_PERIPH(UARTx));
    assert_param(IS_UART_GET_IT(UART_IT));
    
    iesets = UARTx->IE;
    isrflags = UARTx->ISR;
    isrflags &= iesets;

    return ((isrflags & UART_IT) == UART_IT)? SET : RESET;
}

/**
  * @brief  Clears the UARTx's interrupt pending bits.
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  UART_IT: specifies the interrupt pending bit to clear.
  *          This parameter can be one of the following values:
  *            @arg UART_ISR_ABRI:  Auto baud rate adaption interrupt.
  *            @arg UART_ISR_IDLEI: Idle line detection interrupt.
  *            @arg UART_ISR_BCNTI: Bit count completed interrupt. 
  *            @arg UART_ISR_LBDI:  LIN Break detection interrupt
  *            @arg UART_ISR_OEI:   Overrun Error interrupt.
  *            @arg UART_ISR_BEI:   Break Error interrupt.
  *            @arg UART_ISR_PEI:   Parity Error interrupt.
  *            @arg UART_ISR_FEI:   Frame Error interrupt.
  *            @arg UART_ISR_TXI:   Transmit interrupt.
  *                                 When UART FIFO is DISABLED: Interrupt happened when data moved out of DR register
  *                                 When UART FIFO is ENABLED:  see @TXIFLSEL for details
  *            @arg UART_ISR_RXI:   Receive interrupt.
  *                                 When UART FIFO is DISABLED: Interrupt happened when new data moved into DR register
  *                                 When UART FIFO is ENABLED:  see @RXIFLSEL for details
  *                                 UART_ISR_RXI can be also cleared by reading data out of RXFIFO by software
  * @retval None
  */
void UART_ClearITPendingBit(UART_TypeDef* UARTx, uint32_t UART_IT)
{
    assert_param(IS_UART_ALL_PERIPH(UARTx));
    assert_param(IS_UART_CLEAR_IT(UART_IT));
    if(UART_IT == UART_ISR_IDLEI)
    {
        UARTx->ISR = UART_ISR_IDLEI;
        while(UARTx->ISR & UART_ISR_IDLEI)
        {
            UARTx->ISR = 0;
            UARTx->ISR = UART_ISR_IDLEI;
        }
        return;
    }              
    UARTx->ISR = UART_IT;
}

/**
  * @brief  Get UART ISR status(whether the Interrupt will happen depends on the corresponding IE bit set).
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  UART_IT: specifies the UART interrupt source to check.
  *          This parameter can be one of the following values:
  *            @arg UART_ISR_ABRI:  Auto baud rate adaption interrupt.
  *            @arg UART_ISR_IDLEI: Idle line detection interrupt.
  *            @arg UART_ISR_BCNTI: Bit count completed interrupt. 
  *            @arg UART_ISR_LBDI:  LIN Break detection interrupt
  *            @arg UART_ISR_OEI:   Overrun Error interrupt.
  *            @arg UART_ISR_BEI:   Break Error interrupt.
  *            @arg UART_ISR_PEI:   Parity Error interrupt.
  *            @arg UART_ISR_FEI:   Frame Error interrupt.
  *            @arg UART_ISR_TXI:   Transmit interrupt.
  *            @arg UART_ISR_RXI:   Receive interrupt.
  * @retval The new state of UART_IT (SET or RESET).
  */
ITStatus UART_GetISRStatus(UART_TypeDef* UARTx, uint32_t UART_IT)
{
    /* Check the parameters */
    assert_param(IS_UART_ALL_PERIPH(UARTx));
    assert_param(IS_UART_GET_IT(UART_IT));
    
    return ((UARTx->ISR & UART_IT) == UART_IT)? SET : RESET;
}

/**
  * @brief  Clear UART ISR status
  * @param  UARTx: where x can be 1, 2, 3 or 4 to select the UART peripheral.
  * @param  UART_IT: specifies the UART interrupt status to clear.
  *          This parameter can be one of the following values:
  *            @arg UART_ISR_ABRI:  Auto baud rate adaption interrupt.
  *            @arg UART_ISR_IDLEI: Idle line detection interrupt.
  *            @arg UART_ISR_BCNTI: Bit count completed interrupt. 
  *            @arg UART_ISR_LBDI:  LIN Break detection interrupt
  *            @arg UART_ISR_OEI:   Overrun Error interrupt.
  *            @arg UART_ISR_BEI:   Break Error interrupt.
  *            @arg UART_ISR_PEI:   Parity Error interrupt.
  *            @arg UART_ISR_FEI:   Frame Error interrupt.
  *            @arg UART_ISR_TXI:   Transmit interrupt.
  *            @arg UART_ISR_RXI:   Receive interrupt.
  * @retval None
  */
void UART_ClearISRStatus(UART_TypeDef* UARTx, uint32_t UART_IT)
{
    /* Check the parameters */
    assert_param(IS_UART_ALL_PERIPH(UARTx));
    assert_param(IS_UART_GET_IT(UART_IT));
    
    UARTx->ISR = UART_IT;
}

/******************************************************************************
*@brief : which uart instance is selected for debug logging
*         
*@param : UARTx: UART instance.
*@return: None
******************************************************************************/
void UART_SetDebugUart(UART_TypeDef *UARTx)
{
    if(UARTx != NULL)
    {
        assert_param (IS_UART_ALL_PERIPH(UARTx));
    }
    g_DebugUart = UARTx;
}
#if defined ( __CC_ARM   ) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
__weak int fputc(int ch, FILE *f)
{
    if(g_DebugUart)
    {
        g_DebugUart->DR = ch;    
        while ((g_DebugUart->FR & UART_FR_BUSY));        
    }
    return ch;
}
#elif defined (__GNUC__) 
__weak int __io_putchar(int ch)  
{  
    g_DebugUart->DR = ch; 
    while ((g_DebugUart->FR & UART_FR_BUSY));  
    return ch;  
}   

#endif
