#include "uart_dev.h"
#include <stdio.h>
#include <stdarg.h>
#include "timer.h"
#include "gpio.h"
#include "inflash.h"

extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart3;

static void uart_init(uartIndex_e uart_index, int baud);
static u_int8_t uart_putchar(device_handle device, char ch);


device_handle g_term_uart_handle;
device_handle g_rs485_uart_handle;

device_handle uart_dev_init(uartIndex_e uart_index, uint8_t *buff, int buff_size);
static u_int8_t term_in_buff[200];
static u_int8_t rs485_in_buff[300];

u_int8_t rs485_out_buff[100];
static u_int8_t term_out_buff[100];

/**
  * @brief  串口信息初始化,串口号及波特率.
  * @param  uart_index    对应的硬件串口号
  * @param  uart_baudrate 波特率
  */

uart_device_info uart_devices[]={
  [0] = {
      .init          = 0,
      .uart_index    = TERM_UART_INDEX,
      .uart_baudrate = 9600,
  },
  [1] = {
      .init          = 0,
      .uart_index    = RS485_UART_INDEX,
      .uart_baudrate = 9600,
  },
};

/**
  * @brief  初始化串口设备.
  * @param  uart_index 初始化串口号
  * @param  buff       串口循环buff地址
  * @param  buff_size  串口循环buff对应大小
  * @retval 串口句柄
  */
device_handle uart_dev_init(uartIndex_e uart_index, uint8_t *buff, int buff_size)
{
  int i = 0;
  for(; i < ELEMENT_OF(uart_devices); i++){
    if(uart_devices[i].uart_index == uart_index){
      if(!uart_devices[i].init){ 
        InitRingQueue(&uart_devices[i].uart_ring_queue, buff, buff_size); 
        uart_init(uart_index, uart_devices[i].uart_baudrate);  
        
        uart_devices[i].init = 1;
      }
      return (device_handle)(&uart_devices[i]);
    }
  }
  return 0;
}

/**
  * @brief  串口硬件初始化.
  * @param  uart_index 串口号
  * @param  baud 波特率
  * @retval None
  */
static void uart_init(uartIndex_e uart_index, int baud)
{      
    if(uart_index == TERM_UART_INDEX){
//       MX_USART1_UART_Init();
        MX_USART1_UART_Init(baud);
    }else if(uart_index == RS485_UART_INDEX){
        MX_USART3_UART_Init(baud);
//       MX_USART3_UART_Init();
    }
}

/**
  * @brief  关闭串口
  * @param  uart_index 串口号
  * @retval None
  */
void uart_close(uartIndex_e uart_index)
{      
    if(uart_index == TERM_UART_INDEX){
       HAL_UART_MspDeInit(&huart1);
    }else if(uart_index == RS485_UART_INDEX){
       HAL_UART_MspDeInit(&huart3);
    }   
}


/**
  * @brief  发送一个字节.
  * @param  uart_index 串口号
  * @param  ch 待发送字符
  * @retval 1 成功  0失败
  */
static u_int8_t uart_putchar(device_handle device, char ch)
{  
  
   int ret=HAL_ERROR;
   
   uart_device_info *device_info = (uart_device_info *)device; 
   if((!device) || (!device_info->init))
      return 0;
  
    if(device_info->uart_index == TERM_UART_INDEX){
        ret= HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,10); 
    }else if(device_info->uart_index == RS485_UART_INDEX){
        ret= HAL_UART_Transmit(&huart3,(uint8_t*)&ch,1,10);
    }
        
    if(ret == HAL_OK){
       return 1;
    }else{
       return 0;
    }
}

/**
  * @brief  发送字符串.
  * @param  uart_index 串口号
  * @param  str 待发送字符串地址
  * @retval None
  */
void  uart_sendstr(device_handle device,char *str)
{    
    while ((*str) != (char )0u) {
        if (*str == ASCII_CHAR_LINE_FEED){
            uart_putchar(device, (ASCII_CHAR_CARRIAGE_RETURN));
            uart_putchar(device, ASCII_CHAR_LINE_FEED);
            str++;
        }else{
            uart_putchar(device, *str++);
        }
    }
}


/**
  * @brief  串口多字节发送.
  * @param  device 串口句柄
  * @param  data 待发送数据
  * @param  len  待发送数据长度
  * @retval None
  */
void uart_dev_write(device_handle device, void *data, int len)
{  
#if 0
  if(device == g_rs485_uart_handle){
      rs485_tx_enable();
  }
#endif
   for (int i = 0; i < len; i++){
       uart_putchar(device, ((u_int8_t *)data)[i]);
   }
   
#if 0
  if(device == g_rs485_uart_handle){
      rs485_rx_enable();
  }
#endif
   
}


/**
  * @brief  判断串口设备循环buff是否有数据.
  * @param  device 串口句柄
  * @retval 0 空   1有数据
  */
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);
}

/**
  * @brief  从串口设备循环buff读取一个数据.
  * @param  device 串口句柄
  * @retval 读取到的字符
  */
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;
}


/**
  * @brief  判断循环buff是否有数据.
  * @param  ring_queue 循环buff地址
  * @retval 0 空   1有数据
  */
int ring_queue_dev_char_present(RingQueue *ring_queue)
{
    return !RingQueueEmpty(ring_queue);
}

/**
  * @brief  从循环buff读取一个数据.
  * @param  ring_queue 循环buff地址
  * @retval 读取到的字符
  */
char ring_queue_dev_in_char(RingQueue *ring_queue)
{
  char c = 0;
  if (ring_queue_dev_char_present(ring_queue)) 
      OutRingQueue(ring_queue, (u_int8_t*)&c);
  return c;
}

/**999
  * @brief  调试串口 .
  * @param  可变参
  * @retval Null
  */
void term_printf(char *format, ...)
{  
    memset(term_out_buff, 0, sizeof(term_out_buff));
    va_list va_ptr;  
    va_start(va_ptr, format);
    vsprintf((char*)term_out_buff, (char const *)format, va_ptr);
    va_end(va_ptr);

    uart_sendstr(g_term_uart_handle, (char*)term_out_buff);
}
#if 0                        
/**
  * @brief  调试终端读取一行命令 .
  * @param  
  * @param  
  * @param  
  * @retval 读取到的数据长度
  */
int term_uart_readln(u_int8_t *buff, int buff_size, u_int32_t timeout_ms)
{
  int offset = 0;
  char c = 0;
  u_int32_t wait_timeout_flag = 0;

  buff_size--; 

  if(timeout_ms){
     set_flag_timeout(timeout_ms, &wait_timeout_flag);
  }
  
  for(offset = 0; offset<buff_size; offset++){
    while((!uart_dev_char_present(g_term_uart_handle)) && (!wait_timeout_flag));
    
    if(wait_timeout_flag){ 
       break;
    }else{
      c = uart_dev_in_char(g_term_uart_handle);
      
      buff[offset] = c;
     // if(g_term_echo_on)
      //   out_char(c); //回显
        if((c == '\n') || (c == '\r')){
           offset++;
           break;
        }
     }
  }
  if(timeout_ms)
     stop_timout();

  buff[offset] = '\0';
  return offset;
}
#endif


/**
  * @brief  初始化调试串口.
  * @retval None
  */
void init_term_uart()
{    
	g_term_uart_handle = uart_dev_init(TERM_UART_INDEX, term_in_buff, sizeof(term_in_buff));     
}

/**
  * @brief  初始化RS485串口.
  * @retval None
  */
void init_rs485_uart()
{    
	g_rs485_uart_handle = uart_dev_init(RS485_UART_INDEX, rs485_in_buff, sizeof(rs485_in_buff));     
}