132 lines
4.3 KiB
C
132 lines
4.3 KiB
C
/* Includes ----------------------------------------------------------------- */
|
|
#include "vt13.h"
|
|
#include "bsp/uart.h"
|
|
#include "bsp/time.h"
|
|
#include "device.h"
|
|
#include "crc16.h"
|
|
#include <string.h>
|
|
#include <stdbool.h>
|
|
/* --------------------------------------------------------
|
|
串口参数 数值
|
|
波特率 921600
|
|
数据位 8
|
|
停止位 1
|
|
校验位 无
|
|
流控 无
|
|
-------------------------------------------------------- */
|
|
|
|
/* Private variables -------------------------------------------------------- */
|
|
static osThreadId_t thread_alert;
|
|
static bool inited = false;
|
|
|
|
/* Private macro ------------------------------------------------------------ */
|
|
|
|
|
|
/* Private function -------------------------------------------------------- */
|
|
static void VT13_RxCpltCallback(void) {
|
|
osThreadFlagsSet(thread_alert, SIGNAL_VT13_RAW_REDY);
|
|
}
|
|
|
|
static bool VT13_DataCorrupted(const VT13_t *vt13) {
|
|
/* 1. 帧头校验:必须为 0xA9 和 0x53 */
|
|
if (vt13->raw_data.header1 != 0xA9 || vt13->raw_data.header2 != 0x53) {
|
|
return true;
|
|
}
|
|
|
|
/* 2. CRC16 校验:验证整个 21 字节的帧长度 */
|
|
if (!CRC16_Verify((const uint8_t *)&(vt13->raw_data), sizeof(VT13_RawData_t))) {
|
|
return true;
|
|
}
|
|
|
|
/* 3. 挡位范围校验(作为双重保险,因为 CRC 只能保证通信无误,不能保证按键逻辑无误) */
|
|
if (vt13->raw_data.mode > 2) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/* 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;
|
|
|
|
/* 注意:图传模块波特率为 921600 ,请在 UART 初始化时核对 */
|
|
BSP_UART_RegisterCallback(BSP_UART_VT13, 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_VT13));
|
|
__HAL_UART_ENABLE(BSP_UART_GetHandle(BSP_UART_VT13));
|
|
return DEVICE_OK;
|
|
}
|
|
|
|
int8_t VT13_StartDmaRecv(VT13_t *vt13) {
|
|
if (HAL_UART_Receive_DMA(BSP_UART_GetHandle(BSP_UART_VT13),
|
|
(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_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);
|
|
|
|
/* 1. 解析摇杆与拨轮数据并归一化至 [-1.0, 1.0] */
|
|
vt13->data.ch_r_x = 2.0f * ((float)vt13->raw_data.ch_r_x - VT13_CH_VALUE_MID) / full_range;
|
|
vt13->data.ch_r_y = 2.0f * ((float)vt13->raw_data.ch_r_y - VT13_CH_VALUE_MID) / full_range;
|
|
vt13->data.ch_l_y = 2.0f * ((float)vt13->raw_data.ch_l_y - VT13_CH_VALUE_MID) / full_range;
|
|
vt13->data.ch_l_x = 2.0f * ((float)vt13->raw_data.ch_l_x - VT13_CH_VALUE_MID) / full_range;
|
|
vt13->data.dial = 2.0f * ((float)vt13->raw_data.dial - VT13_CH_VALUE_MID) / full_range;
|
|
|
|
/* 2. 解析按钮和开关 [cite: 165] */
|
|
vt13->data.mode = (VT13_Mode_t)vt13->raw_data.mode;
|
|
vt13->data.pause = vt13->raw_data.pause;
|
|
vt13->data.custom_l = vt13->raw_data.custom_l;
|
|
vt13->data.custom_r = vt13->raw_data.custom_r;
|
|
vt13->data.trigger = vt13->raw_data.trigger;
|
|
|
|
/* 3. 解析鼠标数据 */
|
|
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_l;
|
|
vt13->data.mouse.r_click = vt13->raw_data.mouse_r;
|
|
vt13->data.mouse.m_click = vt13->raw_data.mouse_m;
|
|
|
|
/* 4. 解析键盘按键 */
|
|
uint16_t key_value = vt13->raw_data.keyboard;
|
|
for (int i = 0; i < VT13_KEY_NUM; i++) {
|
|
vt13->data.keyboard.key[i] = (key_value & (1 << i)) != 0;
|
|
}
|
|
|
|
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;
|
|
} |