/****
*****串口通信模块
*****在中断中接收数据
*****数据存放环形缓冲队列中
*****创建串口接收任务
*****创建中断接收函数
*****创建串口发送函数
****/

#include "Usart.h"
#include "ptz_struct.h"
#include "gd32f4xx_it.h"
device_handle uart_485_handle = 0;
device_handle uart_422_handle = 0;
BSP_OS_SEM ser_mutex;//用于锁调用发生一个字节函数
uart_device_info uart_devices[6]={
//  init  index       
  { 0,    0,},
  { 0,    1,},
  { 0,    2,},
  { 0,    3,},
  { 0,    4,},
  { 0,    5,}
};

RingQueue ring_que;
u_int8_t ptz_uart_buff[10];


//串口
//RS422
u_int8_t ptz_uart_422_buff[PTZ_UART_422_BUFF_SIZE];
char uart_422_state = 0;
//RS485
u_int8_t ptz_uart_485_buff[PTZ_UART_485_BUFF_SIZE];
char uart_485_state = 0;


int bata;
char uart_data;


/// @brief      初始化串口引脚、波特率
/// @param[in]  usart_periph:USARTx(x=0,1,2)
/// @param[in]  baud:波特率
/// @return     none 
/// @note       修改日志
///             LH于2022-05-20
static void usart_config(uint32_t usart_periph, int baud)
{
  switch(usart_periph)
  {
    case TEST://串口0，调试端口
      //使能端口时钟
      rcu_periph_clock_enable(RCU_GPIOA);
      //使能串口时钟
      rcu_periph_clock_enable(RCU_USART0);
      gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9);//TX
      gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);//RX
      gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE,GPIO_PIN_9);
      gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_9);
      gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE,GPIO_PIN_10);
      gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_10);
      break;
      
      case UART_485://串口1，485
      //使能端口时钟
      rcu_periph_clock_enable(RCU_GPIOD);
      //使能串口时钟
      rcu_periph_clock_enable(RCU_USART1);
      gpio_af_set(GPIOD, GPIO_AF_7, GPIO_PIN_5);//TX
      gpio_af_set(GPIOD, GPIO_AF_7, GPIO_PIN_6);//RX
      gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE,GPIO_PIN_5);
      gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_5);
      gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE,GPIO_PIN_6);
      gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_6);
      ///收发模式选择
      gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,GPIO_PIN_7);
      gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_7);
      break;
      
    //   case UART_422://串口2，422
    //   //使能端口时钟
    //   rcu_periph_clock_enable(RCU_GPIOD);
    //   //使能串口时钟
    //   rcu_periph_clock_enable(RCU_USART2);
    //   gpio_af_set(GPIOD, GPIO_AF_7, GPIO_PIN_8);//TX
    //   gpio_af_set(GPIOD, GPIO_AF_7, GPIO_PIN_9);//RX
    //   gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE,GPIO_PIN_8);
    //   gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_8);
    //   gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE,GPIO_PIN_9);
    //   gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_9);
    //   break;
      
      default:
         break;
  }
  
  ///串口配置使能
  usart_deinit(usart_periph);//时钟复位
  usart_baudrate_set(usart_periph,baud);//设置波特率，默认9600
  usart_receive_config(usart_periph, USART_RECEIVE_ENABLE);//接收使能
  usart_transmit_config(usart_periph, USART_TRANSMIT_ENABLE);//发送使能
  usart_enable(usart_periph);//串口使能
  
  //使能接收中断
  usart_interrupt_enable(usart_periph, USART_INT_RBNE);
  
}



/// @brief      中断嵌套向量配置
/// @param[in]  usart_periph:USARTx(x=0,1,2)
/// @return     none 
/// @note       修改日志
///             LH于2022-05-20
static void Usart_Nvic_config(uint32_t usart_periph)
{
  switch(usart_periph)
  {
    case TEST://串口0，调试端口
      //使能串口中断请求
      nvic_irq_enable(USART0_IRQn, 1, 3);//抢占优先级配置为3，子优先及为0，比以太网低，以太网为2
      break;
      
    case UART_485://串口1，485
      nvic_irq_enable(USART1_IRQn, 1, 2);//优先级配置为3，子优先及为1
      break;
      
    // case UART_422://串口2，422
    //   nvic_irq_enable(USART2_IRQn, 1, 1);//优先级配置为3，子优先及为2
    //   break;
      
      default:
         break;
    
  }
  
}


/// @brief      初始化环形队列、资源锁
/// @param[in]  usart_periph:USARTx(x=0,1,2)
/// @param[in]  index:设备端口
/// @param[in]  *buff:队列地址
/// @param[in]  buff_size:队列长度
/// @return     device_handle：设备地址
/// @note       修改日志
///             LH于2022-05-20
device_handle uart_init(uint32_t usart_periph, uint32_t index, u_int8_t *buff, int buff_size)
{
  if(!uart_devices[index].init)
  {//没有初始化
    InitRingQueue(&uart_devices[index].uart_ring_queue, buff, buff_size); //初始化环形队列缓存
    BSP_OS_SemCreate(&uart_devices[index].port_mutex,1u,"port mutex");
    BSP_OS_SemCreate(&uart_devices[index].ser_mutex,1u,"serial mutex");
    BSP_OS_SemCreate(&uart_devices[index].sem_recv_data,0u,"sem recv data");
    uart_devices[index].init = 1;
  }
  
  return (device_handle)(&uart_devices[index]);
 
}

/// @brief      串口设备初始化
/// @param[in]  none
/// @return     none 
/// @note       修改日志
///             LH于2022-05-20
static void Uart_Init(void)
{
  ///485串口设备初始化UART_485
  usart_config(UART_485, g_ptz.uart_485_baud);//串口初始化
  Usart_Nvic_config(UART_485);//中断配置
  uart_485_handle = uart_init(UART_485, PTZ_UART_485_INDEX, ptz_uart_485_buff, sizeof(ptz_uart_485_buff));
  BSP_IntVectSet(54,USART1_IRQHandler);
  BSP_IntEn(54);
  
//   ///422串口设备初始化
//   usart_config(UART_422, g_ptz.uart_422_baud);//串口初始化
//   Usart_Nvic_config(UART_422);//中断配置
//   uart_422_handle = uart_init(UART_422, PTZ_UART_422_INDEX, ptz_uart_422_buff, sizeof(ptz_uart_422_buff));
//   BSP_IntVectSet(55,USART2_IRQHandler);
//   BSP_IntEn(55);
  
  
  
}


/// @brief      485接收中断处理数据
/// @param[in]  data:
/// @return     none 
/// @note       修改日志
///             LH于2022-05-20
void IRQHandler_485_process(u_int8_t data)
{
  uart_device_info *dev = (uart_device_info *)uart_485_handle;//终端交互

  if(!RingQueueFull(&dev->uart_ring_queue))
  {
     InRingQueue(&dev->uart_ring_queue, data);
  }
  
}

/// @brief      422接收中断处理数据
/// @param[in]  data：
/// @return     none 
/// @note       修改日志
///             LH于2022-05-20
void IRQHandler_422_process(u_int8_t data)
{
  uart_device_info *dev = (uart_device_info *)uart_422_handle;//终端交互

  if(!RingQueueFull(&dev->uart_ring_queue))
  {
     InRingQueue(&dev->uart_ring_queue, data);
  }
  
}
    
///串口设备发送数据
void ptz_uart_dev_send(device_handle device, void *data, int len)
{  
  unsigned char buff;
  
   uart_device_info *device_info = (uart_device_info *)device; 
   if((!device) || (!device_info->init))
   {
    return;
   }
   
   BSP_OS_SemWait(&device_info->ser_mutex, 0u);
   
   if(device == uart_485_handle)
   {
     PTZ_UART_485_TX;
     OSTimeDlyHMSM(0u, 0u, 0u, 10u);
   
     for (int i = 0; i<len; i++)
     {
       buff = ((u_int8_t *)data)[i];
       //等待发送缓冲区位空
       while(RESET == usart_flag_get(USART1, USART_FLAG_TBE)){}
       //写寄存器
       usart_data_transmit(USART1, buff);
       //等待发送完成
       while(RESET == usart_flag_get(USART1, USART_FLAG_TC)){}
       if((i % 100) == 0 && i > 0)
       {
         OSTimeDlyHMSM(0u, 0u, 0u, 2u);
       }
     }
    
     OSTimeDlyHMSM(0u, 0u, 0u, 10u);
     PTZ_UART_485_RX;
   }
   
   if(device == uart_422_handle)
   {
     for (int i = 0; i<len; i++)
     {
       buff = ((u_int8_t *)data)[i];
       //等待发送缓冲区位空
       while(RESET == usart_flag_get(USART2, USART_FLAG_TBE)){}
       //写寄存器
       usart_data_transmit(USART2, buff);
       //等待发送完成
       while(RESET == usart_flag_get(USART2, USART_FLAG_TC)){}
       if((i % 100) == 0 && i > 0)
       {
         OSTimeDlyHMSM(0u, 0u, 0u, 2u);
       }
     }
   }

   BSP_OS_SemPost(&device_info->ser_mutex);
}


/*******************************************************************************
** 函数名称：
** 功    能：串口设备缓冲区是否有数据
** 入口参数：
** 出口参数：
********************************************************************************/
int uart_dev_char_present(device_handle device)
{
  uart_device_info *device_info = (uart_device_info *)device;

  if((!device) || (!device_info->init))
    return 0;
  return !RingQueueEmpty(&device_info->uart_ring_queue);
}

/*******************************************************************************
** 函数名称：
** 功    能：串口设备从缓冲区读入一个数据
** 入口参数：
** 出口参数：
********************************************************************************/
char uart_dev_in_char(device_handle device)
{
  uart_device_info *device_info = (uart_device_info *)device;
  char c = 0;

  if (uart_dev_char_present(device)) //等待环形队列缓存区有数据
     OutRingQueue(&device_info->uart_ring_queue, (u_int8_t*)&c);
  return c;
}



//串口设备从缓冲区读入一个数据
char ptz_uart_dev_in_char(device_handle device)
{
  uart_device_info *device_info = (uart_device_info *)device;
  char c = 0;

  if (uart_dev_char_present(device)) //等待环形队列缓存区有数据
     OutRingQueue(&device_info->uart_ring_queue, (u_int8_t*)&c);
  return c;
}

//串口设备缓冲区是否有数据
int ptz_uart_dev_char_present(device_handle device)
{
  uart_device_info *device_info = (uart_device_info *)device;

  if((!device) || (!device_info->init))
    return 0;
  return !RingQueueEmpty(&device_info->uart_ring_queue);
}



void Usart_init_module()
{
  Uart_Init();
}

//初始化终端串口
void init_term_uart()
{
  //使能端口时钟
  rcu_periph_clock_enable(RCU_GPIOA);
  
  //使能串口时钟
  rcu_periph_clock_enable(RCU_USART0);
  
  /* connect port to USARTx_Tx */
  gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9);
  
  /* connect port to USARTx_Rx */
  gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);
  
  /* configure USART Tx as alternate function push-pull */
  gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_9);
  gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_9);
  
  /* configure USART Rx as alternate function push-pull */
  gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_10);
  gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_10);
  
  /* USART configure */
  usart_deinit(USART0);//时钟复位
  usart_baudrate_set(USART0,9600U);//设置波特率
  usart_receive_config(USART0, USART_RECEIVE_ENABLE);//接收使能
  usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);//发送使能
  usart_enable(USART0);//串口使能
  
//  BSP_OS_SemCreate(&ser_mutex,0u,"udp_send_data_mutex");
  
}
