/*
 * @Description: 红外模块-svc层-串口子模块
 * @Author: yangsw
 * @Date: 2021-06-08 11:24:09
 * @LastEditTime: 2024-01-16 09:49:44
 * @LastEditors: LiDa
 * @Reference: 
 */

#include "svc_ir_uart.h"
#include "svc_ir_protocol.h"
#include "../../log/svc/svc_log.h"
#include "../../com/svc/svc_com.h"
#include "param/svc/svc_flash.h"
#include "../../led/app/app_led.h"
#include "../../factory/svc/svc_factory.h"
#include "hci/led/app/sr_app_led.h"
static S_Ir_Uart s_ir_uart;

static void Ir_Uart_Quene_Init(void);

/**
 * @brief: 红外串口初始化
 * @param  {void}
 * @return {void}
 * @note: 
 * @see: 
 */
void Svc_Ir_Uart_Init(void)
{
  Bsp_Ir_Uart_Init();
  Bsp_Ir_Rx_Enable();
  Ir_Uart_Quene_Init();
//  Svc_Ir_Set_Keep_Alive_Time(IR_OPEN_IR);
//  SR_AppLedSetWork(LED_IR_OPEN); 
}

/**
 * @brief: 设置保持网络连接时间
 * @return {void}
 * @note: 超时后进入休眠
 * @see: 
 * @param {gw_u8} u8Time 保持网络连接时间
 */
void Svc_Ir_Set_Keep_Alive_Time(gw_u8 u8Time){
    Svc_Ir_Set_Cur_State(E_IR_ON);	
    s_ir_uart.u8KeepAliveTime=u8Time;
} 

void Svc_Ir_WakeUp_Init(void)
{
  SR_AppLedSetWork(LED_IR_OPEN);  
  Bsp_Ir_Uart_Init();
  Bsp_Ir_Rx_Enable();
  Ir_Uart_Quene_Init();
  Svc_Ir_Set_Keep_Alive_Time(IR_OPEN_IR);
  Svc_Ir_Set_Cur_State(E_IR_ON);
  
}

/**
 * @brief: 等待下发命令
 * @param  {void}
 * @return {gw_u8} 剩余等待时间
 * @note: 
 * @see: 
 */
gw_u8 Svc_Ir_Wait_Cmd(void){
    return s_ir_uart.u8KeepAliveTime;
}

void Svc_Ir_Open_Timer_Callback(){
    if(s_ir_uart.u8KeepAliveTime>0){
        s_ir_uart.u8KeepAliveTime--;
    } 
}


/**
 * @brief: 唤醒后红外模块初始化
 * @note: 
 * @return {void}
 * @see: 
 * @param {void}
 */
void Svc_Ir_Uart_Wakeup_Init(void)
{
    Bsp_Ir_Wakeup_Uart_Config();
}


/**
 * @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)      //串口队列缓冲区满
  {
      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: 
 */
static 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)
{
  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;
    }
  }
}

/**
 * @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)){
        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: 红外串口低功耗
 * @param  {void}
 * @return {void}
 * @note: 
 * @see: 
 */
void Svc_Ir_Uart_Lp(void)
{
	Svc_Log_Printf(LOG_DEBUG,"%s \r\n",__FUNCTION__);	
	// Bsp_Ir_Uart_Lp(); 		  
	// Bsp_Ir_Rx_Disable();  
	Svc_Ir_Set_Cur_State(E_IR_OFF);	
	// Svc_Ir_Set_Keep_Alive_Time(0);
	SR_AppLedClearWork(LED_IR_START);   
	SR_AppLedClearWork(LED_IR_OPEN);
}

/**
 * @brief: 发送数据
 * @return {void}
 * @note: 
 * @see: 
 * @param  {gw_u8}u8Func:功能码
 * @param  {gw_u8}u8Succ:结果 0-失败 1-成功
 */
void Svc_Factory_Ir_Send_Data(gw_u8 u8Func, gw_u8 u8Succ)
{
  S_Factory_Data *s_fact_data;
  s_fact_data =  Svc_Factory_Get_Data();
	gw_u8 u8Data[30] = {0};
	gw_u8 u8DataLen = 1;		//数据长度，默认为1
	
	u8Data[0] = Frame_header;
	u8Data[1] = Type_code;
	u8Data[2] = PC_Device_addr;
	u8Data[3] = u8Func;
	u8Data[5] = u8Succ;			//数据内容
	
	u8Data[4] = u8DataLen;	//数据长度
	u8Data[5 + u8DataLen] = Util_Data_Check_Sum(u8Data, 5 + u8DataLen);//累加和
	u8Data[6 + u8DataLen] = Frame_end;
	
	Bsp_Ir_Uart_Send_Bytes((gw_s8*)u8Data, u8DataLen + 7);
	
	s_fact_data->u8Func = E_IR_Fun_Null;//清除功能码
}
/**
 * @brief: 红外串口接收
 * @param  {void}
 * @return {void} 
 * @note: 
 * @see: 
 */
void Svc_Ir_Uart_Recv(void){
  if(Ir_Is_Format()>=1){
    gw_u16 recv_len=0;
    gw_u16 buf_len=0;
    gw_u16 i=0;
    gw_u8  *p,*p1;
    S_Factory_Data *ps_factory;
    ps_factory = Svc_Factory_Get_Data();    
    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);
    if(recv_len<IR_UART_RX_BUF_SIZE){
    #if LOG_FUNC_ENABLE      
      for(i=0;i<recv_len;i++){
        Svc_Log_Print("%02X ",s_ir_uart.temp_buf[i]);
      }
      Svc_Log_Print("\r\n");
    #endif
      if(ps_factory->u8FactoryTest == 1)
      {
        gw_u32 u32LeadCode;
        u32LeadCode =( (s_ir_uart.temp_buf[0]&0xFF)<<24 | (s_ir_uart.temp_buf[1]&0xFF)<<16 | (s_ir_uart.temp_buf[2]&0xFF)<<8 | (s_ir_uart.temp_buf[3]&0xFF) );      
        if(u32LeadCode  == MAIN_LEAD_CODE)
        {
            Svc_Ir_Protocol_Parse(s_ir_uart.temp_buf,recv_len);
            return;
        }
        else
        {
            Svc_Factory_Log_Parse(s_ir_uart.temp_buf,recv_len);
        }        
      }
      else
      {
        if(Svc_Factory_Is_Start(s_ir_uart.temp_buf,recv_len) == 1)
        {
            return;
        }
        gw_u8 u8LeadCode;
        u8LeadCode =s_ir_uart.temp_buf[0];      
        if(u8LeadCode  == 0x68)
        {
            Svc_Factory_Log_Parse(s_ir_uart.temp_buf,recv_len);
        }
        gw_u32 u32LeadCode;
        u32LeadCode =( (s_ir_uart.temp_buf[0]&0xFF)<<24 | (s_ir_uart.temp_buf[1]&0xFF)<<16 | (s_ir_uart.temp_buf[2]&0xFF)<<8 | (s_ir_uart.temp_buf[3]&0xFF) ); 
             
        if(u32LeadCode  == MAIN_LEAD_CODE)
        {
            Svc_Ir_Protocol_Parse(s_ir_uart.temp_buf,recv_len);
            return;
        }
        p=(gw_u8 *)strchr((const char *)s_ir_uart.temp_buf,'[');
        p1=(gw_u8 *)strchr((const char *)s_ir_uart.temp_buf,']');
        if((p!=NULL)&&(p1!=NULL)&&(p1>p)){			
            Svc_Ir_Parse(p,p1-p+1);
        }
      }
    }else{
      #if LOG_FUNC_ENABLE  
          Svc_Log_Printf(LOG_WARNING,"IR recv len too long!\r\n");
      #endif
    }
  }
}