/*
    VT13接收机
    Example：

  VT13_Init(&vt13);
  
  while (1) {
    VT13_StartDmaRecv(&vt13);
    if (VT13_WaitDmaCplt(20)) {
      if (VT13_Verify(&vt13)) {
        VT13_ParseData(&vt13);
      } else {
        VT13_Offline(&vt13);
      }
    } else {
      VT13_Offline(&vt13);
    }
}
*/

/* Includes ----------------------------------------------------------------- */
#include "vt13.h"
#include "bsp/uart.h"
#include "bsp/time.h"
#include "device.h"
#include "component/crc16.h"

#include <string.h>
#include <stdbool.h>

/* USER INCLUDE BEGIN */

/* USER INCLUDE END */
/* Private define ----------------------------------------------------------- */
#define VT13_CH_VALUE_MIN (364u)
#define VT13_CH_VALUE_MID (1024u)
#define VT13_CH_VALUE_MAX (1684u)

#define VT13_FRAMEHEADER1 0xA9
#define VT13_FRAMEHEADER2 0x53
/* USER DEFINE BEGIN */

/* USER DEFINE END */

/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */

static osThreadId_t thread_alert;
static bool inited = false;

/* Private function  -------------------------------------------------------- */
static void VT13_RxCpltCallback(void) {
  osThreadFlagsSet(thread_alert, SIGNAL_VT13_RAW_REDY);
}

static bool VT13_Verify(VT13_t *vt13){
  if (vt13 == NULL) return DEVICE_ERR_NULL;

  if (vt13->raw_data.sof_1!=VT13_FRAMEHEADER1) {
    return false;
  }
  if (vt13->raw_data.sof_2!=VT13_FRAMEHEADER2) {
    return false;
  }
  if (!CRC16_Verify((const uint8_t *)&(vt13->raw_data),
                    sizeof(VT13_RawData_t))) {
    return false;
  }

  return true;
}

static bool VT13_DataCorrupted(const VT13_t *vt13) {
  if (vt13 == NULL) return DEVICE_ERR_NULL;

  if ((vt13->raw_data.ch_0 < VT13_CH_VALUE_MIN) ||
      (vt13->raw_data.ch_0 > VT13_CH_VALUE_MAX))
    return DEVICE_ERR;

  if ((vt13->raw_data.ch_1 < VT13_CH_VALUE_MIN) ||
      (vt13->raw_data.ch_1 > VT13_CH_VALUE_MAX))
    return DEVICE_ERR;

  if ((vt13->raw_data.ch_2 < VT13_CH_VALUE_MIN) ||
      (vt13->raw_data.ch_2 > VT13_CH_VALUE_MAX))
    return DEVICE_ERR;

  if ((vt13->raw_data.ch_3 < VT13_CH_VALUE_MIN) ||
      (vt13->raw_data.ch_3 > VT13_CH_VALUE_MAX))
    return DEVICE_ERR;

  if ((vt13->raw_data.wheel < VT13_CH_VALUE_MIN) ||
      (vt13->raw_data.wheel > VT13_CH_VALUE_MAX))
    return DEVICE_ERR;

  if (vt13->raw_data.mode_sw == 0) return DEVICE_ERR;

  if (vt13->raw_data.pause == 0) return DEVICE_ERR;

  if (vt13->raw_data.fn_1 == 0) return DEVICE_ERR;

  if (vt13->raw_data.fn_2 == 0) return DEVICE_ERR;

  return DEVICE_OK;
}

/* Exported functions ------------------------------------------------------- */
int8_t VT13_Init(VT13_t *vt13) {
  if (vt13 == NULL) return DEVICE_ERR_NULL;
  if (inited) return DEVICE_ERR_INITED;
  if ((thread_alert = osThreadGetId()) == NULL) return DEVICE_ERR_NULL;

  BSP_UART_RegisterCallback(BSP_UART_AT9S_PRO, BSP_UART_RX_CPLT_CB,
                            VT13_RxCpltCallback);

  inited = true;
  return DEVICE_OK;
}

int8_t VT13_Restart(void) {
  __HAL_UART_DISABLE(BSP_UART_GetHandle(BSP_UART_AT9S_PRO));
  __HAL_UART_ENABLE(BSP_UART_GetHandle(BSP_UART_AT9S_PRO));
  return DEVICE_OK;
}

int8_t VT13_StartDmaRecv(VT13_t *vt13) {
  if (HAL_UART_Receive_DMA(BSP_UART_GetHandle(BSP_UART_AT9S_PRO),
                           (uint8_t *)&(vt13->raw_data),
                           sizeof(vt13->raw_data)) == HAL_OK)
    return DEVICE_OK;
  return DEVICE_ERR;
}

bool VT13_WaitDmaCplt(uint32_t timeout) {
  return (osThreadFlagsWait(SIGNAL_VT13_RAW_REDY, osFlagsWaitAll, timeout) ==
          SIGNAL_VT13_RAW_REDY);
}

int8_t VT13_ParseData(VT13_t *vt13){
  if (vt13 == NULL) return DEVICE_ERR_NULL;

  if (!VT13_Verify(vt13)) {
    return DEVICE_ERR;
  }
  if (VT13_DataCorrupted(vt13)) {
    return DEVICE_ERR;
  }

  vt13->header.online = true;
  vt13->header.last_online_time = BSP_TIME_Get_us();
  
  memset(&(vt13->data), 0, sizeof(vt13->data));

  float full_range = (float)(VT13_CH_VALUE_MAX - VT13_CH_VALUE_MIN);

  // 解析摇杆数据
  vt13->data.ch_r_x = 2.0f * ((float)vt13->raw_data.ch_0 - VT13_CH_VALUE_MID) / full_range;
  vt13->data.ch_r_y = 2.0f * ((float)vt13->raw_data.ch_1 - VT13_CH_VALUE_MID) / full_range;
  vt13->data.ch_l_x = 2.0f * ((float)vt13->raw_data.ch_2 - VT13_CH_VALUE_MID) / full_range;
  vt13->data.ch_l_y = 2.0f * ((float)vt13->raw_data.ch_3 - VT13_CH_VALUE_MID) / full_range;

  // 解析拨杆位置
  vt13->data.sw_l = (VT13_SwitchPos_t)vt13->raw_data.fn_1;
  vt13->data.sw_r = (VT13_SwitchPos_t)vt13->raw_data.fn_2;
  vt13->data.sw_mode = (VT13_SwitchPos_t)vt13->raw_data.mode_sw;
  vt13->data.sw_pause = (VT13_SwitchPos_t)vt13->raw_data.pause;
  vt13->data.sw_trig = (VT13_SwitchPos_t)vt13->raw_data.trigger;

  // 解析鼠标数据
  vt13->data.mouse.x = vt13->raw_data.mouse_x;
  vt13->data.mouse.y = vt13->raw_data.mouse_y;
  vt13->data.mouse.z = vt13->raw_data.mouse_z;

  vt13->data.mouse.l_click = vt13->raw_data.mouse_left;
  vt13->data.mouse.m_click = vt13->raw_data.mouse_middle;
  vt13->data.mouse.r_click = vt13->raw_data.mouse_right;

  // 解析键盘按键 - 使用union简化代码
  uint16_t key_value = vt13->raw_data.key;
  
  // 解析键盘位映射（W-B键，位0-15）
  for (int i = VT13_KEY_W; i <= VT13_KEY_B; i++) {
    vt13->data.keyboard.key[i] = (key_value & (1 << i)) != 0;
  }

  // 解析鼠标点击
  vt13->data.keyboard.key[VT13_L_CLICK] = vt13->data.mouse.l_click;
  vt13->data.keyboard.key[VT13_R_CLICK] = vt13->data.mouse.r_click;

  // 解析第五通道
  vt13->data.ch_res = 2.0f * ((float)vt13->raw_data.wheel - VT13_CH_VALUE_MID) / full_range;
  
  return DEVICE_OK;
}

int8_t VT13_Offline(VT13_t *vt13){
  if (vt13 == NULL) return DEVICE_ERR_NULL;

  vt13->header.online = false;
  memset(&(vt13->data), 0, sizeof(vt13->data));

  return DEVICE_OK;
}

/* USER FUNCTION BEGIN */

/* USER FUNCTION END */
