#include "sr_uart.h"
#include <string.h>
#include "sr_osal.h"
#include "sr_gpio.h"

#include "sr_bsp_com.h"

#define LUART0      ((USART_Module*)0x00FF0000)    //随便定义的

static void HAL_UART_MspInit(USART_Module  *instance);
static void HAL_UART_MspDeInit(USART_Module  *instance);
static void _BSP_UART_IRQHandler(USART_Module *USARTx, uint8_t srId);

/**
 * @brief ST UART设备，继承朝阳定义的设备，额外多一些适配需要的变量
 */
typedef struct NT_UART_DEV
{
  SR_UART_DEV_T parent;   /*!< 朝阳定义的UART设备*/
  uint8_t  *rxBuf;        /*!< 接收缓存*/
  uint16_t rxBufSize;     /*!< 接收缓存大小*/
  uint16_t rxCnt;         /*!< 接收缓存计数*/
  uint16_t  rxNum;         //接收数据数量
  uint8_t  rxTout;        //接收超时计数
  

}NT_UART_DEV_T;

#ifdef SR_USE_UART1
USART_InitType uart1Handle;

void USART1_IRQHandler(void)
{
    _BSP_UART_IRQHandler(USART1,SR_UART1);
}

#endif

#ifdef SR_USE_UART2
USART_InitType uart2Handle;

void USART2_IRQHandler(void)
{
    
   _BSP_UART_IRQHandler(USART2,SR_UART2);
           
}

#endif



#ifdef SR_USE_UART4
USART_InitType uart4Handle;

void UART4_IRQHandler(void)
{
  
    _BSP_UART_IRQHandler(UART4,SR_UART4);
}

#endif

#ifdef SR_USE_LUART0
LPUART_InitType luart0Handle;


void LPUART_IRQHandler(void)
{
  
    _BSP_UART_IRQHandler(LUART0,SR_LUART0);
}

#endif


static BSP_UART_INFO_T _UartInfo[] =
{

#ifdef SR_USE_UART1
		{
			.name = "uart1",
			.trdHandle = &uart1Handle,
			.instance = USART1,
			.srId = SR_UART1,
		},
#endif

#ifdef SR_USE_UART2
		{
			.name = "uart2",
			.trdHandle = &uart2Handle,
			.instance = USART2,
			.srId = SR_UART2,
		},
#endif
		
#ifdef SR_USE_UART4
		{
			.name = "uart4",
			.trdHandle = &uart4Handle,
			.instance = UART4,
			.srId = SR_UART4,
		},
#endif

#ifdef SR_USE_LUART0
		{
			.name = "luart0",
			.trdHandle = &luart0Handle,
			.instance = LUART0,
			.srId = SR_LUART0,
		},
#endif

};

static NT_UART_DEV_T gs_ntUartDevice[sizeof(_UartInfo) / sizeof(_UartInfo[0])] = {0};

SR_DEVICE_T *BspUartOpen(SR_UART_ID_E uartId)
{
	uint8_t i;
	uint8_t devNum = sizeof(_UartInfo) / sizeof(BSP_UART_INFO_T);
	NT_UART_DEV_T *ntUartDev = SR_NULL;

	for (i = 0; i < devNum; i++)
	{
		if (uartId == _UartInfo[i].srId)
		{
			ntUartDev = &gs_ntUartDevice[i];
			ntUartDev->parent.parent.deviceData = &_UartInfo[i]; // 绑定设备信息数据
			ntUartDev->parent.parent.name = _UartInfo[i].name;  //设备名称
			break;
		}
	}

	return (ntUartDev) ? (&(ntUartDev->parent.parent)) : SR_NULL;
}

int BspUartConfig(SR_DEVICE_T *dev, SR_UART_CFG_T *config)
{
	BSP_UART_INFO_T *info = (BSP_UART_INFO_T *)dev->deviceData;
	NT_UART_DEV_T *ntUartDev = (NT_UART_DEV_T *)dev;

	
	// 检查有效性检查
	if(!dev || !config || !info || !info->trdHandle) return SR_INVALID;

	if((SR_INVALID == (int)config->dataBits) || (SR_INVALID == (int)config->stopBits)) return SR_INVALID;

	//分配接收缓存
  if(ntUartDev->rxBufSize==0 && ntUartDev->rxBuf==SR_NULL && config->rxBufsz>0)
  {
      ntUartDev->rxBuf = (uint8_t *)SR_OsMalloc(config->rxBufsz);
      if(!ntUartDev->rxBuf) return SR_NOMEM;
      ntUartDev->rxBufSize = config->rxBufsz;  //保存缓存长度
  }

	/*UART初始化*/
  HAL_UART_MspInit(info->instance);

  if(info->instance == LUART0)
  {
      LPUART_InitType *handle = (LPUART_InitType *)info->trdHandle ; 
      uint16_t parity=LPUART_PE_NO,flowc = LPUART_HFCTRL_NONE;

      switch(config->parity)
      {
        case USART_PE_EVEN:
          parity = LPUART_PE_EVEN;
        break;
        case USART_PE_ODD:
          parity = LPUART_PE_ODD;
        break;
        default :
          parity = LPUART_PE_NO;
        break;
      }
      if(USART_HFCTRL_RTS_CTS == config->fc) flowc = LPUART_HFCTRL_RTS_CTS;


      LPUART_DeInit();    
      LPUART_StructInit(handle);
      handle->BaudRate            = config->baudrate;
      handle->Parity              = parity;
      handle->RtsThreshold        = LPUART_RTSTH_FIFOFU;
      handle->HardwareFlowControl = flowc;
      handle->Mode                = LPUART_MODE_RX | LPUART_MODE_TX;
      /* Configure LPUART */
      LPUART_Init(handle);

      /* Enable LPUART Receive interrupts */
      LPUART_ConfigInt(LPUART_INT_FIFO_NE, ENABLE);
      //LPUART_ConfigInt(LPUART_INT_TXC, ENABLE);  //发送中断
  }
  else
  {
        USART_InitType *handle = (USART_InitType *)info->trdHandle;
	
        handle->BaudRate = config->baudrate;
        handle->WordLength = config->dataBits;
        handle->StopBits = config->stopBits;
        handle->Parity = config->parity;
        handle->HardwareFlowControl = config->fc;
        handle->Mode = USART_MODE_RX | USART_MODE_TX;

        /* init USART*/
        USART_Init(info->instance, handle);

        /* Enable USARTy Receive interrupts */
        USART_ConfigInt(info->instance, USART_INT_RXDNE, ENABLE);

        /* Enable the USARTy and USARTz */
        USART_Enable(info->instance, ENABLE);

  }

	return SR_OK;

}

int BspUartClose(SR_DEVICE_T *dev)
{
	BSP_UART_INFO_T *info = (BSP_UART_INFO_T *)dev->deviceData;
	NT_UART_DEV_T *ntUartDev = (NT_UART_DEV_T *)dev;

	//参数有效性判断
	if(!dev || !info || !info->instance) return SR_INVALID;

	//串口去初始化
  if(info->instance == LUART0)
  {
    LPUART_DeInit();
    LPUART_ConfigInt(LPUART_INT_FIFO_NE, DISABLE);
  }
  else
  {
    USART_DeInit(info->instance);
    USART_Enable(info->instance, DISABLE);
    USART_ConfigInt(info->instance, USART_INT_RXDNE, DISABLE);    
  }
  HAL_UART_MspDeInit(info->instance);

	//释放接收缓存
	SR_OsFree(ntUartDev->rxBuf); 
	ntUartDev->rxBuf = SR_NULL;
	ntUartDev->rxBufSize =0;

	return 0;
}

srSSize_t BspUartRead(SR_DEVICE_T *dev, void *buffer, srSize_t size)
{
	NT_UART_DEV_T *ntUartDev = (NT_UART_DEV_T *)dev;

	//参数有效性判断
	if(!dev || !buffer ) return SR_INVALID;
	if(size<=0) return SR_INVALID;

	int tmpSize = (size >= ntUartDev->rxNum) ? ntUartDev->rxNum : size;

	memcpy(buffer, ntUartDev->rxBuf, tmpSize);


	return tmpSize;
}


int _SendOne(USART_Module *USARTx,uint16_t data)
{
    uint16_t u16MaxDelay = 0;
    /* Write a character to the USART */
    USART_SendData(USARTx, data);
    
    /* Loop until the end of transmission */
    while (USART_GetFlagStatus(USARTx, USART_FLAG_TXDE) == RESET)
    {
        if (u16MaxDelay++ > 10000)
        {
            //break; // 等待超时退出等待发送标志
           return SR_TIMEOUT;
        }
    }
    return SR_OK;
}


int _SendLen(BSP_UART_INFO_T *info, uint8_t *buf, uint16_t len)
{
    int ret =0;
    uint8_t  *pdata8bits = SR_NULL;
    uint16_t *pdata16bits = SR_NULL;
    USART_InitType *handle = (USART_InitType *)info->trdHandle;
    
    if ((handle->WordLength == USART_WL_9B) && (handle->Parity == USART_PE_NO))
    {
      pdata16bits = (uint16_t *) buf;
    }
    else
    {
      pdata8bits  = buf;
    }
    
    for (uint16_t i = 0; i < len; i++)
    {
        
        if (pdata8bits == SR_NULL)
        {
          //huart->Instance->DR = (uint16_t)(*pdata16bits & 0x01FFU);
          ret = _SendOne(info->instance,(*pdata16bits & 0x01FFU));
          pdata16bits++;
        }
        else
        {
          //huart->Instance->DR = (uint8_t)(*pdata8bits & 0xFFU);
          ret = _SendOne(info->instance,(*pdata8bits & 0xFFU));
          pdata8bits++;
        }
        
        if(ret!=SR_OK) return SR_TIMEOUT;
    }
    
    return SR_OK;
}


int _LuartSendOne(uint8_t u8Buf)
{
    uint16_t u16MaxDelay = 0;
    /* Write a character to the USART */
    LPUART_SendData(u8Buf);
    /* Loop until the end of transmission */
    while (LPUART_GetFlagStatus(LPUART_FLAG_TXC) == RESET)
    {
        if (u16MaxDelay++ > 10000)
        {
            return SR_TIMEOUT; // 等待超时退出等待发送标志
        }
    }
    LPUART_ClrFlag(LPUART_FLAG_TXC);

    return SR_OK;
}

int _LuartSendLen(uint8_t *buf, uint16_t len)
{
  int ret =0;
  for (uint16_t i = 0; i < len; i++)
  {
    ret = _LuartSendOne(buf[i]);

    if(ret!=SR_OK) return SR_TIMEOUT;
  }
  return SR_OK;
}
srSSize_t BspUartWrite(SR_DEVICE_T *dev, void *buffer, srSize_t size)
{
	BSP_UART_INFO_T *info = (BSP_UART_INFO_T *)dev->deviceData;

	//参数有效性判断
	if(!dev || !info || !info->trdHandle || !buffer) return SR_INVALID;
	if(size<=0) return SR_INVALID;

	//原厂串口发送
	int ret;
  if(info->instance == LUART0)
    ret = _LuartSendLen(buffer,size);
  else
    ret = _SendLen(info, buffer,size);
	
	return (ret == SR_OK) ? (srSSize_t)size : SR_FAIL;
}

int BspUartSetCallback(SR_DEVICE_T *dev, UartEventCb cb, void *args)
{
	SR_UART_DEV_T *uartDev = (SR_UART_DEV_T *)dev;  //数据类型转换

	//参数有效性判断
	if(!dev) return SR_INVALID;

	//保存回调函数及其参数
	uartDev->eventCb = cb;
	uartDev->evtCbArgs = args;

	return SR_OK;
}

int BspUartClkIoSel(SR_DEVICE_T *dev,uint32_t clk,SR_UART_IO_T *io)
{

	return  0;
}


#if 0
static void HAL_NvicConfig(IRQn_Type IRQn, uint8_t PreemptPriority, uint8_t SubPriority)
{
    NVIC_InitType NVIC_InitStructure;

    /* Configure the NVIC Preemption Priority Bits */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);

    /* Enable the USARTy Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PreemptPriority;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = SubPriority;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

static void HAL_NvicDisable(IRQn_Type IRQn)
{
    NVIC_InitType NVIC_InitStructure;

    /* Disable the USARTy Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = IRQn;
    NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
    NVIC_Init(&NVIC_InitStructure);
}
#endif

static void LuartRccConfiguration(uint32_t LPUART_CLK_SRC)
{
    switch (LPUART_CLK_SRC)
    {
    case RCC_LPUARTCLK_SRC_LSE:
    {
        RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_PWR, ENABLE);
        PWR->CTRL1 |= PWR_CTRL1_DRBP;
        /* Configures the External Low Speed oscillator (LSE) */
        RCC_ConfigLse(RCC_LSE_ENABLE);
        while (RCC_GetFlagStatus(RCC_LDCTRL_FLAG_LSERD) == RESET)
        {
        }
        /* Specifies the LPUART clock source, LSE selected as LPUART clock */
        RCC_ConfigLPUARTClk(RCC_LPUARTCLK_SRC_LSE);
    }
    break;
    case RCC_LPUARTCLK_SRC_HSI:
    {
        /* Configures the High Speed Internal RC clock (HSI) */
        RCC_ConfigHsi(RCC_HSI_ENABLE);
        while (RCC_GetFlagStatus(RCC_CTRL_FLAG_HSIRDF) == RESET)
        {
        }
        /* Specifies the LPUART clock source, HSI selected as LPUART clock */
        RCC_ConfigLPUARTClk(RCC_LPUARTCLK_SRC_HSI);
    }
    break;
    case RCC_LPUARTCLK_SRC_SYSCLK:
    {
        /* Specifies the LPUART clock source, SYSCLK selected as LPUART clock */
        RCC_ConfigLPUARTClk(RCC_LPUARTCLK_SRC_SYSCLK);
    }
    break;
    default:
    {
        /* Specifies the LPUART clock source, APB1 selected as LPUART clock */
        RCC_ConfigLPUARTClk(RCC_LPUARTCLK_SRC_APB1);
    }
    break;
    }

    /* Enable LPUART and USARTz Clock */
    RCC_EnableRETPeriphClk(RCC_RET_PERIPH_LPUART, ENABLE);
}

static void HAL_UART_MspInit(USART_Module  *instance)
{
    SR_GPIO_CFG_T gpioCfg={0};

    gpioCfg.gpioMode = SR_GPIO_AF_OUTPUT;    //复用推挽输出
    gpioCfg.pull = SR_GPIO_PU;               //上拉 

  if(instance==USART1)
  {
    /* Enable USARTy and USARTz Clock */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_USART1, ENABLE);
    
    //USART1 GPIO Configuration
    gpioCfg.altFun = BSP_UART1_TX_AF;        //复用
    SR_HalGpioInit(BSP_UART1_TX_ID,&gpioCfg);
    gpioCfg.altFun = BSP_UART1_RX_AF;        //复用
    SR_HalGpioInit(BSP_UART1_RX_ID,&gpioCfg);

    /* USART1 interrupt Init */
    HAL_NvicConfig(USART1_IRQn, 3, 0);
  }
#ifdef SR_USE_UART2
  else if(instance==USART2)
  {
    /* Enable USARTy and USARTz Clock */
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_USART2, ENABLE);
    
    //USART2 GPIO Configuration 
    gpioCfg.altFun = BSP_UART2_TX_AF;        //复用
    SR_HalGpioInit(BSP_UART2_TX_ID,&gpioCfg);
    gpioCfg.altFun = BSP_UART2_RX_AF;        //复用
    SR_HalGpioInit(BSP_UART2_RX_ID,&gpioCfg);
  
    /* USART2 interrupt Init */
    HAL_NvicConfig(USART2_IRQn, 1, 0);
  }
#endif
	
#ifdef SR_USE_UART4
  else if(instance==UART4)
  {
    //使能串口时钟
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_UART4, ENABLE);
    
    gpioCfg.altFun = BSP_UART4_TX_AF;        //复用
    SR_HalGpioInit(BSP_UART4_TX_ID,&gpioCfg);
    gpioCfg.altFun = BSP_UART4_RX_AF;        //复用
    SR_HalGpioInit(BSP_UART4_RX_ID,&gpioCfg);

    /* UART4 interrupt Init */
     HAL_NvicConfig(UART4_IRQn, 3, 0);
  }
#endif

#ifdef SR_USE_LUART0
  else if(instance==LUART0)
  {
    /* Enable LUART Clock */
    LuartRccConfiguration(RCC_LPUARTCLK_SRC_LSE);

    gpioCfg.altFun = BSP_LUART0_TX_AF;        //复用
    SR_HalGpioInit(BSP_LUART0_TX_ID,&gpioCfg);
    gpioCfg.altFun = BSP_LUART0_RX_AF;        //复用
    SR_HalGpioInit(BSP_LUART0_RX_ID,&gpioCfg);
    
    /* LUART0 interrupt Init */
     HAL_NvicConfig(LPUART_IRQn, 0, 1);
  }
#endif
}




static void HAL_UART_MspDeInit(USART_Module  *instance)
{

  if(instance==USART1)
  {

    /* Peripheral clock disable */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_USART1, DISABLE);

    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    //GPIO去初始化，待补充

    /* USART1 interrupt Deinit */
    HAL_NvicDisable(USART1_IRQn);
 
  }
#ifdef SR_USE_UART2
	else if(instance==USART2)
  {

    /* Peripheral clock disable */
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_USART2, DISABLE);

    /**USART2 GPIO Configuration
    PA2     ------> USART2_TX
    PA3     ------> USART2_RX
    */
    //GPIO去初始化，待补充

    /* USART2 interrupt Deinit */
    HAL_NvicDisable(USART2_IRQn);

  }
#endif
	
#ifdef SR_USE_UART4
	else if(instance==UART4)
  {

    /* Peripheral clock disable */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_UART4, DISABLE);

    /**UART4 GPIO Configuration
    PB14    ------> UART4_TX
    PB15    ------> UART4_RX
    */
    //GPIO去初始化，待补充

    /* UART4 interrupt Deinit */
    HAL_NvicDisable(UART4_IRQn);

  }
#endif	

#ifdef SR_USE_LUART0
	else if(instance==LUART0)
  {

    /* Peripheral clock disable */
    RCC_EnableRETPeriphClk(RCC_RET_PERIPH_LPUART, DISABLE);

    /**LUART0 GPIO Configuration
    PA1    ------> LUART0_TX
    PA0    ------> LUART0_RX
    */
    //GPIO去初始化，待补充

    /* LUART0 interrupt Deinit */
    HAL_NvicDisable(LPUART_IRQn);

  }
#endif	
}


static void _BSP_UART_IRQHandler(USART_Module *USARTx, uint8_t srId)
{
  uint8_t u8Data,isRecv=0;

#ifdef SR_USE_LUART0
  if(USARTx == LUART0)
  {
      if (LPUART_GetIntStatus(LPUART_INT_FIFO_NE) != RESET)
      {
          u8Data = LPUART_ReceiveData();
          isRecv =1;
      }
      
  }
  else 
  {
#endif  
      if (USART_GetIntStatus(USARTx, USART_INT_RXDNE) != RESET)
      {
          u8Data = USART_ReceiveData(USARTx);

          isRecv =1;
          
      }
#ifdef SR_USE_LUART0
  }
#endif

    if(1==isRecv)
    {
      //接收处理  
      if(gs_ntUartDevice[srId].rxCnt >= gs_ntUartDevice[srId].rxBufSize) return;  //buff满了，返回
      gs_ntUartDevice[srId].rxTout = 1;     //接收超时标识置1
      gs_ntUartDevice[srId].rxBuf[gs_ntUartDevice[srId].rxCnt++] = u8Data ;       //保存数据            
    }
}


//接收轮询task  周期10ms
void BSP_UartRecvTask(void)
{
  
   for (int i = 0; i < SR_UART_MX; i++)
   {
      
       if(gs_ntUartDevice[i].rxTout >0)  //每收到新数据，rx_timeout被重置为1
       {       
            if(gs_ntUartDevice[i].rxTout++ >2)  //等20ms，一段时间内空闲无数据，表示已收到一帧数据
            {
                gs_ntUartDevice[i].rxTout =0;   //清0
             
                //调用用户回调
                gs_ntUartDevice[i].rxNum = gs_ntUartDevice[i].rxCnt;
                             
                if (gs_ntUartDevice[i].parent.eventCb)
                    gs_ntUartDevice[i].parent.eventCb(&gs_ntUartDevice[i].parent.parent, SR_UART_EVT_RXNE, gs_ntUartDevice[i].rxCnt, gs_ntUartDevice[i].parent.evtCbArgs);

       
                gs_ntUartDevice[i].rxCnt = 0;  
                                        
             
                        
            }
       }
   
   }
}



#if  0
// 空闲中断回调
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	uint8_t devNum = sizeof(_UartInfo) / sizeof(BSP_UART_INFO_T);

    // 遍历注册的串口设备
    for (int i = 0; i < devNum; i++)
    {
        if (_UartInfo[i].instance == huart->Instance)
        {
			gs_ntUartDevice[i].rxCnt = Size;

            // 调用朝阳的回调
            if (gs_ntUartDevice[i].parent.eventCb)
                gs_ntUartDevice[i].parent.eventCb(&gs_ntUartDevice[i].parent.parent, SR_UART_EVT_RXNE, Size, gs_ntUartDevice[i].parent.evtCbArgs);

			//重新使能空闲+接收中断
			HAL_UARTEx_ReceiveToIdle_IT(huart, gs_ntUartDevice[i].rxBuf, gs_ntUartDevice[i].rxBufSize);
            break;
        }
    }

	

}
#endif
