/*****************************************************************************
* File Name          : htk_uart.c
* Author             : CrystalSu
* Version            : V1.0.0.0
* Date               : Feb 14, 2020
* Description        : UART function for using with CLI.
******************************************************************************/  
 
#include "htk_uart.h"
#include "bc45_cli.h"
#include "systick_for_timeout.h"

static UART_HandleTypeDef htk_huart;
__IO serial_RB_t rxFIFO;
uint8_t RxBuffer[HTK_UART_BUFFER_SIZE];
 

/**
  * @brief  This function handles UART Communication Timeout.
  * @param  huart: pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @param  Flag: specifies the UART flag to check.
  * @param  Status: The new Flag status (SET or RESET).
  * @param  Tickstart Tick start value
  * @param  Timeout: Timeout duration
  * @retval HAL status
  */
static StatusTypeDef UART_WaitFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout)
{

  while (USART_GetFlagStatus(huart->Instance, Flag) == Status)
	{
    if(Timeout != HAL_MAX_DELAY)
    {
      if((Timeout == 0U)||((Get_TickCount() - Tickstart ) > Timeout))
			{
        /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
        //CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE));
        //CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
				return HAL_TIMEOUT;
			}
		}
	}
  return HAL_OK;
}

/**
  * @brief  Sends an amount of data in blocking mode.
  * @param  huart: pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @param  pData: Pointer to data buffer
  * @param  Size: Amount of data to be sent
  * @param  Timeout: Timeout duration  
  * @retval HAL status
  */
StatusTypeDef UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
  //uint16_t* tmp;
  uint32_t tickstart = 0U;
  
  //huart->ErrorCode = HAL_UART_ERROR_NONE;
	huart->ErrorCode = 0;

	/* Init tickstart for timeout managment */
	tickstart = Get_TickCount();

	huart->TxXferSize = Size;
	huart->TxXferCount = Size;
	while(huart->TxXferCount > 0U)
	{
		huart->TxXferCount--;
		if(UART_WaitFlagUntilTimeout(huart, USART_FLAG_TXDE, RESET, tickstart, Timeout) != HAL_OK)
		{
			return HAL_TIMEOUT;
		}
		huart->Instance->DR = (*pData++ & (uint8_t)0xFF);
	}

	if(UART_WaitFlagUntilTimeout(huart, USART_FLAG_TXC, RESET, tickstart, Timeout) != HAL_OK)
	{
		return HAL_TIMEOUT;
	}
	return HAL_OK;
}

/**
  * @brief  Receives an amount of data in non blocking mode. 
  * @param  huart: pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @param  pData: Pointer to data buffer
  * @param  Size: Amount of data to be received
  * @retval HAL status
  */
StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  /* Check that a Rx process is not already ongoing */
  if(huart->RxState == HAL_UART_STATE_READY)
  {
    if((pData == NULL) || (Size == 0U))
    {
      return HAL_ERROR;
    }

    /* Process Locked */
    //__HAL_LOCK(huart);

    huart->pRxBuffPtr = pData;
    huart->RxXferSize = Size;
    huart->RxXferCount = Size;

    //huart->ErrorCode = HAL_UART_ERROR_NONE;
		huart->ErrorCode = 0;
    huart->RxState = HAL_UART_STATE_BUSY_RX;
    
    /* Process Unlocked */
    //__HAL_UNLOCK(huart);

  /* Configure USART0 & USART1 interrupt                                                                    */
  NVIC_EnableIRQ(COM1_IRQn);

  /* Seting COM1_PORT interrupt-flag                                                                        */
  USART_IntConfig(COM1_PORT, USART_INT_RXDR, ENABLE);

  /* Enable COM1_PORT                                                                                       */
  USART_TxCmd(COM1_PORT, ENABLE);
  USART_RxCmd(COM1_PORT, ENABLE);
#if 0		
    /* Enable the UART Parity Error Interrupt */
    __HAL_UART_ENABLE_IT(huart, UART_IT_PE);

    /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
    __HAL_UART_ENABLE_IT(huart, UART_IT_ERR);

    /* Enable the UART Data Register not empty Interrupt */
    __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
#endif
    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}
/**
  * @brief  Initial UART for using with CLI.
  * @param  huart: A UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @retval None
  */
void htk_UART_Init(HT_USART_TypeDef* huart, uint8_t *pCMDline)
{
	/* Specify UART module */
	htk_huart.Instance = huart;

	/* Init UART RX buffer (Use with RX interrupt)*/
	UART_Receive_IT(&htk_huart, pCMDline, 1);

	/* Init ring buffer */
	htk_ringBufferInit(&rxFIFO, &RxBuffer[0], HTK_UART_BUFFER_SIZE);
}

/**
  * @brief  Transmit an amount of data. 
  * @param  huart: A UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @param  pData: Pointer to data buffer
  * @param  Size: Amount of data to be transmitted
  * @param  Timeout: Timeout duration
  * @retval None
  */
void htk_UART_Transmit(uint8_t * pData, uint16_t size)
{
	size = strlen(pData);
	UART_Transmit(&htk_huart, pData, size, HAL_MAX_DELAY);
}


/**
  * @brief  Convert Data (4-bit Low) to ASCII HEX (0-F).
  * @param  data: data with value 0-15 (4-bit Low)
  * @retval ASCII HEX Character (0-F)
  */
uint8_t toAsciiHex(uint8_t data) 
{
  if(data <= 9) 
  {
	return ('0' + data);
  }
  else 
  {
	return (('A'-10) + data);
  }
}

/**
  * @brief 	Convert Data to ASCII HEX format.
  * @param  dataOut: Pointer to a byte of data input.
  * @param  dataIn: Pointer to data output buffer.
  * @retval None
  */
void dataToHex(uint8_t * dataOut, uint8_t dataIn) 
{
  * (dataOut++) = toAsciiHex((dataIn & 0xF0) >> 4);
  * (dataOut++) = toAsciiHex( dataIn & 0x0F);
  * (dataOut)   = '\0';
}


/*
 * Convert hex data to decimal
 */
void data_to_dec(uint8_t * dataOut, uint8_t dataIn)
{
	* (dataOut++) = 48 + (dataIn/10);
	* (dataOut++) = 48 + (dataIn%10);
}

/**
  * @brief 	Get string length.
  * @param  str: Pointer to a string buffer.
  * @retval Length of the string.
  */
uint8_t customStrLen(uint8_t * str) 
{
  uint8_t len = 0;
  
  while(* str != '\0') 
  {
    str++;
    len++;
  }
  return len;
}


/**
  * @brief  Set string to Lower case.
  * @param  dataStr: Pointer to a string buffer which
					 will be changed to lower case.
  * @param  dataStrLen: Length of the string.
  * @retval None.
  */
void customToLower(uint8_t * dataStr, uint8_t dataStrLen) 
{
  uint8_t i =0;
  uint8_t tmpData;

  for(i=0; i<dataStrLen; i++) 
  {
    tmpData = dataStr[i];
    if((tmpData>=65)&&(tmpData<=90)) 
	{ 
	  // Check Upper Case
      dataStr[i] |= 0x20;
    }
  }
}

/**
  * @brief  Convert string to HEX value (8-bit).
			Example : "2A" = 0x2A
  * @param  s: Pointer to a string buffer which
			   will be changed to HEX value.
  * @param  sLen: Length of the string.
  * @param  valHEX: Pointer to a output buffer which 
				    will be used to store HEX value.
  * @retval Status of parsing.
  */
uint8_t customParseHEX(uint8_t * s, uint8_t sLen, uint8_t * valHEX) 
{
  const uint8_t sftVal[4] = {0,4,8,12};
  uint8_t tmpData;
  uint8_t i = 0;
  uint16_t cal = 0;

  // Check Length
  if(sLen > 2) 
  {
    return 0xFF; // Error:
  }

  for(i=0; i<sLen; i++) 
  {
    tmpData = s[i];
    if((tmpData>='0')&&(tmpData<='9')) 
	{
      tmpData = tmpData - 48;
    }
    else if((tmpData >= 'a')&&(tmpData <= 'f')) 
	{
      tmpData = (tmpData - 97) + 10;
    }
    else 
	{
      return 0xFF; // Error: value such as GHIJ
    }
    // Calculate
    cal |= tmpData << (sftVal[(sLen-1)-i]);
  }
  * valHEX = (uint8_t)(cal & 0xFF);

  return 0; // SUCCESS
}


/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
	#if 0
  /* Tx, move data from buffer to UART                                                                      */
  if (USART_GetFlagStatus(COM1_PORT, USART_FLAG_TXDE))
  {
    if (URTxWriteIndex > 0)
    {
      u8 u8WriteIndex;
      u8 u8ReadIndex;
      USART_SendData(COM1_PORT, URTxBuf[URTxReadIndex]);
      URTxReadIndex++;
      u8WriteIndex = URTxWriteIndex;
      u8ReadIndex = URTxReadIndex;
      if (u8WriteIndex == u8ReadIndex)
      {
        URTxWriteIndex = 0;
        URTxReadIndex = 0;
        USART_IntConfig(COM1_PORT, USART_INT_TXDE, DISABLE);
        HT32F_DVB_LEDOff(HT_LED2);
      }
    }
  }
  /* Rx, move data from UART to buffer                                                                      */
  if (USART_GetFlagStatus(COM1_PORT, USART_FLAG_RXDR))
  {
    URRxBuf[URRxWriteIndex] = USART_ReceiveData(COM1_PORT);
    URRxWriteIndex = (URRxWriteIndex + 1) % USART_BUFSIZE;
    HT32F_DVB_LEDOn(HT_LED2);
  }
	#endif

	#if 1
	/* USER CODE BEGIN USART1_IRQn 0 */
  uint8_t temp ;

  if (USART_GetFlagStatus(htk_huart.Instance, USART_FLAG_RXDR))
  {
    temp = (uint8_t)(htk_huart.Instance->DR);
		//htk_ringBufferWrite(&rxFIFO, temp);
	 if(runningLoop)
	 {
			runningLoop = 0;
			htk_UART_Transmit(
				(uint8_t*)"\r\nStop Scan\r\n",11);

	 }
	 else
	 {
		 htk_ringBufferWrite(&rxFIFO, temp);
	 }

		//htk_UART_Transmit(&temp, 1);
  }
  /* USER CODE END USART1_IRQn 0 */
  //HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
	#endif
}


