god-yuan-hero/User/device/vt13.c

209 lines
5.9 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
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 */