/*
 * @Description: 红外模块-svc层-串口子模块
 * @Author: yangsw
 * @Date: 2021-06-08 11:24:09
 * @LastEditTime: 2022-07-12 13:51:01
 * @LastEditors: yangsw
 * @Reference:
 */

#include "svc_ir_uart.h"
#include "../../log/svc/svc_log.h"
#include "svc_ir_protocol.h"
#include "../../com/svc/svc_com.h"
#include "svc_ir.h"
#include "../../pulse/svc/svc_pulse.h"
// #include "../../factory/svc/svc_factory.h"

static S_Ir_Uart s_ir_uart;

/**
 * @brief: 红外串口初始化
 * @param  {void}
 * @return {void}
 * @note:
 * @see:
 */
void Svc_Ir_Uart_Init(void)
{
  Bsp_Ir_Uart_Init();
  Bsp_PWM_Config(); //上电时定时器关闭
  Ir_Uart_Quene_Init();
//  Bsp_Ir_Rx_Disable(); // 上电时红外关闭
  Bsp_Ir_Rx_Enable();
  Svc_Ir_Set_Keep_Alive_Time(IR_OPEN_TIME);
}

/**
 * @brief: 唤醒后红外模块初始化
 * @return {void}
 * @note:
 * @see:
 * @param {void}
 */
void Svc_Ir_Uart_Wakeup_Init(void)
{
  Bsp_Ir_Uart_Init();
  Bsp_PWM_Config();
  Bsp_Ir_Rx_Enable();
  Ir_Uart_Quene_Init();
  Svc_Ir_Set_Keep_Alive_Time(IR_OPEN_TIME);
}

/**
 * @brief: 将一字节数据放入串口接收队列
 * @return {char} 1：队列满，0：队列未满
 * @note:
 * @see:
 * @param {char} data 待放入数据
 */
char Svc_Ir_Uart_Put_Data_Quene(char data)
{
  s_ir_uart.time_cnt = 0; // 队列计数清零
  s_ir_uart.time_en = 1;
  if (((s_ir_uart.fornt + 1) % IR_UART_RX_BUF_SIZE) == s_ir_uart.rear) // 串口队列缓冲区满
  {
    // Svc_Log_Print("F\r\n");
    s_ir_uart.format = 1;
    return 1;
  }
  s_ir_uart.RX_BUF[s_ir_uart.fornt] = data;
  s_ir_uart.fornt = (s_ir_uart.fornt + 1) % IR_UART_RX_BUF_SIZE;
  return 0;
}

/**
 * @brief: 从串口接收队列中取出一字节数据
 * @param  {char*} data 取出的数据
 * @return {char} 1：队列中没有数据，0：正常
 * @note:
 * @see:
 */
char Svc_Ir_Uart_Out_data_Quene(char *data)
{
  if (s_ir_uart.rear == s_ir_uart.fornt)
  {
    // Svc_Log_Print("C\r\n");
    return 1;
  }
  *data = s_ir_uart.RX_BUF[s_ir_uart.rear];
  s_ir_uart.rear = (s_ir_uart.rear + 1) % IR_UART_RX_BUF_SIZE;
  return 0;
}

/**
 * @brief: 串口队列初始化
 * @param  {void}
 * @return {void}
 * @note:
 * @see:
 */
void Ir_Uart_Quene_Init(void)
{
  s_ir_uart.fornt = 0;
  s_ir_uart.rear = 0;
  s_ir_uart.time_cnt = 0;
  s_ir_uart.format = 0;
  memset(s_ir_uart.RX_BUF, 0, sizeof(s_ir_uart.RX_BUF));
}

/**
 * @brief: 获取当前队列中数据长度
 * @param  {void}
 * @return {short} 当前队列中数据长度
 * @note:
 * @see:
 */
static short Get_Buf_Length(void)
{
  // Svc_Log_Print("gprs_quene->fornt=%d\r\n",gprs_quene->fornt);
  // Svc_Log_Print("gprs_quene->rear=%d\r\n",gprs_quene->rear);
  if (s_ir_uart.fornt >= s_ir_uart.rear)
  {
    return s_ir_uart.fornt - s_ir_uart.rear;
  }
  else
  {
    return s_ir_uart.fornt + IR_UART_RX_BUF_SIZE - s_ir_uart.rear;
  }
}

/**
 * @brief: 获取队列中指定长度的数据
 * @return {short} 实际获取到的数据长度
 * @note:
 * @see:
 * @param {char} *data 存放获取数据的指针
 * @param {short} buf_len 想要获取数据的长度
 */
short Get_Ir_Uart_Bytes(char *data, short buf_len)
{
  short data_len = 0;
  short i = 0;
  char *ptr = data;
  data_len = Get_Buf_Length();
  s_ir_uart.time_cnt = 0;
  s_ir_uart.format = 0;
  s_ir_uart.time_en = 0;
  if (data_len == 0)
  {
    return 0;
  }
  for (i = 0; i < data_len && i < buf_len; i++)
  {
    Svc_Ir_Uart_Out_data_Quene(ptr);
    ptr++;
  }

  return i;
}

/**
 * @brief: 串口自动断帧计数
 * @param  {void}
 * @return {void}
 * @note: 隔1ms检查串口是否有数据
 * @see:
 */
void Svc_Ir_get_Cnt_Add(void) // 隔1ms检查串口是否有数据
{
  if (s_ir_uart.time_en == 1) // 串口有数据
  {
    s_ir_uart.time_cnt++;
    if (s_ir_uart.time_cnt > IR_UART_CNT_MAX) // 接收自动断帧
    {
      s_ir_uart.time_cnt = 0;
      s_ir_uart.format++;
      s_ir_uart.time_en = 0;
    }
  }
}

void Svc_Ir_Timer_Callback(void)
{
  if (s_ir_uart.wakeup_time > 0)
  {
    s_ir_uart.wakeup_time--;
  }
}

/**
 * @brief: 判断一帧数据是否接收完成
 * @param  {void}
 * @return {char} 1：一帧数据收完，0：一帧数据未收完
 * @note:
 * @see:
 */
char Ir_Is_Format(void)
{
  return s_ir_uart.format;
}

/**
 * @brief: 红外模块是否忙
 * @param  {void}
 * @return {E_Result_Check} E_CHECK_OK:正忙，E_CHECK_FAIL:空闲
 * @note:
 * @see:
 */
E_Result_Check Svc_Ir_Is_Busy(void)
{
  /*计量串口有数据正在接收或者有数据待处理时，返回忙*/
  if ((s_ir_uart.time_en == 1) || (s_ir_uart.format > 0) || (s_ir_uart.wakeup_time > 0))
  {
    return E_CHECK_OK;
  }
  return E_CHECK_FAIL;
}

/**
 * @brief: 设置红外模块为忙状态
 * @param  {void}
 * @return {void}
 * @note: RX中断唤醒后要调用此函数，防止MCU再次进入休眠
 * @see:
 */
void Svc_Ir_Set_Busy(void)
{
  /*红外串口有数据正在接收或者有数据待处理时，返回忙*/
  s_ir_uart.time_en = 1;
}
/**
 * @brief: 红外串口发送
 * @return {void}
 * @note:
 * @see:
 * @param {gw_s8} *buf 待发送数据
 * @param {gw_u16} len 待发送数长度
 */
void Svc_Ir_Uart_Send(gw_s8 *buf, gw_u16 len)
{
  Bsp_Ir_Rx_Disable();      // 关闭接收使能，防止自发自收
  Bsp_PWM_Enable(); // 开启定时器，发送38K载波
  Bsp_Ir_Uart_Send_Bytes(buf, len);
  Bsp_PWM_Disable();
  Bsp_Ir_Rx_Enable(); // 开启接收使能
}

S_Ir_Uart *Svc_Ir_Get_Uart_Data(void)
{
  return &s_ir_uart;
}

void Svc_Ir_Set_Keep_Alive_Time(gw_u32 time)
{
  s_ir_uart.wakeup_time = time;
}

/**
 * @brief: 红外串口接收
 * @param  {void}
 * @return {void}
 * @note:
 * @see:
 */
void Svc_Ir_Uart_Recv(void)
{
  if (Ir_Is_Format() >= 1)
  {
    Bsp_Iwdg_Feed();
    gw_u16 recv_len = 0;
    gw_u16 buf_len = 0;
    gw_u16 i = 0;
    s_ir_uart.temp_buf = Svc_Com_Get_Buf();
    buf_len = IR_UART_RX_BUF_SIZE;
    memset(s_ir_uart.temp_buf, 0, buf_len);
    recv_len = Get_Ir_Uart_Bytes((char *)s_ir_uart.temp_buf, buf_len);
    Svc_Log_Printf(LOG_INFO, "IR recv len:%d\r\n", recv_len);
    if (recv_len < IR_UART_RX_BUF_SIZE)
    {
      Svc_Log_Printf(LOG_INFO, "IR Recv: ");
      for (i = 0; i < recv_len; i++)
      {
        Svc_Log_Print("%02X ", s_ir_uart.temp_buf[i]);
      }
      Svc_Log_Print("\r\n");
      Svc_Ir_Protocol_Parse(s_ir_uart.temp_buf, recv_len);
    }
    else
    {
      Svc_Log_Printf(LOG_WARNING, "IR recv len too long!\r\n");
    }
  }
}
