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