diff --git a/.idea/runConfigurations/example_dbus_DJI_Board_TypeA_general_elf.xml b/.idea/runConfigurations/example_dbus_DJI_Board_TypeA_general_elf.xml
deleted file mode 100644
index e8b47ba8..00000000
--- a/.idea/runConfigurations/example_dbus_DJI_Board_TypeA_general_elf.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/runConfigurations/example_dbus_DJI_Board_TypeC_general_elf.xml b/.idea/runConfigurations/example_dbus_DJI_Board_TypeC_general_elf.xml
deleted file mode 100644
index 1d5fc340..00000000
--- a/.idea/runConfigurations/example_dbus_DJI_Board_TypeC_general_elf.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/runConfigurations/example_dbus_DM_MC01_general_elf.xml b/.idea/runConfigurations/example_dbus_DM_MC01_general_elf.xml
deleted file mode 100644
index 4e0c0e77..00000000
--- a/.idea/runConfigurations/example_dbus_DM_MC01_general_elf.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/runConfigurations/example_dbus_DM_MC02_general_elf.xml b/.idea/runConfigurations/example_dbus_DM_MC02_general_elf.xml
deleted file mode 100644
index ff206d64..00000000
--- a/.idea/runConfigurations/example_dbus_DM_MC02_general_elf.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/runConfigurations/example_referee_DJI_Board_TypeC_general_rc_elf.xml b/.idea/runConfigurations/example_referee_DJI_Board_TypeC_general_rc_elf.xml
deleted file mode 100644
index adf94785..00000000
--- a/.idea/runConfigurations/example_referee_DJI_Board_TypeC_general_rc_elf.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/runConfigurations/example_sbus_DJI_Board_TypeC_general_elf.xml b/.idea/runConfigurations/example_sbus_DJI_Board_TypeC_general_elf.xml
deleted file mode 100644
index 1a671c2b..00000000
--- a/.idea/runConfigurations/example_sbus_DJI_Board_TypeC_general_elf.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/boards/CMakeLists.txt b/boards/CMakeLists.txt
index 4ac579e8..2fa82b5b 100644
--- a/boards/CMakeLists.txt
+++ b/boards/CMakeLists.txt
@@ -3,4 +3,4 @@ add_subdirectory(platform)
add_subdirectory(algorithm)
add_subdirectory(drivers)
add_subdirectory(components)
-add_subdirectory(third_party)
\ No newline at end of file
+add_subdirectory(third_party)
diff --git a/boards/base/DJI_Board_TypeC_general/Core/Src/usart.c b/boards/base/DJI_Board_TypeC_general/Core/Src/usart.c
index 2857c9fe..71611ce6 100644
--- a/boards/base/DJI_Board_TypeC_general/Core/Src/usart.c
+++ b/boards/base/DJI_Board_TypeC_general/Core/Src/usart.c
@@ -76,7 +76,7 @@ void MX_USART3_UART_Init(void)
/* USER CODE END USART3_Init 1 */
huart3.Instance = USART3;
huart3.Init.BaudRate = 100000;
- huart3.Init.WordLength = UART_WORDLENGTH_8B;
+ huart3.Init.WordLength = UART_WORDLENGTH_9B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_EVEN;
huart3.Init.Mode = UART_MODE_RX;
diff --git a/boards/base/DJI_Board_TypeC_general/DJI_Board_TypeC_general.ioc b/boards/base/DJI_Board_TypeC_general/DJI_Board_TypeC_general.ioc
index f6cde419..00c2d761 100644
--- a/boards/base/DJI_Board_TypeC_general/DJI_Board_TypeC_general.ioc
+++ b/boards/base/DJI_Board_TypeC_general/DJI_Board_TypeC_general.ioc
@@ -703,7 +703,7 @@ USART3.IPParameters=VirtualMode,Parity,BaudRate,WordLength,Mode
USART3.Mode=MODE_RX
USART3.Parity=PARITY_EVEN
USART3.VirtualMode=VM_ASYNC
-USART3.WordLength=WORDLENGTH_8B
+USART3.WordLength=WORDLENGTH_9B
USART6.IPParameters=VirtualMode
USART6.VirtualMode=VM_ASYNC
USB_DEVICE.CLASS_NAME_FS=CDC
diff --git a/boards/drivers/CMakeLists.txt b/boards/drivers/CMakeLists.txt
index 3562e590..863160ba 100644
--- a/boards/drivers/CMakeLists.txt
+++ b/boards/drivers/CMakeLists.txt
@@ -7,6 +7,7 @@ set(DRIVER_SOURCES
${CRC_CHECK_SOURCES})
set(DRIVER_INCLUDES
${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/controller
${CMAKE_CURRENT_SOURCE_DIR}/include/Motor
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/crc_check/include)
@@ -99,4 +100,4 @@ uicrm_add_board_specific_library(BulletExchanger_F103_drivers
SOURCES ${DRIVER_SOURCES}
INCLUDES ${DRIVER_INCLUDES}
DEPENDS BulletExchanger_F103_platform BulletExchanger_F103_algorithm)
-target_include_directories(BulletExchanger_F103_drivers PUBLIC ${DRIVER_INCLUDES})
\ No newline at end of file
+target_include_directories(BulletExchanger_F103_drivers PUBLIC ${DRIVER_INCLUDES})
diff --git a/boards/drivers/include/connection_driver.h b/boards/drivers/include/connection_driver.h
index ec0881bc..1dc72a50 100644
--- a/boards/drivers/include/connection_driver.h
+++ b/boards/drivers/include/connection_driver.h
@@ -34,7 +34,7 @@ namespace driver {
* @brief 判断节点是否在线
* @return true 表示当前连接节点在线,false 表示当前节点连接离线
*/
- bool IsOnline() const;
+ virtual bool IsOnline() const;
/**
* @return 获取节点上一个心跳包的时间(以毫秒为单位)
diff --git a/boards/drivers/include/controller/controller.h b/boards/drivers/include/controller/controller.h
new file mode 100644
index 00000000..2e70c1fe
--- /dev/null
+++ b/boards/drivers/include/controller/controller.h
@@ -0,0 +1,288 @@
+/*###########################################################
+# Copyright (c) 2026-2027. BNBU/UIC RoboMaster #
+ # #
+ # This program is free software: you can redistribute it #
+ # and/or modify it under the terms of the GNU General #
+ # Public License as published by the Free Software #
+ # Foundation, either version 3 of the License, or (at #
+ # your option) any later version. #
+ # #
+ # This program is distributed in the hope that it will be #
+ # useful, but WITHOUT ANY WARRANTY; without even #
+ # the implied warranty of MERCHANTABILITY or FITNESS #
+ # FOR A PARTICULAR PURPOSE. See the GNU General #
+ # Public License for more details. #
+ # #
+ # You should have received a copy of the GNU General #
+ # Public License along with this program. If not, see #
+ # . #
+ ###########################################################*/
+#pragma once
+
+#include
+#include
+#include
+#include
+
+/** @brief 遥控协议解析与状态管理。 */
+namespace controller {
+ /**
+ * @brief 两档拨杆的公共逻辑位置。
+ * @note 具体设备负责将协议值转换为位置;枚举数值不用于解码或判断拨动方向。
+ */
+ enum class TwoPositionSwitch : uint8_t {
+ Down = 0, ///< 下档。
+ Up = 1 ///< 上档。
+ };
+
+ /**
+ * @brief 三档拨杆的公共逻辑位置。
+ * @note 枚举数值保持稳定。
+ * 各设备须显式映射协议值,不得依赖枚举数值解码或判断物理拨动方向。
+ */
+ enum class ThreePositionSwitch : uint8_t {
+ Up = 1, ///< 上档。
+ Down = 2, ///< 下档。
+ Mid = 3 ///< 中档。
+ };
+
+ /**
+ * @brief 获取两档拨杆的名称,便于日志输出。
+ * @param[in] position 拨杆位置。
+ * @return "Up" 或 "Down";非法枚举值返回 "Unknown"。
+ */
+ constexpr const char* SwitchName(TwoPositionSwitch position) {
+ using enum TwoPositionSwitch;
+ switch (position) {
+ case Up:
+ return "Up";
+ case Down:
+ return "Down";
+ }
+ return "Unknown";
+ }
+
+ /**
+ * @brief 获取三档拨杆的名称,便于日志输出。
+ * @param[in] position 拨杆位置。
+ * @return "Up"、"Mid" 或 "Down";非法枚举值返回 "Unknown"。
+ */
+ constexpr const char* SwitchName(ThreePositionSwitch position) {
+ using enum ThreePositionSwitch;
+ switch (position) {
+ case Up:
+ return "Up";
+ case Mid:
+ return "Mid";
+ case Down:
+ return "Down";
+ }
+ return "Unknown";
+ }
+
+ /**
+ * @brief DBUS 与 RefereeRC 共用的鼠标状态。
+ * @details 三轴保留协议中的原始有符号数值,范围 -32768~32767,静止值为 0,
+ * 不套用摇杆的 ±660 范围或死区。按键 false 表示松开,true 表示按下。
+ * @note 协议未提供的按键保持 false;DBUS 不提供中键,RefereeRC 支持左、右、中键。
+ */
+ struct MouseState {
+ int16_t x = 0; ///< 鼠标 X 轴输入。
+ int16_t y = 0; ///< 鼠标 Y 轴输入。
+ int16_t z = 0; ///< 鼠标滚轮输入。
+ bool left = false; ///< 鼠标左键是否按下。
+ bool right = false; ///< 鼠标右键是否按下。
+ bool middle = false; ///< 鼠标中键是否按下;DBUS 始终为 false。
+ };
+
+ /**
+ * @brief DBUS 与 RefereeRC 共用的 16 键键盘状态。
+ * @details code 与 bit 共享两字节存储;各按键位 0 表示松开、1 表示按下,
+ * 多个按键可同时按下。默认 code 为 0,支持 keyboard.code 和 keyboard.bit.W 等访问。
+ * @note 位域视图采用本项目 GCC/ARM 布局;线上数据仍由各协议按小端字节显式解码,
+ * 不把接收缓存强制转换为此类型。更换编译器平台须验证位域布局。
+ */
+ union KeyboardState {
+ uint16_t code = 0; ///< 完整 16 位按键位图,范围 0~65535。
+ struct {
+ uint16_t W : 1; ///< bit0:W 键是否按下。
+ uint16_t S : 1; ///< bit1:S 键是否按下。
+ uint16_t A : 1; ///< bit2:A 键是否按下。
+ uint16_t D : 1; ///< bit3:D 键是否按下。
+ uint16_t SHIFT : 1; ///< bit4:SHIFT 键是否按下。
+ uint16_t CTRL : 1; ///< bit5:CTRL 键是否按下。
+ uint16_t Q : 1; ///< bit6:Q 键是否按下。
+ uint16_t E : 1; ///< bit7:E 键是否按下。
+ uint16_t R : 1; ///< bit8:R 键是否按下。
+ uint16_t F : 1; ///< bit9:F 键是否按下。
+ uint16_t G : 1; ///< bit10:G 键是否按下。
+ uint16_t Z : 1; ///< bit11:Z 键是否按下。
+ uint16_t X : 1; ///< bit12:X 键是否按下。
+ uint16_t C : 1; ///< bit13:C 键是否按下。
+ uint16_t V : 1; ///< bit14:V 键是否按下。
+ uint16_t B : 1; ///< bit15:B 键是否按下。
+ } __attribute__((packed)) bit;
+ } __attribute__((packed));
+ static_assert(sizeof(KeyboardState) == 2, "KeyboardState must occupy two bytes");
+
+ /**
+ * @brief 遥控接收器的公共状态接口。
+ * @details 仅管理有效帧序号、接收时间及协议失控标志,不统一各协议的通道布局。
+ * UART、时钟和控制映射由接入层提供。校验失败或数据未收齐时不提交状态。
+ * @note 不提供内部同步;与接收中断并发读取时,不保证各字段来自同一帧。
+ * UpdateData 只允许单一接收上下文调用;解析、重置及协议配置不得并发执行。
+ */
+ class ControllerReceiver {
+ public:
+ /**
+ * @brief 设置接收器的初始在线超时。
+ * @param[in] online_threshold_ms 超时阈值,单位毫秒,默认 250。
+ */
+ explicit ControllerReceiver(uint32_t online_threshold_ms = 250) : online_threshold_ms_(online_threshold_ms) {
+ }
+
+ /** @brief 支持通过基类指针销毁派生接收器。 */
+ virtual ~ControllerReceiver() = default;
+
+ /**
+ * @brief 输入接收字节,具体边界和校验规则由派生协议定义。
+ * @param[in] data 接收数据地址,调用结束后不保留该指针;空指针不提交有效帧。
+ * @param[in] size 数据字节数。
+ * @param[in] now_ms 本次输入的时间,单位毫秒,须与 IsOnline 使用相同时间基准。
+ * @note DBUS 每次输入必须是具有明确边界的完整 18 字节块;SBUS/VT13 可输入半包或连续字节流。
+ */
+ virtual void UpdateData(const uint8_t* data, size_t size, uint32_t now_ms) = 0;
+
+ /**
+ * @brief 判断最近一次有效帧是否仍在超时范围内。
+ * @param[in] now_ms 当前时间,单位毫秒,须与 UpdateData 使用相同时间基准。
+ * @return 已接收有效帧且时间差严格小于阈值时为 true,否则为 false。
+ * @note 支持时间为 0 的首帧及 uint32_t 计时回绕;超过完整计时周期无法区分。
+ * 在线仅表示通信仍在更新,不代表 IsFailsafe 为 false 或机器人允许控制。
+ */
+ bool IsOnline(uint32_t now_ms) const {
+ return received_ && uint32_t(now_ms - last_valid_ms_) < online_threshold_ms_;
+ }
+
+ /** @brief 获取有效帧提交序号,每帧递增一次,按 uint32_t 自然回绕;首次提交前为 0。 */
+ uint32_t GetSequence() const {
+ return sequence_;
+ }
+
+ /**
+ * @brief 获取最近有效帧的协议失控标志。
+ * @return 最近有效帧报告失控时为 true,否则为 false;首次有效帧前为 false。
+ * @note 无失控标志的协议提交 false;此接口不包含超时或机器人模式判定。
+ */
+ bool IsFailsafe() const {
+ return failsafe_;
+ }
+
+ /**
+ * @brief 获取最近一次有效帧的提交时间,单位毫秒。
+ * @return 最近有效帧的 now_ms;首次提交前为 0,是否已有帧须使用 HasState 判断。
+ */
+ uint32_t GetLastValidTimeMs() const {
+ return last_valid_ms_;
+ }
+
+ /** @brief 判断是否曾接收有效帧;后续超时或重置半包不会清除此标志。 */
+ bool HasState() const {
+ return received_;
+ }
+
+ /**
+ * @brief 修改在线超时阈值,不清除最后状态或接收时间。
+ * @param[in] threshold_ms 超时阈值,单位毫秒;设为 0 时 IsOnline 始终返回 false。
+ */
+ void SetThreshold(uint32_t threshold_ms) {
+ online_threshold_ms_ = threshold_ms;
+ }
+
+ protected:
+ /**
+ * @brief 派生接收器在完整校验并更新协议状态后提交有效帧。
+ * @param[in] now_ms 有效帧的接收时间,单位毫秒。
+ * @param[in] failsafe 当前帧的协议失控标志。
+ * @details 更新接收时间及失控标志,标记已有状态,并将有效帧序号递增一次。
+ */
+ void CommitFrame(uint32_t now_ms, bool failsafe) {
+ last_valid_ms_ = now_ms;
+ failsafe_ = failsafe;
+ received_ = true;
+ ++sequence_;
+ }
+
+ private:
+ uint32_t online_threshold_ms_; ///< 在线超时阈值,单位毫秒。
+ uint32_t last_valid_ms_ = 0; ///< 最近有效帧时间,单位毫秒。
+ uint32_t sequence_ = 0; ///< 有效帧提交序号。
+ bool received_ = false; ///< 是否曾提交有效帧。
+ bool failsafe_ = false; ///< 最近有效帧的协议失控标志。
+ };
+ /** @brief 接收器内部字节解码工具,不涉及 UART、控制映射或有效帧提交。 */
+ namespace detail {
+ /**
+ * @brief 按低位优先的位序提取无符号字段,可跨越字节边界。
+ * @param[in] data 数据起始地址,不得为空。
+ * @param[in] bit_offset 起始位偏移,单位为位;0 表示 data[0] 的最低位。
+ * @param[in] bit_count 提取位数,范围 0~16;为 0 时返回 0。
+ * @return 提取后的无符号数,源起始位成为结果最低位。
+ * @pre data 必须覆盖全部待读位,bit_offset + bit_count 不得溢出。
+ * @note 不检查缓冲长度,不做符号扩展、数值范围校验或中心转换。
+ * 例如 DecodeBits(data, 11, 11) 提取 DBUS 通道 1 的原始编码。
+ */
+ inline uint16_t DecodeBits(const uint8_t* data, size_t bit_offset, unsigned bit_count) {
+ uint16_t value = 0;
+ for (unsigned i = 0; i < bit_count; ++i) {
+ value |= uint16_t((data[(bit_offset + i) / 8] >> ((bit_offset + i) % 8)) & 1u) << i;
+ }
+ return value;
+ }
+
+ /**
+ * @brief 从两个小端字节解码无符号 16 位整数。
+ * @param[in] data 字段起始地址,须至少包含两个可读字节,不得为空。
+ * @return data[0] 为低字节、data[1] 为高字节,结果范围 0~65535。
+ * @note 不检查缓冲长度,与主机字节序及对齐方式无关。
+ * 例如字节 {0x34, 0x12} 解码为 0x1234,可用于键盘位图和帧内 CRC 值。
+ */
+ inline uint16_t DecodeUint16LE(const uint8_t* data) {
+ return uint16_t(data[0]) | (uint16_t(data[1]) << 8);
+ }
+
+ /**
+ * @brief 从两个小端字节解码二进制补码形式的有符号 16 位整数。
+ * @param[in] data 字段起始地址,须至少包含两个可读字节,不得为空。
+ * @return 保留符号的数值,范围 -32768~32767。
+ * @details 先读取无符号编码;编码超过 32767 时减去 65536 得到负值。
+ * @note 不检查缓冲长度,不做死区或比例转换;例如 {0xFF, 0xFF} 解码为 -1。
+ */
+ inline int16_t DecodeInt16LE(const uint8_t* data) {
+ const uint16_t value = DecodeUint16LE(data);
+ return static_cast(value <= 32767 ? int32_t(value) : int32_t(value) - 65536);
+ }
+
+ /**
+ * @brief 错帧后从缓存后缀查找下一个可能的帧头,并将保留数据移到缓存起始位置。
+ * @tparam N 固定缓存容量,单位字节。
+ * @param[in,out] buffer 当前候选帧缓存;保留的数据可能只是下一帧的半包。
+ * @param[in,out] used 调用前为有效字节数,调用后为保留字节数。
+ * @param[in] sof 要查找的帧头字节,例如 SBUS 的 0x0F 或 VT13 的 0xA9。
+ * @pre 1 <= used <= N,只在当前候选帧被判定无效后调用。
+ * @details 从下标 1 开始查找,跳过当前无效帧头;找到后保留该字节及其后的全部数据。
+ * 未找到时 used 置 0。buffer 中 used 之后的内容无效,不必清零。
+ * @note 只恢复候选边界,不验证帧长度、命令字或 CRC,不修改接收器状态。
+ * DBUS 没有帧头,不能使用此方法恢复对齐。
+ */
+ template
+ void FindNextFrame(std::array& buffer, size_t& used, uint8_t sof) {
+ size_t offset = 1;
+ while (offset < used && buffer[offset] != sof) {
+ ++offset;
+ }
+ used -= offset;
+ std::memmove(buffer.data(), buffer.data() + offset, used);
+ }
+ } // namespace detail
+} // namespace controller
diff --git a/boards/drivers/include/controller/dbus.h b/boards/drivers/include/controller/dbus.h
new file mode 100644
index 00000000..05a59a66
--- /dev/null
+++ b/boards/drivers/include/controller/dbus.h
@@ -0,0 +1,144 @@
+/*###########################################################
+ # Copyright (c) 2026-2027. BNBU/UIC RoboMaster #
+ # #
+ # This program is free software: you can redistribute it #
+ # and/or modify it under the terms of the GNU General #
+ # Public License as published by the Free Software #
+ # Foundation, either version 3 of the License, or (at #
+ # your option) any later version. #
+ # #
+ # This program is distributed in the hope that it will be #
+ # useful, but WITHOUT ANY WARRANTY; without even #
+ # the implied warranty of MERCHANTABILITY or FITNESS #
+ # FOR A PARTICULAR PURPOSE. See the GNU General #
+ # Public License for more details. #
+ # #
+ # You should have received a copy of the GNU General #
+ # Public License along with this program. If not, see #
+ # . #
+ ###########################################################*/
+
+#pragma once
+
+#include
+
+#include "controller.h"
+#include "bsp_uart.h"
+
+namespace controller {
+ /**
+ * @brief DBUS 有效帧快照,通道数值沿用旧 DBUS 的减中心与死区处理。
+ * @details 原始值减去 1024,绝对值不大于 10 时置零,正常行程为 -660~660。
+ * 不额外缩放或限幅;任何通道的原始值超出 364~1684 时拒绝整帧。
+ */
+ struct DbusFrame {
+ /**
+ * @brief 五个通道的有符号输入值,正常行程为 -660~660,中心为 0。
+ * @details 下标 0:右摇杆 X;1:右摇杆 Y;2:左摇杆 X;3:左摇杆 Y;4:左拨轮。
+ * 摇杆方向沿用旧代码:X 左负右正,Y 上负下正;拨轮方向沿用设备原编码。
+ * @note 遥控器的样式
+ *
+ * ch4()
+ *
+ * L_sw* *R_sw
+ * ch3-^ ^-ch1
+ * ch2-< >+ -< >+ch0
+ * +v v+
+ */
+ std::array channels{};
+ ThreePositionSwitch right_switch = ThreePositionSwitch::Mid; ///< 右拨杆位置。
+ ThreePositionSwitch left_switch = ThreePositionSwitch::Mid; ///< 左拨杆位置。
+ MouseState mouse{}; ///< 鼠标状态;DBUS 不提供中键,middle 始终为 false。
+ KeyboardState keyboard{}; ///< 键盘状态,支持 code 和 bit 按键访问。
+ };
+
+ /**
+ * @brief DBUS 18 字节接收器,支持通过 UART 句柄构造后自动接收。
+ * @details DBUS 无帧头及 CRC,校验长度、拨杆、鼠标按钮和配置的通道范围。
+ * 字段合理性检查不能保证完整性,也不能用于猜测字节流的帧边界。
+ * @note UART 模式内部通过 IDLE 回调接收;并发读取不保证整帧一致性。
+ * UpdateData 与 SetChannelRange 不得并发调用,UART 模式下修改范围须先停止接收。
+ */
+ class DBUS final : public ControllerReceiver {
+ public:
+ static constexpr size_t FRAME_SIZE = 18; ///< 单帧长度,单位字节。
+ static constexpr uint16_t CHANNEL_MIN = 364; ///< 原始通道有效下限。
+ static constexpr uint16_t CHANNEL_MAX = 1684; ///< 原始通道有效上限。
+
+ /**
+ * @brief 绑定并拥有 UART 接收对象,自动配置缓存和接收回调。
+ * @param[in] huart 已完成板级配置的 UART 句柄,不得为同一 UART 重复创建接收对象。
+ * @param[in] online_threshold_ms 在线超时,单位毫秒,默认 250。
+ * @note 内部配置 100000 baud、8E1(HAL 使用 9 位字长以包含偶校验位)。
+ * 引脚、DMA、中断及信号反相由板级配置;绑定前不得启动该 UART 的收发。
+ * 对象须覆盖中断使用周期。
+ */
+ explicit DBUS(UART_HandleTypeDef* huart, uint32_t online_threshold_ms = 250);
+
+ /** @brief 释放本接收器拥有的 UART;调用前须停止相关接收中断。 */
+ ~DBUS() override;
+
+ DBUS(const DBUS&) = delete;
+
+ DBUS& operator=(const DBUS&) = delete;
+
+ /** @brief 使用系统毫秒时钟判断有效 DBUS 帧是否在线,无需调用方传时间。 */
+ bool IsOnline() const;
+
+ /**
+ * @brief 输入具有明确边界的完整 DBUS 接收块,一次调用只处理一帧。
+ * @param[in] data 接收块地址,须从帧起点开始,调用结束后不保留该指针。
+ * @param[in] size 接收块字节数,必须恰好为 FRAME_SIZE(18 字节)。
+ * @param[in] now_ms 本块接收时间,单位毫秒。
+ * @details UART IDLE 回调自动调用本接口;手动接入时调用方负责提供帧边界。
+ * 空指针、错误长度或无效字段不修改状态、序号或有效帧时间。
+ * @note 不累积半包,不拆分多帧块;5+13 字节的两次调用和一次 36 字节输入均拒绝。
+ */
+ void UpdateData(const uint8_t* data, size_t size, uint32_t now_ms) override;
+
+ /**
+ * @brief 拷贝最后一帧有效状态。
+ * @param[out] output 成功时接收完整快照;失败时保持原值。
+ * @return 曾接收有效帧时为 true,否则为 false。
+ * @note 离线后仍可读取最后状态;用于控制前须另行判断 IsOnline。
+ */
+ bool GetState(DbusFrame& output) const;
+
+ /**
+ * @brief 设置五个通道统一使用的原始值校验范围,默认 364~1684。
+ * @param[in] minimum 允许的最小值,包含边界。
+ * @param[in] maximum 允许的最大值,包含边界。
+ * @return 364 <= minimum <= maximum <= 1684 时为 true;否则返回 false 并保留配置。
+ * @note 参数使用线上的原始编码值,仅影响后续帧校验;输出仍按旧 DBUS 语义减中心并处理死区。
+ */
+ bool SetChannelRange(uint16_t minimum, uint16_t maximum);
+
+ private:
+ /** @brief UART 接收回调入口,读取接收块并按 IDLE 边界校验。 */
+ void RxCompleteCallback();
+
+ /**
+ * @brief 将 DBUS 两位拨杆编码显式转换为公共三档位置。
+ * @param[in] raw 协议编码:1 为上档,2 为下档,3 为中档,0 非法。
+ * @param[out] output 成功时接收逻辑位置;失败时保持原值。
+ * @return 编码合法时为 true,否则为 false。
+ */
+ static bool DecodeSwitch(uint16_t raw, ThreePositionSwitch& output);
+
+ /**
+ * @brief 校验并解码一帧,对有效数据更新快照并提交状态。
+ * @param[in] data 已收齐的 FRAME_SIZE 字节候选帧。
+ * @param[in] now_ms 本帧接收时间,单位毫秒。
+ * @return 校验通过并提交时为 true,否则为 false。
+ * @details 校验五通道原始范围、左右拨杆及鼠标按钮;转换通道中心与死区,解码键鼠。
+ * 所有校验通过后才整体替换最后状态并调用 CommitFrame;失败时状态、序号及有效时间不变。
+ * @note 仅由内部完整候选帧入口调用,不负责收集半包或恢复字节边界。
+ */
+ bool Decode(const uint8_t* data, uint32_t now_ms);
+ static void UartCallback(void* context); ///< UART 回调转发入口。
+ bsp::UART* uart_ = nullptr; ///< 内部独占的 UART。
+ uint16_t channel_min_ = CHANNEL_MIN; ///< 原始通道值校验下限。
+ uint16_t channel_max_ = CHANNEL_MAX; ///< 原始通道值校验上限。
+ DbusFrame state_{}; ///< 最后一帧有效状态。
+ };
+} // namespace controller
diff --git a/boards/drivers/include/controller/refereerc.h b/boards/drivers/include/controller/refereerc.h
new file mode 100644
index 00000000..ac9873e8
--- /dev/null
+++ b/boards/drivers/include/controller/refereerc.h
@@ -0,0 +1,138 @@
+/*###########################################################
+# Copyright (c) 2026-2027. BNBU/UIC RoboMaster #
+ # #
+ # This program is free software: you can redistribute it #
+ # and/or modify it under the terms of the GNU General #
+ # Public License as published by the Free Software #
+ # Foundation, either version 3 of the License, or (at #
+ # your option) any later version. #
+ # #
+ # This program is distributed in the hope that it will be #
+ # useful, but WITHOUT ANY WARRANTY; without even #
+ # the implied warranty of MERCHANTABILITY or FITNESS #
+ # FOR A PARTICULAR PURPOSE. See the GNU General #
+ # Public License for more details. #
+ # #
+ # You should have received a copy of the GNU General #
+ # Public License along with this program. If not, see #
+ # . #
+ ###########################################################*/
+#pragma once
+
+#include
+
+#include "bsp_uart.h"
+#include "controller.h"
+
+namespace controller {
+ /** @brief RefereeRC 遥控模式编码;是否允许控制由本车逻辑决定。 */
+ enum class RefereeRcMode : uint8_t {
+ C = 0, ///< C 模式。
+ N = 1, ///< N 模式。
+ S = 2 ///< S 模式。
+ };
+
+ /** @brief RefereeRC 有效帧快照,通道减中心并处理死区,不包含本车控制映射。 */
+ struct RefereeRcFrame {
+ /**
+ * @brief 五通道减去 1024,包含 ±10 死区;不缩放或额外限幅。
+ * @details 输出范围 -660~660,中心为 0;顺序为右 X/Y、左 Y/X、拨轮。
+ */
+ std::array channels{};
+ RefereeRcMode mode = RefereeRcMode::C; ///< 模式选择,不自动转换为协议失控标志。
+ bool pause = false; ///< 暂停按钮状态。
+ bool left_button = false; ///< 遥控器左侧按钮状态,与鼠标左键不同。
+ bool right_button = false; ///< 遥控器右侧按钮状态,与鼠标右键不同。
+ bool trigger = false; ///< 扳机状态。
+ MouseState mouse{}; ///< 鼠标状态,包含左、右、中键。
+ KeyboardState keyboard{}; ///< 键盘状态,支持 code 和 bit 按键访问。
+ uint16_t crc16 = 0; ///< 已通过校验的帧内 CRC16 值。
+ };
+
+ /**
+ * @brief RefereeRC 21 字节遥控接收器,支持 UART 自动接收和手动输入。
+ * @details 验证 0xA9 帧头、0x53 命令字、既有 CRC16、合法模式 0/1/2、
+ * 五通道范围 364~1684,以及各占两位的鼠标左/右/中键编码 0/1。
+ * 仅有效帧更新数据和独立在线时间,N/S 模式及暂停按钮不自动视为协议失控。
+ * @note UART 直连仅用于纯遥控字节流;混合 A5/A9 数据须先由外部链路分帧。
+ * 并发读取不保证整帧一致性;UpdateData 与 ResetStream 须在同一接收上下文串行调用或停止接收后调用。
+ */
+ class RefereeRC final : public ControllerReceiver {
+ public:
+ static constexpr size_t FRAME_SIZE = 21; ///< 单帧长度,单位字节。
+ static constexpr uint8_t SOF = 0xA9; ///< RefereeRC 帧头。
+ static constexpr uint8_t CMD = 0x53; ///< RefereeRC 命令字。
+ static constexpr uint16_t CHANNEL_MIN = 364; ///< 五通道原始值有效下限,包含边界。
+ static constexpr uint16_t CHANNEL_MAX = 1684; ///< 五通道原始值有效上限,包含边界。
+ static constexpr uint16_t CHANNEL_CENTER = 1024;
+ static constexpr int16_t CHANNEL_DEADZONE = 10;
+ /**
+ * @brief 创建手动输入模式接收器,不分配 UART。
+ * @param[in] online_threshold_ms 有效遥控帧超时阈值,单位 ms。
+ */
+ explicit RefereeRC(uint32_t online_threshold_ms = 250);
+
+ /**
+ * @brief 创建并拥有 UART,自动注册回调及配置接收缓存。
+ * @param[in] huart 已配置的 UART 句柄,不得为空或重复绑定。
+ * @param[in] online_threshold_ms 有效遥控帧超时阈值,单位 ms。
+ * @note 内部配置 921600 baud、8N1;引脚、DMA、中断由板级配置。
+ * 绑定前不得启动该 UART 的收发;对象须覆盖接收中断使用期。
+ */
+ explicit RefereeRC(UART_HandleTypeDef* huart, uint32_t online_threshold_ms = 250);
+
+ /** @brief 释放内部 UART;调用前须停止接收及相关中断。 */
+ ~RefereeRC() override;
+
+ /** @brief 禁止复制,避免重复拥有 UART 和回调上下文。 */
+ RefereeRC(const RefereeRC&) = delete;
+ /** @brief 禁止复制赋值。 */
+ RefereeRC& operator=(const RefereeRC&) = delete;
+
+ /** @brief 使用系统毫秒时钟判断有效遥控帧是否在线。 */
+ bool IsOnline() const;
+ /** @brief 保留手动输入使用的显式时间查询接口。 */
+ using ControllerReceiver::IsOnline;
+
+ /**
+ * @brief 输入纯 RefereeRC 遥控字节流,支持半包、连续帧及错误后的后缀恢复。
+ * @param[in] data 接收字节地址,空指针不提交状态,调用结束后不保留该指针。
+ * @param[in] size 数据字节数。
+ * @param[in] now_ms 本次输入的时间,单位毫秒;完成的有效帧使用此时间提交。
+ * @warning 不直接输入混合 A5/A9 图传流,应由 Protocol::Receive 完成分帧后接入。
+ */
+ void UpdateData(const uint8_t* data, size_t size, uint32_t now_ms) override;
+
+ /** @brief 清除暂存半包,保留最后有效状态、序号和接收时间。 */
+ void ResetStream();
+
+ /**
+ * @brief 拷贝最后一帧有效状态。
+ * @param[out] output 成功时接收完整快照;失败时保持原值。
+ * @return 曾接收有效帧时为 true,否则为 false。
+ * @note 离线后仍可读取最后状态;控制前须检查 IsOnline 及本车模式允许条件。
+ */
+ bool GetState(RefereeRcFrame& output) const;
+
+ private:
+ /**
+ * @brief 读取 UART 接收块并直接输入解析器,读取错误时丢弃半包。
+ * @param[in] context 注册回调时传入的有效 RefereeRC 实例指针。
+ */
+ static void UartCallback(void* context);
+
+ /**
+ * @brief 校验并解码内部缓存的完整候选帧,对有效数据更新快照并提交状态。
+ * @param[in] now_ms 本帧接收时间,单位毫秒。
+ * @return 校验通过并提交时为 true,否则为 false。
+ * @details 校验帧头、命令字、CRC16、模式编码、通道范围及鼠标按钮;解码五通道、控制按钮和键鼠。
+ * 所有校验通过后才整体替换最后状态并调用 CommitFrame;失败时状态、序号及有效时间不变。
+ * @note 仅由内部完整候选帧入口调用,不负责收集半包或恢复字节边界。
+ */
+ bool Decode(uint32_t now_ms);
+ bsp::UART* uart_ = nullptr; ///< 独占 UART;手动输入模式为 nullptr。
+ std::array buffer_{}; ///< 候选帧缓存。
+ size_t used_ = 0; ///< 已缓存字节数。
+ RefereeRcFrame state_{}; ///< 最后一帧有效状态。
+ };
+} // namespace controller
diff --git a/boards/drivers/include/controller/sbus.h b/boards/drivers/include/controller/sbus.h
new file mode 100644
index 00000000..aa2741dc
--- /dev/null
+++ b/boards/drivers/include/controller/sbus.h
@@ -0,0 +1,210 @@
+/*###########################################################
+# Copyright (c) 2026-2027. BNBU/UIC RoboMaster #
+ # #
+ # This program is free software: you can redistribute it #
+ # and/or modify it under the terms of the GNU General #
+ # Public License as published by the Free Software #
+ # Foundation, either version 3 of the License, or (at #
+ # your option) any later version. #
+ # #
+ # This program is distributed in the hope that it will be #
+ # useful, but WITHOUT ANY WARRANTY; without even #
+ # the implied warranty of MERCHANTABILITY or FITNESS #
+ # FOR A PARTICULAR PURPOSE. See the GNU General #
+ # Public License for more details. #
+ # #
+ # You should have received a copy of the GNU General #
+ # Public License along with this program. If not, see #
+ # . #
+ ###########################################################*/
+/**
+ * @file sbus.h
+ * @brief SBUS 协议接收器及 FS-i6X/iA10B 设备适配接口。
+ */
+#pragma once
+
+#include
+
+#include "bsp_uart.h"
+#include "controller.h"
+
+namespace controller {
+ /** @brief SBUS 原始帧快照,不做减中心、死区处理或设备映射。 */
+ struct SbusFrame {
+ std::array channels{}; ///< CH1~16 原始 11 位值,范围 0~2047。
+ uint8_t flags = 0; ///< 原始标志字节,保留所有位。
+ bool channel17 = false; ///< flags bit0:数字通道 17。
+ bool channel18 = false; ///< flags bit1:数字通道 18。
+ bool frame_lost = false; ///< flags bit2:接收机报告丢帧,不等同于失控。
+ bool failsafe = false; ///< flags bit3:接收机报告失控,不等同于通信离线。
+ };
+
+ /**
+ * @brief 通用 SBUS 接收器,管理 UART、分帧、原始状态及有效帧时间。
+ * @details 可绑定 UART 自动接收,也可通过 UpdateData 手动输入字节流。
+ * 每个有效帧更新状态和序号;帧中的失控标志不阻止在线时间更新。
+ * @note 不提供内部同步;与接收中断并发读取时,不保证整帧一致性。
+ * UpdateData、ResetStream、SetFooter 须在同一接收上下文串行调用或停止接收后调用。
+ * @see I6x
+ */
+ class SBUS : public ControllerReceiver {
+ public:
+ static constexpr size_t FRAME_SIZE = 25; ///< SBUS 单帧字节数。
+
+ /**
+ * @brief 创建手动输入模式接收器,不分配 UART。
+ * @param[in] online_threshold_ms 有效帧超时阈值,单位 ms;0 表示始终离线。
+ * @param[in] footer 唯一允许的帧尾字节,应与实际接收机一致。
+ */
+ explicit SBUS(uint32_t online_threshold_ms = 250, uint8_t footer = 0x00);
+
+ /**
+ * @brief 创建并拥有一个 UART,配置接收缓存并注册接收回调。
+ * @param[in] huart 已完成板级配置的 UART 句柄,不得为空或重复绑定。
+ * @param[in] online_threshold_ms 有效帧超时阈值,单位 ms。
+ * @param[in] footer 唯一允许的帧尾字节。
+ * @note 内部配置 100000 baud、8E2(HAL 使用 9 位字长以包含偶校验位)。
+ * 引脚、DMA、中断及信号反相由板级配置;绑定前不得启动该 UART 的收发。
+ * 对象生命周期须覆盖 UART 中断使用期。
+ */
+ explicit SBUS(UART_HandleTypeDef* huart, uint32_t online_threshold_ms = 250, uint8_t footer = 0x00);
+
+ /**
+ * @brief 释放内部 UART;手动输入模式无需释放外设。
+ * @pre 调用方已停止接收及相关中断,不再触发本对象的回调。
+ */
+ ~SBUS() override;
+
+ /** @brief 禁止复制,避免重复拥有 UART 和回调上下文。 */
+ SBUS(const SBUS&) = delete;
+ /** @brief 禁止复制赋值,保持 UART 所有权唯一。 */
+ SBUS& operator=(const SBUS&) = delete;
+
+ /**
+ * @brief 使用系统毫秒时钟判断最近有效帧是否在线。
+ * @return 已收到有效帧且未达到超时阈值时为 true,否则为 false。
+ * @note 手动输入的时间须与系统时钟同源,否则使用带 now_ms 的重载。
+ * 在线不代表无失控;控制前还须检查帧状态及应用策略。
+ */
+ bool IsOnline() const;
+ /** @brief 保留基类的显式毫秒时钟查询接口。 */
+ using ControllerReceiver::IsOnline;
+
+ /**
+ * @brief 拷贝最后一帧有效原始状态。
+ * @param[out] output 成功时接收原始快照;失败时保持原值。
+ * @return 曾收到有效帧时为 true,首次有效帧前为 false。
+ * @note 离线后保留最后状态,返回值不表示输入当前可用于控制。
+ */
+ bool GetRawState(SbusFrame& output) const;
+
+ /**
+ * @brief 输入字节流,累积半包并逐帧校验、解码。
+ * @param[in] data 输入数据,不保留指针;为空时忽略本次输入。
+ * @param[in] size 输入字节数;0 表示不处理数据。
+ * @param[in] now_ms 接收时间,单位 ms;本次完成的所有有效帧使用此时间。
+ * @details 查找 0x0F 帧头,收齐 25 字节后检查配置的帧尾。
+ * 无效候选帧保留下一帧头起始的后缀,继续处理后续字节。
+ * 无效数据不刷新最后有效状态;有效失控帧仍更新状态及在线时间。
+ * @note SBUS 无 CRC,帧头和帧尾校验不能保证数据完整性。
+ */
+ void UpdateData(const uint8_t* data, size_t size, uint32_t now_ms) override;
+
+ /** @brief 丢弃暂存半包,保留最后有效帧、序号、时间及失控状态。 */
+ void ResetStream();
+
+ /**
+ * @brief 修改唯一允许的帧尾字节,并丢弃暂存半包。
+ * @param[in] footer 实际接收机使用的帧尾字节。
+ * @note 不清除最后有效帧和接收状态。
+ */
+ void SetFooter(uint8_t footer);
+
+ private:
+ /**
+ * @brief 将 UART 回调转发到接收器实例。
+ * @param[in] context 注册回调时传入的有效 SBUS 实例指针。
+ */
+ static void UartCallback(void* context);
+
+ /**
+ * @brief 读取 UART 接收块,以系统毫秒时间调用 UpdateData。
+ * @details 空接收块不处理;读取错误或非空块缺少数据指针时清除半包。
+ */
+ void RxCompleteCallback();
+
+ /**
+ * @brief 校验并解码完整候选帧,成功后发布原始状态。
+ * @param[in] now_ms 本帧有效接收时间,单位 ms。
+ * @return 帧头、帧尾正确且已提交状态时为 true,否则为 false。
+ * @pre buffer_ 中已收齐 FRAME_SIZE 字节。
+ * @note 失败不改变最后有效状态;本函数不负责重新查找帧头。
+ */
+ bool Decode(uint32_t now_ms);
+
+ bsp::UART* uart_ = nullptr; ///< 独占的 UART;手动输入模式为 nullptr。
+ std::array buffer_{}; ///< 正在收集的候选帧。
+ size_t used_ = 0; ///< 候选帧内已缓存的字节数。
+ uint8_t footer_; ///< 当前允许的帧尾字节。
+ SbusFrame state_{}; ///< 最后有效帧,离线时仍保留。
+ };
+
+ /**
+ * @brief i6X 控件快照,原始帧通过继承的 GetRawState 获取。
+ * @details 丢帧及失控标志来自参与映射的同一帧,不包含在线超时判定。
+ */
+ struct I6xState {
+ std::array channels{}; ///< CH1~6:右 X/Y、左 Y/X、VrA/VrB,范围 ±660。
+ TwoPositionSwitch sw_a = TwoPositionSwitch::Down; ///< CH7:SwA,两档。
+ TwoPositionSwitch sw_b = TwoPositionSwitch::Down; ///< CH8:SwB,两档。
+ ThreePositionSwitch sw_c = ThreePositionSwitch::Mid; ///< CH9:SwC,三档。
+ TwoPositionSwitch sw_d = TwoPositionSwitch::Down; ///< CH10:SwD,两档。
+ bool frame_lost = false; ///< 接收机报告丢帧,原样传递。
+ bool failsafe = false; ///< 接收机报告失控,原样传递。
+ };
+
+ /**
+ * @brief FS-i6X/iA10B 设备适配,继承 SBUS 的接收和在线状态。
+ * @details 使用 240/1024/1807 标定端点及中心,原始 ±10 死区包含边界。
+ * 中心两侧按各自行程缩放并四舍五入,输出饱和至 ±660。
+ * 高拨杆通道值对应上档,模拟通道保持固定方向。
+ * @note 发射机应保持 I6xState 所述通道分配;本类不包含机器人动作。
+ * 不另建 UART、接收缓存或在线时间。
+ */
+ class I6x final : public SBUS {
+ public:
+ /** @brief 继承 SBUS 的手动输入及 UART 构造,使用固定设备映射。 */
+ using SBUS::SBUS;
+
+ /**
+ * @brief 从基类最后有效帧转换得到 i6X 控件状态。
+ * @param[out] output 成功时接收映射结果;失败时保持原值。
+ * @return 曾收到有效帧时为 true,首次有效帧前为 false。
+ * @note 不另外缓存映射结果,不修改接收时间和序号。
+ * 离线或失控后仍可读取;控制前须另行判断输入是否可用。
+ */
+ bool GetState(I6xState& output) const;
+
+ private:
+ /**
+ * @brief 对模拟通道执行减中心、死区、标定缩放和限幅。
+ * @param[in] raw SBUS 原始通道值,范围 0~2047。
+ * @return 范围为 -660~660 的映射值,死区内为 0。
+ */
+ static int16_t MapChannel(uint16_t raw);
+
+ /**
+ * @brief 以原始中心值 1024 为界解码两档拨杆。
+ * @param[in] raw SBUS 原始通道值。
+ * @return raw >= 1024 为 Up,否则为 Down。
+ */
+ static TwoPositionSwitch TwoPosition(uint16_t raw);
+
+ /**
+ * @brief 按最近标定位置解码三档拨杆。
+ * @param[in] raw SBUS 原始通道值。
+ * @return 小于 632 为 Down,632~1415 为 Mid,至少 1416 为 Up。
+ */
+ static ThreePositionSwitch ThreePosition(uint16_t raw);
+ };
+} // namespace controller
diff --git a/boards/drivers/include/dji_dbus.h b/boards/drivers/include/dji_dbus.h
deleted file mode 100644
index b97f55a4..00000000
--- a/boards/drivers/include/dji_dbus.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*###########################################################
- # Copyright (c) 2023-2024. BNU-HKBU UIC RoboMaster #
- # #
- # This program is free software: you can redistribute it #
- # and/or modify it under the terms of the GNU General #
- # Public License as published by the Free Software #
- # Foundation, either version 3 of the License, or (at #
- # your option) any later version. #
- # #
- # This program is distributed in the hope that it will be #
- # useful, but WITHOUT ANY WARRANTY; without even #
- # the implied warranty of MERCHANTABILITY or FITNESS #
- # FOR A PARTICULAR PURPOSE. See the GNU General #
- # Public License for more details. #
- # #
- # You should have received a copy of the GNU General #
- # Public License along with this program. If not, see #
- # . #
- ###########################################################*/
-
-#pragma once
-
-#include "bsp_uart.h"
-#include "connection_driver.h"
-#include "dji_remote.h"
-
-namespace remote {
-
- typedef enum {
- UP = 1,
- DOWN = 2,
- MID = 3,
- } switch_t;
-
- // inline uint8_t operator- (const switch_t a, const switch_t b)
- // {return static_cast(a) - static_cast(b);}
-
- /**
- * @brief DBUS 遥控器接收类
- * @note 用于DJI DR16接收机
- */
- /**
- * @brief DBUS remote receiver class
- * @note used for DJI DR16 receiver
- */
- class DBUS : public bsp::UART, public driver::ConnectionDriver {
- public:
- /**
- * @brief 构造函数
- * @note 和uart类似,dbus需要时间进行初始化
- *
- * @param huart uart实例
- */
- /**
- * @brief intialize DBUS the same way as a generic UART peripheral
- * @note like uart, dbus needs time to initialize
- *
- * @param huart uart instance
- */
- DBUS(UART_HandleTypeDef* huart);
-
- // Add custom rx data handler
- void RxCompleteCallback() override final;
-
- // rocker channel information
- /**
- * @note 遥控器的样式
- *
- * @note the style of the remote
- *
- * C4(
- * SWL* *SWR
- * C3-^ ^-C1
- * C2-< >+ -< >+C0
- * +v v+
- *
- */
- /**
- * @brief 获取右摇杆的x轴值
- */
- volatile int16_t ch0;
- /**
- * @brief 获取右摇杆的y轴值
- */
- volatile int16_t ch1;
- /**
- * @brief 获取左摇杆的x轴值
- */
- volatile int16_t ch2;
- /**
- * @brief 获取左摇杆的y轴值
- */
- volatile int16_t ch3;
-
- // left and right switch information
- /**
- * @brief 获取左拨杆的状态
- */
- volatile switch_t swl;
- /**
- * @brief 获取右拨杆的状态
- */
- volatile switch_t swr;
- // left track wheel
- /**
- * @brief 获取左波轮的x轴值
- */
- volatile int16_t ch4;
- // mouse movement and button information
- /**
- * @brief 获取鼠标的数据,仅限于DT7连接上电脑之后
- */
- mouse_t mouse;
- // keyboard key information
- /**
- * @brief 获取键盘的数据,仅限于DT7连接上电脑之后
- */
- keyboard_t keyboard;
-
- static const int16_t ROCKER_MIN = -660;
- static const int16_t ROCKER_MAX = 660;
- };
-
-} /* namespace remote */
diff --git a/boards/drivers/include/dji_remote.h b/boards/drivers/include/dji_remote.h
deleted file mode 100644
index 31850f57..00000000
--- a/boards/drivers/include/dji_remote.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*###########################################################
- # Copyright (c) 2023-2024. BNU-HKBU UIC RoboMaster #
- # #
- # This program is free software: you can redistribute it #
- # and/or modify it under the terms of the GNU General #
- # Public License as published by the Free Software #
- # Foundation, either version 3 of the License, or (at #
- # your option) any later version. #
- # #
- # This program is distributed in the hope that it will be #
- # useful, but WITHOUT ANY WARRANTY; without even #
- # the implied warranty of MERCHANTABILITY or FITNESS #
- # FOR A PARTICULAR PURPOSE. See the GNU General #
- # Public License for more details. #
- # #
- # You should have received a copy of the GNU General #
- # Public License along with this program. If not, see #
- # . #
- ###########################################################*/
-
-#pragma once
-
-#include "main.h"
-
-namespace remote {
- typedef struct {
- int16_t x;
- int16_t y;
- int16_t z;
- uint8_t l;
- uint8_t r;
- } __packed mouse_t;
-
-#define mouse_xy_max 32767.0
-
- typedef union {
- uint16_t code;
- struct {
- uint16_t W : 1; // 前
- uint16_t S : 1; // 后
- uint16_t A : 1; // 左
- uint16_t D : 1; // 右
- uint16_t SHIFT : 1; // boost
- uint16_t CTRL : 1; // 切换 小陀螺/自瞄/坦克/标准 模式
- uint16_t Q : 1; // 小陀螺加速/减速
- uint16_t E : 1; // 小陀螺加速/减速
- uint16_t R : 1; //
- uint16_t F : 1; //
- uint16_t G : 1; //
- uint16_t Z : 1; // 摩擦轮
- uint16_t X : 1; //
- uint16_t C : 1; // 清除自定义UI
- uint16_t V : 1; // 强制刷新自定义UI
- uint16_t B : 1; //
- } __packed bit;
- } __packed keyboard_t;
-
- typedef struct vt13_remote_t {
- uint64_t ch0 : 11;
- uint64_t ch1 : 11;
- uint64_t ch2 : 11;
- uint64_t ch3 : 11;
- enum vt13_mode_t : uint64_t {
- MODE_C = 0,
- MODE_N = 1,
- MODE_S = 2,
- } mode_sw : 2;
- uint64_t pause : 1;
- uint64_t swl : 1;
- uint64_t swr : 1;
- uint64_t ch4 : 11;
- uint64_t trigger : 1;
- constexpr static uint16_t ROCKER_MID = 1024;
- constexpr static uint16_t ROCKER_RANGE = 660;
- } __packed vt13_remote_t;
-
- typedef struct vt13_mouse_t {
- int16_t x;
- int16_t y;
- int16_t roll;
- struct {
- uint8_t l : 1;
- uint8_t reserved : 1; // 不知道为什么,VT13目前的包中间空了一位
- uint8_t r : 1;
- uint8_t mid : 1;
- };
- explicit operator mouse_t() const {
- mouse_t result;
- result.x = x;
- result.y = y;
- result.z = roll;
- result.l = l; // shoot
- result.r = r; // unload
- return result;
- }
- } __packed vt13_mouse_t;
-
- typedef struct vt13_packet_t {
- constexpr static uint8_t SOF = 0xA9;
- constexpr static uint8_t CMD = 0x53;
- uint8_t sof; // 0xA9
- uint8_t cmd; // 0x53
- vt13_remote_t remote;
- vt13_mouse_t mouse;
- keyboard_t keyboard;
- uint16_t crc16;
- } __packed vt13_packet_t;
-} // namespace remote
\ No newline at end of file
diff --git a/boards/drivers/include/protocol.h b/boards/drivers/include/protocol.h
index f9b6e652..1c6a7b30 100644
--- a/boards/drivers/include/protocol.h
+++ b/boards/drivers/include/protocol.h
@@ -25,7 +25,7 @@
#include "bsp_uart.h"
#include "bsp_usb.h"
#include "connection_driver.h"
-#include "dji_remote.h"
+#include "refereerc.h"
namespace communication {
@@ -46,6 +46,9 @@ namespace communication {
* @return true for success; false for failure
*/
bool Receive(package_t package);
+ const controller::RefereeRC& RefereeRc() const {
+ return refereerc_;
+ }
/**
* @brief Generate the package to be sent according to the command and save to the internal
@@ -64,15 +67,6 @@ namespace communication {
uint8_t bufferRx[MAX_FRAME_LEN] = {0};
uint8_t bufferTx[MAX_FRAME_LEN] = {0};
- struct {
- int idx = 0;
- enum mode {
- WAITING_FOR_SOF,
- RECEIVING_REFEREE,
- RECEIVING_VT13,
- } mode = WAITING_FOR_SOF;
- } rx_state;
-
/**
* @brief verify the header of frame with crc8
*
@@ -126,6 +120,12 @@ namespace communication {
* @return length of the data that is copied into buffer
*/
virtual int ProcessDataTx(int cmd_id, uint8_t* data) = 0;
+
+ private:
+ size_t rx_used_ = 0;
+ controller::RefereeRC refereerc_;
+ void DiscardRx(size_t size);
+ void ResyncRx();
};
class UARTProtocol : public Protocol {
@@ -215,7 +215,6 @@ namespace communication {
* 0x0301 STUDENT_INTERACTIVE
* 0x0302 ROBOT_INTERACTIVE [x]
* 0x0303 ROBOT_COMMAND [x]
- * 0x0304 REMOTE_CONTROL_DATA
* 0x0305 CLIENT_MAP_COMMAND [x]
*/
@@ -240,8 +239,6 @@ namespace communication {
RFID_STATUS = 0x0209,
DART_CLIENT_CMD = 0x020A,
STUDENT_INTERACTIVE = 0x0301,
- REMOTE_CONTROL_DATA = 0x304,
- REMOTE_CONTROL_VT13 = 0x53,
CUSTOM_CLIENT_DATA = 0x0306,
} referee_cmd;
@@ -535,13 +532,6 @@ namespace communication {
uint8_t cmd_source;
} __packed map_command_t;
- /* ===== REMOTE_CONTROL_DATA 0x0304 30Hz ===== */
- typedef struct {
- remote::mouse_t mouse;
- remote::keyboard_t keyboard;
- uint16_t reserved;
- } __packed remote_control_t;
-
/* ===== MAP_ROBOT_DATA 0x0305 ===== */
typedef struct {
uint16_t target_robot_id;
@@ -610,14 +600,11 @@ namespace communication {
custom_robot_data_t custom_robot_data{}; // 0x0302
map_command_t map_command{}; // 0x0303
- remote_control_t remote_control{}; // 0x0304
map_robot_data_t map_robot_data{}; // 0x0305
custom_client_data_t custom_client_data{}; // 0x0306
custom_client_map_command_t custom_client_map_command{}; // 0x0307
custom_info_t custom_info{}; // 0x0308
- remote::vt13_packet_t vt13_packet{};
-
void PrepareUIContent(content graph_content);
private:
@@ -859,4 +846,4 @@ namespace communication {
#endif
-} /* namespace communication */
\ No newline at end of file
+} /* namespace communication */
diff --git a/boards/drivers/include/sbus.h b/boards/drivers/include/sbus.h
deleted file mode 100644
index 656a6943..00000000
--- a/boards/drivers/include/sbus.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*###########################################################
- # Copyright (c) 2023-2024. BNU-HKBU UIC RoboMaster #
- # #
- # This program is free software: you can redistribute it #
- # and/or modify it under the terms of the GNU General #
- # Public License as published by the Free Software #
- # Foundation, either version 3 of the License, or (at #
- # your option) any later version. #
- # #
- # This program is distributed in the hope that it will be #
- # useful, but WITHOUT ANY WARRANTY; without even #
- # the implied warranty of MERCHANTABILITY or FITNESS #
- # FOR A PARTICULAR PURPOSE. See the GNU General #
- # Public License for more details. #
- # #
- # You should have received a copy of the GNU General #
- # Public License along with this program. If not, see #
- # . #
- ###########################################################*/
-
-#pragma once
-
-#include "bsp_uart.h"
-#include "connection_driver.h"
-
-namespace remote {
-
- /**
- * @brief SBUS 遥控器接收类
- * @note 用于支持SBUS的接收机
- */
- /**
- * @brief DBUS remote receiver class
- * @note used for DJI DR16 receiver
- */
- class SBUS : public bsp::UART, public driver::ConnectionDriver {
- public:
- /**
- * @brief 构造函数
- * @note 和uart类似,sbus需要时间进行初始化
- *
- * @param huart uart实例
- */
- /**
- * @brief intialize SBUS the same way as a generic UART peripheral
- * @note like uart, sbus needs time to initialize
- *
- * @param huart uart instance
- */
- SBUS(UART_HandleTypeDef* huart);
-
- // Add custom rx data handler
- void RxCompleteCallback() override final;
-
- // rocker channel information
- /**
- * @note 遥控器的样式
- *
- * @note the style of the remote
- *
- * C4(
- * SWL* *SWR
- * C3-^ ^-C1
- * C2-< >+ -< >+C0
- * +v v+
- *
- */
-
- volatile int16_t ch1;
- volatile int16_t ch2;
- volatile int16_t ch3;
- volatile int16_t ch4;
- volatile int16_t ch5;
- volatile int16_t ch6;
- volatile int16_t ch7;
- volatile int16_t ch8;
- volatile int16_t ch9;
- volatile int16_t ch10;
- volatile int16_t ch11;
- volatile int16_t ch12;
- volatile int16_t ch13;
- volatile int16_t ch14;
- volatile int16_t ch15;
- volatile int16_t ch16;
- volatile uint8_t flag;
-
- // timestamp of the update interrupt
- /**
- * @brief 获取更新中断的时间戳
- */
- uint32_t timestamp;
-
- static const int16_t ROCKER_MIN = -1023;
- static const int16_t ROCKER_MAX = 1023;
- };
-
-} /* namespace remote */
diff --git a/boards/drivers/src/controller/dbus.cpp b/boards/drivers/src/controller/dbus.cpp
new file mode 100644
index 00000000..ecaa508f
--- /dev/null
+++ b/boards/drivers/src/controller/dbus.cpp
@@ -0,0 +1,133 @@
+/*###########################################################
+ # Copyright (c) 2026-2027. BNBU/UIC RoboMaster #
+ # #
+ # This program is free software: you can redistribute it #
+ # and/or modify it under the terms of the GNU General #
+ # Public License as published by the Free Software #
+ # Foundation, either version 3 of the License, or (at #
+ # your option) any later version. #
+ # #
+ # This program is distributed in the hope that it will be #
+ # useful, but WITHOUT ANY WARRANTY; without even #
+ # the implied warranty of MERCHANTABILITY or FITNESS #
+ # FOR A PARTICULAR PURPOSE. See the GNU General #
+ # Public License for more details. #
+ # #
+ # You should have received a copy of the GNU General #
+ # Public License along with this program. If not, see #
+ # . #
+ ###########################################################*/
+#include "dbus.h"
+
+#include "bsp_os.h"
+
+namespace controller {
+ DBUS::DBUS(UART_HandleTypeDef* huart, uint32_t online_threshold_ms) : ControllerReceiver(online_threshold_ms) {
+ huart->Init.BaudRate = 100000;
+ huart->Init.WordLength = UART_WORDLENGTH_9B;
+ huart->Init.Parity = UART_PARITY_EVEN;
+ huart->Init.StopBits = UART_STOPBITS_1;
+ if (HAL_UART_Init(huart) != HAL_OK) {
+ Error_Handler();
+ return;
+ }
+ uart_ = new bsp::UART(huart);
+ uart_->RegisterCallback(UartCallback, this);
+ uart_->SetupRx(FRAME_SIZE + 1);
+ }
+
+ DBUS::~DBUS() {
+ delete uart_;
+ }
+
+ bool DBUS::IsOnline() const {
+ return ControllerReceiver::IsOnline(bsp::GetHighresTickMilliSec());
+ }
+
+ void DBUS::UartCallback(void* context) {
+ static_cast(context)->RxCompleteCallback();
+ }
+
+ void DBUS::RxCompleteCallback() {
+ if (!uart_)
+ return;
+ uint8_t* data = nullptr;
+ const int32_t length = uart_->Read(&data);
+ UpdateData(data, length > 0 ? static_cast(length) : 0, bsp::GetHighresTickMilliSec());
+ }
+
+ void DBUS::UpdateData(const uint8_t* data, size_t size, uint32_t now_ms) {
+ // UART IDLE supplies a candidate frame boundary; only a full block is accepted.
+ if (data != nullptr && size == FRAME_SIZE) {
+ Decode(data, now_ms);
+ }
+ }
+
+ bool DBUS::SetChannelRange(uint16_t minimum, uint16_t maximum) {
+ if (minimum < CHANNEL_MIN || minimum > maximum || maximum > CHANNEL_MAX) {
+ return false;
+ }
+ channel_min_ = minimum;
+ channel_max_ = maximum;
+ return true;
+ }
+
+ bool DBUS::GetState(DbusFrame& output) const {
+ if (!HasState()) {
+ return false;
+ }
+ output = state_;
+ return true;
+ }
+
+ bool DBUS::DecodeSwitch(uint16_t raw, ThreePositionSwitch& output) {
+ switch (raw) {
+ case 1:
+ output = ThreePositionSwitch::Up;
+ return true;
+ case 2:
+ output = ThreePositionSwitch::Down;
+ return true;
+ case 3:
+ output = ThreePositionSwitch::Mid;
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool DBUS::Decode(const uint8_t* data, uint32_t now_ms) {
+ DbusFrame next;
+ for (size_t i = 0; i < next.channels.size(); ++i) {
+ // 处理 ch0-4
+ const size_t offset = i < 4 ? 11 * i : 128;
+ const uint16_t raw = detail::DecodeBits(data, offset, 11);
+
+ // 检测范围 364 - 1024 - 1684
+ if (raw < channel_min_ || raw > channel_max_) {
+ return false;
+ }
+ // 原始值转通道值
+ const int16_t value = static_cast(raw) - 1024;
+ // 死区处理
+ next.channels[i] = value >= -10 && value <= 10 ? 0 : value;
+ }
+ // 处理左右拨杆
+ const auto right = detail::DecodeBits(data, 44, 2);
+ const auto left = detail::DecodeBits(data, 46, 2);
+ // 检测左右拨杆范围 + 鼠标左右键(data[12]/data[13])
+ if (!DecodeSwitch(right, next.right_switch) || !DecodeSwitch(left, next.left_switch) || data[12] > 1 ||
+ data[13] > 1) {
+ return false;
+ }
+ next.mouse.x = detail::DecodeInt16LE(data + 6);
+ next.mouse.y = detail::DecodeInt16LE(data + 8);
+ next.mouse.z = detail::DecodeInt16LE(data + 10);
+ next.mouse.left = data[12] != 0;
+ next.mouse.right = data[13] != 0;
+ next.keyboard.code = detail::DecodeUint16LE(data + 14);
+ state_ = next;
+ CommitFrame(now_ms, false);
+ return true;
+ }
+} // namespace controller
diff --git a/boards/drivers/src/controller/refereerc.cpp b/boards/drivers/src/controller/refereerc.cpp
new file mode 100644
index 00000000..56967909
--- /dev/null
+++ b/boards/drivers/src/controller/refereerc.cpp
@@ -0,0 +1,138 @@
+/*###########################################################
+ # Copyright (c) 2026-2027. BNBU/UIC RoboMaster #
+ # #
+ # This program is free software: you can redistribute it #
+ # and/or modify it under the terms of the GNU General #
+ # Public License as published by the Free Software #
+ # Foundation, either version 3 of the License, or (at #
+ # your option) any later version. #
+ # #
+ # This program is distributed in the hope that it will be #
+ # useful, but WITHOUT ANY WARRANTY; without even #
+ # the implied warranty of MERCHANTABILITY or FITNESS #
+ # FOR A PARTICULAR PURPOSE. See the GNU General #
+ # Public License for more details. #
+ # #
+ # You should have received a copy of the GNU General #
+ # Public License along with this program. If not, see #
+ # . #
+ ###########################################################*/
+#include "refereerc.h"
+
+#include "bsp_os.h"
+#include "crc_check.h"
+
+namespace controller {
+ RefereeRC::RefereeRC(uint32_t online_threshold_ms) : ControllerReceiver(online_threshold_ms) {
+ }
+
+ RefereeRC::RefereeRC(UART_HandleTypeDef* huart, uint32_t online_threshold_ms)
+ : ControllerReceiver(online_threshold_ms) {
+ huart->Init.BaudRate = 921600;
+ huart->Init.WordLength = UART_WORDLENGTH_8B;
+ huart->Init.Parity = UART_PARITY_NONE;
+ huart->Init.StopBits = UART_STOPBITS_1;
+ if (HAL_UART_Init(huart) != HAL_OK) {
+ Error_Handler();
+ return;
+ }
+ uart_ = new bsp::UART(huart);
+ uart_->RegisterCallback(UartCallback, this);
+ uart_->SetupRx(300);
+ }
+
+ RefereeRC::~RefereeRC() {
+ delete uart_;
+ }
+
+ bool RefereeRC::IsOnline() const {
+ return ControllerReceiver::IsOnline(bsp::GetHighresTickMilliSec());
+ }
+
+ void RefereeRC::UpdateData(const uint8_t* data, size_t size, uint32_t now_ms) {
+ if (data == nullptr) {
+ return;
+ }
+ for (size_t i = 0; i < size; ++i) {
+ if (used_ == 0 && data[i] != SOF) {
+ continue;
+ }
+ buffer_[used_++] = data[i];
+ if (used_ == FRAME_SIZE) {
+ if (Decode(now_ms)) {
+ used_ = 0;
+ } else {
+ detail::FindNextFrame(buffer_, used_, SOF);
+ }
+ }
+ }
+ }
+
+ void RefereeRC::ResetStream() {
+ used_ = 0;
+ }
+
+ bool RefereeRC::GetState(RefereeRcFrame& output) const {
+ if (!HasState()) {
+ return false;
+ }
+ output = state_;
+ return true;
+ }
+
+ void RefereeRC::UartCallback(void* context) {
+ auto* self = static_cast(context);
+ uint8_t* data = nullptr;
+ const int32_t length = self->uart_->Read(&data);
+ if (length <= 0 || data == nullptr) {
+ if (length != 0) {
+ self->ResetStream();
+ }
+ return;
+ }
+ self->UpdateData(data, static_cast(length), bsp::GetHighresTickMilliSec());
+ }
+
+ bool RefereeRC::Decode(uint32_t now_ms) {
+ if (buffer_[0] != SOF || buffer_[1] != CMD || !verify_crc16_check_sum(buffer_.data(), FRAME_SIZE)) {
+ return false;
+ }
+ RefereeRcFrame next;
+ for (size_t i = 0; i < next.channels.size(); ++i) {
+ const size_t offset = i < 4 ? 16 + 11 * i : 65;
+ const uint16_t raw = detail::DecodeBits(buffer_.data(), offset, 11);
+ if (raw < CHANNEL_MIN || raw > CHANNEL_MAX) {
+ return false;
+ }
+ const int16_t value = static_cast(raw) - CHANNEL_CENTER;
+ next.channels[i] = value >= -CHANNEL_DEADZONE && value <= CHANNEL_DEADZONE ? 0 : value;
+ }
+ const auto mode = detail::DecodeBits(buffer_.data(), 60, 2);
+ if (mode > 2) {
+ return false;
+ }
+ next.mode = static_cast(mode);
+ next.pause = detail::DecodeBits(buffer_.data(), 62, 1) != 0;
+ next.left_button = detail::DecodeBits(buffer_.data(), 63, 1) != 0;
+ next.right_button = detail::DecodeBits(buffer_.data(), 64, 1) != 0;
+ next.trigger = detail::DecodeBits(buffer_.data(), 76, 1) != 0;
+ next.mouse.x = detail::DecodeInt16LE(buffer_.data() + 10);
+ next.mouse.y = detail::DecodeInt16LE(buffer_.data() + 12);
+ next.mouse.z = detail::DecodeInt16LE(buffer_.data() + 14);
+ // Each mouse button occupies two bits, but only 0 and 1 are valid.
+ const auto left = detail::DecodeBits(buffer_.data(), 128, 2);
+ const auto right = detail::DecodeBits(buffer_.data(), 130, 2);
+ const auto middle = detail::DecodeBits(buffer_.data(), 132, 2);
+ if (left > 1 || right > 1 || middle > 1) {
+ return false;
+ }
+ next.mouse.left = left != 0;
+ next.mouse.right = right != 0;
+ next.mouse.middle = middle != 0;
+ next.keyboard.code = detail::DecodeUint16LE(buffer_.data() + 17);
+ next.crc16 = detail::DecodeUint16LE(buffer_.data() + 19);
+ state_ = next;
+ CommitFrame(now_ms, false);
+ return true;
+ }
+} // namespace controller
diff --git a/boards/drivers/src/controller/sbus.cpp b/boards/drivers/src/controller/sbus.cpp
new file mode 100644
index 00000000..b8ec9047
--- /dev/null
+++ b/boards/drivers/src/controller/sbus.cpp
@@ -0,0 +1,177 @@
+/*###########################################################
+# Copyright (c) 2026-2027. BNBU/UIC RoboMaster #
+ # #
+ # This program is free software: you can redistribute it #
+ # and/or modify it under the terms of the GNU General #
+ # Public License as published by the Free Software #
+ # Foundation, either version 3 of the License, or (at #
+ # your option) any later version. #
+ # #
+ # This program is distributed in the hope that it will be #
+ # useful, but WITHOUT ANY WARRANTY; without even #
+ # the implied warranty of MERCHANTABILITY or FITNESS #
+ # FOR A PARTICULAR PURPOSE. See the GNU General #
+ # Public License for more details. #
+ # #
+ # You should have received a copy of the GNU General #
+ # Public License along with this program. If not, see #
+ # . #
+ ###########################################################*/
+
+/**
+ * @file sbus.cpp
+ * @brief SBUS 字节流接收与 i6X 设备映射实现。
+ * @details 函数顺序与 sbus.h
+ * 一致;接口契约集中记录在头文件中。
+ */
+#include "sbus.h"
+
+#include "bsp_os.h"
+
+namespace controller {
+ SBUS::SBUS(uint32_t online_threshold_ms, uint8_t footer)
+ : ControllerReceiver(online_threshold_ms), footer_(footer) {
+ }
+
+ SBUS::SBUS(UART_HandleTypeDef* huart, uint32_t online_threshold_ms, uint8_t footer)
+ : ControllerReceiver(online_threshold_ms), footer_(footer) {
+ huart->Init.BaudRate = 100000;
+ huart->Init.WordLength = UART_WORDLENGTH_9B;
+ huart->Init.Parity = UART_PARITY_EVEN;
+ huart->Init.StopBits = UART_STOPBITS_2;
+ if (HAL_UART_Init(huart) != HAL_OK) {
+ Error_Handler();
+ return;
+ }
+ uart_ = new bsp::UART(huart);
+ uart_->RegisterCallback(UartCallback, this);
+ uart_->SetupRx(FRAME_SIZE + 1);
+ }
+
+ SBUS::~SBUS() {
+ delete uart_;
+ }
+
+ bool SBUS::IsOnline() const {
+ return ControllerReceiver::IsOnline(bsp::GetHighresTickMilliSec());
+ }
+
+ bool SBUS::GetRawState(SbusFrame& output) const {
+ if (!HasState()) {
+ return false;
+ }
+ output = state_;
+ return true;
+ }
+
+ void SBUS::UpdateData(const uint8_t* data, size_t size, uint32_t now_ms) {
+ if (data == nullptr) {
+ return;
+ }
+ for (size_t i = 0; i < size; ++i) {
+ if (used_ == 0 && data[i] != 0x0F) {
+ continue;
+ }
+ buffer_[used_++] = data[i];
+ if (used_ == FRAME_SIZE) {
+ if (Decode(now_ms)) {
+ used_ = 0;
+ } else {
+ detail::FindNextFrame(buffer_, used_, 0x0F);
+ }
+ }
+ }
+ }
+
+ void SBUS::ResetStream() {
+ used_ = 0;
+ }
+
+ void SBUS::SetFooter(uint8_t footer) {
+ footer_ = footer;
+ ResetStream();
+ }
+
+ void SBUS::UartCallback(void* context) {
+ static_cast(context)->RxCompleteCallback();
+ }
+
+ void SBUS::RxCompleteCallback() {
+ if (!uart_)
+ return;
+ uint8_t* data = nullptr;
+ const int32_t length = uart_->Read(&data);
+ if (length <= 0 || data == nullptr) {
+ if (length != 0)
+ ResetStream();
+ return;
+ }
+ UpdateData(data, static_cast(length), bsp::GetHighresTickMilliSec());
+ }
+
+ bool SBUS::Decode(uint32_t now_ms) {
+ if (buffer_[0] != 0x0F || buffer_[24] != footer_) {
+ return false;
+ }
+ SbusFrame next;
+ for (size_t i = 0; i < next.channels.size(); ++i) {
+ next.channels[i] = detail::DecodeBits(buffer_.data(), 8 + 11 * i, 11);
+ }
+ next.flags = buffer_[23];
+ next.channel17 = (next.flags & 0x01) != 0;
+ next.channel18 = (next.flags & 0x02) != 0;
+ next.frame_lost = (next.flags & 0x04) != 0;
+ next.failsafe = (next.flags & 0x08) != 0;
+ state_ = next;
+ CommitFrame(now_ms, next.failsafe);
+ return true;
+ }
+
+ bool I6x::GetState(I6xState& output) const {
+ SbusFrame raw;
+ if (!GetRawState(raw)) {
+ return false;
+ }
+ for (size_t i = 0; i < output.channels.size(); ++i) {
+ output.channels[i] = MapChannel(raw.channels[i]);
+ }
+ output.sw_a = TwoPosition(raw.channels[6]);
+ output.sw_b = TwoPosition(raw.channels[7]);
+ output.sw_c = ThreePosition(raw.channels[8]);
+ output.sw_d = TwoPosition(raw.channels[9]);
+ output.frame_lost = raw.frame_lost;
+ output.failsafe = raw.failsafe;
+ return true;
+ }
+
+ int16_t I6x::MapChannel(uint16_t raw) {
+ constexpr int32_t center = 1024;
+ constexpr int32_t minimum = 240;
+ constexpr int32_t maximum = 1807;
+ constexpr int32_t range = 660;
+ const int32_t offset = static_cast(raw) - center;
+ if (offset >= -10 && offset <= 10) {
+ return 0;
+ }
+ const bool negative = offset < 0;
+ const int32_t span = negative ? center - minimum : maximum - center;
+ const int32_t magnitude = negative ? -offset : offset;
+ const int32_t scaled = magnitude >= span ? range : (magnitude * range + span / 2) / span;
+ return static_cast(negative ? -scaled : scaled);
+ }
+
+ TwoPositionSwitch I6x::TwoPosition(uint16_t raw) {
+ return raw >= 1024 ? TwoPositionSwitch::Up : TwoPositionSwitch::Down;
+ }
+
+ ThreePositionSwitch I6x::ThreePosition(uint16_t raw) {
+ // Classify by the nearest calibrated position: 240, 1024, 1807.
+ if (raw < (240 + 1024) / 2) {
+ return ThreePositionSwitch::Down;
+ }
+ if (raw > (1024 + 1807) / 2) {
+ return ThreePositionSwitch::Up;
+ }
+ return ThreePositionSwitch::Mid;
+ }
+} // namespace controller
diff --git a/boards/drivers/src/dji_dbus.cpp b/boards/drivers/src/dji_dbus.cpp
deleted file mode 100644
index 5dfce5bb..00000000
--- a/boards/drivers/src/dji_dbus.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*###########################################################
- # Copyright (c) 2023-2024. BNU-HKBU UIC RoboMaster #
- # #
- # This program is free software: you can redistribute it #
- # and/or modify it under the terms of the GNU General #
- # Public License as published by the Free Software #
- # Foundation, either version 3 of the License, or (at #
- # your option) any later version. #
- # #
- # This program is distributed in the hope that it will be #
- # useful, but WITHOUT ANY WARRANTY; without even #
- # the implied warranty of MERCHANTABILITY or FITNESS #
- # FOR A PARTICULAR PURPOSE. See the GNU General #
- # Public License for more details. #
- # #
- # You should have received a copy of the GNU General #
- # Public License along with this program. If not, see #
- # . #
- ###########################################################*/
-
-#include "dji_dbus.h"
-
-#include
-#include
-
-#include "bsp_error_handler.h"
-
-/* rocker range and deadzones */
-#define RC_ROCKER_MID 1024
-#define RC_ROCKER_ZERO_DRIFT 10 // Range of possible drift around initial position
-// Range of possible drift around min or max position
-
-namespace remote {
-
- // helper struct for decoding raw bytes
- typedef struct {
- /* rocker channel information */
- uint16_t ch0 : 11; // S1* *S2
- uint16_t ch1 : 11; // C3-^ ^-C1
- uint16_t ch2 : 11; // C2-< >+ -< >+C0
- uint16_t ch3 : 11; // +v v+
- /* left and right switch information */
- uint8_t swr : 2;
- uint8_t swl : 2;
- /* mouse movement and button information */
- remote::mouse_t mouse;
- /* keyboard key information */
- remote::keyboard_t keyboard;
- uint16_t ch4 : 11;
- } __packed dbus_t;
-
- DBUS::DBUS(UART_HandleTypeDef* huart) : bsp::UART(huart) {
- SetupRx(sizeof(dbus_t) + 1);
- }
-
- void DBUS::RxCompleteCallback() {
- Heartbeat();
-
- uint8_t* data;
- // data frame misalignment
- if (this->Read(&data) != sizeof(dbus_t))
- return;
-
- // re-interpret the data buffer and decode into class properties
- dbus_t* repr = reinterpret_cast(data);
- this->ch0 = repr->ch0 - RC_ROCKER_MID;
- this->ch1 = repr->ch1 - RC_ROCKER_MID;
- this->ch2 = repr->ch2 - RC_ROCKER_MID;
- this->ch3 = repr->ch3 - RC_ROCKER_MID;
- this->ch4 = repr->ch4 - RC_ROCKER_MID;
- this->ch0 = abs(this->ch0) <= RC_ROCKER_ZERO_DRIFT ? 0 : this->ch0;
- this->ch1 = abs(this->ch1) <= RC_ROCKER_ZERO_DRIFT ? 0 : this->ch1;
- this->ch2 = abs(this->ch2) <= RC_ROCKER_ZERO_DRIFT ? 0 : this->ch2;
- this->ch3 = abs(this->ch3) <= RC_ROCKER_ZERO_DRIFT ? 0 : this->ch3;
- this->ch4 = abs(this->ch4) <= RC_ROCKER_ZERO_DRIFT ? 0 : this->ch4;
- this->swl = static_cast(repr->swl);
- this->swr = static_cast(repr->swr);
-
- memcpy(&this->mouse, &repr->mouse, sizeof(mouse_t));
- memcpy(&this->keyboard, &repr->keyboard, sizeof(keyboard_t));
- }
-
-} /* namespace remote */
diff --git a/boards/drivers/src/protocol.cpp b/boards/drivers/src/protocol.cpp
index 272cf974..01907f0c 100644
--- a/boards/drivers/src/protocol.cpp
+++ b/boards/drivers/src/protocol.cpp
@@ -24,7 +24,7 @@
#include "bsp_usb.h"
#include "crc_check.h"
-#include "dji_remote.h"
+#include "bsp_os.h"
static const uint8_t SOF = 0xA5;
static const int FRAME_HEADER_LEN = 5;
@@ -33,46 +33,75 @@ static const int FRAME_TAIL_LEN = 2;
static const int BYTE = 8;
namespace communication {
+ void Protocol::DiscardRx(size_t size) {
+ rx_used_ -= size;
+ std::memmove(bufferRx, bufferRx + size, rx_used_);
+ }
+
+ void Protocol::ResyncRx() {
+ size_t next = 1;
+ while (next < rx_used_ && bufferRx[next] != SOF && bufferRx[next] != controller::RefereeRC::SOF) {
+ ++next;
+ }
+ DiscardRx(next);
+ }
+
bool Protocol::Receive(package_t package) {
+ if (!package.data || package.length <= 0)
+ return false;
+ // Preserve the legacy link heartbeat. Input-source health is independent.
Heartbeat();
+ const uint32_t now_ms = bsp::GetHighresTickMilliSec();
for (int i = 0; i < package.length; ++i) {
- if (rx_state.mode == rx_state.mode::WAITING_FOR_SOF) {
- // 还未接收到帧头,检测是否为帧头
- if (package.data[i] == SOF) {
- rx_state.mode = rx_state.mode::RECEIVING_REFEREE;
- bufferRx[0] = SOF;
- rx_state.idx = 1;
- } else if (package.data[i] == remote::vt13_packet_t::SOF) {
- rx_state.mode = rx_state.mode::RECEIVING_VT13;
- bufferRx[0] = remote::vt13_packet_t::SOF;
- rx_state.idx = 1;
+ const auto byte = package.data[i];
+ if (!rx_used_ && byte != SOF && byte != controller::RefereeRC::SOF)
+ continue;
+ // A5 lengths are capped below; every full candidate is consumed or
+ // resynchronized before the next append, keeping this buffer bounded.
+ bufferRx[rx_used_++] = byte;
+ while (rx_used_) {
+ if (bufferRx[0] != SOF && bufferRx[0] != controller::RefereeRC::SOF) {
+ ResyncRx();
+ continue;
}
- } else if (rx_state.mode == rx_state.RECEIVING_REFEREE) {
- // 接收裁判系统的数据
- bufferRx[rx_state.idx++] = package.data[i];
-
- if (rx_state.idx >= FRAME_HEADER_LEN + CMD_ID_LEN + FRAME_TAIL_LEN) {
- int DATA_LENGTH = bufferRx[2] << BYTE | bufferRx[1];
- if (rx_state.idx >= FRAME_HEADER_LEN + CMD_ID_LEN + DATA_LENGTH + FRAME_TAIL_LEN) {
- if (VerifyHeader(bufferRx, FRAME_HEADER_LEN) &&
- VerifyFrame(bufferRx, FRAME_HEADER_LEN + CMD_ID_LEN + DATA_LENGTH + FRAME_TAIL_LEN)) {
- int cmd_id = bufferRx[FRAME_HEADER_LEN + 1] << BYTE | bufferRx[FRAME_HEADER_LEN];
- ProcessDataRx(cmd_id, bufferRx + FRAME_HEADER_LEN + CMD_ID_LEN, DATA_LENGTH);
- }
- rx_state.mode = rx_state.WAITING_FOR_SOF;
- rx_state.idx = 0;
+ if (bufferRx[0] == controller::RefereeRC::SOF) {
+ if (rx_used_ < 2)
+ break;
+ if (bufferRx[1] != controller::RefereeRC::CMD) {
+ ResyncRx();
+ continue;
}
- }
- } else if (rx_state.mode == rx_state.mode::RECEIVING_VT13) {
- // VT13遥控器与图传链路从同一个UART输出,包头不同。
- // Todo: 应该把图传链路和遥控器数据分开处理
- bufferRx[rx_state.idx++] = package.data[i];
- if (rx_state.idx >= static_cast(sizeof(remote::vt13_packet_t))) {
- if (verify_crc16_check_sum(bufferRx, sizeof(remote::vt13_packet_t))) {
- ProcessDataRx(REMOTE_CONTROL_VT13, bufferRx, sizeof(remote::vt13_packet_t));
+ if (rx_used_ < controller::RefereeRC::FRAME_SIZE)
+ break;
+ // Protocol owns stream framing; the receiver owns VT13
+ // validation, decoding and the independent input timestamp.
+ refereerc_.ResetStream();
+ const auto sequence = refereerc_.GetSequence();
+ refereerc_.UpdateData(bufferRx, controller::RefereeRC::FRAME_SIZE, now_ms);
+ refereerc_.ResetStream();
+ if (refereerc_.GetSequence() == sequence) {
+ ResyncRx();
+ continue;
+ }
+ DiscardRx(controller::RefereeRC::FRAME_SIZE);
+ } else {
+ if (rx_used_ < FRAME_HEADER_LEN)
+ break;
+ const int payload = int(bufferRx[1]) | (int(bufferRx[2]) << BYTE);
+ if (!VerifyHeader(bufferRx, FRAME_HEADER_LEN) || payload > MAX_FRAME_LEN - 9) {
+ ResyncRx();
+ continue;
}
- rx_state.mode = rx_state.WAITING_FOR_SOF;
- rx_state.idx = 0;
+ const int total = payload + FRAME_HEADER_LEN + CMD_ID_LEN + FRAME_TAIL_LEN;
+ if (rx_used_ < static_cast(total))
+ break;
+ if (!VerifyFrame(bufferRx, total)) {
+ ResyncRx();
+ continue;
+ }
+ const int cmd = int(bufferRx[5]) | (int(bufferRx[6]) << BYTE);
+ ProcessDataRx(cmd, bufferRx + FRAME_HEADER_LEN + CMD_ID_LEN, payload);
+ DiscardRx(static_cast(total));
}
}
}
@@ -82,7 +111,7 @@ namespace communication {
package_t Protocol::Transmit(int cmd_id) {
bufferTx[0] = SOF;
int DATA_LENGTH = ProcessDataTx(cmd_id, bufferTx + FRAME_HEADER_LEN + CMD_ID_LEN);
- if (DATA_LENGTH < 0)
+ if (DATA_LENGTH < 0 || DATA_LENGTH > MAX_FRAME_LEN - 9)
return package_t{nullptr, 0};
bufferTx[1] = (uint8_t)((uint32_t)DATA_LENGTH & 0xFF);
bufferTx[2] = (uint8_t)((uint32_t)DATA_LENGTH >> BYTE);
@@ -138,7 +167,8 @@ namespace communication {
package_t UARTProtocol::Transmit(int cmd_id) {
package_t package = Protocol::Transmit(cmd_id);
- uart_->Write(package.data, package.length);
+ if (package.data && package.length > 0)
+ uart_->Write(package.data, package.length);
return package;
}
@@ -177,7 +207,8 @@ namespace communication {
package_t USBProtocol::Transmit(int cmd_id) {
package_t package = Protocol::Transmit(cmd_id);
- usb_->Write(package.data, package.length);
+ if (package.data && package.length > 0)
+ usb_->Write(package.data, package.length);
return package;
}
@@ -191,61 +222,89 @@ namespace communication {
bool Referee::ProcessDataRx(int cmd_id, const uint8_t* data, int length) {
switch (cmd_id) {
case GAME_STATUS:
- memcpy(&game_status, data, length);
+ if (length != static_cast(sizeof(game_status)))
+ return false;
+ memcpy(&game_status, data, sizeof(game_status));
break;
case GAME_RESULT:
- memcpy(&game_result, data, length);
+ if (length != static_cast(sizeof(game_result)))
+ return false;
+ memcpy(&game_result, data, sizeof(game_result));
break;
case GAME_ROBOT_HP:
- memcpy(&game_robot_HP, data, length);
+ if (length != static_cast(sizeof(game_robot_HP)))
+ return false;
+ memcpy(&game_robot_HP, data, sizeof(game_robot_HP));
break;
case EVENT_DATA:
- memcpy(&event_data, data, length);
+ if (length != static_cast(sizeof(event_data)))
+ return false;
+ memcpy(&event_data, data, sizeof(event_data));
break;
case SUPPLY_PROJECTILE_ACTION:
- memcpy(&supply_projectile_action, data, length);
+ if (length != static_cast(sizeof(supply_projectile_action)))
+ return false;
+ memcpy(&supply_projectile_action, data, sizeof(supply_projectile_action));
break;
case REFEREE_WARNING:
- memcpy(&referee_warning, data, length);
+ if (length != static_cast(sizeof(referee_warning)))
+ return false;
+ memcpy(&referee_warning, data, sizeof(referee_warning));
break;
case DART_REMAINING_TIME:
- memcpy(&dart_remaining_time, data, length);
+ if (length != static_cast(sizeof(dart_remaining_time)))
+ return false;
+ memcpy(&dart_remaining_time, data, sizeof(dart_remaining_time));
break;
case GAME_ROBOT_STATUS:
- memcpy(&game_robot_status, data, length);
+ if (length != static_cast(sizeof(game_robot_status)))
+ return false;
+ memcpy(&game_robot_status, data, sizeof(game_robot_status));
break;
case POWER_HEAT_DATA:
- memcpy(&power_heat_data, data, length);
+ if (length != static_cast(sizeof(power_heat_data)))
+ return false;
+ memcpy(&power_heat_data, data, sizeof(power_heat_data));
break;
case GAME_ROBOT_POS:
- memcpy(&game_robot_pos, data, length);
+ if (length != static_cast(sizeof(game_robot_pos)))
+ return false;
+ memcpy(&game_robot_pos, data, sizeof(game_robot_pos));
break;
case BUFF:
- memcpy(&buff, data, length);
+ if (length != static_cast(sizeof(buff)))
+ return false;
+ memcpy(&buff, data, sizeof(buff));
break;
case AERIAL_ROBOT_ENERGY:
- memcpy(&aerial_robot_energy, data, length);
+ if (length != static_cast(sizeof(aerial_robot_energy)))
+ return false;
+ memcpy(&aerial_robot_energy, data, sizeof(aerial_robot_energy));
break;
case ROBOT_HURT:
- memcpy(&robot_hurt, data, length);
+ if (length != static_cast(sizeof(robot_hurt)))
+ return false;
+ memcpy(&robot_hurt, data, sizeof(robot_hurt));
break;
case SHOOT_DATA:
- memcpy(&shoot_data, data, length);
+ if (length != static_cast(sizeof(shoot_data)))
+ return false;
+ memcpy(&shoot_data, data, sizeof(shoot_data));
break;
case BULLET_REMAINING:
- memcpy(&bullet_remaining, data, length);
+ if (length != static_cast(sizeof(bullet_remaining)))
+ return false;
+ memcpy(&bullet_remaining, data, sizeof(bullet_remaining));
break;
case RFID_STATUS:
- memcpy(&rfid_status, data, length);
+ if (length != static_cast(sizeof(rfid_status)))
+ return false;
+ memcpy(&rfid_status, data, sizeof(rfid_status));
break;
case DART_CLIENT_CMD:
- memcpy(&dart_client_cmd, data, length);
- break;
- case REMOTE_CONTROL_DATA:
- memcpy(&remote_control, data, length);
- break;
- case REMOTE_CONTROL_VT13:
- memcpy(&vt13_packet, data, length);
+ if (length != static_cast(sizeof(dart_client_cmd)))
+ return false;
+ memcpy(&dart_client_cmd, data, sizeof(dart_client_cmd));
break;
default:
return false;
@@ -299,8 +358,6 @@ namespace communication {
default:
data_len = -1;
}
- if (data_len > 0)
- uart_->Write(data, data_len);
return data_len;
}
@@ -314,35 +371,55 @@ namespace communication {
bool Host::ProcessDataRx(int cmd_id, const uint8_t* data, int length) {
switch (cmd_id) {
case PACK:
- memcpy(&pack, data, length);
+ if (length != static_cast(sizeof(pack)))
+ return false;
+ memcpy(&pack, data, sizeof(pack));
break;
case TARGET_ANGLE:
// memset(&target_angle, 0, sizeof(target_angle));
- memcpy(&target_angle, data, length);
+ if (length != static_cast(sizeof(target_angle)))
+ return false;
+ memcpy(&target_angle, data, sizeof(target_angle));
break;
case NO_TARGET_FLAG:
- memcpy(&no_target_flag, data, length);
+ if (length != static_cast(sizeof(no_target_flag)))
+ return false;
+ memcpy(&no_target_flag, data, sizeof(no_target_flag));
break;
case SHOOT_CMD:
- memcpy(&shoot_cmd, data, length);
+ if (length != static_cast(sizeof(shoot_cmd)))
+ return false;
+ memcpy(&shoot_cmd, data, sizeof(shoot_cmd));
break;
case ROBOT_MOVE_SPEED:
- memcpy(&robot_move, data, length);
+ if (length != static_cast(sizeof(robot_move)))
+ return false;
+ memcpy(&robot_move, data, sizeof(robot_move));
break;
case ROBOT_POWER_HEAT_HP_UPLOAD:
- memcpy(&robot_power_heat_hp_upload, data, length);
+ if (length != static_cast(sizeof(robot_power_heat_hp_upload)))
+ return false;
+ memcpy(&robot_power_heat_hp_upload, data, sizeof(robot_power_heat_hp_upload));
break;
case GIMBAL_CURRENT_STATUS:
- memcpy(&gimbal_current_status, data, length);
+ if (length != static_cast(sizeof(gimbal_current_status)))
+ return false;
+ memcpy(&gimbal_current_status, data, sizeof(gimbal_current_status));
break;
case CHASSIS_CURRENT_STATUS:
- memcpy(&chassis_current_status, data, length);
+ if (length != static_cast(sizeof(chassis_current_status)))
+ return false;
+ memcpy(&chassis_current_status, data, sizeof(chassis_current_status));
break;
case AUTOAIM_ENABLE:
- memcpy(&autoaim_enable, data, length);
+ if (length != static_cast(sizeof(autoaim_enable)))
+ return false;
+ memcpy(&autoaim_enable, data, sizeof(autoaim_enable));
break;
case ROBOT_STATUS_UPLOAD:
- memcpy(&robot_status_upload, data, length);
+ if (length != static_cast(sizeof(robot_status_upload)))
+ return false;
+ memcpy(&robot_status_upload, data, sizeof(robot_status_upload));
break;
default:
return false;
@@ -408,35 +485,55 @@ namespace communication {
bool HostUSB::ProcessDataRx(int cmd_id, const uint8_t* data, int length) {
switch (cmd_id) {
case PACK:
- memcpy(&pack, data, length);
+ if (length != static_cast(sizeof(pack)))
+ return false;
+ memcpy(&pack, data, sizeof(pack));
break;
case TARGET_ANGLE:
// memset(&target_angle, 0, sizeof(target_angle));
- memcpy(&target_angle, data, length);
+ if (length != static_cast(sizeof(target_angle)))
+ return false;
+ memcpy(&target_angle, data, sizeof(target_angle));
break;
case NO_TARGET_FLAG:
- memcpy(&no_target_flag, data, length);
+ if (length != static_cast(sizeof(no_target_flag)))
+ return false;
+ memcpy(&no_target_flag, data, sizeof(no_target_flag));
break;
case SHOOT_CMD:
- memcpy(&shoot_cmd, data, length);
+ if (length != static_cast(sizeof(shoot_cmd)))
+ return false;
+ memcpy(&shoot_cmd, data, sizeof(shoot_cmd));
break;
case ROBOT_MOVE_SPEED:
- memcpy(&robot_move, data, length);
+ if (length != static_cast(sizeof(robot_move)))
+ return false;
+ memcpy(&robot_move, data, sizeof(robot_move));
break;
case ROBOT_POWER_HEAT_HP_UPLOAD:
- memcpy(&robot_power_heat_hp_upload, data, length);
+ if (length != static_cast(sizeof(robot_power_heat_hp_upload)))
+ return false;
+ memcpy(&robot_power_heat_hp_upload, data, sizeof(robot_power_heat_hp_upload));
break;
case GIMBAL_CURRENT_STATUS:
- memcpy(&gimbal_current_status, data, length);
+ if (length != static_cast(sizeof(gimbal_current_status)))
+ return false;
+ memcpy(&gimbal_current_status, data, sizeof(gimbal_current_status));
break;
case CHASSIS_CURRENT_STATUS:
- memcpy(&chassis_current_status, data, length);
+ if (length != static_cast(sizeof(chassis_current_status)))
+ return false;
+ memcpy(&chassis_current_status, data, sizeof(chassis_current_status));
break;
case AUTOAIM_ENABLE:
- memcpy(&autoaim_enable, data, length);
+ if (length != static_cast(sizeof(autoaim_enable)))
+ return false;
+ memcpy(&autoaim_enable, data, sizeof(autoaim_enable));
break;
case ROBOT_STATUS_UPLOAD:
- memcpy(&robot_status_upload, data, length);
+ if (length != static_cast(sizeof(robot_status_upload)))
+ return false;
+ memcpy(&robot_status_upload, data, sizeof(robot_status_upload));
break;
default:
return false;
diff --git a/boards/drivers/src/sbus.cpp b/boards/drivers/src/sbus.cpp
deleted file mode 100644
index 756584d7..00000000
--- a/boards/drivers/src/sbus.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-/*###########################################################
- # Copyright (c) 2023-2024. BNU-HKBU UIC RoboMaster #
- # #
- # This program is free software: you can redistribute it #
- # and/or modify it under the terms of the GNU General #
- # Public License as published by the Free Software #
- # Foundation, either version 3 of the License, or (at #
- # your option) any later version. #
- # #
- # This program is distributed in the hope that it will be #
- # useful, but WITHOUT ANY WARRANTY; without even #
- # the implied warranty of MERCHANTABILITY or FITNESS #
- # FOR A PARTICULAR PURPOSE. See the GNU General #
- # Public License for more details. #
- # #
- # You should have received a copy of the GNU General #
- # Public License along with this program. If not, see #
- # . #
- ###########################################################*/
-
-#include "sbus.h"
-
-#include
-#include
-
-#include "bsp_error_handler.h"
-#include "utils.h"
-
-/* rocker range and deadzones */
-#define SBUS_RC_ROCKER_MID 1024
-#define SBUS_RC_ROCKER_ZERO_DRIFT 10 // Range of possible drift around initial position
-// Range of possible drift around min or max position
-
-namespace remote {
-
- // helper struct for decoding raw bytes
- typedef struct {
- uint8_t start : 8;
- uint16_t ch1 : 11;
- uint16_t ch2 : 11;
- uint16_t ch3 : 11;
- uint16_t ch4 : 11;
- uint16_t ch5 : 11;
- uint16_t ch6 : 11;
- uint16_t ch7 : 11;
- uint16_t ch8 : 11;
- uint16_t ch9 : 11;
- uint16_t ch10 : 11;
- uint16_t ch11 : 11;
- uint16_t ch12 : 11;
- uint16_t ch13 : 11;
- uint16_t ch14 : 11;
- uint16_t ch15 : 11;
- uint16_t ch16 : 11;
- uint8_t flag : 8;
- uint8_t end : 8;
- } __packed sbus_t;
-
- SBUS::SBUS(UART_HandleTypeDef* huart) : bsp::UART(huart) {
- SetupRx(sizeof(sbus_t) + 1);
- }
-
- void SBUS::RxCompleteCallback() {
- Heartbeat();
-
- uint8_t* data;
- // data frame misalignment
- if (this->Read(&data) != sizeof(sbus_t))
- return;
-
- // re-interpret the data buffer and decode into class properties
- sbus_t* repr = reinterpret_cast(data);
- this->ch1 = clip(repr->ch1 - SBUS_RC_ROCKER_MID, -660, 660);
- this->ch2 = clip(repr->ch2 - SBUS_RC_ROCKER_MID, -660, 660);
- this->ch3 = clip(repr->ch3 - SBUS_RC_ROCKER_MID, -660, 660);
- this->ch4 = clip(repr->ch4 - SBUS_RC_ROCKER_MID, -660, 660);
- this->ch5 = clip(repr->ch5 - SBUS_RC_ROCKER_MID, -660, 660);
- this->ch6 = clip(repr->ch6 - SBUS_RC_ROCKER_MID, -660, 660);
- this->ch7 = clip(repr->ch7 - SBUS_RC_ROCKER_MID, -660, 660);
- this->ch8 = clip(repr->ch8 - SBUS_RC_ROCKER_MID, -660, 660);
- this->ch9 = clip(repr->ch9 - SBUS_RC_ROCKER_MID, -660, 660);
- this->ch10 = clip(repr->ch10 - SBUS_RC_ROCKER_MID, -660, 660);
- this->ch11 = clip(repr->ch11 - SBUS_RC_ROCKER_MID, -660, 660);
- this->ch12 = clip(repr->ch12 - SBUS_RC_ROCKER_MID, -660, 660);
- this->ch13 = clip(repr->ch13 - SBUS_RC_ROCKER_MID, -660, 660);
- this->ch14 = clip(repr->ch14 - SBUS_RC_ROCKER_MID, -660, 660);
- this->ch15 = clip(repr->ch15 - SBUS_RC_ROCKER_MID, -660, 660);
- this->ch16 = clip(repr->ch16 - SBUS_RC_ROCKER_MID, -660, 660);
- this->ch1 = abs(this->ch1) <= SBUS_RC_ROCKER_ZERO_DRIFT ? 0 : this->ch1;
- this->ch2 = abs(this->ch2) <= SBUS_RC_ROCKER_ZERO_DRIFT ? 0 : this->ch2;
- this->ch3 = abs(this->ch3) <= SBUS_RC_ROCKER_ZERO_DRIFT ? 0 : this->ch3;
- this->ch4 = abs(this->ch4) <= SBUS_RC_ROCKER_ZERO_DRIFT ? 0 : this->ch4;
- this->ch5 = abs(this->ch5) <= SBUS_RC_ROCKER_ZERO_DRIFT ? 0 : this->ch5;
- this->ch6 = abs(this->ch6) <= SBUS_RC_ROCKER_ZERO_DRIFT ? 0 : this->ch6;
- this->ch7 = abs(this->ch7) <= SBUS_RC_ROCKER_ZERO_DRIFT ? 0 : this->ch7;
- this->ch8 = abs(this->ch8) <= SBUS_RC_ROCKER_ZERO_DRIFT ? 0 : this->ch8;
- this->ch9 = abs(this->ch9) <= SBUS_RC_ROCKER_ZERO_DRIFT ? 0 : this->ch9;
- this->ch10 = abs(this->ch10) <= SBUS_RC_ROCKER_ZERO_DRIFT ? 0 : this->ch10;
- this->ch11 = abs(this->ch11) <= SBUS_RC_ROCKER_ZERO_DRIFT ? 0 : this->ch11;
- this->ch12 = abs(this->ch12) <= SBUS_RC_ROCKER_ZERO_DRIFT ? 0 : this->ch12;
- this->ch13 = abs(this->ch13) <= SBUS_RC_ROCKER_ZERO_DRIFT ? 0 : this->ch13;
- this->ch14 = abs(this->ch14) <= SBUS_RC_ROCKER_ZERO_DRIFT ? 0 : this->ch14;
- this->ch15 = abs(this->ch15) <= SBUS_RC_ROCKER_ZERO_DRIFT ? 0 : this->ch15;
- this->ch16 = abs(this->ch16) <= SBUS_RC_ROCKER_ZERO_DRIFT ? 0 : this->ch16;
- this->flag = repr->flag;
- this->timestamp = GetLastUptime();
- }
-
-} /* namespace remote */
diff --git a/boards/third_party/crc_check/include/crc_check.h b/boards/third_party/crc_check/include/crc_check.h
index e64b0c19..4da80f4f 100644
--- a/boards/third_party/crc_check/include/crc_check.h
+++ b/boards/third_party/crc_check/include/crc_check.h
@@ -25,7 +25,7 @@
extern "C" {
#endif
-#include "main.h"
+#include
/**
* Verify CRC8
diff --git a/boards/third_party/crc_check/src/crc_check.c b/boards/third_party/crc_check/src/crc_check.c
index a485c6fa..6f11d2c2 100644
--- a/boards/third_party/crc_check/src/crc_check.c
+++ b/boards/third_party/crc_check/src/crc_check.c
@@ -20,6 +20,8 @@
#include "crc_check.h"
+#include
+
// crc8 generator polynomial:G(x)=x8+x5+x4+1
const uint8_t CRC8_INIT = 0xff;
const uint8_t CRC8_TAB[256] = {
diff --git a/examples/DJI_Board_TypeA_general/CMakeLists.txt b/examples/DJI_Board_TypeA_general/CMakeLists.txt
index f9967ae9..8e64eaf6 100644
--- a/examples/DJI_Board_TypeA_general/CMakeLists.txt
+++ b/examples/DJI_Board_TypeA_general/CMakeLists.txt
@@ -3,11 +3,10 @@ set(BOARD_NAME ${CURRENT_DIR_NAME})
add_subdirectory(buzzer)
add_subdirectory(can_bridge)
add_subdirectory(chassis)
-add_subdirectory(dbus)
add_subdirectory(MPU6500)
add_subdirectory(fatfs)
add_subdirectory(led_flow)
add_subdirectory(gimbal)
add_subdirectory(motor)
add_subdirectory(witimu)
-add_subdirectory(referee)
\ No newline at end of file
+add_subdirectory(referee)
diff --git a/examples/DJI_Board_TypeA_general/can_bridge/host.cpp b/examples/DJI_Board_TypeA_general/can_bridge/host.cpp
index 7cc0b12a..a35515c2 100644
--- a/examples/DJI_Board_TypeA_general/can_bridge/host.cpp
+++ b/examples/DJI_Board_TypeA_general/can_bridge/host.cpp
@@ -24,13 +24,13 @@
#include "bsp_uart.h"
#include "can_bridge.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
static bsp::CAN* can1 = nullptr;
static communication::CanBridge* can_bridge = nullptr;
-static remote::DBUS* dbus = nullptr;
+static controller::DBUS* dbus = nullptr;
void RM_RTOS_Init(void) {
print_use_usb();
@@ -38,18 +38,21 @@ void RM_RTOS_Init(void) {
can1 = new bsp::CAN(&hcan1, true, 8);
can_bridge = new communication::CanBridge(can1, 0x02);
- dbus = new remote::DBUS(&huart1);
+ dbus = new controller::DBUS(&huart1);
}
void RM_RTOS_Default_Task(const void* argument) {
UNUSED(argument);
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
communication::can_bridge_data_t data;
- data.data_four_int16.data[0] = dbus->ch0;
- data.data_four_int16.data[1] = dbus->ch1;
- data.data_four_int16.data[2] = dbus->ch2;
- data.data_four_int16.data[3] = dbus->ch3;
+ data.data_four_int16.data[0] = dbus_state.channels[0];
+ data.data_four_int16.data[1] = dbus_state.channels[1];
+ data.data_four_int16.data[2] = dbus_state.channels[2];
+ data.data_four_int16.data[3] = dbus_state.channels[3];
communication::can_bridge_ext_id_t ext_id;
ext_id.data.rx_id = 0x01;
ext_id.data.type = communication::CAN_BRIDGE_TYPE_FOUR_INT16;
diff --git a/examples/DJI_Board_TypeA_general/chassis/CMakeLists.txt b/examples/DJI_Board_TypeA_general/chassis/CMakeLists.txt
index e69f68d4..72baf94f 100644
--- a/examples/DJI_Board_TypeA_general/chassis/CMakeLists.txt
+++ b/examples/DJI_Board_TypeA_general/chassis/CMakeLists.txt
@@ -8,10 +8,6 @@ uicrm_add_arm_executable(${PROJECT_NAME}_omni
TARGET ${BOARD_NAME}
SOURCES omni_example.cpp)
-uicrm_add_arm_executable(${PROJECT_NAME}_sbus
- TARGET ${BOARD_NAME}
- SOURCES sbus.cpp)
-
uicrm_add_arm_executable(${PROJECT_NAME}_can_bridge
TARGET ${BOARD_NAME}
SOURCES can_bridge_chassis.cpp)
diff --git a/examples/DJI_Board_TypeA_general/chassis/can_bridge_chassis_sender.cpp b/examples/DJI_Board_TypeA_general/chassis/can_bridge_chassis_sender.cpp
index c01f40f9..77933064 100644
--- a/examples/DJI_Board_TypeA_general/chassis/can_bridge_chassis_sender.cpp
+++ b/examples/DJI_Board_TypeA_general/chassis/can_bridge_chassis_sender.cpp
@@ -21,7 +21,7 @@
#include "bsp_print.h"
#include "can_bridge.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
#ifndef PI
@@ -29,7 +29,7 @@
#endif
static bsp::CAN* can1 = nullptr;
-static remote::DBUS* dbus = nullptr;
+static controller::DBUS* dbus = nullptr;
static communication::CanBridge* can_bridge = nullptr;
void RM_RTOS_Init() {
@@ -38,11 +38,13 @@ void RM_RTOS_Init() {
can1 = new bsp::CAN(&hcan1, true);
can_bridge = new communication::CanBridge(can1, 0x51);
- dbus = new remote::DBUS(&huart1);
+ dbus = new controller::DBUS(&huart1);
HAL_Delay(300);
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
osDelay(500); // DBUS initialization needs time
@@ -50,10 +52,13 @@ void RM_RTOS_Default_Task(const void* args) {
communication::can_bridge_ext_id_t ext_id;
communication::can_bridge_data_t can_bridge_data;
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
const float ratio = 1.0f / 660.0f * 6 * PI;
ext_id.data.type = communication::CAN_BRIDGE_TYPE_TWO_FLOAT;
ext_id.data.rx_id = 0x52;
- if (dbus->swr == remote::DOWN) {
+ if (dbus_state.right_switch == Down) {
{
ext_id.data.reg = 0x71;
@@ -68,8 +73,8 @@ void RM_RTOS_Default_Task(const void* args) {
{
ext_id.data.reg = 0x70;
- can_bridge_data.data_two_float.data[0] = (float)dbus->ch0 * ratio;
- can_bridge_data.data_two_float.data[1] = (float)dbus->ch1 * ratio;
+ can_bridge_data.data_two_float.data[0] = (float)dbus_state.channels[0] * ratio;
+ can_bridge_data.data_two_float.data[1] = (float)dbus_state.channels[1] * ratio;
can_bridge->Send(ext_id, can_bridge_data);
osDelay(1);
@@ -78,7 +83,7 @@ void RM_RTOS_Default_Task(const void* args) {
ext_id.data.reg = 0x71;
can_bridge_data.data_two_float.data[0] = (float)1;
- can_bridge_data.data_two_float.data[1] = (float)dbus->ch2 * ratio;
+ can_bridge_data.data_two_float.data[1] = (float)dbus_state.channels[2] * ratio;
can_bridge->Send(ext_id, can_bridge_data);
osDelay(1);
diff --git a/examples/DJI_Board_TypeA_general/chassis/mecanum_example.cpp b/examples/DJI_Board_TypeA_general/chassis/mecanum_example.cpp
index 05e03be5..bca0dcaa 100644
--- a/examples/DJI_Board_TypeA_general/chassis/mecanum_example.cpp
+++ b/examples/DJI_Board_TypeA_general/chassis/mecanum_example.cpp
@@ -23,7 +23,7 @@
#include "bsp_print.h"
#include "chassis.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
bsp::CAN* can = nullptr;
driver::DjiMotorBase* fl_motor = nullptr;
@@ -32,7 +32,7 @@ driver::DjiMotorBase* bl_motor = nullptr;
driver::DjiMotorBase* br_motor = nullptr;
control::Chassis* chassis = nullptr;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
void RM_RTOS_Init() {
HAL_Delay(200);
@@ -87,21 +87,27 @@ void RM_RTOS_Init() {
chassis_data.model = control::CHASSIS_MECANUM_WHEEL;
chassis = new control::Chassis(chassis_data);
- dbus = new remote::DBUS(&huart1);
+ dbus = new controller::DBUS(&huart1);
HAL_Delay(300);
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
osDelay(500); // DBUS initialization needs time
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
const float ratio = 1.0f / 660.0f * 6 * PI;
- chassis->SetSpeed(dbus->ch0 * ratio, dbus->ch1 * ratio, dbus->ch2 * ratio);
+ chassis
+ ->SetSpeed(dbus_state.channels[0] * ratio, dbus_state.channels[1] * ratio, dbus_state.channels[2] * ratio);
// Kill switch
- if (dbus->swl == remote::UP || dbus->swl == remote::DOWN) {
+ if (dbus_state.left_switch == Up || dbus_state.left_switch == Down) {
RM_ASSERT_TRUE(false, "Operation killed");
}
chassis->SetPower(false, 30, 20, 60);
diff --git a/examples/DJI_Board_TypeA_general/chassis/omni_example.cpp b/examples/DJI_Board_TypeA_general/chassis/omni_example.cpp
index 8c0f034c..8176612c 100644
--- a/examples/DJI_Board_TypeA_general/chassis/omni_example.cpp
+++ b/examples/DJI_Board_TypeA_general/chassis/omni_example.cpp
@@ -24,7 +24,7 @@
#include "bsp_print.h"
#include "chassis.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
bsp::CAN* can = nullptr;
driver::DjiMotorBase* fl_motor = nullptr;
@@ -33,7 +33,7 @@ driver::DjiMotorBase* bl_motor = nullptr;
driver::DjiMotorBase* br_motor = nullptr;
control::Chassis* chassis = nullptr;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
void RM_RTOS_Init() {
HAL_Delay(200);
@@ -88,21 +88,27 @@ void RM_RTOS_Init() {
chassis_data.model = control::CHASSIS_OMNI_WHEEL;
chassis = new control::Chassis(chassis_data);
- dbus = new remote::DBUS(&huart1);
+ dbus = new controller::DBUS(&huart1);
HAL_Delay(300);
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
osDelay(500); // DBUS initialization needs time
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
const float ratio = 1.0f / 660.0f * 6 * PI;
- chassis->SetSpeed(dbus->ch0 * ratio, dbus->ch1 * ratio, dbus->ch2 * ratio);
+ chassis
+ ->SetSpeed(dbus_state.channels[0] * ratio, dbus_state.channels[1] * ratio, dbus_state.channels[2] * ratio);
// Kill switch
- if (dbus->swl == remote::UP || dbus->swl == remote::DOWN) {
+ if (dbus_state.left_switch == Up || dbus_state.left_switch == Down) {
RM_ASSERT_TRUE(false, "Operation killed");
}
chassis->SetPower(false, 30, 20, 60);
diff --git a/examples/DJI_Board_TypeA_general/chassis/sbus.cpp b/examples/DJI_Board_TypeA_general/chassis/sbus.cpp
deleted file mode 100644
index fe86e640..00000000
--- a/examples/DJI_Board_TypeA_general/chassis/sbus.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*###########################################################
- # Copyright (c) 2023-2024. BNU-HKBU UIC RoboMaster #
- # #
- # This program is free software: you can redistribute it #
- # and/or modify it under the terms of the GNU General #
- # Public License as published by the Free Software #
- # Foundation, either version 3 of the License, or (at #
- # your option) any later version. #
- # #
- # This program is distributed in the hope that it will be #
- # useful, but WITHOUT ANY WARRANTY; without even #
- # the implied warranty of MERCHANTABILITY or FITNESS #
- # FOR A PARTICULAR PURPOSE. See the GNU General #
- # Public License for more details. #
- # #
- # You should have received a copy of the GNU General #
- # Public License along with this program. If not, see #
- # . #
- ###########################################################*/
-
-#include "sbus.h"
-
-#include "bsp_print.h"
-#include "chassis.h"
-#include "cmsis_os.h"
-#include "main.h"
-
-bsp::CAN* can = nullptr;
-driver::DjiMotorBase* fl_motor = nullptr;
-driver::DjiMotorBase* fr_motor = nullptr;
-driver::DjiMotorBase* bl_motor = nullptr;
-driver::DjiMotorBase* br_motor = nullptr;
-
-control::Chassis* chassis = nullptr;
-remote::SBUS* sbus = nullptr;
-
-void RM_RTOS_Init() {
- HAL_Delay(200);
- print_use_uart(&huart8);
- can = new bsp::CAN(&hcan1, true);
- fl_motor = new driver::Motor3508(can, 0x202);
- fr_motor = new driver::Motor3508(can, 0x201);
- bl_motor = new driver::Motor3508(can, 0x203);
- br_motor = new driver::Motor3508(can, 0x204);
-
- control::ConstrainedPID::PID_Init_t omega_pid_init = {
- .kp = 2500,
- .ki = 3,
- .kd = 0,
- .max_out = 30000,
- .max_iout = 10000,
- .deadband = 0, // 死区
- .A = 6000, // 变速积分所能达到的最大值为A+B
- .B = 4000, // 启动变速积分的死区
- .output_filtering_coefficient = 0.1, // 输出滤波系数
- .derivative_filtering_coefficient = 0, // 微分滤波系数
- .mode = control::ConstrainedPID::Integral_Limit | // 积分限幅
- control::ConstrainedPID::OutputFilter | // 输出滤波
- control::ConstrainedPID::Trapezoid_Intergral | // 梯形积分
- control::ConstrainedPID::ChangingIntegralRate, // 变速积分
- };
-
- fl_motor->ReInitPID(omega_pid_init, driver::DjiMotorBase::OMEGA);
- fl_motor->SetMode(driver::DjiMotorBase::OMEGA);
- fl_motor->SetTransmissionRatio(19);
-
- fr_motor->ReInitPID(omega_pid_init, driver::DjiMotorBase::OMEGA);
- fr_motor->SetMode(driver::DjiMotorBase::OMEGA);
- fr_motor->SetTransmissionRatio(19);
-
- bl_motor->ReInitPID(omega_pid_init, driver::DjiMotorBase::OMEGA);
- bl_motor->SetMode(driver::DjiMotorBase::OMEGA);
- bl_motor->SetTransmissionRatio(19);
-
- br_motor->ReInitPID(omega_pid_init, driver::DjiMotorBase::OMEGA);
- br_motor->SetMode(driver::DjiMotorBase::OMEGA);
- br_motor->SetTransmissionRatio(19);
-
- driver::DjiMotorBase* motors[control::FourWheel::motor_num];
- motors[control::FourWheel::front_left] = fl_motor;
- motors[control::FourWheel::front_right] = fr_motor;
- motors[control::FourWheel::back_left] = bl_motor;
- motors[control::FourWheel::back_right] = br_motor;
-
- control::chassis_t chassis_data;
- chassis_data.motors = motors;
- chassis_data.model = control::CHASSIS_MECANUM_WHEEL;
- chassis = new control::Chassis(chassis_data);
-
- sbus = new remote::SBUS(&huart1);
- HAL_Delay(300);
-}
-
-void RM_RTOS_Default_Task(const void* args) {
- UNUSED(args);
-
- osDelay(500); // DBUS initialization needs time
-
- while (true) {
- const float ratio = 1.0f / 660.0f * 6 * PI;
- chassis->SetSpeed(-sbus->ch1 * ratio, sbus->ch2 * ratio, sbus->ch4 * ratio);
-
- // Kill switch
- if (sbus->ch5 >= 550) {
- RM_ASSERT_TRUE(false, "Operation killed");
- }
-
- chassis->SetPower(false, 30, 20, 60);
- chassis->Update();
- osDelay(10);
- }
-}
diff --git a/examples/DJI_Board_TypeA_general/dbus/CMakeLists.txt b/examples/DJI_Board_TypeA_general/dbus/CMakeLists.txt
deleted file mode 100644
index 45816a8d..00000000
--- a/examples/DJI_Board_TypeA_general/dbus/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-project(example_dbus_${BOARD_NAME} ASM C CXX)
-
-uicrm_add_arm_executable(${PROJECT_NAME}
- TARGET ${BOARD_NAME}
- SOURCES main.cpp)
-
diff --git a/examples/DJI_Board_TypeA_general/dbus/main.cpp b/examples/DJI_Board_TypeA_general/dbus/main.cpp
deleted file mode 100644
index 7d289410..00000000
--- a/examples/DJI_Board_TypeA_general/dbus/main.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/*###########################################################
- # Copyright (c) 2023-2024. BNU-HKBU UIC RoboMaster #
- # #
- # This program is free software: you can redistribute it #
- # and/or modify it under the terms of the GNU General #
- # Public License as published by the Free Software #
- # Foundation, either version 3 of the License, or (at #
- # your option) any later version. #
- # #
- # This program is distributed in the hope that it will be #
- # useful, but WITHOUT ANY WARRANTY; without even #
- # the implied warranty of MERCHANTABILITY or FITNESS #
- # FOR A PARTICULAR PURPOSE. See the GNU General #
- # Public License for more details. #
- # #
- # You should have received a copy of the GNU General #
- # Public License along with this program. If not, see #
- # . #
- ###########################################################*/
-
-#include "main.h"
-
-#include "bsp_print.h"
-#include "cmsis_os.h"
-#include "dji_dbus.h"
-
-static remote::DBUS* dbus;
-
-void RM_RTOS_Init(void) {
- print_use_uart(&huart8);
- dbus = new remote::DBUS(&huart1);
-}
-
-void RM_RTOS_Default_Task(const void* arguments) {
- UNUSED(arguments);
-
- // NOTE(alvin): print is split because of stack usage is almost reaching
- // limits
- while (true) {
- set_cursor(0, 0);
- clear_screen();
- print(
- "CH0: %-4d CH1: %-4d CH2: %-4d CH3: %-4d \r\nSWL: %d SWR: %d "
- "TWL: %d "
- "@ %d "
- "ms\r\n",
- dbus->ch0,
- dbus->ch1,
- dbus->ch2,
- dbus->ch3,
- dbus->swl,
- dbus->swr,
- dbus->ch4,
- dbus->GetLastUptime()
- );
- print(
- "W: %d A: %d S: %d D: %d\r\n",
- dbus->keyboard.bit.W,
- dbus->keyboard.bit.A,
- dbus->keyboard.bit.S,
- dbus->keyboard.bit.D
- );
- print(
- "Q: %d E: %d R: %d F: %d G: %d\r\n",
- dbus->keyboard.bit.Q,
- dbus->keyboard.bit.E,
- dbus->keyboard.bit.R,
- dbus->keyboard.bit.F,
- dbus->keyboard.bit.G
- );
- print(
- "Z: %d X: %d C: %d V: %d B: %d\r\n",
- dbus->keyboard.bit.Z,
- dbus->keyboard.bit.X,
- dbus->keyboard.bit.C,
- dbus->keyboard.bit.V,
- dbus->keyboard.bit.B
- );
- print("SHIFT: %d CTRL: %d\r\n", dbus->keyboard.bit.SHIFT, dbus->keyboard.bit.CTRL);
- print(
- "Mouse: x: %d y: %d z: %d l: %d r: %d\r\n",
- dbus->mouse.x,
- dbus->mouse.y,
- dbus->mouse.z,
- dbus->mouse.l,
- dbus->mouse.r
- );
-
- osDelay(50);
- }
-}
diff --git a/examples/DJI_Board_TypeA_general/gimbal/typeA.cpp b/examples/DJI_Board_TypeA_general/gimbal/typeA.cpp
index dc43be2a..95c67b6e 100644
--- a/examples/DJI_Board_TypeA_general/gimbal/typeA.cpp
+++ b/examples/DJI_Board_TypeA_general/gimbal/typeA.cpp
@@ -26,7 +26,7 @@
#include "bsp_os.h"
#include "bsp_spi.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "gimbal.h"
#include "heater.h"
#include "main.h"
@@ -88,7 +88,7 @@ void imuUpdateTask(void* arguments) {
static bsp::CAN* can1 = nullptr;
static bsp::CAN* can2 = nullptr;
-static remote::DBUS* dbus = nullptr;
+static controller::DBUS* dbus = nullptr;
static driver::DjiMotorBase* pitch_motor = nullptr;
static driver::DjiMotorBase* yaw_motor = nullptr;
@@ -120,11 +120,16 @@ const osThreadAttr_t gimbalTaskAttribute =
osThreadId_t gimbalTaskHandle;
void gimbalTask(void* arg) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(arg);
print("Wait for beginning signal...\r\n");
while (true) {
- if (dbus->keyboard.bit.V || dbus->swr == remote::DOWN) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.keyboard.bit.V || dbus_state.right_switch == Down) {
break;
}
osDelay(100);
@@ -159,19 +164,24 @@ void gimbalTask(void* arg) {
float pitch_target = 0, yaw_target = 0;
while (true) {
- if (dbus->keyboard.bit.B || dbus->swl == remote::DOWN) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.keyboard.bit.B || dbus_state.left_switch == Down) {
while (true) {
- if (dbus->keyboard.bit.V) {
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.keyboard.bit.V) {
break;
}
osDelay(10);
}
}
- pitch_ratio = dbus->mouse.y / 32767.0 * 7.5 / 7.0;
- yaw_ratio = -dbus->mouse.x / 32767.0 * 7.5 / 7.0;
- pitch_ratio = -dbus->ch3 / 18000.0 / 7.0;
- yaw_ratio = dbus->ch2 / 18000.0 / 7.0;
+ pitch_ratio = dbus_state.mouse.y / 32767.0 * 7.5 / 7.0;
+ yaw_ratio = -dbus_state.mouse.x / 32767.0 * 7.5 / 7.0;
+ pitch_ratio = -dbus_state.channels[3] / 18000.0 / 7.0;
+ yaw_ratio = dbus_state.channels[2] / 18000.0 / 7.0;
pitch_target = clip(pitch_ratio, -gimbal_param->pitch_max_, gimbal_param->pitch_max_);
yaw_target = clip(yaw_ratio, -gimbal_param->yaw_max_, gimbal_param->yaw_max_);
@@ -194,7 +204,7 @@ void RM_RTOS_Init(void) {
can1 = new bsp::CAN(&hcan1, true);
can2 = new bsp::CAN(&hcan2, false);
- dbus = new remote::DBUS(&huart1);
+ dbus = new controller::DBUS(&huart1);
imu_cs = new bsp::GPIO(ONBOARD_IMU_CS_GROUP, ONBOARD_IMU_CS_PIN);
mpu6500_it = new bsp::GPIT(MPU6500_IT_Pin);
@@ -309,7 +319,10 @@ void RM_RTOS_Threads_Init(void) {
void KillAll() {
RM_EXPECT_TRUE(false, "Operation killed\r\n");
while (true) {
- if (dbus->keyboard.bit.V) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.keyboard.bit.V) {
break;
}
pitch_motor->Disable();
@@ -320,11 +333,16 @@ void KillAll() {
}
void RM_RTOS_Default_Task(const void* arg) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(arg);
mpu6500->RegisterCallback(MPU6500ReceiveDone);
while (true) {
- if (dbus->keyboard.bit.B || dbus->swl == remote::DOWN)
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.keyboard.bit.B || dbus_state.left_switch == Down)
KillAll();
set_cursor(0, 0);
@@ -345,8 +363,19 @@ void RM_RTOS_Default_Task(const void* arg) {
print("\r\n");
- print("CH0: %-4d CH1: %-4d CH2: %-4d CH3: %-4d ", dbus->ch0, dbus->ch1, dbus->ch2, dbus->ch3);
- print("SWL: %d SWR: %d @ %d ms\r\n", dbus->swl, dbus->swr, dbus->GetLastUptime());
+ print(
+ "CH0: %-4d CH1: %-4d CH2: %-4d CH3: %-4d ",
+ dbus_state.channels[0],
+ dbus_state.channels[1],
+ dbus_state.channels[2],
+ dbus_state.channels[3]
+ );
+ print(
+ "SWL: %s SWR: %s @ %d ms\r\n",
+ controller::SwitchName(dbus_state.left_switch),
+ controller::SwitchName(dbus_state.right_switch),
+ dbus->GetLastValidTimeMs()
+ );
osDelay(100);
}
diff --git a/examples/DJI_Board_TypeA_general/motor/m2305.cpp b/examples/DJI_Board_TypeA_general/motor/m2305.cpp
index 18003a4a..7086fd9e 100644
--- a/examples/DJI_Board_TypeA_general/motor/m2305.cpp
+++ b/examples/DJI_Board_TypeA_general/motor/m2305.cpp
@@ -22,7 +22,7 @@
#include "bsp_gpio.h"
#include "bsp_print.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
#include "utils.h"
@@ -38,10 +38,10 @@
driver::PWMMotorBase* motor1;
driver::PWMMotorBase* motor2;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
void RM_RTOS_Init() {
- dbus = new remote::DBUS(&huart1);
+ dbus = new controller::DBUS(&huart1);
print_use_uart(&huart8);
motor1 = new driver::PWMMotorBase(&htim1, LEFT_MOTOR_PWM_CHANNEL, TIM_CLOCK_FREQ, MOTOR_OUT_FREQ, IDLE_THROTTLE);
motor2 = new driver::PWMMotorBase(&htim1, RIGHT_MOTOR_PWM_CHANNEL, TIM_CLOCK_FREQ, MOTOR_OUT_FREQ, IDLE_THROTTLE);
@@ -52,20 +52,25 @@ void RM_RTOS_Init() {
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
bsp::GPIO key(KEY_GPIO_GROUP, KEY_GPIO_PIN);
RampSource ramp_1 = RampSource(0, 0, 800, 0.001);
RampSource ramp_2 = RampSource(0, 0, 800, 0.001);
int current = 0;
int state = 0;
- int8_t last_state = remote::MID;
+ auto last_state = Mid;
while (true) {
- if (dbus->swl == remote::UP) {
- if (last_state == remote::MID)
- last_state = remote::UP;
- } else if (dbus->swl == remote::MID) {
- if (last_state == remote::UP) {
- last_state = remote::MID;
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.left_switch == Up) {
+ if (last_state == Mid)
+ last_state = Up;
+ } else if (dbus_state.left_switch == Mid) {
+ if (last_state == Up) {
+ last_state = Mid;
if (state == 0) {
state = 1;
diff --git a/examples/DJI_Board_TypeA_general/motor/servo_m2006.cpp b/examples/DJI_Board_TypeA_general/motor/servo_m2006.cpp
index 3bd3eefd..a494c1db 100644
--- a/examples/DJI_Board_TypeA_general/motor/servo_m2006.cpp
+++ b/examples/DJI_Board_TypeA_general/motor/servo_m2006.cpp
@@ -23,20 +23,20 @@
#include "bsp_os.h"
#include "bsp_print.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
bsp::CAN* can2 = NULL;
driver::DjiMotorBase* motor1 = NULL;
driver::ServoMotor* load_servo = NULL;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
float load_step_angle = 2 * PI / 8;
void RM_RTOS_Init() {
bsp::SetHighresClockTimer(&htim7);
HAL_Delay(200);
print_use_uart(&huart8);
- dbus = new remote::DBUS(&huart1);
+ dbus = new controller::DBUS(&huart1);
can2 = new bsp::CAN(&hcan1, true);
motor1 = new driver::Motor2006(can2, 0x201);
driver::servo_t servo_data;
@@ -56,27 +56,32 @@ void RM_RTOS_Init() {
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
- int last_state = remote::MID;
+ auto last_state = Mid;
while (true) {
- if (last_state != dbus->swl && dbus->swl == remote::MID) {
- if (last_state == remote::UP) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (last_state != dbus_state.left_switch && dbus_state.left_switch == Mid) {
+ if (last_state == Up) {
load_servo->SetTarget(load_servo->GetTarget() + load_step_angle);
- } else if (last_state == remote::DOWN) {
+ } else if (last_state == Down) {
load_servo->SetTarget(load_servo->GetTarget() - load_step_angle);
}
} else {
- if (dbus->ch3 > 0) {
+ if (dbus_state.channels[3] > 0) {
load_servo->SetTarget(load_servo->GetTarget() + load_step_angle);
- } else if (dbus->ch3 < 0) {
+ } else if (dbus_state.channels[3] < 0) {
load_servo->SetTarget(load_servo->GetTarget() - load_step_angle);
}
}
load_servo->CalcOutput();
- last_state = dbus->swl;
+ last_state = dbus_state.left_switch;
osDelay(1);
}
}
diff --git a/examples/DJI_Board_TypeA_general/motor/servo_m3508.cpp b/examples/DJI_Board_TypeA_general/motor/servo_m3508.cpp
index 2d91ef4e..757d3810 100644
--- a/examples/DJI_Board_TypeA_general/motor/servo_m3508.cpp
+++ b/examples/DJI_Board_TypeA_general/motor/servo_m3508.cpp
@@ -23,20 +23,20 @@
#include "bsp_os.h"
#include "bsp_print.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
bsp::CAN* can1 = NULL;
driver::DjiMotorBase* motor1 = NULL;
driver::ServoMotor* load_servo = NULL;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
float load_step_angle = 2 * PI / 8;
void RM_RTOS_Init() {
bsp::SetHighresClockTimer(&htim7);
HAL_Delay(200);
print_use_uart(&huart8);
- dbus = new remote::DBUS(&huart1);
+ dbus = new controller::DBUS(&huart1);
can1 = new bsp::CAN(&hcan1, true);
motor1 = new driver::Motor2006(can1, 0x201);
@@ -56,17 +56,22 @@ void RM_RTOS_Init() {
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
- int last_state = remote::MID;
+ auto last_state = Mid;
int state = 0;
while (true) {
- if (dbus->swl == remote::UP) {
- if (last_state == remote::MID)
- last_state = remote::UP;
- } else if (dbus->swl == remote::MID) {
- if (last_state == remote::UP) {
- last_state = remote::MID;
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.left_switch == Up) {
+ if (last_state == Mid)
+ last_state = Up;
+ } else if (dbus_state.left_switch == Mid) {
+ if (last_state == Up) {
+ last_state = Mid;
load_servo->SetTarget(load_servo->GetTarget() + load_step_angle);
if (state == 0) {
state = 1;
diff --git a/examples/DJI_Board_TypeA_general/referee/CMakeLists.txt b/examples/DJI_Board_TypeA_general/referee/CMakeLists.txt
index 88e8e8d0..9fce1431 100644
--- a/examples/DJI_Board_TypeA_general/referee/CMakeLists.txt
+++ b/examples/DJI_Board_TypeA_general/referee/CMakeLists.txt
@@ -3,7 +3,3 @@ project(example_referee_${BOARD_NAME} ASM C CXX)
uicrm_add_arm_executable(${PROJECT_NAME}
TARGET ${BOARD_NAME}
SOURCES main.cpp)
-
-uicrm_add_arm_executable(${PROJECT_NAME}_rc
- TARGET ${BOARD_NAME}
- SOURCES rc.cpp)
\ No newline at end of file
diff --git a/examples/DJI_Board_TypeA_general/referee/rc.cpp b/examples/DJI_Board_TypeA_general/referee/rc.cpp
deleted file mode 100644
index 8ed031cc..00000000
--- a/examples/DJI_Board_TypeA_general/referee/rc.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*###########################################################
- # Copyright (c) 2023-2024. BNU-HKBU UIC RoboMaster #
- # #
- # This program is free software: you can redistribute it #
- # and/or modify it under the terms of the GNU General #
- # Public License as published by the Free Software #
- # Foundation, either version 3 of the License, or (at #
- # your option) any later version. #
- # #
- # This program is distributed in the hope that it will be #
- # useful, but WITHOUT ANY WARRANTY; without even #
- # the implied warranty of MERCHANTABILITY or FITNESS #
- # FOR A PARTICULAR PURPOSE. See the GNU General #
- # Public License for more details. #
- # #
- # You should have received a copy of the GNU General #
- # Public License along with this program. If not, see #
- # . #
- ###########################################################*/
-
-#include "bsp_print.h"
-#include "bsp_uart.h"
-#include "cmsis_os.h"
-#include "dji_dbus.h"
-#include "main.h"
-#include "protocol.h"
-
-communication::Referee* referee = nullptr;
-bsp::UART* referee_uart = nullptr;
-
-communication::Referee* refereeRc = nullptr;
-bsp::UART* refereeRc_uart = nullptr;
-
-void RM_RTOS_Init(void) {
- print_use_uart(&huart8);
-
- referee_uart = new bsp::UART(&huart3);
- referee_uart->SetupRx(300);
- referee_uart->SetupTx(300);
-
- refereeRc_uart = new bsp::UART(&huart6);
- refereeRc_uart->SetupRx(300);
- refereeRc_uart->SetupTx(300);
-
- referee = new communication::Referee(referee_uart);
-
- refereeRc = new communication::Referee(refereeRc_uart);
-}
-
-void RM_RTOS_Threads_Init(void) {
-}
-
-void RM_RTOS_Default_Task(const void* argument) {
- UNUSED(argument);
-
- while (true) {
- set_cursor(0, 0);
- clear_screen();
- // print("Chassis Volt: %.3f\r\n", referee->power_heat_data.chassis_volt / 1000.0);
- // print("Chassis Curr: %.3f\r\n", referee->power_heat_data.chassis_current /
- // 1000.0); print("Chassis Power: %.3f\r\n", referee->power_heat_data.chassis_power);
- // print("Chassis Power Limit: %d\r\n",
- // referee->game_robot_status.chassis_power_limit); print("\r\n"); print("Shooter
- // Cooling Heat: %hu\r\n",
- // referee->power_heat_data.shooter_id1_17mm_cooling_heat);
- // print("Bullet Frequency: %hhu\r\n", referee->shoot_data.bullet_freq);
- // print("Bullet Speed: %.3f\r\n", referee->shoot_data.bullet_speed);
- // print("\r\n");
- // print("Current HP %d/%d\n", referee->game_robot_status.remain_HP,
- // referee->game_robot_status.max_HP);
- // print("Remain bullet %d\n", referee->bullet_remaining.bullet_remaining_num_17mm);
- remote::keyboard_t keyboard = referee->remote_control.keyboard;
- remote::mouse_t mouse = referee->remote_control.mouse;
- print(
- "W: %d A: %d S: %d D: %d\r\n"
- "Q: %d E: %d R: %d F: %d G: %d\r\n"
- "Z: %d X: %d C: %d V: %d B: %d\r\n"
- "SHIFT: %d CTRL: %d\r\n"
- "Mouse: x: %d y: %d z: %d l: %d r: %d\r\n",
- keyboard.bit.W,
- keyboard.bit.A,
- keyboard.bit.S,
- keyboard.bit.D,
- keyboard.bit.Q,
- keyboard.bit.E,
- keyboard.bit.R,
- keyboard.bit.F,
- keyboard.bit.G,
- keyboard.bit.Z,
- keyboard.bit.X,
- keyboard.bit.C,
- keyboard.bit.V,
- keyboard.bit.B,
- keyboard.bit.SHIFT,
- keyboard.bit.CTRL,
- mouse.x,
- mouse.y,
- mouse.z,
- mouse.l,
- mouse.r
- );
- osDelay(1);
- }
-}
\ No newline at end of file
diff --git a/examples/DJI_Board_TypeC_general/CMakeLists.txt b/examples/DJI_Board_TypeC_general/CMakeLists.txt
index 411274d9..0425a0fb 100644
--- a/examples/DJI_Board_TypeC_general/CMakeLists.txt
+++ b/examples/DJI_Board_TypeC_general/CMakeLists.txt
@@ -5,7 +5,7 @@ add_subdirectory(buzzer)
add_subdirectory(can_bridge)
add_subdirectory(chassis)
add_subdirectory(cybergear)
-add_subdirectory(dbus)
+add_subdirectory(controller)
add_subdirectory(gimbal)
add_subdirectory(imu)
add_subdirectory(ist8310)
@@ -15,8 +15,7 @@ add_subdirectory(motor)
add_subdirectory(oled)
add_subdirectory(onboard_temp)
add_subdirectory(referee)
-add_subdirectory(sbus)
add_subdirectory(witimu)
add_subdirectory(usb)
add_subdirectory(supercap)
-add_subdirectory(Automata)
\ No newline at end of file
+add_subdirectory(Automata)
diff --git a/examples/DJI_Board_TypeC_general/can_bridge/host.cpp b/examples/DJI_Board_TypeC_general/can_bridge/host.cpp
index 93278398..3ade6dc1 100644
--- a/examples/DJI_Board_TypeC_general/can_bridge/host.cpp
+++ b/examples/DJI_Board_TypeC_general/can_bridge/host.cpp
@@ -24,13 +24,13 @@
#include "bsp_uart.h"
#include "can_bridge.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
static bsp::CAN* can1 = nullptr;
static communication::CanBridge* can_bridge = nullptr;
-static remote::DBUS* dbus = nullptr;
+static controller::DBUS* dbus = nullptr;
void RM_RTOS_Init(void) {
print_use_usb();
@@ -38,18 +38,21 @@ void RM_RTOS_Init(void) {
can1 = new bsp::CAN(&hcan1, true, 8);
can_bridge = new communication::CanBridge(can1, 0x02);
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
}
void RM_RTOS_Default_Task(const void* argument) {
UNUSED(argument);
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
communication::can_bridge_data_t data;
- data.data_four_int16.data[0] = dbus->ch0;
- data.data_four_int16.data[1] = dbus->ch1;
- data.data_four_int16.data[2] = dbus->ch2;
- data.data_four_int16.data[3] = dbus->ch3;
+ data.data_four_int16.data[0] = dbus_state.channels[0];
+ data.data_four_int16.data[1] = dbus_state.channels[1];
+ data.data_four_int16.data[2] = dbus_state.channels[2];
+ data.data_four_int16.data[3] = dbus_state.channels[3];
communication::can_bridge_ext_id_t ext_id;
ext_id.data.rx_id = 0x01;
ext_id.data.type = communication::CAN_BRIDGE_TYPE_FOUR_INT16;
diff --git a/examples/DJI_Board_TypeC_general/chassis/CMakeLists.txt b/examples/DJI_Board_TypeC_general/chassis/CMakeLists.txt
index 5fe43b9a..199d7983 100644
--- a/examples/DJI_Board_TypeC_general/chassis/CMakeLists.txt
+++ b/examples/DJI_Board_TypeC_general/chassis/CMakeLists.txt
@@ -8,10 +8,6 @@ uicrm_add_arm_executable(${PROJECT_NAME}_omni
TARGET ${BOARD_NAME}
SOURCES omni_example.cpp)
-uicrm_add_arm_executable(${PROJECT_NAME}_sbus
- TARGET ${BOARD_NAME}
- SOURCES sbus.cpp)
-
uicrm_add_arm_executable(${PROJECT_NAME}_can_bridge
TARGET ${BOARD_NAME}
SOURCES can_bridge_chassis.cpp)
@@ -24,4 +20,4 @@ uicrm_add_arm_executable(${PROJECT_NAME}_power_data_collect
uicrm_add_arm_executable(${PROJECT_NAME}_power_limit_test
TARGET ${BOARD_NAME}
SOURCES power_limit_test.cpp
-)
\ No newline at end of file
+)
diff --git a/examples/DJI_Board_TypeC_general/chassis/mecanum_example.cpp b/examples/DJI_Board_TypeC_general/chassis/mecanum_example.cpp
index fe64efc1..66fd98cb 100644
--- a/examples/DJI_Board_TypeC_general/chassis/mecanum_example.cpp
+++ b/examples/DJI_Board_TypeC_general/chassis/mecanum_example.cpp
@@ -23,7 +23,7 @@
#include "bsp_print.h"
#include "chassis.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
bsp::CAN* can = nullptr;
driver::DjiMotorBase* fl_motor = nullptr;
@@ -32,7 +32,7 @@ driver::DjiMotorBase* bl_motor = nullptr;
driver::DjiMotorBase* br_motor = nullptr;
control::Chassis* chassis = nullptr;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
void RM_RTOS_Init() {
HAL_Delay(200);
@@ -86,21 +86,27 @@ void RM_RTOS_Init() {
chassis_data.model = control::CHASSIS_MECANUM_WHEEL;
chassis = new control::Chassis(chassis_data);
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
HAL_Delay(300);
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
osDelay(500); // DBUS initialization needs time
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
const float ratio = 1.0f / 660.0f * 6 * PI;
- chassis->SetSpeed(dbus->ch0 * ratio, dbus->ch1 * ratio, dbus->ch2 * ratio);
+ chassis
+ ->SetSpeed(dbus_state.channels[0] * ratio, dbus_state.channels[1] * ratio, dbus_state.channels[2] * ratio);
// Kill switch
- if (dbus->swl == remote::UP || dbus->swl == remote::DOWN) {
+ if (dbus_state.left_switch == Up || dbus_state.left_switch == Down) {
RM_ASSERT_TRUE(false, "Operation killed");
}
chassis->SetPower(false, 30, 20, 60);
diff --git a/examples/DJI_Board_TypeC_general/chassis/omni_example.cpp b/examples/DJI_Board_TypeC_general/chassis/omni_example.cpp
index 33d2b7fd..73ab45c0 100644
--- a/examples/DJI_Board_TypeC_general/chassis/omni_example.cpp
+++ b/examples/DJI_Board_TypeC_general/chassis/omni_example.cpp
@@ -24,7 +24,7 @@
#include "bsp_print.h"
#include "chassis.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
bsp::CAN* can = nullptr;
driver::DjiMotorBase* fl_motor = nullptr;
@@ -33,7 +33,7 @@ driver::DjiMotorBase* bl_motor = nullptr;
driver::DjiMotorBase* br_motor = nullptr;
control::Chassis* chassis = nullptr;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
void RM_RTOS_Init() {
HAL_Delay(200);
@@ -88,21 +88,27 @@ void RM_RTOS_Init() {
chassis_data.model = control::CHASSIS_OMNI_WHEEL;
chassis = new control::Chassis(chassis_data);
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
HAL_Delay(300);
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
osDelay(500); // DBUS initialization needs time
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
const float ratio = 1.0f / 660.0f * 6 * PI;
- chassis->SetSpeed(dbus->ch0 * ratio, dbus->ch1 * ratio, dbus->ch2 * ratio);
+ chassis
+ ->SetSpeed(dbus_state.channels[0] * ratio, dbus_state.channels[1] * ratio, dbus_state.channels[2] * ratio);
// Kill switch
- if (dbus->swl == remote::UP || dbus->swl == remote::DOWN) {
+ if (dbus_state.left_switch == Up || dbus_state.left_switch == Down) {
RM_ASSERT_TRUE(false, "Operation killed");
}
chassis->SetPower(false, 30, 20, 60);
@@ -120,17 +126,17 @@ void RM_RTOS_Default_Task(const void* args) {
// DBUS info
print(
- "DBUS [CH0: %-4d] [CH1: %-4d] [CH2: %-4d] [CH3: %-4d] [TWL: %d] [SWL: %d] [SWR: %d]"
+ "DBUS [CH0: %-4d] [CH1: %-4d] [CH2: %-4d] [CH3: %-4d] [TWL: %d] [SWL: %s] [SWR: %s]"
"@ %d "
"ms\r\n",
- dbus->ch0,
- dbus->ch1,
- dbus->ch2,
- dbus->ch3,
- dbus->ch4,
- dbus->swl,
- dbus->swr,
- dbus->GetLastUptime()
+ dbus_state.channels[0],
+ dbus_state.channels[1],
+ dbus_state.channels[2],
+ dbus_state.channels[3],
+ dbus_state.channels[4],
+ controller::SwitchName(dbus_state.left_switch),
+ controller::SwitchName(dbus_state.right_switch),
+ dbus->GetLastValidTimeMs()
);
print("\r\n");
diff --git a/examples/DJI_Board_TypeC_general/chassis/power_data_collect.cpp b/examples/DJI_Board_TypeC_general/chassis/power_data_collect.cpp
index 6bb18f3b..693e34d3 100644
--- a/examples/DJI_Board_TypeC_general/chassis/power_data_collect.cpp
+++ b/examples/DJI_Board_TypeC_general/chassis/power_data_collect.cpp
@@ -21,7 +21,7 @@
#include "bsp_print.h"
#include "chassis.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
#include "power_meter.h"
@@ -32,7 +32,7 @@ driver::DjiMotorBase* bl_motor = nullptr;
driver::DjiMotorBase* br_motor = nullptr;
control::Chassis* chassis = nullptr;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
power_meter* power_meter_1 = nullptr;
@@ -107,7 +107,7 @@ void RM_RTOS_Init() {
chassis_data.model = control::CHASSIS_MECANUM_WHEEL;
chassis = new control::Chassis(chassis_data);
- dbus = new remote::DBUS(&BOARD_DBUS);
+ dbus = new controller::DBUS(&BOARD_DBUS);
power_meter_1 = new power_meter(&BOARD_UART2, 1, callback);
@@ -123,8 +123,11 @@ void RM_RTOS_Default_Task(const void* args) {
osDelay(500); // DBUS initialization needs time
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
const float ratio = 1.0f / 660.0f * PI * 12;
- float target = ratio * dbus->ch0;
+ float target = ratio * dbus_state.channels[0];
fr_motor->SetTarget(target, true);
osDelay(10);
}
diff --git a/examples/DJI_Board_TypeC_general/chassis/power_limit_test.cpp b/examples/DJI_Board_TypeC_general/chassis/power_limit_test.cpp
index e4e18b0f..3038933c 100644
--- a/examples/DJI_Board_TypeC_general/chassis/power_limit_test.cpp
+++ b/examples/DJI_Board_TypeC_general/chassis/power_limit_test.cpp
@@ -22,7 +22,7 @@
#include "bsp_print.h"
#include "chassis.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
#include "power_meter.h"
@@ -33,7 +33,7 @@ driver::DjiMotorBase* bl_motor = nullptr;
driver::DjiMotorBase* br_motor = nullptr;
control::Chassis* chassis = nullptr;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
power_meter* power_meter_1 = nullptr;
bsp::BatteryVol* battery_vol = nullptr;
@@ -110,7 +110,7 @@ void RM_RTOS_Init() {
chassis_data.power_limit_on = true;
chassis = new control::Chassis(chassis_data);
- dbus = new remote::DBUS(&BOARD_DBUS);
+ dbus = new controller::DBUS(&BOARD_DBUS);
power_meter_1 = new power_meter(&BOARD_UART2, 1, callback);
battery_vol = new bsp::BatteryVol(&hadc3, ADC_CHANNEL_8, 1, ADC_SAMPLETIME_3CYCLES);
@@ -122,16 +122,22 @@ void RM_RTOS_Init() {
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
osDelay(500); // DBUS initialization needs time
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
const float ratio = 1.0f / 660.0f * 6 * PI;
- chassis->SetSpeed(dbus->ch0 * ratio, dbus->ch1 * ratio, dbus->ch2 * ratio);
+ chassis
+ ->SetSpeed(dbus_state.channels[0] * ratio, dbus_state.channels[1] * ratio, dbus_state.channels[2] * ratio);
// Kill switch
- if (dbus->swl == remote::UP || dbus->swl == remote::DOWN) {
+ if (dbus_state.left_switch == Up || dbus_state.left_switch == Down) {
RM_ASSERT_TRUE(false, "Operation killed");
}
chassis->UpdatePower(true, 60, battery_vol->GetBatteryVol(), 50);
diff --git a/examples/DJI_Board_TypeC_general/chassis/sbus.cpp b/examples/DJI_Board_TypeC_general/chassis/sbus.cpp
deleted file mode 100644
index 08ca40e0..00000000
--- a/examples/DJI_Board_TypeC_general/chassis/sbus.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*###########################################################
- # Copyright (c) 2023-2024. BNU-HKBU UIC RoboMaster #
- # #
- # This program is free software: you can redistribute it #
- # and/or modify it under the terms of the GNU General #
- # Public License as published by the Free Software #
- # Foundation, either version 3 of the License, or (at #
- # your option) any later version. #
- # #
- # This program is distributed in the hope that it will be #
- # useful, but WITHOUT ANY WARRANTY; without even #
- # the implied warranty of MERCHANTABILITY or FITNESS #
- # FOR A PARTICULAR PURPOSE. See the GNU General #
- # Public License for more details. #
- # #
- # You should have received a copy of the GNU General #
- # Public License along with this program. If not, see #
- # . #
- ###########################################################*/
-
-#include "sbus.h"
-
-#include "bsp_print.h"
-#include "chassis.h"
-#include "cmsis_os.h"
-#include "main.h"
-
-bsp::CAN* can = nullptr;
-driver::DjiMotorBase* fl_motor = nullptr;
-driver::DjiMotorBase* fr_motor = nullptr;
-driver::DjiMotorBase* bl_motor = nullptr;
-driver::DjiMotorBase* br_motor = nullptr;
-
-control::Chassis* chassis = nullptr;
-remote::SBUS* sbus = nullptr;
-
-void RM_RTOS_Init() {
- HAL_Delay(200);
- print_use_uart(&huart1);
- can = new bsp::CAN(&hcan1, true);
- fl_motor = new driver::Motor3508(can, 0x202);
- fr_motor = new driver::Motor3508(can, 0x201);
- bl_motor = new driver::Motor3508(can, 0x203);
- br_motor = new driver::Motor3508(can, 0x204);
-
- control::ConstrainedPID::PID_Init_t omega_pid_init = {
- .kp = 2500,
- .ki = 3,
- .kd = 0,
- .max_out = 30000,
- .max_iout = 10000,
- .deadband = 0, // 死区
- .A = 3 * PI, // 变速积分所能达到的最大值为A+B
- .B = 2 * PI, // 启动变速积分的死区
- .output_filtering_coefficient = 0.1, // 输出滤波系数
- .derivative_filtering_coefficient = 0, // 微分滤波系数
- .mode = control::ConstrainedPID::Integral_Limit | // 积分限幅
- control::ConstrainedPID::OutputFilter | // 输出滤波
- control::ConstrainedPID::Trapezoid_Intergral | // 梯形积分
- control::ConstrainedPID::ChangingIntegralRate, // 变速积分
- };
-
- fl_motor->ReInitPID(omega_pid_init, driver::DjiMotorBase::OMEGA);
- fl_motor->SetMode(driver::DjiMotorBase::OMEGA);
- fl_motor->SetTransmissionRatio(19);
-
- fr_motor->ReInitPID(omega_pid_init, driver::DjiMotorBase::OMEGA);
- fr_motor->SetMode(driver::DjiMotorBase::OMEGA);
- fr_motor->SetTransmissionRatio(19);
-
- bl_motor->ReInitPID(omega_pid_init, driver::DjiMotorBase::OMEGA);
- bl_motor->SetMode(driver::DjiMotorBase::OMEGA);
- bl_motor->SetTransmissionRatio(19);
-
- br_motor->ReInitPID(omega_pid_init, driver::DjiMotorBase::OMEGA);
- br_motor->SetMode(driver::DjiMotorBase::OMEGA);
- br_motor->SetTransmissionRatio(19);
-
- driver::DjiMotorBase* motors[control::FourWheel::motor_num];
- motors[control::FourWheel::front_left] = fl_motor;
- motors[control::FourWheel::front_right] = fr_motor;
- motors[control::FourWheel::back_left] = bl_motor;
- motors[control::FourWheel::back_right] = br_motor;
-
- control::chassis_t chassis_data;
- chassis_data.motors = motors;
- chassis_data.model = control::CHASSIS_MECANUM_WHEEL;
- chassis = new control::Chassis(chassis_data);
-
- sbus = new remote::SBUS(&huart3);
- HAL_Delay(300);
-}
-
-void RM_RTOS_Default_Task(const void* args) {
- UNUSED(args);
-
- osDelay(500); // DBUS initialization needs time
-
- while (true) {
- const float ratio = 1.0f / 660.0f * 6 * PI;
- chassis->SetSpeed(-sbus->ch1 * ratio, sbus->ch2 * ratio, sbus->ch4 * ratio);
-
- // Kill switch
- if (sbus->ch5 >= 550) {
- RM_ASSERT_TRUE(false, "Operation killed");
- }
-
- chassis->SetPower(false, 30, 20, 60);
- chassis->Update();
- osDelay(10);
- }
-}
diff --git a/examples/DJI_Board_TypeC_general/controller/CMakeLists.txt b/examples/DJI_Board_TypeC_general/controller/CMakeLists.txt
new file mode 100644
index 00000000..01adbde1
--- /dev/null
+++ b/examples/DJI_Board_TypeC_general/controller/CMakeLists.txt
@@ -0,0 +1,13 @@
+project(example_controller_${BOARD_NAME} ASM C CXX)
+
+uicrm_add_arm_executable(${PROJECT_NAME}_dt7
+ TARGET ${BOARD_NAME}
+ SOURCES dt7.cpp)
+
+uicrm_add_arm_executable(${PROJECT_NAME}_vt13
+ TARGET ${BOARD_NAME}
+ SOURCES vt13.cpp)
+
+uicrm_add_arm_executable(${PROJECT_NAME}_fs_i6x
+ TARGET ${BOARD_NAME}
+ SOURCES fs_i6x.cpp)
diff --git a/examples/DJI_Board_TypeC_general/controller/dt7.cpp b/examples/DJI_Board_TypeC_general/controller/dt7.cpp
new file mode 100644
index 00000000..e619bc99
--- /dev/null
+++ b/examples/DJI_Board_TypeC_general/controller/dt7.cpp
@@ -0,0 +1,75 @@
+/*###########################################################
+# Copyright (c) 2026-2027. BNBU/UIC RoboMaster #
+ # #
+ # This program is free software: you can redistribute it #
+ # and/or modify it under the terms of the GNU General #
+ # Public License as published by the Free Software #
+ # Foundation, either version 3 of the License, or (at #
+ # your option) any later version. #
+ # #
+ # This program is distributed in the hope that it will be #
+ # useful, but WITHOUT ANY WARRANTY; without even #
+ # the implied warranty of MERCHANTABILITY or FITNESS #
+ # FOR A PARTICULAR PURPOSE. See the GNU General #
+ # Public License for more details. #
+ # #
+ # You should have received a copy of the GNU General #
+ # Public License along with this program. If not, see #
+ # . #
+ ###########################################################*/
+
+#include "main.h"
+
+#include "bsp_print.h"
+#include "cmsis_os.h"
+#include "dbus.h"
+
+namespace {
+ controller::DBUS* receiver = nullptr;
+}
+
+void RM_RTOS_Init(void) {
+ print_use_uart(&huart1);
+
+ receiver = new controller::DBUS(&huart3);
+}
+
+void RM_RTOS_Default_Task(const void* argument) {
+ UNUSED(argument);
+ while (true) {
+ controller::DbusFrame state;
+ const bool has_state = receiver->GetState(state);
+ const bool online = receiver->IsOnline();
+ const uint32_t sequence = receiver->GetSequence();
+ const uint32_t last_valid_ms = receiver->GetLastValidTimeMs();
+
+ set_cursor(0, 0);
+ clear_screen();
+ print("DT7: %s\r\n", online ? "ONLINE" : "OFFLINE");
+ print("Sequence: %lu\r\n", static_cast(sequence));
+ print("Last valid: %lu ms\r\n", static_cast(last_valid_ms));
+ if (has_state) {
+ // 离线仍保留最后有效帧;实际控制必须先检查 online。
+ print("Right X/Y: %d / %d\r\n", state.channels[0], state.channels[1]);
+ print("Left X/Y: %d / %d\r\n", state.channels[2], state.channels[3]);
+ print("Dial: %d\r\n", state.channels[4]);
+ print(
+ "Switch L/R: %s / %s\r\n",
+ controller::SwitchName(state.left_switch),
+ controller::SwitchName(state.right_switch)
+ );
+ print("Mouse X/Y: %d / %d\r\n", state.mouse.x, state.mouse.y);
+ print("Mouse Z: %d\r\n", state.mouse.z);
+ print("Mouse L/R: %d / %d\r\n", state.mouse.left, state.mouse.right);
+ print("Keyboard: 0x%04X\r\n", static_cast(state.keyboard.code));
+ const auto& key = state.keyboard.bit;
+ print("W/S/A/D: %d %d %d %d\r\n", key.W, key.S, key.A, key.D);
+ print("SHIFT/CTRL: %d %d\r\n", key.SHIFT, key.CTRL);
+ print("Q/E/R/F/G: %d %d %d %d %d\r\n", key.Q, key.E, key.R, key.F, key.G);
+ print("Z/X/C/V/B: %d %d %d %d %d\r\n", key.Z, key.X, key.C, key.V, key.B);
+ } else {
+ print("Waiting for a valid frame\r\n");
+ }
+ osDelay(100);
+ }
+}
diff --git a/examples/DJI_Board_TypeC_general/controller/fs_i6x.cpp b/examples/DJI_Board_TypeC_general/controller/fs_i6x.cpp
new file mode 100644
index 00000000..dcf6d12a
--- /dev/null
+++ b/examples/DJI_Board_TypeC_general/controller/fs_i6x.cpp
@@ -0,0 +1,82 @@
+/*###########################################################
+# Copyright (c) 2026-2027. BNBU/UIC RoboMaster #
+ # #
+ # This program is free software: you can redistribute it #
+ # and/or modify it under the terms of the GNU General #
+ # Public License as published by the Free Software #
+ # Foundation, either version 3 of the License, or (at #
+ # your option) any later version. #
+ # #
+ # This program is distributed in the hope that it will be #
+ # useful, but WITHOUT ANY WARRANTY; without even #
+ # the implied warranty of MERCHANTABILITY or FITNESS #
+ # FOR A PARTICULAR PURPOSE. See the GNU General #
+ # Public License for more details. #
+ # #
+ # You should have received a copy of the GNU General #
+ # Public License along with this program. If not, see #
+ # . #
+ ###########################################################*/
+
+#include "main.h"
+
+#include "bsp_print.h"
+#include "cmsis_os.h"
+#include "sbus.h"
+
+static controller::I6x* receiver = nullptr;
+
+void RM_RTOS_Init(void) {
+ print_use_uart(&huart1);
+
+ // I6x 继承 SBUS 的 UART 接收,无需另外创建 SBUS 或注册回调。
+ receiver = new controller::I6x(&huart3);
+}
+
+void RM_RTOS_Default_Task(const void* argument) {
+ UNUSED(argument);
+ while (true) {
+ controller::I6xState state;
+ controller::SbusFrame raw;
+
+ const bool has_state = receiver->GetState(state) && receiver->GetRawState(raw);
+ const bool online = receiver->IsOnline();
+ const uint32_t sequence = receiver->GetSequence();
+ const uint32_t last_valid_ms = receiver->GetLastValidTimeMs();
+
+ set_cursor(0, 0);
+ clear_screen();
+ print("FS-i6X / iA10B: %s\r\n", online ? "ONLINE" : "OFFLINE");
+ print("Sequence: %lu\r\n", static_cast(sequence));
+ print("Last valid: %lu ms\r\n", static_cast(last_valid_ms));
+ if (has_state) {
+ print(
+ "Frame lost: %d Failsafe: %d Flags: 0x%02X\r\n",
+ state.frame_lost,
+ state.failsafe,
+ static_cast(raw.flags)
+ );
+ // CH1/2:右 X/Y;CH3/4:左 Y/X;CH5/6:VrA/VrB;CH7~10:SwA~SwD。
+ // I6x 已统一映射到 ±660 并处理原始 ±10 死区;原始通道保留用于诊断。
+ print("Right X/Y: %d / %d\r\n", state.channels[0], state.channels[1]);
+ print("Left X/Y: %d / %d\r\n", state.channels[3], state.channels[2]);
+ print("VrA/VrB: %d / %d\r\n", state.channels[4], state.channels[5]);
+ print(
+ "Switch A/B/C/D: %s / %s / %s / %s\r\n",
+ controller::SwitchName(state.sw_a),
+ controller::SwitchName(state.sw_b),
+ controller::SwitchName(state.sw_c),
+ controller::SwitchName(state.sw_d)
+ );
+ print("Usable: %d\r\n", online && !state.failsafe && !state.frame_lost);
+ for (size_t i = 0; i < raw.channels.size(); ++i) {
+ print("Raw CH%u: %u\r\n", static_cast(i + 1), static_cast(raw.channels[i]));
+ }
+ print("Digital CH17/18: %d / %d\r\n", raw.channel17, raw.channel18);
+ // 离线仍可读到最后有效帧,在线也可能失控;实际控制须分别检查。
+ } else {
+ print("Waiting for a valid SBUS frame\r\n");
+ }
+ osDelay(100);
+ }
+}
diff --git a/examples/DJI_Board_TypeC_general/controller/vt13.cpp b/examples/DJI_Board_TypeC_general/controller/vt13.cpp
new file mode 100644
index 00000000..51998f8f
--- /dev/null
+++ b/examples/DJI_Board_TypeC_general/controller/vt13.cpp
@@ -0,0 +1,76 @@
+/*###########################################################
+# Copyright (c) 2026-2027. BNBU/UIC RoboMaster #
+ # #
+ # This program is free software: you can redistribute it #
+ # and/or modify it under the terms of the GNU General #
+ # Public License as published by the Free Software #
+ # Foundation, either version 3 of the License, or (at #
+ # your option) any later version. #
+ # #
+ # This program is distributed in the hope that it will be #
+ # useful, but WITHOUT ANY WARRANTY; without even #
+ # the implied warranty of MERCHANTABILITY or FITNESS #
+ # FOR A PARTICULAR PURPOSE. See the GNU General #
+ # Public License for more details. #
+ # #
+ # You should have received a copy of the GNU General #
+ # Public License along with this program. If not, see #
+ # . #
+ ###########################################################*/
+
+#include "main.h"
+
+#include "bsp_print.h"
+#include "cmsis_os.h"
+#include "refereerc.h"
+
+static controller::RefereeRC* receiver = nullptr;
+
+void RM_RTOS_Init(void) {
+ print_use_uart(&huart1);
+
+ // 只接收纯遥控字节流;UART 接入、分帧及校验均由 RefereeRC 完成。
+ receiver = new controller::RefereeRC(&huart6);
+}
+
+void RM_RTOS_Default_Task(const void* argument) {
+ UNUSED(argument);
+ while (true) {
+ controller::RefereeRcFrame state;
+ const bool has_state = receiver->GetState(state);
+ const bool online = receiver->IsOnline();
+ const uint32_t sequence = receiver->GetSequence();
+ const uint32_t last_valid_ms = receiver->GetLastValidTimeMs();
+
+ set_cursor(0, 0);
+ clear_screen();
+ // 只有有效遥控帧刷新在线状态;离线后仍保留最后有效输入。
+ print("VT13: %s\r\n", online ? "ONLINE" : "OFFLINE");
+ print("Sequence: %lu\r\n", static_cast(sequence));
+ print("Last valid: %lu ms\r\n", static_cast(last_valid_ms));
+ if (has_state) {
+ // VT13 通道为 -660~660,中心 0,包含 ±10 死区;左摇杆的顺序是 Y/X。
+ print("Right X/Y: %d / %d\r\n", state.channels[0], state.channels[1]);
+ print("Left Y/X: %d / %d\r\n", state.channels[2], state.channels[3]);
+ print("Dial: %d\r\n", state.channels[4]);
+ const char* mode = state.mode == controller::RefereeRcMode::C ? "C" :
+ state.mode == controller::RefereeRcMode::N ? "N" :
+ "S";
+ print("Mode: %s Pause: %d\r\n", mode, state.pause);
+ print("Button L/R: %d / %d\r\n", state.left_button, state.right_button);
+ print("Trigger: %d\r\n", state.trigger);
+ print("Mouse X/Y: %d / %d\r\n", state.mouse.x, state.mouse.y);
+ print("Mouse Z: %d\r\n", state.mouse.z);
+ print("Mouse L/R/M: %d %d %d\r\n", state.mouse.left, state.mouse.right, state.mouse.middle);
+ print("Keyboard: 0x%04X\r\n", static_cast(state.keyboard.code));
+ const auto& key = state.keyboard.bit;
+ print("W/S/A/D: %d %d %d %d\r\n", key.W, key.S, key.A, key.D);
+ print("SHIFT/CTRL: %d %d\r\n", key.SHIFT, key.CTRL);
+ print("Q/E/R/F/G: %d %d %d %d %d\r\n", key.Q, key.E, key.R, key.F, key.G);
+ print("Z/X/C/V/B: %d %d %d %d %d\r\n", key.Z, key.X, key.C, key.V, key.B);
+ } else {
+ print("Waiting for a valid frame\r\n");
+ }
+ osDelay(100);
+ }
+}
diff --git a/examples/DJI_Board_TypeC_general/dbus/CMakeLists.txt b/examples/DJI_Board_TypeC_general/dbus/CMakeLists.txt
deleted file mode 100644
index 45816a8d..00000000
--- a/examples/DJI_Board_TypeC_general/dbus/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-project(example_dbus_${BOARD_NAME} ASM C CXX)
-
-uicrm_add_arm_executable(${PROJECT_NAME}
- TARGET ${BOARD_NAME}
- SOURCES main.cpp)
-
diff --git a/examples/DJI_Board_TypeC_general/dbus/main.cpp b/examples/DJI_Board_TypeC_general/dbus/main.cpp
deleted file mode 100644
index fa77b0a3..00000000
--- a/examples/DJI_Board_TypeC_general/dbus/main.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/*###########################################################
- # Copyright (c) 2023-2024. BNU-HKBU UIC RoboMaster #
- # #
- # This program is free software: you can redistribute it #
- # and/or modify it under the terms of the GNU General #
- # Public License as published by the Free Software #
- # Foundation, either version 3 of the License, or (at #
- # your option) any later version. #
- # #
- # This program is distributed in the hope that it will be #
- # useful, but WITHOUT ANY WARRANTY; without even #
- # the implied warranty of MERCHANTABILITY or FITNESS #
- # FOR A PARTICULAR PURPOSE. See the GNU General #
- # Public License for more details. #
- # #
- # You should have received a copy of the GNU General #
- # Public License along with this program. If not, see #
- # . #
- ###########################################################*/
-
-#include "main.h"
-
-#include "bsp_print.h"
-#include "cmsis_os.h"
-#include "dji_dbus.h"
-
-static remote::DBUS* dbus;
-
-void RM_RTOS_Init(void) {
- print_use_uart(&huart1);
- dbus = new remote::DBUS(&huart3);
-}
-
-void RM_RTOS_Default_Task(const void* arguments) {
- UNUSED(arguments);
-
- // NOTE(alvin): print is split because of stack usage is almost reaching
- // limits
- while (true) {
- set_cursor(0, 0);
- clear_screen();
- print(
- "CH0: %-4d CH1: %-4d CH2: %-4d CH3: %-4d \r\nSWL: %d SWR: %d "
- "TWL: %d "
- "@ %d "
- "ms\r\n",
- dbus->ch0,
- dbus->ch1,
- dbus->ch2,
- dbus->ch3,
- dbus->swl,
- dbus->swr,
- dbus->ch4,
- dbus->GetLastUptime()
- );
- print(
- "W: %d A: %d S: %d D: %d\r\n",
- dbus->keyboard.bit.W,
- dbus->keyboard.bit.A,
- dbus->keyboard.bit.S,
- dbus->keyboard.bit.D
- );
- print(
- "Q: %d E: %d R: %d F: %d G: %d\r\n",
- dbus->keyboard.bit.Q,
- dbus->keyboard.bit.E,
- dbus->keyboard.bit.R,
- dbus->keyboard.bit.F,
- dbus->keyboard.bit.G
- );
- print(
- "Z: %d X: %d C: %d V: %d B: %d\r\n",
- dbus->keyboard.bit.Z,
- dbus->keyboard.bit.X,
- dbus->keyboard.bit.C,
- dbus->keyboard.bit.V,
- dbus->keyboard.bit.B
- );
- print("SHIFT: %d CTRL: %d\r\n", dbus->keyboard.bit.SHIFT, dbus->keyboard.bit.CTRL);
- print(
- "Mouse: x: %d y: %d z: %d l: %d r: %d\r\n",
- dbus->mouse.x,
- dbus->mouse.y,
- dbus->mouse.z,
- dbus->mouse.l,
- dbus->mouse.r
- );
-
- osDelay(50);
- }
-}
diff --git a/examples/DJI_Board_TypeC_general/gimbal/CMakeLists.txt b/examples/DJI_Board_TypeC_general/gimbal/CMakeLists.txt
index d4aceac7..5722fb26 100644
--- a/examples/DJI_Board_TypeC_general/gimbal/CMakeLists.txt
+++ b/examples/DJI_Board_TypeC_general/gimbal/CMakeLists.txt
@@ -4,7 +4,3 @@ project(example_gimbal_${BOARD_NAME} ASM C CXX)
uicrm_add_arm_executable(${PROJECT_NAME}
TARGET ${BOARD_NAME}
SOURCES typeC.cpp)
-
-uicrm_add_arm_executable(${PROJECT_NAME}_sbus
- TARGET ${BOARD_NAME}
- SOURCES typeC_sbus.cpp)
\ No newline at end of file
diff --git a/examples/DJI_Board_TypeC_general/gimbal/typeC.cpp b/examples/DJI_Board_TypeC_general/gimbal/typeC.cpp
index 21ea1f74..256d0188 100644
--- a/examples/DJI_Board_TypeC_general/gimbal/typeC.cpp
+++ b/examples/DJI_Board_TypeC_general/gimbal/typeC.cpp
@@ -21,14 +21,14 @@
#include "bsp_imu.h"
#include "bsp_print.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "gimbal.h"
#include "i2c.h"
#include "main.h"
#include "spi.h"
static bsp::CAN* can1 = nullptr;
-static remote::DBUS* dbus = nullptr;
+static controller::DBUS* dbus = nullptr;
#define RX_SIGNAL (1 << 0)
@@ -92,11 +92,16 @@ const osThreadAttr_t gimbalTaskAttribute =
osThreadId_t gimbalTaskHandle;
void gimbalTask(void* arg) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(arg);
print("Wait for beginning signal...\r\n");
while (true) {
- if (dbus->keyboard.bit.V || dbus->swr == remote::DOWN) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.keyboard.bit.V || dbus_state.right_switch == Down) {
break;
}
osDelay(100);
@@ -129,19 +134,24 @@ void gimbalTask(void* arg) {
float pitch_target = 0, yaw_target = 0;
while (true) {
- if (dbus->keyboard.bit.B || dbus->swl == remote::DOWN) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.keyboard.bit.B || dbus_state.left_switch == Down) {
while (true) {
- if (dbus->keyboard.bit.V) {
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.keyboard.bit.V) {
break;
}
osDelay(10);
}
}
- pitch_ratio = dbus->mouse.y / 32767.0 * 7.5 / 7.0;
- yaw_ratio = -dbus->mouse.x / 32767.0 * 7.5 / 7.0;
- pitch_ratio = dbus->ch3 / 18000.0 / 7.0;
- yaw_ratio = -dbus->ch2 / 18000.0 / 7.0;
+ pitch_ratio = dbus_state.mouse.y / 32767.0 * 7.5 / 7.0;
+ yaw_ratio = -dbus_state.mouse.x / 32767.0 * 7.5 / 7.0;
+ pitch_ratio = dbus_state.channels[3] / 18000.0 / 7.0;
+ yaw_ratio = -dbus_state.channels[2] / 18000.0 / 7.0;
pitch_target = clip(pitch_ratio, -gimbal_param->pitch_max_, gimbal_param->pitch_max_);
yaw_target = clip(yaw_ratio, -gimbal_param->yaw_max_, gimbal_param->yaw_max_);
@@ -162,7 +172,7 @@ void RM_RTOS_Init(void) {
print_use_uart(&huart6);
can1 = new bsp::CAN(&hcan1, true);
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
bsp::IST8310_init_t IST8310_init;
IST8310_init.hi2c = &hi2c3;
@@ -303,7 +313,10 @@ void RM_RTOS_Threads_Init(void) {
void KillAll() {
RM_EXPECT_TRUE(false, "Operation killed\r\n");
while (true) {
- if (dbus->keyboard.bit.V) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.keyboard.bit.V) {
break;
}
pitch_motor->SetOutput(0);
@@ -313,10 +326,15 @@ void KillAll() {
}
void RM_RTOS_Default_Task(const void* arg) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(arg);
while (true) {
- if (dbus->keyboard.bit.B || dbus->swl == remote::DOWN)
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.keyboard.bit.B || dbus_state.left_switch == Down)
KillAll();
set_cursor(0, 0);
@@ -337,8 +355,19 @@ void RM_RTOS_Default_Task(const void* arg) {
print("\r\n");
- print("CH0: %-4d CH1: %-4d CH2: %-4d CH3: %-4d ", dbus->ch0, dbus->ch1, dbus->ch2, dbus->ch3);
- print("SWL: %d SWR: %d @ %d ms\r\n", dbus->swl, dbus->swr, dbus->GetLastUptime());
+ print(
+ "CH0: %-4d CH1: %-4d CH2: %-4d CH3: %-4d ",
+ dbus_state.channels[0],
+ dbus_state.channels[1],
+ dbus_state.channels[2],
+ dbus_state.channels[3]
+ );
+ print(
+ "SWL: %s SWR: %s @ %d ms\r\n",
+ controller::SwitchName(dbus_state.left_switch),
+ controller::SwitchName(dbus_state.right_switch),
+ dbus->GetLastValidTimeMs()
+ );
osDelay(100);
}
diff --git a/examples/DJI_Board_TypeC_general/gimbal/typeC_sbus.cpp b/examples/DJI_Board_TypeC_general/gimbal/typeC_sbus.cpp
deleted file mode 100644
index b17f8b34..00000000
--- a/examples/DJI_Board_TypeC_general/gimbal/typeC_sbus.cpp
+++ /dev/null
@@ -1,321 +0,0 @@
-/*###########################################################
- # Copyright (c) 2023-2024. BNU-HKBU UIC RoboMaster #
- # #
- # This program is free software: you can redistribute it #
- # and/or modify it under the terms of the GNU General #
- # Public License as published by the Free Software #
- # Foundation, either version 3 of the License, or (at #
- # your option) any later version. #
- # #
- # This program is distributed in the hope that it will be #
- # useful, but WITHOUT ANY WARRANTY; without even #
- # the implied warranty of MERCHANTABILITY or FITNESS #
- # FOR A PARTICULAR PURPOSE. See the GNU General #
- # Public License for more details. #
- # #
- # You should have received a copy of the GNU General #
- # Public License along with this program. If not, see #
- # . #
- ###########################################################*/
-
-#include "bsp_imu.h"
-#include "bsp_print.h"
-#include "cmsis_os.h"
-#include "gimbal.h"
-#include "i2c.h"
-#include "main.h"
-#include "sbus.h"
-#include "spi.h"
-
-static bsp::CAN* can1 = nullptr;
-static remote::SBUS* sbus = nullptr;
-
-#define RX_SIGNAL (1 << 0)
-
-const osThreadAttr_t imuTaskAttribute =
- {.name = "imuTask",
- .attr_bits = osThreadDetached,
- .cb_mem = nullptr,
- .cb_size = 0,
- .stack_mem = nullptr,
- .stack_size = 256 * 4,
- .priority = (osPriority_t)osPriorityNormal,
- .tz_module = 0,
- .reserved = 0};
-osThreadId_t imuTaskHandle;
-
-class IMU : public bsp::IMU_typeC {
- public:
- using bsp::IMU_typeC::IMU_typeC;
-
- protected:
- void RxCompleteCallback() final {
- osThreadFlagsSet(imuTaskHandle, RX_SIGNAL);
- }
-};
-
-static IMU* imu = nullptr;
-
-void imuTask(void* arg) {
- UNUSED(arg);
-
- while (true) {
- uint32_t flags = osThreadFlagsWait(RX_SIGNAL, osFlagsWaitAll, osWaitForever);
- if (flags & RX_SIGNAL) { // unnecessary check
- imu->Update();
- }
- }
-}
-
-static driver::DjiMotorBase* pitch_motor = nullptr;
-static driver::DjiMotorBase* yaw_motor = nullptr;
-static control::Gimbal* gimbal = nullptr;
-static control::gimbal_data_t* gimbal_param = nullptr;
-
-const control::gimbal_data_t gimbal_init_data =
- {.pitch_offset_ = 2.8582f, .yaw_offset_ = 2.5840f, .pitch_max_ = 0.4897f, .yaw_max_ = PI / 2, .yaw_circle_ = true};
-
-const osThreadAttr_t gimbalTaskAttribute =
- {.name = "gimbalTask",
- .attr_bits = osThreadDetached,
- .cb_mem = nullptr,
- .cb_size = 0,
- .stack_mem = nullptr,
- .stack_size = 256 * 4,
- .priority = (osPriority_t)osPriorityNormal,
- .tz_module = 0,
- .reserved = 0};
-osThreadId_t gimbalTaskHandle;
-
-void gimbalTask(void* arg) {
- UNUSED(arg);
-
- print("Wait for beginning signal...\r\n");
- while (true) {
- if (sbus->ch7 >= 0) {
- break;
- }
- osDelay(100);
- }
-
- int i = 0;
- while (i < 2000 || !imu->DataReady()) {
- gimbal->TargetAbs(0, 0);
- gimbal->Update();
- osDelay(1);
- ++i;
- }
-
- print("Start Calibration.\r\n");
- imu->Calibrate();
-
- i = 0;
- while (!imu->DataReady() || !imu->CaliDone()) {
- gimbal->TargetAbs(0, 0);
- gimbal->Update();
- osDelay(1);
- ++i;
- }
-
- print("Gimbal Begin!\r\n");
-
- float pitch_ratio, yaw_ratio;
- float pitch_curr, yaw_curr;
- float pitch_diff, yaw_diff;
- float pitch_target = 0, yaw_target = 0;
-
- while (true) {
- if (sbus->ch7 < 0) {
- while (true) {
- if (sbus->ch7 >= 0) {
- break;
- }
- osDelay(10);
- }
- }
-
- pitch_ratio = sbus->ch3 / 18000.0 / 7.0;
- yaw_ratio = -sbus->ch4 / 18000.0 / 7.0;
- pitch_target = clip(pitch_ratio, -gimbal_param->pitch_max_, gimbal_param->pitch_max_);
- yaw_target = clip(yaw_ratio, -gimbal_param->yaw_max_, gimbal_param->yaw_max_);
-
- pitch_diff = wrap(pitch_target, -PI, PI);
- yaw_diff = wrap(yaw_target, -PI, PI);
-
- pitch_curr = imu->INS_angle[2];
- yaw_curr = imu->INS_angle[0];
-
- gimbal->TargetRel(pitch_diff, yaw_diff);
-
- gimbal->UpdateIMU(pitch_curr, yaw_curr);
- osDelay(1);
- }
-}
-
-void RM_RTOS_Init(void) {
- print_use_uart(&huart6);
-
- can1 = new bsp::CAN(&hcan2, false);
- sbus = new remote::SBUS(&huart3);
-
- bsp::IST8310_init_t IST8310_init;
- IST8310_init.hi2c = &hi2c3;
- IST8310_init.int_pin = DRDY_IST8310_Pin;
- IST8310_init.rst_group = GPIOG;
- IST8310_init.rst_pin = GPIO_PIN_6;
- bsp::BMI088_init_t BMI088_init;
- BMI088_init.hspi = &hspi1;
- BMI088_init.CS_ACCEL_Port = CS1_ACCEL_GPIO_Port;
- BMI088_init.CS_ACCEL_Pin = CS1_ACCEL_Pin;
- BMI088_init.CS_GYRO_Port = CS1_GYRO_GPIO_Port;
- BMI088_init.CS_GYRO_Pin = CS1_GYRO_Pin;
- bsp::heater_init_t heater_init;
- heater_init.htim = &htim10;
- heater_init.channel = 1;
- heater_init.clock_freq = 1000000;
- heater_init.temp = 45;
- bsp::IMU_typeC_init_t imu_init;
- imu_init.IST8310 = IST8310_init;
- imu_init.BMI088 = BMI088_init;
- imu_init.heater = heater_init;
- imu_init.hspi = &hspi1;
- imu_init.hdma_spi_rx = &hdma_spi1_rx;
- imu_init.hdma_spi_tx = &hdma_spi1_tx;
- imu_init.Accel_INT_pin_ = INT1_ACCEL_Pin;
- imu_init.Gyro_INT_pin_ = INT1_GYRO_Pin;
- imu = new IMU(imu_init, false);
-
- pitch_motor = new driver::Motor6020(can1, 0x205);
- yaw_motor = new driver::Motor6020(can1, 0x206);
- pitch_motor = new driver::Motor6020(can1, 0x206);
- yaw_motor = new driver::Motor6020(can1, 0x205);
-
- pitch_motor->SetTransmissionRatio(1);
- control::ConstrainedPID::PID_Init_t pitch_theta_pid_init = {
- .kp = 20,
- .ki = 0,
- .kd = 0,
- .max_out = 6 * PI,
- .max_iout = 0,
- .deadband = 0, // 死区
- .A = 0, // 变速积分所能达到的最大值为A+B
- .B = 0, // 启动变速积分的死区
- .output_filtering_coefficient = 0.1, // 输出滤波系数
- .derivative_filtering_coefficient = 0, // 微分滤波系数
- .mode = control::ConstrainedPID::OutputFilter // 输出滤波
- };
- pitch_motor->ReInitPID(pitch_theta_pid_init, driver::DjiMotorBase::THETA);
- control::ConstrainedPID::PID_Init_t pitch_omega_pid_init = {
- .kp = 200,
- .ki = 1,
- .kd = 0,
- .max_out = 16384,
- .max_iout = 2000,
- .deadband = 0, // 死区
- .A = 1.5 * PI, // 变速积分所能达到的最大值为A+B
- .B = 1 * PI, // 启动变速积分的死区
- .output_filtering_coefficient = 0.1, // 输出滤波系数
- .derivative_filtering_coefficient = 0, // 微分滤波系数
- .mode = control::ConstrainedPID::Integral_Limit | // 积分限幅
- control::ConstrainedPID::OutputFilter | // 输出滤波
- control::ConstrainedPID::Trapezoid_Intergral | // 梯形积分
- control::ConstrainedPID::ChangingIntegralRate, // 变速积分
- };
- pitch_motor->ReInitPID(pitch_omega_pid_init, driver::DjiMotorBase::OMEGA);
- pitch_motor->SetMode(driver::DjiMotorBase::THETA | driver::DjiMotorBase::OMEGA | driver::DjiMotorBase::ABSOLUTE);
-
- yaw_motor->SetTransmissionRatio(1);
- control::ConstrainedPID::PID_Init_t yaw_theta_pid_init = {
- .kp = 20,
- .ki = 0,
- .kd = 0,
- .max_out = 6 * PI,
- .max_iout = 0,
- .deadband = 0, // 死区
- .A = 0, // 变速积分所能达到的最大值为A+B
- .B = 0, // 启动变速积分的死区
- .output_filtering_coefficient = 0.1, // 输出滤波系数
- .derivative_filtering_coefficient = 0, // 微分滤波系数
- .mode = control::ConstrainedPID::OutputFilter // 输出滤波
- };
- yaw_motor->ReInitPID(yaw_theta_pid_init, driver::DjiMotorBase::THETA);
- control::ConstrainedPID::PID_Init_t yaw_omega_pid_init = {
- .kp = 200,
- .ki = 1,
- .kd = 0,
- .max_out = 16384,
- .max_iout = 2000,
- .deadband = 0, // 死区
- .A = 1.5 * PI, // 变速积分所能达到的最大值为A+B
- .B = 1 * PI, // 启动变速积分的死区
- .output_filtering_coefficient = 0.1, // 输出滤波系数
- .derivative_filtering_coefficient = 0, // 微分滤波系数
- .mode = control::ConstrainedPID::Integral_Limit | // 积分限幅
- control::ConstrainedPID::OutputFilter | // 输出滤波
- control::ConstrainedPID::Trapezoid_Intergral | // 梯形积分
- control::ConstrainedPID::ChangingIntegralRate, // 变速积分
- };
- yaw_motor->ReInitPID(yaw_omega_pid_init, driver::DjiMotorBase::OMEGA);
- yaw_motor->SetMode(driver::DjiMotorBase::THETA | driver::DjiMotorBase::OMEGA | driver::DjiMotorBase::ABSOLUTE);
-
- control::gimbal_t gimbal_data;
- gimbal_data.data = gimbal_init_data;
- gimbal_data.pitch_motor = pitch_motor;
- gimbal_data.yaw_motor = yaw_motor;
-
- gimbal = new control::Gimbal(gimbal_data);
- gimbal_param = gimbal->GetData();
-}
-
-void RM_RTOS_Threads_Init(void) {
- imuTaskHandle = osThreadNew(imuTask, nullptr, &imuTaskAttribute);
- gimbalTaskHandle = osThreadNew(gimbalTask, nullptr, &gimbalTaskAttribute);
-}
-
-void KillAll() {
- RM_EXPECT_TRUE(false, "Operation killed\r\n");
- while (true) {
- pitch_motor->SetOutput(0);
- yaw_motor->SetOutput(0);
- osDelay(10);
- }
-}
-
-void RM_RTOS_Default_Task(const void* arg) {
- UNUSED(arg);
-
- while (true) {
- if (sbus->ch5 > 0)
- KillAll();
-
- set_cursor(0, 0);
- clear_screen();
-
- print(
- "# %.2f s, IMU %s\r\n",
- HAL_GetTick() / 1000.0,
- imu->CaliDone() ? "\033[1;42mReady\033[0m" : "\033[1;41mNot Ready\033[0m"
- );
- print("Temp: %.2f\r\n", imu->Temp);
- print(
- "Euler Angles: %.2f, %.2f, %.2f\r\n",
- imu->INS_angle[0] / PI * 180,
- imu->INS_angle[1] / PI * 180,
- imu->INS_angle[2] / PI * 180
- );
-
- print("\r\n");
-
- print("CH1: %-4d CH2: %-4d CH3: %-4d CH4: %-4d ", sbus->ch1, sbus->ch2, sbus->ch3, sbus->ch4);
- print(
- "CH5: %d CH6: %d CH7: %d CH8: %d @ %d ms\r\n",
- sbus->ch5,
- sbus->ch6,
- sbus->ch7,
- sbus->ch8,
- sbus->timestamp
- );
-
- osDelay(100);
- }
-}
diff --git a/examples/DJI_Board_TypeC_general/motor/m2305.cpp b/examples/DJI_Board_TypeC_general/motor/m2305.cpp
index 2b4a4247..95eac943 100644
--- a/examples/DJI_Board_TypeC_general/motor/m2305.cpp
+++ b/examples/DJI_Board_TypeC_general/motor/m2305.cpp
@@ -22,7 +22,7 @@
#include "bsp_gpio.h"
#include "bsp_print.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
#include "utils.h"
@@ -38,10 +38,10 @@
driver::PWMMotorBase* motor1;
driver::PWMMotorBase* motor2;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
void RM_RTOS_Init() {
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
print_use_uart(&huart6);
motor1 =
new driver::PWMMotorBase(&htim1, LEFT_MOTOR_PWM_CHANNEL, TIM_CLOCK_FREQ, MOTOR_OUT_FREQ, SNAIL_IDLE_THROTTLE);
@@ -54,20 +54,25 @@ void RM_RTOS_Init() {
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
bsp::GPIO key(KEY_GPIO_GROUP, KEY_GPIO_PIN);
RampSource ramp_1 = RampSource(0, 0, 450, 0.001);
RampSource ramp_2 = RampSource(0, 0, 450, 0.001);
int current = 0;
int state = 0;
- int8_t last_state = remote::MID;
+ auto last_state = Mid;
while (true) {
- if (dbus->swl == remote::UP) {
- if (last_state == remote::MID)
- last_state = remote::UP;
- } else if (dbus->swl == remote::MID) {
- if (last_state == remote::UP) {
- last_state = remote::MID;
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.left_switch == Up) {
+ if (last_state == Mid)
+ last_state = Up;
+ } else if (dbus_state.left_switch == Mid) {
+ if (last_state == Up) {
+ last_state = Mid;
if (state == 0) {
state = 1;
diff --git a/examples/DJI_Board_TypeC_general/motor/servo_m2006.cpp b/examples/DJI_Board_TypeC_general/motor/servo_m2006.cpp
index 8fd08ac2..cefdb1cf 100644
--- a/examples/DJI_Board_TypeC_general/motor/servo_m2006.cpp
+++ b/examples/DJI_Board_TypeC_general/motor/servo_m2006.cpp
@@ -23,20 +23,20 @@
#include "bsp_os.h"
#include "bsp_print.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
bsp::CAN* can2 = NULL;
driver::DjiMotorBase* motor1 = NULL;
driver::ServoMotor* load_servo = NULL;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
float load_step_angle = 2 * PI / 8;
void RM_RTOS_Init() {
bsp::SetHighresClockTimer(&htim5);
HAL_Delay(200);
print_use_uart(&huart1);
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
can2 = new bsp::CAN(&hcan1, true);
motor1 = new driver::Motor2006(can2, 0x201);
driver::servo_t servo_data;
@@ -56,27 +56,32 @@ void RM_RTOS_Init() {
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
- int last_state = remote::MID;
+ auto last_state = Mid;
while (true) {
- if (last_state != dbus->swl && dbus->swl == remote::MID) {
- if (last_state == remote::UP) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (last_state != dbus_state.left_switch && dbus_state.left_switch == Mid) {
+ if (last_state == Up) {
load_servo->SetTarget(load_servo->GetTarget() + load_step_angle);
- } else if (last_state == remote::DOWN) {
+ } else if (last_state == Down) {
load_servo->SetTarget(load_servo->GetTarget() - load_step_angle);
}
} else {
- if (dbus->ch3 > 0) {
+ if (dbus_state.channels[3] > 0) {
load_servo->SetTarget(load_servo->GetTarget() + load_step_angle);
- } else if (dbus->ch3 < 0) {
+ } else if (dbus_state.channels[3] < 0) {
load_servo->SetTarget(load_servo->GetTarget() - load_step_angle);
}
}
load_servo->CalcOutput();
- last_state = dbus->swl;
+ last_state = dbus_state.left_switch;
osDelay(1);
}
}
diff --git a/examples/DJI_Board_TypeC_general/motor/servo_m3508.cpp b/examples/DJI_Board_TypeC_general/motor/servo_m3508.cpp
index 1b8c86d3..be90b823 100644
--- a/examples/DJI_Board_TypeC_general/motor/servo_m3508.cpp
+++ b/examples/DJI_Board_TypeC_general/motor/servo_m3508.cpp
@@ -23,20 +23,20 @@
#include "bsp_os.h"
#include "bsp_print.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
bsp::CAN* can1 = NULL;
driver::DjiMotorBase* motor1 = NULL;
driver::ServoMotor* load_servo = NULL;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
float load_step_angle = 10 * PI;
void RM_RTOS_Init() {
bsp::SetHighresClockTimer(&htim5);
HAL_Delay(200);
print_use_uart(&huart6);
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
can1 = new bsp::CAN(&hcan1, true);
motor1 = new driver::Motor3508(can1, 0x201);
@@ -56,26 +56,31 @@ void RM_RTOS_Init() {
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
- int last_state = remote::MID;
+ auto last_state = Mid;
while (true) {
- if (last_state != dbus->swl && dbus->swl == remote::MID) {
- if (last_state == remote::UP) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (last_state != dbus_state.left_switch && dbus_state.left_switch == Mid) {
+ if (last_state == Up) {
load_servo->SetTarget(load_servo->GetTarget() + load_step_angle);
- } else if (last_state == remote::DOWN) {
+ } else if (last_state == Down) {
load_servo->SetTarget(load_servo->GetTarget() - load_step_angle);
}
} else {
- if (dbus->ch3 > 0) {
+ if (dbus_state.channels[3] > 0) {
load_servo->SetTarget(load_servo->GetTarget() + load_step_angle);
- } else if (dbus->ch3 < 0) {
+ } else if (dbus_state.channels[3] < 0) {
load_servo->SetTarget(load_servo->GetTarget() - load_step_angle);
}
}
load_servo->CalcOutput();
- last_state = dbus->swl;
+ last_state = dbus_state.left_switch;
osDelay(1);
}
}
diff --git a/examples/DJI_Board_TypeC_general/referee/CMakeLists.txt b/examples/DJI_Board_TypeC_general/referee/CMakeLists.txt
index 88e8e8d0..9fce1431 100644
--- a/examples/DJI_Board_TypeC_general/referee/CMakeLists.txt
+++ b/examples/DJI_Board_TypeC_general/referee/CMakeLists.txt
@@ -3,7 +3,3 @@ project(example_referee_${BOARD_NAME} ASM C CXX)
uicrm_add_arm_executable(${PROJECT_NAME}
TARGET ${BOARD_NAME}
SOURCES main.cpp)
-
-uicrm_add_arm_executable(${PROJECT_NAME}_rc
- TARGET ${BOARD_NAME}
- SOURCES rc.cpp)
\ No newline at end of file
diff --git a/examples/DJI_Board_TypeC_general/referee/rc.cpp b/examples/DJI_Board_TypeC_general/referee/rc.cpp
deleted file mode 100644
index e36f506c..00000000
--- a/examples/DJI_Board_TypeC_general/referee/rc.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*###########################################################
- # Copyright (c) 2023-2024. BNU-HKBU UIC RoboMaster #
- # #
- # This program is free software: you can redistribute it #
- # and/or modify it under the terms of the GNU General #
- # Public License as published by the Free Software #
- # Foundation, either version 3 of the License, or (at #
- # your option) any later version. #
- # #
- # This program is distributed in the hope that it will be #
- # useful, but WITHOUT ANY WARRANTY; without even #
- # the implied warranty of MERCHANTABILITY or FITNESS #
- # FOR A PARTICULAR PURPOSE. See the GNU General #
- # Public License for more details. #
- # #
- # You should have received a copy of the GNU General #
- # Public License along with this program. If not, see #
- # . #
- ###########################################################*/
-
-#include "bsp_print.h"
-#include "bsp_uart.h"
-#include "cmsis_os.h"
-#include "dji_dbus.h"
-#include "main.h"
-#include "protocol.h"
-
-communication::Referee* referee = nullptr;
-bsp::UART* referee_uart = nullptr;
-
-communication::Referee* refereeRc = nullptr;
-bsp::UART* refereeRc_uart = nullptr;
-
-void RM_RTOS_Init(void) {
- print_use_usb();
-
- referee_uart = new bsp::UART(&huart1);
- referee_uart->SetupRx(300);
- referee_uart->SetupTx(300);
-
- refereeRc_uart = new bsp::UART(&huart6);
- refereeRc_uart->SetupRx(300);
- refereeRc_uart->SetupTx(300);
-
- referee = new communication::Referee(referee_uart);
-
- refereeRc = new communication::Referee(refereeRc_uart);
-}
-
-void RM_RTOS_Threads_Init(void) {
-}
-
-void RM_RTOS_Default_Task(const void* argument) {
- UNUSED(argument);
-
- while (true) {
- set_cursor(0, 0);
- clear_screen();
- // print("Chassis Volt: %.3f\r\n", referee->power_heat_data.chassis_volt / 1000.0);
- // print("Chassis Curr: %.3f\r\n", referee->power_heat_data.chassis_current /
- // 1000.0); print("Chassis Power: %.3f\r\n", referee->power_heat_data.chassis_power);
- // print("Chassis Power Limit: %d\r\n",
- // referee->game_robot_status.chassis_power_limit); print("\r\n"); print("Shooter
- // Cooling Heat: %hu\r\n",
- // referee->power_heat_data.shooter_id1_17mm_cooling_heat);
- // print("Bullet Frequency: %hhu\r\n", referee->shoot_data.bullet_freq);
- // print("Bullet Speed: %.3f\r\n", referee->shoot_data.bullet_speed);
- // print("\r\n");
- // print("Current HP %d/%d\n", referee->game_robot_status.remain_HP,
- // referee->game_robot_status.max_HP);
- // print("Remain bullet %d\n", referee->bullet_remaining.bullet_remaining_num_17mm);
- remote::keyboard_t keyboard = referee->remote_control.keyboard;
- remote::mouse_t mouse = referee->remote_control.mouse;
- print(
- "W: %d A: %d S: %d D: %d\r\n"
- "Q: %d E: %d R: %d F: %d G: %d\r\n"
- "Z: %d X: %d C: %d V: %d B: %d\r\n"
- "SHIFT: %d CTRL: %d\r\n"
- "Mouse: x: %d y: %d z: %d l: %d r: %d\r\n",
- keyboard.bit.W,
- keyboard.bit.A,
- keyboard.bit.S,
- keyboard.bit.D,
- keyboard.bit.Q,
- keyboard.bit.E,
- keyboard.bit.R,
- keyboard.bit.F,
- keyboard.bit.G,
- keyboard.bit.Z,
- keyboard.bit.X,
- keyboard.bit.C,
- keyboard.bit.V,
- keyboard.bit.B,
- keyboard.bit.SHIFT,
- keyboard.bit.CTRL,
- mouse.x,
- mouse.y,
- mouse.z,
- mouse.l,
- mouse.r
- );
- osDelay(1);
- }
-}
\ No newline at end of file
diff --git a/examples/DJI_Board_TypeC_general/sbus/CMakeLists.txt b/examples/DJI_Board_TypeC_general/sbus/CMakeLists.txt
deleted file mode 100644
index f1ea8bb9..00000000
--- a/examples/DJI_Board_TypeC_general/sbus/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-project(example_sbus_${BOARD_NAME} ASM C CXX)
-
-uicrm_add_arm_executable(${PROJECT_NAME}
- TARGET ${BOARD_NAME}
- SOURCES main.cpp)
-
diff --git a/examples/DJI_Board_TypeC_general/sbus/main.cpp b/examples/DJI_Board_TypeC_general/sbus/main.cpp
deleted file mode 100644
index 137d1b10..00000000
--- a/examples/DJI_Board_TypeC_general/sbus/main.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*###########################################################
- # Copyright (c) 2023-2024. BNU-HKBU UIC RoboMaster #
- # #
- # This program is free software: you can redistribute it #
- # and/or modify it under the terms of the GNU General #
- # Public License as published by the Free Software #
- # Foundation, either version 3 of the License, or (at #
- # your option) any later version. #
- # #
- # This program is distributed in the hope that it will be #
- # useful, but WITHOUT ANY WARRANTY; without even #
- # the implied warranty of MERCHANTABILITY or FITNESS #
- # FOR A PARTICULAR PURPOSE. See the GNU General #
- # Public License for more details. #
- # #
- # You should have received a copy of the GNU General #
- # Public License along with this program. If not, see #
- # . #
- ###########################################################*/
-
-#include "main.h"
-
-#include "bsp_print.h"
-#include "cmsis_os.h"
-#include "sbus.h"
-
-static remote::SBUS* dbus;
-
-void RM_RTOS_Init(void) {
- print_use_uart(&huart1);
- dbus = new remote::SBUS(&huart3);
-}
-
-void RM_RTOS_Default_Task(const void* arguments) {
- UNUSED(arguments);
-
- // NOTE(alvin): print is split because of stack usage is almost reaching
- // limits
- while (true) {
- set_cursor(0, 0);
- clear_screen();
- print(
- "CH1: %-4d CH2: %-4d CH3: %-4d CH4: %-4d \r\n"
- "CH5: %-4d CH6: %-4d CH7: %-4d CH8: %-4d \r\n"
- "CH9: %-4d CH10: %-4d CH11: %-4d CH12: %-4d \r\n"
- "CH13: %-4d CH14: %-4d CH15: %-4d CH16: %-4d \r\n",
- dbus->ch1,
- dbus->ch2,
- dbus->ch3,
- dbus->ch4,
- dbus->ch5,
- dbus->ch6,
- dbus->ch7,
- dbus->ch8,
- dbus->ch9,
- dbus->ch10,
- dbus->ch11,
- dbus->ch12,
- dbus->ch13,
- dbus->ch14,
- dbus->ch15,
- dbus->ch16
- );
-
- osDelay(50);
- }
-}
diff --git a/examples/DM_MC01_general/CMakeLists.txt b/examples/DM_MC01_general/CMakeLists.txt
index f3af1263..c0b990b3 100644
--- a/examples/DM_MC01_general/CMakeLists.txt
+++ b/examples/DM_MC01_general/CMakeLists.txt
@@ -4,7 +4,6 @@ add_subdirectory(BMI088)
add_subdirectory(buzzer)
add_subdirectory(can_bridge)
add_subdirectory(chassis)
-add_subdirectory(dbus)
add_subdirectory(led)
add_subdirectory(motor)
-add_subdirectory(onboard_temp)
\ No newline at end of file
+add_subdirectory(onboard_temp)
diff --git a/examples/DM_MC01_general/can_bridge/host.cpp b/examples/DM_MC01_general/can_bridge/host.cpp
index 93278398..3ade6dc1 100644
--- a/examples/DM_MC01_general/can_bridge/host.cpp
+++ b/examples/DM_MC01_general/can_bridge/host.cpp
@@ -24,13 +24,13 @@
#include "bsp_uart.h"
#include "can_bridge.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
static bsp::CAN* can1 = nullptr;
static communication::CanBridge* can_bridge = nullptr;
-static remote::DBUS* dbus = nullptr;
+static controller::DBUS* dbus = nullptr;
void RM_RTOS_Init(void) {
print_use_usb();
@@ -38,18 +38,21 @@ void RM_RTOS_Init(void) {
can1 = new bsp::CAN(&hcan1, true, 8);
can_bridge = new communication::CanBridge(can1, 0x02);
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
}
void RM_RTOS_Default_Task(const void* argument) {
UNUSED(argument);
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
communication::can_bridge_data_t data;
- data.data_four_int16.data[0] = dbus->ch0;
- data.data_four_int16.data[1] = dbus->ch1;
- data.data_four_int16.data[2] = dbus->ch2;
- data.data_four_int16.data[3] = dbus->ch3;
+ data.data_four_int16.data[0] = dbus_state.channels[0];
+ data.data_four_int16.data[1] = dbus_state.channels[1];
+ data.data_four_int16.data[2] = dbus_state.channels[2];
+ data.data_four_int16.data[3] = dbus_state.channels[3];
communication::can_bridge_ext_id_t ext_id;
ext_id.data.rx_id = 0x01;
ext_id.data.type = communication::CAN_BRIDGE_TYPE_FOUR_INT16;
diff --git a/examples/DM_MC01_general/chassis/CMakeLists.txt b/examples/DM_MC01_general/chassis/CMakeLists.txt
index e56b178e..ddfd01bd 100644
--- a/examples/DM_MC01_general/chassis/CMakeLists.txt
+++ b/examples/DM_MC01_general/chassis/CMakeLists.txt
@@ -8,10 +8,6 @@ uicrm_add_arm_executable(${PROJECT_NAME}_omni
TARGET ${BOARD_NAME}
SOURCES omni_example.cpp)
-uicrm_add_arm_executable(${PROJECT_NAME}_sbus
- TARGET ${BOARD_NAME}
- SOURCES sbus.cpp)
-
uicrm_add_arm_executable(${PROJECT_NAME}_can_bridge
TARGET ${BOARD_NAME}
SOURCES can_bridge_chassis.cpp)
diff --git a/examples/DM_MC01_general/chassis/mecanum_example.cpp b/examples/DM_MC01_general/chassis/mecanum_example.cpp
index 3a36e112..c7d9ebd1 100644
--- a/examples/DM_MC01_general/chassis/mecanum_example.cpp
+++ b/examples/DM_MC01_general/chassis/mecanum_example.cpp
@@ -23,7 +23,7 @@
#include "bsp_print.h"
#include "chassis.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
bsp::CAN* can = nullptr;
driver::DjiMotorBase* fl_motor = nullptr;
@@ -32,7 +32,7 @@ driver::DjiMotorBase* bl_motor = nullptr;
driver::DjiMotorBase* br_motor = nullptr;
control::Chassis* chassis = nullptr;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
void RM_RTOS_Init() {
HAL_Delay(200);
@@ -86,21 +86,27 @@ void RM_RTOS_Init() {
chassis_data.model = control::CHASSIS_MECANUM_WHEEL;
chassis = new control::Chassis(chassis_data);
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
HAL_Delay(300);
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
osDelay(500); // DBUS initialization needs time
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
const float ratio = 1.0f / 660.0f * 6 * PI;
- chassis->SetSpeed(dbus->ch0 * ratio, dbus->ch1 * ratio, dbus->ch2 * ratio);
+ chassis
+ ->SetSpeed(dbus_state.channels[0] * ratio, dbus_state.channels[1] * ratio, dbus_state.channels[2] * ratio);
// Kill switch
- if (dbus->swl == remote::UP || dbus->swl == remote::DOWN) {
+ if (dbus_state.left_switch == Up || dbus_state.left_switch == Down) {
RM_ASSERT_TRUE(false, "Operation killed");
}
chassis->SetPower(false, 30, 20, 60);
diff --git a/examples/DM_MC01_general/chassis/omni_example.cpp b/examples/DM_MC01_general/chassis/omni_example.cpp
index ba9e9f80..a509b549 100644
--- a/examples/DM_MC01_general/chassis/omni_example.cpp
+++ b/examples/DM_MC01_general/chassis/omni_example.cpp
@@ -24,7 +24,7 @@
#include "bsp_print.h"
#include "chassis.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
bsp::CAN* can = nullptr;
driver::DjiMotorBase* fl_motor = nullptr;
@@ -33,7 +33,7 @@ driver::DjiMotorBase* bl_motor = nullptr;
driver::DjiMotorBase* br_motor = nullptr;
control::Chassis* chassis = nullptr;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
void RM_RTOS_Init() {
bsp::SetHighresClockTimer(&htim2); // TIM2 is configured with a 1 MHz counter.
@@ -88,21 +88,27 @@ void RM_RTOS_Init() {
chassis_data.model = control::CHASSIS_OMNI_WHEEL;
chassis = new control::Chassis(chassis_data);
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
HAL_Delay(300);
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
osDelay(500); // DBUS initialization needs time
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
const float ratio = 1.0f / 660.0f * 6 * PI;
- chassis->SetSpeed(dbus->ch0 * ratio, dbus->ch1 * ratio, dbus->ch2 * ratio);
+ chassis
+ ->SetSpeed(dbus_state.channels[0] * ratio, dbus_state.channels[1] * ratio, dbus_state.channels[2] * ratio);
// Kill switch
- if (dbus->swl == remote::UP || dbus->swl == remote::DOWN) {
+ if (dbus_state.left_switch == Up || dbus_state.left_switch == Down) {
RM_ASSERT_TRUE(false, "Operation killed");
}
chassis->SetPower(false, 30, 20, 60);
diff --git a/examples/DM_MC01_general/chassis/sbus.cpp b/examples/DM_MC01_general/chassis/sbus.cpp
deleted file mode 100644
index caace711..00000000
--- a/examples/DM_MC01_general/chassis/sbus.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*###########################################################
- # Copyright (c) 2023-2024. BNU-HKBU UIC RoboMaster #
- # #
- # This program is free software: you can redistribute it #
- # and/or modify it under the terms of the GNU General #
- # Public License as published by the Free Software #
- # Foundation, either version 3 of the License, or (at #
- # your option) any later version. #
- # #
- # This program is distributed in the hope that it will be #
- # useful, but WITHOUT ANY WARRANTY; without even #
- # the implied warranty of MERCHANTABILITY or FITNESS #
- # FOR A PARTICULAR PURPOSE. See the GNU General #
- # Public License for more details. #
- # #
- # You should have received a copy of the GNU General #
- # Public License along with this program. If not, see #
- # . #
- ###########################################################*/
-
-#include "sbus.h"
-
-#include "bsp_print.h"
-#include "chassis.h"
-#include "cmsis_os.h"
-#include "main.h"
-
-bsp::CAN* can = nullptr;
-driver::DjiMotorBase* fl_motor = nullptr;
-driver::DjiMotorBase* fr_motor = nullptr;
-driver::DjiMotorBase* bl_motor = nullptr;
-driver::DjiMotorBase* br_motor = nullptr;
-
-control::Chassis* chassis = nullptr;
-remote::SBUS* sbus = nullptr;
-
-void RM_RTOS_Init() {
- HAL_Delay(200);
- print_use_uart(&huart5);
- can = new bsp::CAN(&hcan1, true);
- fl_motor = new driver::Motor3508(can, 0x202);
- fr_motor = new driver::Motor3508(can, 0x201);
- bl_motor = new driver::Motor3508(can, 0x203);
- br_motor = new driver::Motor3508(can, 0x204);
-
- control::ConstrainedPID::PID_Init_t omega_pid_init = {
- .kp = 2500,
- .ki = 3,
- .kd = 0,
- .max_out = 30000,
- .max_iout = 10000,
- .deadband = 0, // 死区
- .A = 3 * PI, // 变速积分所能达到的最大值为A+B
- .B = 2 * PI, // 启动变速积分的死区
- .output_filtering_coefficient = 0.1, // 输出滤波系数
- .derivative_filtering_coefficient = 0, // 微分滤波系数
- .mode = control::ConstrainedPID::Integral_Limit | // 积分限幅
- control::ConstrainedPID::OutputFilter | // 输出滤波
- control::ConstrainedPID::Trapezoid_Intergral | // 梯形积分
- control::ConstrainedPID::ChangingIntegralRate, // 变速积分
- };
-
- fl_motor->ReInitPID(omega_pid_init, driver::DjiMotorBase::OMEGA);
- fl_motor->SetMode(driver::DjiMotorBase::OMEGA);
- fl_motor->SetTransmissionRatio(19);
-
- fr_motor->ReInitPID(omega_pid_init, driver::DjiMotorBase::OMEGA);
- fr_motor->SetMode(driver::DjiMotorBase::OMEGA);
- fr_motor->SetTransmissionRatio(19);
-
- bl_motor->ReInitPID(omega_pid_init, driver::DjiMotorBase::OMEGA);
- bl_motor->SetMode(driver::DjiMotorBase::OMEGA);
- bl_motor->SetTransmissionRatio(19);
-
- br_motor->ReInitPID(omega_pid_init, driver::DjiMotorBase::OMEGA);
- br_motor->SetMode(driver::DjiMotorBase::OMEGA);
- br_motor->SetTransmissionRatio(19);
-
- driver::DjiMotorBase* motors[control::FourWheel::motor_num];
- motors[control::FourWheel::front_left] = fl_motor;
- motors[control::FourWheel::front_right] = fr_motor;
- motors[control::FourWheel::back_left] = bl_motor;
- motors[control::FourWheel::back_right] = br_motor;
-
- control::chassis_t chassis_data;
- chassis_data.motors = motors;
- chassis_data.model = control::CHASSIS_MECANUM_WHEEL;
- chassis = new control::Chassis(chassis_data);
-
- sbus = new remote::SBUS(&huart3);
- HAL_Delay(300);
-}
-
-void RM_RTOS_Default_Task(const void* args) {
- UNUSED(args);
-
- osDelay(500); // DBUS initialization needs time
-
- while (true) {
- const float ratio = 1.0f / 660.0f * 6 * PI;
- chassis->SetSpeed(-sbus->ch1 * ratio, sbus->ch2 * ratio, sbus->ch4 * ratio);
-
- // Kill switch
- if (sbus->ch5 >= 550) {
- RM_ASSERT_TRUE(false, "Operation killed");
- }
-
- chassis->SetPower(false, 30, 20, 60);
- chassis->Update();
- osDelay(10);
- }
-}
diff --git a/examples/DM_MC01_general/dbus/CMakeLists.txt b/examples/DM_MC01_general/dbus/CMakeLists.txt
deleted file mode 100644
index 45816a8d..00000000
--- a/examples/DM_MC01_general/dbus/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-project(example_dbus_${BOARD_NAME} ASM C CXX)
-
-uicrm_add_arm_executable(${PROJECT_NAME}
- TARGET ${BOARD_NAME}
- SOURCES main.cpp)
-
diff --git a/examples/DM_MC01_general/dbus/main.cpp b/examples/DM_MC01_general/dbus/main.cpp
deleted file mode 100644
index 5c98eab9..00000000
--- a/examples/DM_MC01_general/dbus/main.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*###########################################################
- # Copyright (c) 2023-2024. BNU-HKBU UIC RoboMaster #
- # #
- # This program is free software: you can redistribute it #
- # and/or modify it under the terms of the GNU General #
- # Public License as published by the Free Software #
- # Foundation, either version 3 of the License, or (at #
- # your option) any later version. #
- # #
- # This program is distributed in the hope that it will be #
- # useful, but WITHOUT ANY WARRANTY; without even #
- # the implied warranty of MERCHANTABILITY or FITNESS #
- # FOR A PARTICULAR PURPOSE. See the GNU General #
- # Public License for more details. #
- # #
- # You should have received a copy of the GNU General #
- # Public License along with this program. If not, see #
- # . #
- ###########################################################*/
-
-#include "main.h"
-
-#include "bsp_print.h"
-#include "cmsis_os.h"
-#include "dji_dbus.h"
-
-static remote::DBUS* dbus;
-
-void RM_RTOS_Init(void) {
- // print_use_uart(&huart5);
- print_use_usb();
- dbus = new remote::DBUS(&huart3);
-}
-
-void RM_RTOS_Default_Task(const void* arguments) {
- UNUSED(arguments);
-
- // NOTE(alvin): print is split because of stack usage is almost reaching
- // limits
- while (true) {
- set_cursor(0, 0);
- clear_screen();
- print("Online: %s\r\n", (dbus->IsOnline() ? "true" : "false"));
- print(
- "CH0: %-4d CH1: %-4d CH2: %-4d CH3: %-4d \r\nSWL: %d SWR: %d "
- "TWL: %d "
- "@ %d "
- "ms\r\n",
- dbus->ch0,
- dbus->ch1,
- dbus->ch2,
- dbus->ch3,
- dbus->swl,
- dbus->swr,
- dbus->ch4,
- dbus->GetLastUptime()
- );
- print(
- "W: %d A: %d S: %d D: %d\r\n",
- dbus->keyboard.bit.W,
- dbus->keyboard.bit.A,
- dbus->keyboard.bit.S,
- dbus->keyboard.bit.D
- );
- print(
- "Q: %d E: %d R: %d F: %d G: %d\r\n",
- dbus->keyboard.bit.Q,
- dbus->keyboard.bit.E,
- dbus->keyboard.bit.R,
- dbus->keyboard.bit.F,
- dbus->keyboard.bit.G
- );
- print(
- "Z: %d X: %d C: %d V: %d B: %d\r\n",
- dbus->keyboard.bit.Z,
- dbus->keyboard.bit.X,
- dbus->keyboard.bit.C,
- dbus->keyboard.bit.V,
- dbus->keyboard.bit.B
- );
- print("SHIFT: %d CTRL: %d\r\n", dbus->keyboard.bit.SHIFT, dbus->keyboard.bit.CTRL);
- print(
- "Mouse: x: %d y: %d z: %d l: %d r: %d\r\n",
- dbus->mouse.x,
- dbus->mouse.y,
- dbus->mouse.z,
- dbus->mouse.l,
- dbus->mouse.r
- );
-
- osDelay(50);
- }
-}
diff --git a/examples/DM_MC01_general/motor/m2305.cpp b/examples/DM_MC01_general/motor/m2305.cpp
index 226a724c..1337d7e8 100644
--- a/examples/DM_MC01_general/motor/m2305.cpp
+++ b/examples/DM_MC01_general/motor/m2305.cpp
@@ -22,7 +22,7 @@
#include "bsp_gpio.h"
#include "bsp_print.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
#include "utils.h"
@@ -38,10 +38,10 @@
driver::PWMMotorBase* motor1;
driver::PWMMotorBase* motor2;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
void RM_RTOS_Init() {
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
print_use_uart(&huart4);
motor1 =
new driver::PWMMotorBase(&htim8, LEFT_MOTOR_PWM_CHANNEL, TIM_CLOCK_FREQ, MOTOR_OUT_FREQ, SNAIL_IDLE_THROTTLE);
@@ -54,20 +54,25 @@ void RM_RTOS_Init() {
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
bsp::GPIO key(KEY_GPIO_GROUP, KEY_GPIO_PIN);
RampSource ramp_1 = RampSource(0, 0, 450, 0.001);
RampSource ramp_2 = RampSource(0, 0, 450, 0.001);
int current = 0;
int state = 0;
- int8_t last_state = remote::MID;
+ auto last_state = Mid;
while (true) {
- if (dbus->swl == remote::UP) {
- if (last_state == remote::MID)
- last_state = remote::UP;
- } else if (dbus->swl == remote::MID) {
- if (last_state == remote::UP) {
- last_state = remote::MID;
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.left_switch == Up) {
+ if (last_state == Mid)
+ last_state = Up;
+ } else if (dbus_state.left_switch == Mid) {
+ if (last_state == Up) {
+ last_state = Mid;
if (state == 0) {
state = 1;
diff --git a/examples/DM_MC01_general/motor/servo_m2006.cpp b/examples/DM_MC01_general/motor/servo_m2006.cpp
index 750c237f..c45be460 100644
--- a/examples/DM_MC01_general/motor/servo_m2006.cpp
+++ b/examples/DM_MC01_general/motor/servo_m2006.cpp
@@ -23,20 +23,20 @@
#include "bsp_os.h"
#include "bsp_print.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
bsp::CAN* can2 = NULL;
driver::DjiMotorBase* motor1 = NULL;
driver::ServoMotor* load_servo = NULL;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
float load_step_angle = 2 * PI / 8;
void RM_RTOS_Init() {
bsp::SetHighresClockTimer(&htim5);
HAL_Delay(200);
print_use_uart(&huart4);
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
can2 = new bsp::CAN(&hcan2, false);
motor1 = new driver::Motor2006(can2, 0x207);
driver::servo_t servo_data;
@@ -56,17 +56,22 @@ void RM_RTOS_Init() {
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
- int last_state = remote::MID;
+ auto last_state = Mid;
int state = 0;
while (true) {
- if (dbus->swl == remote::UP) {
- if (last_state == remote::MID)
- last_state = remote::UP;
- } else if (dbus->swl == remote::MID) {
- if (last_state == remote::UP) {
- last_state = remote::MID;
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.left_switch == Up) {
+ if (last_state == Mid)
+ last_state = Up;
+ } else if (dbus_state.left_switch == Mid) {
+ if (last_state == Up) {
+ last_state = Mid;
load_servo->SetTarget(load_servo->GetTarget() + load_step_angle);
if (state == 0) {
state = 1;
diff --git a/examples/DM_MC01_general/motor/servo_m3508.cpp b/examples/DM_MC01_general/motor/servo_m3508.cpp
index e251ffcf..f093b318 100644
--- a/examples/DM_MC01_general/motor/servo_m3508.cpp
+++ b/examples/DM_MC01_general/motor/servo_m3508.cpp
@@ -23,20 +23,20 @@
#include "bsp_os.h"
#include "bsp_print.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
bsp::CAN* can1 = NULL;
driver::DjiMotorBase* motor1 = NULL;
driver::ServoMotor* load_servo = NULL;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
float load_step_angle = 2 * PI / 8;
void RM_RTOS_Init() {
bsp::SetHighresClockTimer(&htim5);
HAL_Delay(200);
print_use_uart(&huart4);
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
can1 = new bsp::CAN(&hcan1, true);
motor1 = new driver::Motor2006(can1, 0x201);
@@ -56,17 +56,22 @@ void RM_RTOS_Init() {
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
- int last_state = remote::MID;
+ auto last_state = Mid;
int state = 0;
while (true) {
- if (dbus->swl == remote::UP) {
- if (last_state == remote::MID)
- last_state = remote::UP;
- } else if (dbus->swl == remote::MID) {
- if (last_state == remote::UP) {
- last_state = remote::MID;
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.left_switch == Up) {
+ if (last_state == Mid)
+ last_state = Up;
+ } else if (dbus_state.left_switch == Mid) {
+ if (last_state == Up) {
+ last_state = Mid;
load_servo->SetTarget(load_servo->GetTarget() + load_step_angle);
if (state == 0) {
state = 1;
diff --git a/examples/DM_MC02_general/CMakeLists.txt b/examples/DM_MC02_general/CMakeLists.txt
index 15988480..168051e1 100644
--- a/examples/DM_MC02_general/CMakeLists.txt
+++ b/examples/DM_MC02_general/CMakeLists.txt
@@ -3,7 +3,6 @@ set(BOARD_NAME ${CURRENT_DIR_NAME})
add_subdirectory(BMI088)
add_subdirectory(buzzer)
add_subdirectory(can_bridge)
-add_subdirectory(dbus)
add_subdirectory(led)
add_subdirectory(motor)
add_subdirectory(uart)
diff --git a/examples/DM_MC02_general/can_bridge/host.cpp b/examples/DM_MC02_general/can_bridge/host.cpp
index c5978933..d8b72f07 100644
--- a/examples/DM_MC02_general/can_bridge/host.cpp
+++ b/examples/DM_MC02_general/can_bridge/host.cpp
@@ -24,13 +24,13 @@
#include "bsp_uart.h"
#include "can_bridge.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
static bsp::CAN* can1 = nullptr;
static communication::CanBridge* can_bridge = nullptr;
-static remote::DBUS* dbus = nullptr;
+static controller::DBUS* dbus = nullptr;
void RM_RTOS_Init(void) {
print_use_usb();
@@ -38,18 +38,21 @@ void RM_RTOS_Init(void) {
can1 = new bsp::CAN(&hfdcan1, true, 8);
can_bridge = new communication::CanBridge(can1, 0x02);
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
}
void RM_RTOS_Default_Task(const void* argument) {
UNUSED(argument);
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
communication::can_bridge_data_t data;
- data.data_four_int16.data[0] = dbus->ch0;
- data.data_four_int16.data[1] = dbus->ch1;
- data.data_four_int16.data[2] = dbus->ch2;
- data.data_four_int16.data[3] = dbus->ch3;
+ data.data_four_int16.data[0] = dbus_state.channels[0];
+ data.data_four_int16.data[1] = dbus_state.channels[1];
+ data.data_four_int16.data[2] = dbus_state.channels[2];
+ data.data_four_int16.data[3] = dbus_state.channels[3];
communication::can_bridge_ext_id_t ext_id;
ext_id.data.rx_id = 0x01;
ext_id.data.type = communication::CAN_BRIDGE_TYPE_FOUR_INT16;
diff --git a/examples/DM_MC02_general/dbus/CMakeLists.txt b/examples/DM_MC02_general/dbus/CMakeLists.txt
deleted file mode 100644
index 45816a8d..00000000
--- a/examples/DM_MC02_general/dbus/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-project(example_dbus_${BOARD_NAME} ASM C CXX)
-
-uicrm_add_arm_executable(${PROJECT_NAME}
- TARGET ${BOARD_NAME}
- SOURCES main.cpp)
-
diff --git a/examples/DM_MC02_general/dbus/main.cpp b/examples/DM_MC02_general/dbus/main.cpp
deleted file mode 100644
index 25af5d30..00000000
--- a/examples/DM_MC02_general/dbus/main.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/*###########################################################
- # Copyright (c) 2023-2024. BNU-HKBU UIC RoboMaster #
- # #
- # This program is free software: you can redistribute it #
- # and/or modify it under the terms of the GNU General #
- # Public License as published by the Free Software #
- # Foundation, either version 3 of the License, or (at #
- # your option) any later version. #
- # #
- # This program is distributed in the hope that it will be #
- # useful, but WITHOUT ANY WARRANTY; without even #
- # the implied warranty of MERCHANTABILITY or FITNESS #
- # FOR A PARTICULAR PURPOSE. See the GNU General #
- # Public License for more details. #
- # #
- # You should have received a copy of the GNU General #
- # Public License along with this program. If not, see #
- # . #
- ###########################################################*/
-
-#include "main.h"
-
-#include "bsp_print.h"
-#include "cmsis_os.h"
-#include "dji_dbus.h"
-
-static remote::DBUS* dbus;
-
-void RM_RTOS_Init(void) {
- print_use_uart(&huart1);
- dbus = new remote::DBUS(&huart5);
-}
-
-void RM_RTOS_Default_Task(const void* arguments) {
- UNUSED(arguments);
-
- // NOTE(alvin): print is split because of stack usage is almost reaching
- // limits
- while (true) {
- set_cursor(0, 0);
- clear_screen();
- print(
- "CH0: %-4d CH1: %-4d CH2: %-4d CH3: %-4d \r\nSWL: %d SWR: %d "
- "TWL: %d "
- "@ %d "
- "ms\r\n",
- dbus->ch0,
- dbus->ch1,
- dbus->ch2,
- dbus->ch3,
- dbus->swl,
- dbus->swr,
- dbus->ch4,
- dbus->GetLastUptime()
- );
- print(
- "W: %d A: %d S: %d D: %d\r\n",
- dbus->keyboard.bit.W,
- dbus->keyboard.bit.A,
- dbus->keyboard.bit.S,
- dbus->keyboard.bit.D
- );
- print(
- "Q: %d E: %d R: %d F: %d G: %d\r\n",
- dbus->keyboard.bit.Q,
- dbus->keyboard.bit.E,
- dbus->keyboard.bit.R,
- dbus->keyboard.bit.F,
- dbus->keyboard.bit.G
- );
- print(
- "Z: %d X: %d C: %d V: %d B: %d\r\n",
- dbus->keyboard.bit.Z,
- dbus->keyboard.bit.X,
- dbus->keyboard.bit.C,
- dbus->keyboard.bit.V,
- dbus->keyboard.bit.B
- );
- print("SHIFT: %d CTRL: %d\r\n", dbus->keyboard.bit.SHIFT, dbus->keyboard.bit.CTRL);
- print(
- "Mouse: x: %d y: %d z: %d l: %d r: %d\r\n",
- dbus->mouse.x,
- dbus->mouse.y,
- dbus->mouse.z,
- dbus->mouse.l,
- dbus->mouse.r
- );
-
- osDelay(50);
- }
-}
diff --git a/examples/DM_MC02_general/motor/m2305.cpp b/examples/DM_MC02_general/motor/m2305.cpp
index 415b235e..99446d1c 100644
--- a/examples/DM_MC02_general/motor/m2305.cpp
+++ b/examples/DM_MC02_general/motor/m2305.cpp
@@ -22,7 +22,7 @@
#include "bsp_gpio.h"
#include "bsp_print.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
#include "utils.h"
@@ -38,10 +38,10 @@
driver::PWMMotorBase* motor1;
driver::PWMMotorBase* motor2;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
void RM_RTOS_Init() {
- dbus = new remote::DBUS(&huart5);
+ dbus = new controller::DBUS(&huart5);
print_use_uart(&huart1);
motor1 =
new driver::PWMMotorBase(&htim1, LEFT_MOTOR_PWM_CHANNEL, TIM_CLOCK_FREQ, MOTOR_OUT_FREQ, SNAIL_IDLE_THROTTLE);
@@ -54,20 +54,25 @@ void RM_RTOS_Init() {
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
bsp::GPIO key(KEY_GPIO_GROUP, KEY_GPIO_PIN);
RampSource ramp_1 = RampSource(0, 0, 450, 0.001);
RampSource ramp_2 = RampSource(0, 0, 450, 0.001);
int current = 0;
int state = 0;
- int8_t last_state = remote::MID;
+ auto last_state = Mid;
while (true) {
- if (dbus->swl == remote::UP) {
- if (last_state == remote::MID)
- last_state = remote::UP;
- } else if (dbus->swl == remote::MID) {
- if (last_state == remote::UP) {
- last_state = remote::MID;
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.left_switch == Up) {
+ if (last_state == Mid)
+ last_state = Up;
+ } else if (dbus_state.left_switch == Mid) {
+ if (last_state == Up) {
+ last_state = Mid;
if (state == 0) {
state = 1;
diff --git a/examples/DM_MC02_general/motor/servo_m2006.cpp b/examples/DM_MC02_general/motor/servo_m2006.cpp
index d1471ceb..eaba062b 100644
--- a/examples/DM_MC02_general/motor/servo_m2006.cpp
+++ b/examples/DM_MC02_general/motor/servo_m2006.cpp
@@ -23,20 +23,20 @@
#include "bsp_os.h"
#include "bsp_print.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
bsp::CAN* can2 = NULL;
driver::DjiMotorBase* motor1 = NULL;
driver::ServoMotor* load_servo = NULL;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
float load_step_angle = 2 * PI / 8;
void RM_RTOS_Init() {
bsp::SetHighresClockTimer(&htim24);
HAL_Delay(200);
print_use_uart(&huart1);
- dbus = new remote::DBUS(&huart5);
+ dbus = new controller::DBUS(&huart5);
can2 = new bsp::CAN(&hfdcan2, false);
motor1 = new driver::Motor2006(can2, 0x207);
driver::servo_t servo_data;
@@ -56,17 +56,22 @@ void RM_RTOS_Init() {
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
- int last_state = remote::MID;
+ auto last_state = Mid;
int state = 0;
while (true) {
- if (dbus->swl == remote::UP) {
- if (last_state == remote::MID)
- last_state = remote::UP;
- } else if (dbus->swl == remote::MID) {
- if (last_state == remote::UP) {
- last_state = remote::MID;
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.left_switch == Up) {
+ if (last_state == Mid)
+ last_state = Up;
+ } else if (dbus_state.left_switch == Mid) {
+ if (last_state == Up) {
+ last_state = Mid;
load_servo->SetTarget(load_servo->GetTarget() + load_step_angle);
if (state == 0) {
state = 1;
diff --git a/examples/DM_MC02_general/motor/servo_m3508.cpp b/examples/DM_MC02_general/motor/servo_m3508.cpp
index 41d2b98c..10057095 100644
--- a/examples/DM_MC02_general/motor/servo_m3508.cpp
+++ b/examples/DM_MC02_general/motor/servo_m3508.cpp
@@ -23,20 +23,20 @@
#include "bsp_os.h"
#include "bsp_print.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
bsp::CAN* can1 = NULL;
driver::DjiMotorBase* motor1 = NULL;
driver::ServoMotor* load_servo = NULL;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
float load_step_angle = 2 * PI / 8;
void RM_RTOS_Init() {
bsp::SetHighresClockTimer(&htim24);
HAL_Delay(200);
print_use_uart(&huart1);
- dbus = new remote::DBUS(&huart5);
+ dbus = new controller::DBUS(&huart5);
can1 = new bsp::CAN(&hfdcan1, true);
motor1 = new driver::Motor2006(can1, 0x201);
@@ -56,17 +56,22 @@ void RM_RTOS_Init() {
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
- int last_state = remote::MID;
+ auto last_state = Mid;
int state = 0;
while (true) {
- if (dbus->swl == remote::UP) {
- if (last_state == remote::MID)
- last_state = remote::UP;
- } else if (dbus->swl == remote::MID) {
- if (last_state == remote::UP) {
- last_state = remote::MID;
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.left_switch == Up) {
+ if (last_state == Mid)
+ last_state = Up;
+ } else if (dbus_state.left_switch == Mid) {
+ if (last_state == Up) {
+ last_state = Mid;
load_servo->SetTarget(load_servo->GetTarget() + load_step_angle);
if (state == 0) {
state = 1;
diff --git a/examples/F103_Nano_general/motor/m2305.cpp b/examples/F103_Nano_general/motor/m2305.cpp
index 0d0bcec2..268303ab 100644
--- a/examples/F103_Nano_general/motor/m2305.cpp
+++ b/examples/F103_Nano_general/motor/m2305.cpp
@@ -22,7 +22,7 @@
#include "bsp_gpio.h"
#include "bsp_print.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
#include "utils.h"
@@ -38,10 +38,10 @@
driver::PWMMotorBase* motor1;
driver::PWMMotorBase* motor2;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
void RM_RTOS_Init() {
- dbus = new remote::DBUS(&huart2);
+ dbus = new controller::DBUS(&huart2);
print_use_uart(&huart1);
motor1 =
new driver::PWMMotorBase(&htim1, LEFT_MOTOR_PWM_CHANNEL, TIM_CLOCK_FREQ, MOTOR_OUT_FREQ, SNAIL_IDLE_THROTTLE);
@@ -54,20 +54,25 @@ void RM_RTOS_Init() {
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
bsp::GPIO key(KEY_GPIO_GROUP, KEY_GPIO_PIN);
RampSource ramp_1 = RampSource(0, 0, 450, 0.001);
RampSource ramp_2 = RampSource(0, 0, 450, 0.001);
int current = 0;
int state = 0;
- int8_t last_state = remote::MID;
+ auto last_state = Mid;
while (true) {
- if (dbus->swl == remote::UP) {
- if (last_state == remote::MID)
- last_state = remote::UP;
- } else if (dbus->swl == remote::MID) {
- if (last_state == remote::UP) {
- last_state = remote::MID;
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.left_switch == Up) {
+ if (last_state == Mid)
+ last_state = Up;
+ } else if (dbus_state.left_switch == Mid) {
+ if (last_state == Up) {
+ last_state = Mid;
if (state == 0) {
state = 1;
diff --git a/examples/F103_Nano_general/motor/servo_m2006.cpp b/examples/F103_Nano_general/motor/servo_m2006.cpp
index ea632c09..0a40d9e6 100644
--- a/examples/F103_Nano_general/motor/servo_m2006.cpp
+++ b/examples/F103_Nano_general/motor/servo_m2006.cpp
@@ -23,20 +23,20 @@
#include "bsp_os.h"
#include "bsp_print.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
bsp::CAN* can2 = NULL;
driver::DjiMotorBase* motor1 = NULL;
driver::ServoMotor* load_servo = NULL;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
float load_step_angle = 2 * PI / 8;
void RM_RTOS_Init() {
bsp::SetHighresClockTimer(&htim1);
HAL_Delay(200);
print_use_uart(&huart1);
- dbus = new remote::DBUS(&huart2);
+ dbus = new controller::DBUS(&huart2);
can2 = new bsp::CAN(&hcan1, true);
motor1 = new driver::Motor2006(can2, 0x201);
driver::servo_t servo_data;
@@ -56,27 +56,32 @@ void RM_RTOS_Init() {
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
- int last_state = remote::MID;
+ auto last_state = Mid;
while (true) {
- if (last_state != dbus->swl && dbus->swl == remote::MID) {
- if (last_state == remote::UP) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (last_state != dbus_state.left_switch && dbus_state.left_switch == Mid) {
+ if (last_state == Up) {
load_servo->SetTarget(load_servo->GetTarget() + load_step_angle);
- } else if (last_state == remote::DOWN) {
+ } else if (last_state == Down) {
load_servo->SetTarget(load_servo->GetTarget() - load_step_angle);
}
} else {
- if (dbus->ch3 > 0) {
+ if (dbus_state.channels[3] > 0) {
load_servo->SetTarget(load_servo->GetTarget() + load_step_angle);
- } else if (dbus->ch3 < 0) {
+ } else if (dbus_state.channels[3] < 0) {
load_servo->SetTarget(load_servo->GetTarget() - load_step_angle);
}
}
load_servo->CalcOutput();
- last_state = dbus->swl;
+ last_state = dbus_state.left_switch;
osDelay(1);
}
}
diff --git a/examples/F103_Nano_general/motor/servo_m3508.cpp b/examples/F103_Nano_general/motor/servo_m3508.cpp
index 51dfcb21..ef7ac9f5 100644
--- a/examples/F103_Nano_general/motor/servo_m3508.cpp
+++ b/examples/F103_Nano_general/motor/servo_m3508.cpp
@@ -23,20 +23,20 @@
#include "bsp_os.h"
#include "bsp_print.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
bsp::CAN* can1 = NULL;
driver::DjiMotorBase* motor1 = NULL;
driver::ServoMotor* load_servo = NULL;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
float load_step_angle = 2 * PI / 8;
void RM_RTOS_Init() {
bsp::SetHighresClockTimer(&htim1);
HAL_Delay(200);
print_use_uart(&huart1);
- dbus = new remote::DBUS(&huart2);
+ dbus = new controller::DBUS(&huart2);
can1 = new bsp::CAN(&hcan1, true);
motor1 = new driver::Motor2006(can1, 0x201);
@@ -56,17 +56,22 @@ void RM_RTOS_Init() {
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
- int last_state = remote::MID;
+ auto last_state = Mid;
int state = 0;
while (true) {
- if (dbus->swl == remote::UP) {
- if (last_state == remote::MID)
- last_state = remote::UP;
- } else if (dbus->swl == remote::MID) {
- if (last_state == remote::UP) {
- last_state = remote::MID;
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
+ if (dbus_state.left_switch == Up) {
+ if (last_state == Mid)
+ last_state = Up;
+ } else if (dbus_state.left_switch == Mid) {
+ if (last_state == Up) {
+ last_state = Mid;
load_servo->SetTarget(load_servo->GetTarget() + load_step_angle);
if (state == 0) {
state = 1;
diff --git "a/examples/Host/Automata/[Automata]\347\273\204\344\273\266\347\224\250\346\210\267\346\211\213\345\206\214.md" "b/examples/Host/Automata/[Automata]\347\273\204\344\273\266\347\224\250\346\210\267\346\211\213\345\206\214.md"
index 4988feb7..0533e343 100644
--- "a/examples/Host/Automata/[Automata]\347\273\204\344\273\266\347\224\250\346\210\267\346\211\213\345\206\214.md"
+++ "b/examples/Host/Automata/[Automata]\347\273\204\344\273\266\347\224\250\346\210\267\346\211\213\345\206\214.md"
@@ -146,8 +146,10 @@ auto aut = control::AutomataBuilder()
```cpp
// 射击(供弹轮)
+controller::DbusFrame dbus_state{};
+dbus->GetState(dbus_state);
auto shoot_builder_with_items = control::AutomataBuilder()
- .item(dbus->swl)
+ .item(dbus_state.left_switch)
.item(SHOOT_FRIC_MODE_STOP)
.item(is_referee_shoot_available)
.item(bool{}); // shoot_key
@@ -157,7 +159,7 @@ auto tranlogic_shooting_condition = TRANLOGIC {
const auto& fric_state = COMPONENT(1);
const auto& referee_permit = COMPONENT(2);
const auto& shoot_key = COMPONENT(3);
- return (swl.get() == remote::DOWN || shoot_key.get()) &&
+ return (swl.get() == controller::ThreePositionSwitch::Down || shoot_key.get()) &&
fric_state.get() == SHOOT_FRIC_MODE_PREPARED &&
referee_permit.get();
};
diff --git a/programs/Ares/chassis/src/chassis_example.cpp b/programs/Ares/chassis/src/chassis_example.cpp
index 30cd208d..65f8454a 100644
--- a/programs/Ares/chassis/src/chassis_example.cpp
+++ b/programs/Ares/chassis/src/chassis_example.cpp
@@ -21,7 +21,7 @@
#include "bsp_print.h"
#include "chassis.h"
#include "cmsis_os.h"
-#include "dji_dbus.h"
+#include "dbus.h"
bsp::CAN* can = nullptr;
driver::DjiMotorBase* fl_motor = nullptr;
@@ -30,7 +30,7 @@ driver::DjiMotorBase* bl_motor = nullptr;
driver::DjiMotorBase* br_motor = nullptr;
control::Chassis* chassis = nullptr;
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
void RM_RTOS_Init() {
HAL_Delay(200);
@@ -89,21 +89,27 @@ void RM_RTOS_Init() {
chassis_data.model = control::CHASSIS_MECANUM_WHEEL;
chassis = new control::Chassis(chassis_data);
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
HAL_Delay(300);
}
void RM_RTOS_Default_Task(const void* args) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(args);
osDelay(500); // DBUS initialization needs time
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
const float ratio = 1.0f / 660.0f * 6 * PI;
- chassis->SetSpeed(dbus->ch0 * ratio, dbus->ch1 * ratio, dbus->ch2 * ratio);
+ chassis
+ ->SetSpeed(dbus_state.channels[0] * ratio, dbus_state.channels[1] * ratio, dbus_state.channels[2] * ratio);
// Kill switch
- if (dbus->swl == remote::UP || dbus->swl == remote::DOWN) {
+ if (dbus_state.left_switch == Up || dbus_state.left_switch == Down) {
RM_ASSERT_TRUE(false, "Operation killed");
}
chassis->SetPower(false, 30, 20, 60);
diff --git a/programs/Ares/gimbal/include/referee_task.h b/programs/Ares/gimbal/include/referee_task.h
index 0446d82f..bb008599 100644
--- a/programs/Ares/gimbal/include/referee_task.h
+++ b/programs/Ares/gimbal/include/referee_task.h
@@ -22,7 +22,7 @@
#include "bsp_print.h"
#include "bsp_uart.h"
#include "cmsis_os2.h"
-#include "dji_dbus.h"
+#include "refereerc.h"
#include "main.h"
#include "protocol.h"
@@ -30,7 +30,6 @@
extern bsp::UART* referee_uart;
extern communication::Referee* referee;
-extern bsp::UART* refereerc_uart;
-extern communication::Referee* refereerc;
+extern controller::RefereeRC* refereerc;
void init_referee();
\ No newline at end of file
diff --git a/programs/Ares/gimbal/include/remote_task.h b/programs/Ares/gimbal/include/remote_task.h
index 61c0a8c6..99e17f17 100644
--- a/programs/Ares/gimbal/include/remote_task.h
+++ b/programs/Ares/gimbal/include/remote_task.h
@@ -20,12 +20,12 @@
#pragma once
#include "cmsis_os2.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
#include "referee_task.h"
#include "user_define.h"
#include "utils.h"
-extern remote::DBUS* dbus;
+extern controller::DBUS* dbus;
extern bool turbo_shoot;
/**
* @brief Dbus Init
diff --git a/programs/Ares/gimbal/src/chassis_task.cpp b/programs/Ares/gimbal/src/chassis_task.cpp
index bc9a67fc..ef889708 100644
--- a/programs/Ares/gimbal/src/chassis_task.cpp
+++ b/programs/Ares/gimbal/src/chassis_task.cpp
@@ -51,6 +51,13 @@ void chassisTask(void* arg) {
chassis->Enable();
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
if (remote_mode == REMOTE_MODE_KILL) {
kill_chassis();
while (remote_mode == REMOTE_MODE_KILL) {
@@ -60,14 +67,14 @@ void chassisTask(void* arg) {
continue;
}
- const bool vt13_c_mode = (refereerc != nullptr) && refereerc->IsOnline() &&
- (refereerc->vt13_packet.remote.mode_sw == remote::vt13_remote_t::MODE_C);
+ const bool vt13_c_mode =
+ (refereerc != nullptr) && refereerc->IsOnline() && (refereerc_state.mode == controller::RefereeRcMode::C);
- remote::keyboard_t keyboard{};
+ controller::KeyboardState keyboard{};
if (dbus->IsOnline()) {
- keyboard = dbus->keyboard;
+ keyboard = dbus_state.keyboard;
} else if (vt13_c_mode) {
- keyboard = refereerc->vt13_packet.keyboard;
+ keyboard = refereerc_state.keyboard;
}
// 以云台为基准的(整车的)运动速度,范围为[-1, 1]
@@ -80,26 +87,21 @@ void chassisTask(void* arg) {
// car_vy = 0;
// car_vt = 0;
// } else
- if (dbus->IsOnline() && (abs(dbus->ch0) > dbus_rocker_deadband || abs(dbus->ch1) > dbus_rocker_deadband ||
- abs(dbus->ch4) > dbus_rocker_deadband)) {
+ if (dbus->IsOnline() &&
+ (abs(dbus_state.channels[0]) > dbus_rocker_deadband || abs(dbus_state.channels[1]) > dbus_rocker_deadband ||
+ abs(dbus_state.channels[4]) > dbus_rocker_deadband)) {
// 优先使用遥控器
const float speed_scale = 0.5;
- car_vx = (float)dbus->ch0 / dbus->ROCKER_MAX * speed_scale;
- car_vy = (float)dbus->ch1 / dbus->ROCKER_MAX * speed_scale;
- car_vt = (float)dbus->ch4 / dbus->ROCKER_MAX * speed_scale;
- } else if (vt13_c_mode && (abs((int)refereerc->vt13_packet.remote.ch0 - remote::vt13_remote_t::ROCKER_MID) >
- vt13_rocker_deadband ||
- abs((int)refereerc->vt13_packet.remote.ch1 - remote::vt13_remote_t::ROCKER_MID) >
- vt13_rocker_deadband ||
- abs((int)refereerc->vt13_packet.remote.ch4 - remote::vt13_remote_t::ROCKER_MID) >
- vt13_rocker_deadband)) {
+ car_vx = (float)dbus_state.channels[0] / 660.0f * speed_scale;
+ car_vy = (float)dbus_state.channels[1] / 660.0f * speed_scale;
+ car_vt = (float)dbus_state.channels[4] / 660.0f * speed_scale;
+ } else if (vt13_c_mode && (abs((int)refereerc_state.channels[0]) > vt13_rocker_deadband ||
+ abs((int)refereerc_state.channels[1]) > vt13_rocker_deadband ||
+ abs((int)refereerc_state.channels[4]) > vt13_rocker_deadband)) {
const float speed_scale = 0.5;
- car_vx = (float)((int)refereerc->vt13_packet.remote.ch0 - remote::vt13_remote_t::ROCKER_MID) /
- remote::vt13_remote_t::ROCKER_RANGE * speed_scale;
- car_vy = (float)((int)refereerc->vt13_packet.remote.ch1 - remote::vt13_remote_t::ROCKER_MID) /
- remote::vt13_remote_t::ROCKER_RANGE * speed_scale;
- car_vt = (float)((int)refereerc->vt13_packet.remote.ch4 - remote::vt13_remote_t::ROCKER_MID) /
- remote::vt13_remote_t::ROCKER_RANGE * speed_scale;
+ car_vx = (float)((int)refereerc_state.channels[0]) / 660.0f * speed_scale;
+ car_vy = (float)((int)refereerc_state.channels[1]) / 660.0f * speed_scale;
+ car_vt = (float)((int)refereerc_state.channels[4]) / 660.0f * speed_scale;
} else {
// 使用键盘
const float keyboard_speed = keyboard.bit.SHIFT ? 1 : 0.5;
diff --git a/programs/Ares/gimbal/src/gimbal_task.cpp b/programs/Ares/gimbal/src/gimbal_task.cpp
index 522e5810..c5c4651c 100644
--- a/programs/Ares/gimbal/src/gimbal_task.cpp
+++ b/programs/Ares/gimbal/src/gimbal_task.cpp
@@ -18,7 +18,7 @@
#include "gimbal_task.h"
#include "chassis_task.h"
-#include "dji_remote.h"
+#include "dbus.h"
// #include "minipc_task.h"
osThreadId_t gimbalTaskHandle;
@@ -77,6 +77,13 @@ void gimbalTask(void* arg) {
// float pitch_target, yaw_target;
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
// 如果遥控器处于关闭状态,关闭两个电机
check_kill();
@@ -85,7 +92,7 @@ void gimbalTask(void* arg) {
yaw_curr = imu->INS_angle[0];
// pitch_curr = witimu->INS_angle[0];
// yaw_curr = wrap(witimu->INS_angle[2]-yaw_offset, -PI, PI);
- // if (dbus->swr == remote::UP) {
+ // if (dbus_state.right_switch == controller::ThreePositionSwitch::Up) {
// gimbal->TargetAbs(0, 0);
// gimbal->Update();
// pitch_target = pitch_curr;
@@ -98,28 +105,25 @@ void gimbalTask(void* arg) {
const float mouse_ratio = 0.5;
const float remote_ratio = 0.005;
- const bool vt13_c_mode = (refereerc != nullptr) && refereerc->IsOnline() &&
- (refereerc->vt13_packet.remote.mode_sw == remote::vt13_remote_t::MODE_C);
+ const bool vt13_c_mode =
+ (refereerc != nullptr) && refereerc->IsOnline() && (refereerc_state.mode == controller::RefereeRcMode::C);
if (dbus->IsOnline()) {
- if (dbus->mouse.x != 0 || dbus->mouse.y != 0) {
- pitch_ratio = (float)dbus->mouse.y / mouse_xy_max * mouse_ratio;
- yaw_ratio = (float)dbus->mouse.x / mouse_xy_max * mouse_ratio;
+ if (dbus_state.mouse.x != 0 || dbus_state.mouse.y != 0) {
+ pitch_ratio = (float)dbus_state.mouse.y / 32767.0 * mouse_ratio;
+ yaw_ratio = (float)dbus_state.mouse.x / 32767.0 * mouse_ratio;
} else {
- pitch_ratio = (float)dbus->ch3 / dbus->ROCKER_MAX * remote_ratio;
- yaw_ratio = (float)dbus->ch2 / dbus->ROCKER_MAX * remote_ratio;
+ pitch_ratio = (float)dbus_state.channels[3] / 660.0f * remote_ratio;
+ yaw_ratio = (float)dbus_state.channels[2] / 660.0f * remote_ratio;
}
} else if (vt13_c_mode) {
// DBUS离线时使用VT13:优先摇杆,否则鼠标
- if (refereerc->vt13_packet.remote.ch3 != remote::vt13_remote_t::ROCKER_MID ||
- refereerc->vt13_packet.remote.ch2 != remote::vt13_remote_t::ROCKER_MID) {
- pitch_ratio = (float)(refereerc->vt13_packet.remote.ch2 - remote::vt13_remote_t::ROCKER_MID) /
- remote::vt13_remote_t::ROCKER_RANGE / 18000.0 * 660.0 / 7.0;
- yaw_ratio = (float)(refereerc->vt13_packet.remote.ch3 - remote::vt13_remote_t::ROCKER_MID) /
- remote::vt13_remote_t::ROCKER_RANGE / 18000.0 * 660.0 / 7.0;
+ if (refereerc_state.channels[3] != 0 || refereerc_state.channels[2] != 0) {
+ pitch_ratio = (float)(refereerc_state.channels[2]) / 660.0f / 18000.0 * 660.0 / 7.0;
+ yaw_ratio = (float)(refereerc_state.channels[3]) / 660.0f / 18000.0 * 660.0 / 7.0;
} else {
- pitch_ratio = -refereerc->vt13_packet.mouse.y / 32767.0 * 7.5 / 7.0;
- yaw_ratio = refereerc->vt13_packet.mouse.x / 32767.0 * 7.5 / 7.0;
+ pitch_ratio = -refereerc_state.mouse.y / 32767.0 * 7.5 / 7.0;
+ yaw_ratio = refereerc_state.mouse.x / 32767.0 * 7.5 / 7.0;
}
} else {
pitch_ratio = 0;
diff --git a/programs/Ares/gimbal/src/main.cpp b/programs/Ares/gimbal/src/main.cpp
index ea4f0205..baf92a99 100644
--- a/programs/Ares/gimbal/src/main.cpp
+++ b/programs/Ares/gimbal/src/main.cpp
@@ -76,6 +76,11 @@ void RM_RTOS_Default_Task(const void* arg) {
// }
char s[50];
while (true) {
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
set_cursor(0, 0);
clear_screen();
switch (remote_mode) {
@@ -143,7 +148,7 @@ void RM_RTOS_Default_Task(const void* arg) {
// }
print("[UI] ");
- if (refereerc->vt13_packet.keyboard.bit.V) {
+ if (refereerc_state.keyboard.bit.V) {
print("UI refresh success");
}
print("\n");
@@ -164,20 +169,23 @@ void RM_RTOS_Default_Task(const void* arg) {
print(
"VT13 [CH0: %-4d] [CH1: %-4d] [CH2: %-4d] [CH3: %-4d] [CH4: %-4d] [Mode: %d] [SWL: %d] "
"[SWR: %d] [Trig: %d]\r\n",
- refereerc->vt13_packet.remote.ch0,
- refereerc->vt13_packet.remote.ch1,
- refereerc->vt13_packet.remote.ch2,
- refereerc->vt13_packet.remote.ch3,
- refereerc->vt13_packet.remote.ch4,
- refereerc->vt13_packet.remote.mode_sw,
- refereerc->vt13_packet.remote.swl,
- refereerc->vt13_packet.remote.swr,
- refereerc->vt13_packet.remote.trigger
+ refereerc_state.channels[0],
+ refereerc_state.channels[1],
+ refereerc_state.channels[2],
+ refereerc_state.channels[3],
+ refereerc_state.channels[4],
+ static_cast(refereerc_state.mode),
+ refereerc_state.left_button,
+ refereerc_state.right_button,
+ refereerc_state.trigger
);
print("\r\n");
print("[Referee %s] ", referee->IsOnline() ? "\033[32mOnline\033[0m" : "\033[31mOffline\033[0m");
print("\r\n");
- print("[Referee RC %s] ", refereerc->IsOnline() ? "\033[32mOnline\033[0m" : "\033[31mOffline\033[0m");
+ print(
+ "[Referee RC %s] ",
+ (refereerc != nullptr && refereerc->IsOnline()) ? "\033[32mOnline\033[0m" : "\033[31mOffline\033[0m"
+ );
print("\r\n");
// Gimbal info
diff --git a/programs/Ares/gimbal/src/referee_task.cpp b/programs/Ares/gimbal/src/referee_task.cpp
index 8f947c39..a44a83e7 100644
--- a/programs/Ares/gimbal/src/referee_task.cpp
+++ b/programs/Ares/gimbal/src/referee_task.cpp
@@ -21,9 +21,8 @@
#include "referee_task.h"
bsp::UART* referee_uart = nullptr;
-bsp::UART* refereerc_uart = nullptr;
communication::Referee* referee = nullptr;
-communication::Referee* refereerc = nullptr;
+controller::RefereeRC* refereerc = nullptr;
void init_referee() {
referee_uart = new bsp::UART(&huart6);
@@ -31,9 +30,5 @@ void init_referee() {
referee_uart->SetupTx(300);
referee = new communication::Referee(referee_uart);
- refereerc_uart = new bsp::UART(&huart1);
- refereerc_uart->SetBaudrate(921600);
- refereerc_uart->SetupRx(300);
- refereerc_uart->SetupTx(300, false);
- refereerc = new communication::Referee(refereerc_uart);
+ refereerc = new controller::RefereeRC(&huart1);
}
diff --git a/programs/Ares/gimbal/src/remote_task.cpp b/programs/Ares/gimbal/src/remote_task.cpp
index 710534a6..7960076c 100644
--- a/programs/Ares/gimbal/src/remote_task.cpp
+++ b/programs/Ares/gimbal/src/remote_task.cpp
@@ -24,7 +24,7 @@
#include "imu_task.h"
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
RemoteMode remote_mode = REMOTE_MODE_FOLLOW;
RemoteMode last_remote_mode = REMOTE_MODE_FOLLOW;
RemoteMode available_remote_mode[] = {REMOTE_MODE_FOLLOW, REMOTE_MODE_SPIN, REMOTE_MODE_ADVANCED};
@@ -41,13 +41,15 @@ bool turbo_shoot = false;
// dbus
void init_dbus() {
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
}
osThreadId_t remoteTaskHandle;
// main loop
void remoteTask(void* arg) {
+ using enum controller::ThreePositionSwitch;
+
// 接口转换
UNUSED(arg);
osDelay(1000);
@@ -60,20 +62,16 @@ void remoteTask(void* arg) {
bool shoot_stop_switch = false;
// uint32_t shoot_burst_timestamp = 0;
- remote::switch_t last_state_r = remote::MID;
- remote::switch_t last_state_l = remote::MID;
- remote::keyboard_t last_keyboard;
- remote::mouse_t last_mouse;
- remote::switch_t state_r = remote::MID;
- remote::switch_t state_l = remote::MID;
- remote::keyboard_t keyboard;
- remote::mouse_t mouse;
+ controller::ThreePositionSwitch last_state_r = Mid;
+ controller::ThreePositionSwitch last_state_l = Mid;
+ controller::KeyboardState last_keyboard{};
+ controller::MouseState last_mouse{};
+ controller::ThreePositionSwitch state_r = Mid;
+ controller::ThreePositionSwitch state_l = Mid;
+ controller::KeyboardState keyboard{};
+ controller::MouseState mouse{};
// 键鼠状态清零
- memset(&keyboard, 0, sizeof(keyboard));
- memset(&mouse, 0, sizeof(mouse));
- memset(&last_keyboard, 0, sizeof(last_keyboard));
- memset(&last_mouse, 0, sizeof(last_mouse));
//
bool is_dbus_offline;
@@ -93,11 +91,18 @@ void remoteTask(void* arg) {
BoolEdgeDetector* vt13_trigger_edge = new BoolEdgeDetector(false);
while (1) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
const bool vt13_c_mode =
- refereerc->IsOnline() && (refereerc->vt13_packet.remote.mode_sw == remote::vt13_remote_t::MODE_C);
+ (refereerc != nullptr && refereerc->IsOnline()) && (refereerc_state.mode == controller::RefereeRcMode::C);
// Offline Detection && Security Check
- is_dbus_offline = (!dbus->IsOnline()) || dbus->swr == remote::DOWN;
+ is_dbus_offline = (!dbus->IsOnline()) || dbus_state.right_switch == Down;
// VT13必须在线且处于C模式才算可控
is_vt13_offline = !vt13_c_mode;
#ifdef HAS_REFEREE
@@ -137,30 +142,30 @@ void remoteTask(void* arg) {
last_state_l = state_l;
last_keyboard = keyboard;
last_mouse = mouse;
- state_r = remote::MID;
- state_l = remote::MID;
- memset(&keyboard, 0, sizeof(keyboard));
- memset(&mouse, 0, sizeof(mouse));
+ state_r = Mid;
+ state_l = Mid;
+ keyboard = {};
+ mouse = {};
// Update State
if (dbus->IsOnline()) { // DBUS
- state_r = dbus->swr;
- state_l = dbus->swl;
- keyboard = dbus->keyboard;
- mouse = dbus->mouse;
+ state_r = dbus_state.right_switch;
+ state_l = dbus_state.left_switch;
+ keyboard = dbus_state.keyboard;
+ mouse = dbus_state.mouse;
} else if (vt13_c_mode) {
// referee control use keyboard & mouse
- state_r = remote::MID;
- state_l = remote::MID;
- keyboard = refereerc->vt13_packet.keyboard;
- mouse = (remote::mouse_t)refereerc->vt13_packet.mouse;
+ state_r = Mid;
+ state_l = Mid;
+ keyboard = refereerc_state.keyboard;
+ mouse = refereerc_state.mouse;
}
// Update Timestamp
z_edge->input(keyboard.bit.Z);
shift_edge->input(keyboard.bit.SHIFT);
- mouse_left_edge->input(mouse.l);
- mouse_right_edge->input(mouse.r);
+ mouse_left_edge->input(mouse.left);
+ mouse_right_edge->input(mouse.right);
shoot_burst_edge->input(keyboard.bit.F);
@@ -169,25 +174,25 @@ void remoteTask(void* arg) {
}
// VT13 边沿检测(仅在VT13可控时有效,避免离线脏数据触发)
- vt13_pause_edge->input(vt13_c_mode && refereerc->vt13_packet.remote.pause);
- vt13_left_edge->input(vt13_c_mode && refereerc->vt13_packet.remote.swl);
- vt13_trigger_edge->input(vt13_c_mode && refereerc->vt13_packet.remote.trigger);
+ vt13_pause_edge->input(vt13_c_mode && refereerc_state.pause);
+ vt13_left_edge->input(vt13_c_mode && refereerc_state.left_button);
+ vt13_trigger_edge->input(vt13_c_mode && refereerc_state.trigger);
// ========== 模式切换 ==========
// DT7 右摇杆上拨
switch (state_r) {
- case remote::UP:
- if (last_state_r == remote::MID && dbus->IsOnline()) {
+ case Up:
+ if (last_state_r == Mid && dbus->IsOnline()) {
mode_switch = true;
}
break;
- case remote::MID:
+ case Mid:
// 键盘 SHIFT 切换模式
if (shift_edge->posEdge()) {
mode_switch = true;
}
break;
- case remote::DOWN:
+ case Down:
break;
}
// VT13 暂停键切换模式
@@ -205,31 +210,31 @@ void remoteTask(void* arg) {
// shoot mode switch
switch (state_l) {
- case remote::UP:
- if (last_state_l == remote::MID && dbus->IsOnline()) {
+ case Up:
+ if (last_state_l == Mid && dbus->IsOnline()) {
shoot_fric_switch = true;
}
break;
- case remote::DOWN:
- if (last_state_l == remote::MID && dbus->IsOnline()) {
+ case Down:
+ if (last_state_l == Mid && dbus->IsOnline()) {
shoot_switch = true;
// shoot_burst_timestamp = 0;
}
- // else if (last_state_l == remote::DOWN && selftest.dbus) {
+ // else if (last_state_l == Down && selftest.dbus) {
// shoot_burst_timestamp++;
// if (shoot_burst_timestamp > 500 * REMOTE_OS_DELAY) {
// shoot_burst_switch = true;
// }
// }
break;
- case remote::MID:
+ case Mid:
switch (last_state_l) {
- case remote::DOWN:
+ case Down:
shoot_stop_switch = true;
break;
- case remote::UP:
+ case Up:
break;
- case remote::MID:
+ case Mid:
// 键盘 Z键 切换摩擦轮
if (z_edge->posEdge()) {
shoot_fric_switch = true;
@@ -281,12 +286,12 @@ void remoteTask(void* arg) {
}
if (shoot_flywheel_mode == SHOOT_FRIC_MODE_STOP && vt13_c_mode) {
- if (refereerc->vt13_packet.remote.ch4 < 424) {
+ if (refereerc_state.channels[4] < -600) {
shoot_load_mode = SHOOT_MODE_UNLOAD;
- } else if (refereerc->vt13_packet.remote.ch4 > 1624) {
+ } else if (refereerc_state.channels[4] > 600) {
shoot_load_mode = SHOOT_MODE_STOP;
} else {
- if (refereerc->vt13_packet.remote.ch4 > 800 && refereerc->vt13_packet.remote.ch4 < 1248) {
+ if (refereerc_state.channels[4] > -224 && refereerc_state.channels[4] < 224) {
shoot_load_mode = SHOOT_MODE_STOP;
}
}
diff --git a/programs/Ares/gimbal/src/remote_task_automata.cpp b/programs/Ares/gimbal/src/remote_task_automata.cpp
index 088ba797..ced408b9 100644
--- a/programs/Ares/gimbal/src/remote_task_automata.cpp
+++ b/programs/Ares/gimbal/src/remote_task_automata.cpp
@@ -25,23 +25,28 @@
#include "AutomataSystem.h"
#include "imu_task.h"
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
RemoteMode remote_mode = REMOTE_MODE_FOLLOW;
ShootFricMode shoot_flywheel_mode = SHOOT_FRIC_MODE_STOP;
ShootMode shoot_load_mode = SHOOT_MODE_STOP;
bool turbo_shoot = false;
void init_dbus() {
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
}
osThreadId_t remoteTaskHandle;
void remoteTask(void* arg) {
+ using enum controller::ThreePositionSwitch;
+
// 接口转换
UNUSED(arg);
osDelay(1000);
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
// 遥控器是否在线
bool is_controller_online = false;
// 裁判系统端机器人是否阵亡
@@ -49,21 +54,24 @@ void remoteTask(void* arg) {
// 裁判系统端是否允许射击
bool is_referee_shoot_available = false;
- remote::switch_t state_r = remote::MID;
- remote::switch_t state_l = remote::MID;
- remote::keyboard_t keyboard{};
- remote::mouse_t mouse{};
+ controller::ThreePositionSwitch state_r = Mid;
+ controller::ThreePositionSwitch state_l = Mid;
+ controller::KeyboardState keyboard{};
+ controller::MouseState mouse{};
BoolEdgeDetector turbo_edge{false};
// clang-format off
// 使/失能(上/下电)
auto tranlogic_active_condition = TRANLOGIC {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
const auto& referee_cmd_dead = COMPONENT(0);
const auto& control_online = COMPONENT(1);
// 遥控器在线 && 右摇杆不在最下档 && 裁判系统反馈 未阵亡
return control_online.get()
- && (!dbus->IsOnline() || dbus->swr != remote::DOWN)
+ && (!dbus->IsOnline() || dbus_state.right_switch != Down)
&& !referee_cmd_dead.get();
};
auto activate_aut = control::AutomataBuilder()
@@ -79,12 +87,12 @@ void remoteTask(void* arg) {
const auto& swr = COMPONENT(0);
const auto& mode_change_key = COMPONENT(1);
const auto& vt13_change_button = COMPONENT(2);
- return (swr.downEdge() && swr.get() == remote::UP)
+ return (swr.downEdge() && swr.get() == Up)
|| mode_change_key.upEdge()
|| vt13_change_button.upEdge();
};
auto remote_mode_aut = control::AutomataBuilder()
- .item(dbus->swr)
+ .item(dbus_state.right_switch)
.item(bool{}) // mode_change_key
.item(bool{}) // vt13_change_button
.transition(tranlogic_next_remote_mode_trigger)
@@ -97,12 +105,12 @@ void remoteTask(void* arg) {
const auto& swl = COMPONENT(0);
const auto& fric_key = COMPONENT(1);
const auto& vt13_fric_button = COMPONENT(2);
- return (swl.downEdge() && swl.get() == remote::UP)
+ return (swl.downEdge() && swl.get() == Up)
|| fric_key.upEdge()
|| vt13_fric_button.upEdge();
};
auto fric_wheel_aut = control::AutomataBuilder()
- .item(dbus->swl)
+ .item(dbus_state.left_switch)
.item(bool{}) // friction_key
.item(bool{}) // vt13_fric_button
// 加速中 → 停
@@ -125,12 +133,12 @@ void remoteTask(void* arg) {
const auto& referee_permit = COMPONENT(2);
const auto& shoot_key = COMPONENT(3);
const auto& vt13_shoot_button = COMPONENT(4);
- return (swl.get() == remote::DOWN || shoot_key.get() || vt13_shoot_button.get()) &&
+ return (swl.get() == Down || shoot_key.get() || vt13_shoot_button.get()) &&
fric_state.get() == SHOOT_FRIC_MODE_PREPARED &&
referee_permit.get();
};
auto shoot_aut = control::AutomataBuilder()
- .item(dbus->swl)
+ .item(dbus_state.left_switch)
.item(SHOOT_FRIC_MODE_STOP)
.item(is_referee_shoot_available)
.item(bool{}) // shoot_key
@@ -142,10 +150,18 @@ void remoteTask(void* arg) {
// clang-format on
while (true) {
- const bool is_dbus_offline = (!dbus->IsOnline()) || (dbus->swr == remote::DOWN);
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
+ const bool is_dbus_offline = (!dbus->IsOnline()) || (dbus_state.right_switch == Down);
// VT13必须在线且处于C模式才算可控
const bool is_vt13_offline =
- !(refereerc->IsOnline() && (refereerc->vt13_packet.remote.mode_sw == remote::vt13_remote_t::MODE_C));
+ !((refereerc != nullptr && refereerc->IsOnline()) && (refereerc_state.mode == controller::RefereeRcMode::C)
+ );
is_controller_online = !is_dbus_offline || !is_vt13_offline;
#ifdef HAS_REFEREE
@@ -172,22 +188,22 @@ void remoteTask(void* arg) {
}
// 每帧先清零,再按当前在线的控制源更新,避免残留上一帧键鼠输入
- state_r = remote::MID;
- state_l = remote::MID;
- memset(&keyboard, 0, sizeof(keyboard));
- memset(&mouse, 0, sizeof(mouse));
+ state_r = Mid;
+ state_l = Mid;
+ keyboard = {};
+ mouse = {};
const bool vt13_c_mode =
- refereerc->IsOnline() && (refereerc->vt13_packet.remote.mode_sw == remote::vt13_remote_t::MODE_C);
+ (refereerc != nullptr && refereerc->IsOnline()) && (refereerc_state.mode == controller::RefereeRcMode::C);
if (dbus->IsOnline()) { // DBUS
- state_r = dbus->swr;
- state_l = dbus->swl;
- keyboard = dbus->keyboard;
- mouse = dbus->mouse;
+ state_r = dbus_state.right_switch;
+ state_l = dbus_state.left_switch;
+ keyboard = dbus_state.keyboard;
+ mouse = dbus_state.mouse;
} else if (vt13_c_mode) {
- keyboard = refereerc->vt13_packet.keyboard;
- mouse = (remote::mouse_t)refereerc->vt13_packet.mouse;
+ keyboard = refereerc_state.keyboard;
+ mouse = refereerc_state.mouse;
}
turbo_edge.input(keyboard.bit.F);
@@ -200,14 +216,14 @@ void remoteTask(void* arg) {
remote_mode_aut.input(std::make_tuple(
state_r,
static_cast(keyboard.bit.SHIFT),
- vt13_c_mode && static_cast(refereerc->vt13_packet.remote.pause)
+ vt13_c_mode && static_cast(refereerc_state.pause)
));
remote_mode = remote_mode_aut.state();
fric_wheel_aut.input(std::make_tuple(
state_l,
static_cast(keyboard.bit.Z),
- vt13_c_mode && static_cast(refereerc->vt13_packet.remote.swl)
+ vt13_c_mode && static_cast(refereerc_state.left_button)
));
shoot_flywheel_mode = fric_wheel_aut.state();
@@ -215,8 +231,8 @@ void remoteTask(void* arg) {
state_l,
shoot_flywheel_mode,
shoot_permitted,
- static_cast(mouse.l),
- vt13_c_mode && static_cast(refereerc->vt13_packet.remote.trigger)
+ static_cast(mouse.left),
+ vt13_c_mode && static_cast(refereerc_state.trigger)
));
shoot_load_mode = shoot_aut.state();
diff --git a/programs/Ares/gimbal/src/shoot_task.cpp b/programs/Ares/gimbal/src/shoot_task.cpp
index 5e3f2624..f9f02062 100644
--- a/programs/Ares/gimbal/src/shoot_task.cpp
+++ b/programs/Ares/gimbal/src/shoot_task.cpp
@@ -60,8 +60,8 @@ void shootTask(void* arg) {
while (!imu->DataReady() || !imu->CaliDone()) {
osDelay(SHOOT_OS_DELAY);
}
- // int last_state = remote::MID;
- // int last_state_2 = remote::MID;
+ // auto last_state = controller::ThreePositionSwitch::Mid;
+ // auto last_state_2 = controller::ThreePositionSwitch::Mid;
// uint8_t shoot_state = 0;
// int shoot_flywheel_offset = 0;
// uint8_t shoot_state_2 = 0;
diff --git a/programs/Ares/gimbal/src/ui_task.cpp b/programs/Ares/gimbal/src/ui_task.cpp
index 9dc4051d..96423dd1 100644
--- a/programs/Ares/gimbal/src/ui_task.cpp
+++ b/programs/Ares/gimbal/src/ui_task.cpp
@@ -130,6 +130,13 @@ void uiTask(void* arg) {
BoolEdgeDetector* shoot_jam_edge = new BoolEdgeDetector(false);
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
// Update chassis GUI
// 通过两个云台电机的角度
relative_angle = yaw_motor->GetThetaDelta(gimbal_param->yaw_offset_);
@@ -256,10 +263,10 @@ void uiTask(void* arg) {
}
// V key to refresh UI (via refereerc VT13 link)
- if (refereerc->IsOnline()) {
- v_edge->input(refereerc->vt13_packet.keyboard.bit.V);
+ if ((refereerc != nullptr && refereerc->IsOnline())) {
+ v_edge->input(refereerc_state.keyboard.bit.V);
} else {
- v_edge->input(dbus->keyboard.bit.V);
+ v_edge->input(dbus_state.keyboard.bit.V);
}
if (v_edge->posEdge()) {
@@ -320,9 +327,9 @@ void uiTask(void* arg) {
// C key to clear diagnostics messages
if (dbus->IsOnline()) {
- c_edge->input(dbus->keyboard.bit.C);
+ c_edge->input(dbus_state.keyboard.bit.C);
} else {
- c_edge->input(refereerc->vt13_packet.keyboard.bit.C);
+ c_edge->input(refereerc_state.keyboard.bit.C);
}
if (c_edge->posEdge()) {
diagGUI->Clear(UI_Delay);
diff --git a/programs/Cakey/include/referee_task.h b/programs/Cakey/include/referee_task.h
index 1caa3466..5618d212 100644
--- a/programs/Cakey/include/referee_task.h
+++ b/programs/Cakey/include/referee_task.h
@@ -22,7 +22,7 @@
#include "bsp_print.h"
#include "bsp_uart.h"
#include "cmsis_os2.h"
-#include "dji_dbus.h"
+#include "refereerc.h"
#include "main.h"
#include "protocol.h"
@@ -30,8 +30,7 @@
extern bsp::UART* referee_uart;
extern communication::Referee* referee;
-extern bsp::UART* refereerc_uart;
-extern communication::Referee* refereerc;
+extern controller::RefereeRC* refereerc;
extern bsp::UART* minipc_uart;
extern communication::Host* minipc;
diff --git a/programs/Cakey/include/remote_task.h b/programs/Cakey/include/remote_task.h
index a409c001..b2c4d2d5 100644
--- a/programs/Cakey/include/remote_task.h
+++ b/programs/Cakey/include/remote_task.h
@@ -20,12 +20,12 @@
#pragma once
#include "cmsis_os2.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
#include "referee_task.h"
#include "user_define.h"
#include "utils.h"
-extern remote::DBUS* dbus;
+extern controller::DBUS* dbus;
/**
* @brief Dbus Init
*/
diff --git a/programs/Cakey/src/chassis_task.cpp b/programs/Cakey/src/chassis_task.cpp
index d6e8f515..d6e94517 100644
--- a/programs/Cakey/src/chassis_task.cpp
+++ b/programs/Cakey/src/chassis_task.cpp
@@ -55,6 +55,13 @@ void chassisTask(void* arg) {
chassis->Enable();
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
if (remote_mode == REMOTE_MODE_KILL) {
kill_chassis();
while (remote_mode == REMOTE_MODE_KILL) {
@@ -64,21 +71,22 @@ void chassisTask(void* arg) {
continue;
}
- remote::keyboard_t keyboard;
+ controller::KeyboardState keyboard{};
if (dbus->IsOnline()) {
- keyboard = dbus->keyboard;
- } else if (refereerc->IsOnline()) {
- keyboard = refereerc->remote_control.keyboard;
+ keyboard = dbus_state.keyboard;
+ } else if ((refereerc != nullptr && refereerc->IsOnline())) {
+ keyboard = refereerc_state.keyboard;
}
// 以云台为基准的(整车的)运动速度,范围为[-1, 1]
float car_vx, car_vy, car_vt;
- if (dbus->ch0 || dbus->ch1 || dbus->ch2 || dbus->ch3 || dbus->ch4) {
+ if (dbus_state.channels[0] || dbus_state.channels[1] || dbus_state.channels[2] || dbus_state.channels[3] ||
+ dbus_state.channels[4]) {
// 优先使用遥控器
const float speed_scale = 0.5;
- car_vx = (float)dbus->ch0 / dbus->ROCKER_MAX * speed_scale;
- car_vy = (float)dbus->ch1 / dbus->ROCKER_MAX * speed_scale;
- car_vt = (float)dbus->ch4 / dbus->ROCKER_MAX * speed_scale;
+ car_vx = (float)dbus_state.channels[0] / 660.0f * speed_scale;
+ car_vy = (float)dbus_state.channels[1] / 660.0f * speed_scale;
+ car_vt = (float)dbus_state.channels[4] / 660.0f * speed_scale;
} else {
// 使用键盘
const float keyboard_speed = keyboard.bit.SHIFT ? 1 : 0.5;
diff --git a/programs/Cakey/src/gimbal_task.cpp b/programs/Cakey/src/gimbal_task.cpp
index a368585c..1ee7fe33 100644
--- a/programs/Cakey/src/gimbal_task.cpp
+++ b/programs/Cakey/src/gimbal_task.cpp
@@ -21,7 +21,7 @@
#include "gimbal_task.h"
#include "chassis_task.h"
-#include "dji_remote.h"
+#include "dbus.h"
#include "minipc_task.h"
osThreadId_t gimbalTaskHandle;
@@ -80,6 +80,13 @@ void gimbalTask(void* arg) {
float pitch_target = 0, yaw_target = 0;
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
// 如果遥控器处于关闭状态,关闭两个电机
check_kill();
@@ -88,7 +95,7 @@ void gimbalTask(void* arg) {
INS_Angle.yaw = ahrs->INS_angle[0];
// pitch_curr = witimu->INS_angle[0];
// yaw_curr = wrap(witimu->INS_angle[2]-yaw_offset, -PI, PI);
- // if (dbus->swr == remote::UP) {
+ // if (dbus_state.right_switch == controller::ThreePositionSwitch::Up) {
// gimbal->TargetAbs(0, 0);
// gimbal->Update();
// pitch_target = pitch_curr;
@@ -101,16 +108,16 @@ void gimbalTask(void* arg) {
const float mouse_ratio = 0.5;
const float remote_ratio = 0.005;
if (dbus->IsOnline()) {
- if (dbus->mouse.x != 0 || dbus->mouse.y != 0) {
- pitch_ratio = (float)dbus->mouse.y / mouse_xy_max * mouse_ratio;
- yaw_ratio = (float)dbus->mouse.x / mouse_xy_max * mouse_ratio;
+ if (dbus_state.mouse.x != 0 || dbus_state.mouse.y != 0) {
+ pitch_ratio = (float)dbus_state.mouse.y / 32767.0 * mouse_ratio;
+ yaw_ratio = (float)dbus_state.mouse.x / 32767.0 * mouse_ratio;
} else {
- pitch_ratio = (float)dbus->ch3 / dbus->ROCKER_MAX * remote_ratio;
- yaw_ratio = (float)dbus->ch2 / dbus->ROCKER_MAX * remote_ratio;
+ pitch_ratio = (float)dbus_state.channels[3] / 660.0f * remote_ratio;
+ yaw_ratio = (float)dbus_state.channels[2] / 660.0f * remote_ratio;
}
- } else if (refereerc->IsOnline()) {
- pitch_ratio = -refereerc->remote_control.mouse.y / mouse_xy_max * mouse_ratio;
- yaw_ratio = -refereerc->remote_control.mouse.x / mouse_xy_max * mouse_ratio;
+ } else if ((refereerc != nullptr && refereerc->IsOnline())) {
+ pitch_ratio = -refereerc_state.mouse.y / 32767.0 * mouse_ratio;
+ yaw_ratio = -refereerc_state.mouse.x / 32767.0 * mouse_ratio;
} else {
pitch_ratio = 0;
yaw_ratio = 0;
diff --git a/programs/Cakey/src/main.cpp b/programs/Cakey/src/main.cpp
index 0635467e..c5215faf 100644
--- a/programs/Cakey/src/main.cpp
+++ b/programs/Cakey/src/main.cpp
@@ -101,6 +101,9 @@ void RM_RTOS_Default_Task(const void* arg) {
// }
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
if (referee->game_robot_status.mains_power_gimbal_output) {
gimbal_power->High();
} else {
@@ -119,17 +122,17 @@ void RM_RTOS_Default_Task(const void* arg) {
// DBUS info
print(
- "DBUS [CH0: %-4d] [CH1: %-4d] [CH2: %-4d] [CH3: %-4d] [TWL: %d] [SWL: %d] [SWR: %d]"
+ "DBUS [CH0: %-4d] [CH1: %-4d] [CH2: %-4d] [CH3: %-4d] [TWL: %d] [SWL: %s] [SWR: %s]"
"@ %d "
"ms\r\n",
- dbus->ch0,
- dbus->ch1,
- dbus->ch2,
- dbus->ch3,
- dbus->ch4,
- dbus->swl,
- dbus->swr,
- dbus->GetLastUptime()
+ dbus_state.channels[0],
+ dbus_state.channels[1],
+ dbus_state.channels[2],
+ dbus_state.channels[3],
+ dbus_state.channels[4],
+ controller::SwitchName(dbus_state.left_switch),
+ controller::SwitchName(dbus_state.right_switch),
+ dbus->GetLastValidTimeMs()
);
print("\r\n");
diff --git a/programs/Cakey/src/referee_task.cpp b/programs/Cakey/src/referee_task.cpp
index 39552af3..95a66986 100644
--- a/programs/Cakey/src/referee_task.cpp
+++ b/programs/Cakey/src/referee_task.cpp
@@ -21,9 +21,8 @@
#include "referee_task.h"
bsp::UART* referee_uart = nullptr;
-bsp::UART* refereerc_uart = nullptr;
communication::Referee* referee = nullptr;
-communication::Referee* refereerc = nullptr;
+controller::RefereeRC* refereerc = nullptr;
void init_referee() {
// 启动裁判系统
@@ -33,9 +32,5 @@ void init_referee() {
referee = new communication::Referee(referee_uart);
// 启动裁判系统图传链路
- refereerc_uart = new bsp::UART(&huart2);
- refereerc_uart->SetupRx(300);
- // UART7没有打开DMA发送,所以这里需要将DMA发送关闭
- refereerc_uart->SetupTx(300, false);
- refereerc = new communication::Referee(refereerc_uart);
+ refereerc = new controller::RefereeRC(&huart2);
}
diff --git a/programs/Cakey/src/remote_task.cpp b/programs/Cakey/src/remote_task.cpp
index f3ab94af..080775c2 100644
--- a/programs/Cakey/src/remote_task.cpp
+++ b/programs/Cakey/src/remote_task.cpp
@@ -25,7 +25,7 @@
#include "gimbal_task.h"
#include "imu_task.h"
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
RemoteMode remote_mode = REMOTE_MODE_FOLLOW;
RemoteMode last_remote_mode = REMOTE_MODE_FOLLOW;
RemoteMode available_remote_mode[] = {REMOTE_MODE_FOLLOW, REMOTE_MODE_SPIN, REMOTE_MODE_ADVANCED, REMOTE_MODE_AUTOAIM};
@@ -44,24 +44,24 @@ bool is_autoaim = false;
void init_dbus() {
// 初始化遥控器
- dbus = new remote::DBUS(&huart1);
+ dbus = new controller::DBUS(&huart1);
}
osThreadId_t remoteTaskHandle;
// #define HAS_REFEREE
void remoteTask(void* arg) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(arg);
osDelay(1000);
uint32_t shoot_burst_timestamp = 0;
- remote::switch_t state_r = remote::MID;
- remote::switch_t state_l = remote::MID;
- remote::keyboard_t keyboard;
- remote::mouse_t mouse;
+ controller::ThreePositionSwitch state_r = Mid;
+ controller::ThreePositionSwitch state_l = Mid;
+ controller::KeyboardState keyboard{};
+ controller::MouseState mouse{};
- memset(&keyboard, 0, sizeof(keyboard));
- memset(&mouse, 0, sizeof(mouse));
bool is_dbus_offline;
bool is_robot_dead;
bool is_shoot_available;
@@ -74,8 +74,15 @@ void remoteTask(void* arg) {
BoolEdgeDetector* keyboard_B_edge = new BoolEdgeDetector(false);
while (1) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
// 检测遥控器是否离线,或者遥控器是否在安全模式下
- is_dbus_offline = (!dbus->IsOnline()) || dbus->swr == remote::DOWN;
+ is_dbus_offline = (!dbus->IsOnline()) || dbus_state.right_switch == Down;
#ifdef HAS_REFEREE
// Kill Detection
is_robot_dead = referee->game_robot_status.remain_HP == 0;
@@ -112,20 +119,20 @@ void remoteTask(void* arg) {
}
if (dbus->IsOnline()) {
- state_r = dbus->swr;
- state_l = dbus->swl;
- keyboard = dbus->keyboard;
- mouse = dbus->mouse;
- } else if (refereerc->IsOnline()) {
- state_r = remote::MID;
- state_l = remote::MID;
- keyboard = refereerc->remote_control.keyboard;
- mouse = refereerc->remote_control.mouse;
+ state_r = dbus_state.right_switch;
+ state_l = dbus_state.left_switch;
+ keyboard = dbus_state.keyboard;
+ mouse = dbus_state.mouse;
+ } else if ((refereerc != nullptr && refereerc->IsOnline())) {
+ state_r = Mid;
+ state_l = Mid;
+ keyboard = refereerc_state.keyboard;
+ mouse = refereerc_state.mouse;
}
// Update Timestamp
- mouse_left_edge->input(mouse.l);
- mouse_right_edge->input(mouse.r);
+ mouse_left_edge->input(mouse.left);
+ mouse_right_edge->input(mouse.right);
keyboard_ctrl_edge->input(keyboard.bit.CTRL);
keyboard_G_edge->input(keyboard.bit.G);
@@ -133,7 +140,7 @@ void remoteTask(void* arg) {
// remote mode switch
static BoolEdgeDetector* mode_switch_edge = new BoolEdgeDetector(false);
- mode_switch_edge->input(state_r == remote::UP);
+ mode_switch_edge->input(state_r == Up);
if (mode_switch_edge->posEdge() || keyboard_ctrl_edge->posEdge()) {
RemoteMode next_mode = (RemoteMode)(remote_mode + 1);
@@ -158,7 +165,7 @@ void remoteTask(void* arg) {
if (shoot_flywheel_mode == SHOOT_FRIC_MODE_STOP) {
static BoolEdgeDetector* test_edge = new BoolEdgeDetector(false);
- test_edge->input(state_l == remote::DOWN);
+ test_edge->input(state_l == Down);
if (test_edge->posEdge()) {
gimbal->TargetReal(0, PI / 1.5);
}
@@ -180,7 +187,7 @@ void remoteTask(void* arg) {
// 切换摩擦轮
static BoolEdgeDetector* flywheel_switch_edge = new BoolEdgeDetector(false);
- flywheel_switch_edge->input(state_l == remote::UP);
+ flywheel_switch_edge->input(state_l == Up);
keyboard_Z_edge->input(keyboard.bit.Z);
if (flywheel_switch_edge->posEdge() || keyboard_Z_edge->posEdge()) {
if (shoot_flywheel_mode == SHOOT_FRIC_MODE_STOP) { // 原来停止则开始转
@@ -196,7 +203,7 @@ void remoteTask(void* arg) {
if (!is_autoaim || !minipc->IsOnline()) {
// 单发
static BoolEdgeDetector* shoot_switch_edge = new BoolEdgeDetector(false);
- shoot_switch_edge->input(state_l == remote::DOWN);
+ shoot_switch_edge->input(state_l == Down);
if (shoot_switch_edge->posEdge() || mouse_left_edge->posEdge()) {
shoot_load_mode = SHOOT_MODE_SINGLE;
@@ -204,7 +211,7 @@ void remoteTask(void* arg) {
}
// 连发
- if (state_l == remote::DOWN || mouse.l) {
+ if (state_l == Down || mouse.left) {
shoot_burst_timestamp++;
}
static BoolEdgeDetector* shoot_burst_switch_edge = new BoolEdgeDetector(false);
@@ -221,7 +228,7 @@ void remoteTask(void* arg) {
} else {
// 自喵模式下只有连发
if (minipc->IsOnline()) {
- if (minipc->target_angle.shoot_cmd != 0 && mouse.l) {
+ if (minipc->target_angle.shoot_cmd != 0 && mouse.left) {
shoot_load_mode = SHOOT_MODE_BURST;
} else {
shoot_load_mode = SHOOT_MODE_STOP;
diff --git a/programs/Cakey/src/ui_task.cpp b/programs/Cakey/src/ui_task.cpp
index dd6f29c4..1e86a3a1 100644
--- a/programs/Cakey/src/ui_task.cpp
+++ b/programs/Cakey/src/ui_task.cpp
@@ -144,6 +144,13 @@ void uiTask(void* arg) {
BoolEdgeDetector* imu_temp_edge = new BoolEdgeDetector(false);
BoolEdgeDetector* shoot_jam_edge = new BoolEdgeDetector(false);
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
// Update chassis GUI
// 通过两个云台电机的角度
relative_angle = yaw_motor->GetThetaDelta(gimbal_param->yaw_offset_);
@@ -302,9 +309,9 @@ void uiTask(void* arg) {
// v键清理UI
if (dbus->IsOnline()) {
- v_edge->input(dbus->keyboard.bit.V);
+ v_edge->input(dbus_state.keyboard.bit.V);
} else {
- v_edge->input(refereerc->remote_control.keyboard.bit.V);
+ v_edge->input(refereerc_state.keyboard.bit.V);
}
if (v_edge->posEdge()) {
@@ -373,9 +380,9 @@ void uiTask(void* arg) {
}
// c键清理消息
if (dbus->IsOnline()) {
- c_edge->input(dbus->keyboard.bit.C);
+ c_edge->input(dbus_state.keyboard.bit.C);
} else {
- c_edge->input(refereerc->remote_control.keyboard.bit.C);
+ c_edge->input(refereerc_state.keyboard.bit.C);
}
if (c_edge->posEdge()) {
diagGUI->Clear(UI_Delay);
diff --git a/programs/DGStandard/gimbal/include/referee_task.h b/programs/DGStandard/gimbal/include/referee_task.h
index 1caa3466..5618d212 100644
--- a/programs/DGStandard/gimbal/include/referee_task.h
+++ b/programs/DGStandard/gimbal/include/referee_task.h
@@ -22,7 +22,7 @@
#include "bsp_print.h"
#include "bsp_uart.h"
#include "cmsis_os2.h"
-#include "dji_dbus.h"
+#include "refereerc.h"
#include "main.h"
#include "protocol.h"
@@ -30,8 +30,7 @@
extern bsp::UART* referee_uart;
extern communication::Referee* referee;
-extern bsp::UART* refereerc_uart;
-extern communication::Referee* refereerc;
+extern controller::RefereeRC* refereerc;
extern bsp::UART* minipc_uart;
extern communication::Host* minipc;
diff --git a/programs/DGStandard/gimbal/include/remote_task.h b/programs/DGStandard/gimbal/include/remote_task.h
index a409c001..b2c4d2d5 100644
--- a/programs/DGStandard/gimbal/include/remote_task.h
+++ b/programs/DGStandard/gimbal/include/remote_task.h
@@ -20,12 +20,12 @@
#pragma once
#include "cmsis_os2.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
#include "referee_task.h"
#include "user_define.h"
#include "utils.h"
-extern remote::DBUS* dbus;
+extern controller::DBUS* dbus;
/**
* @brief Dbus Init
*/
diff --git a/programs/DGStandard/gimbal/src/chassis_task.cpp b/programs/DGStandard/gimbal/src/chassis_task.cpp
index 7fd7ed0c..a31c47cf 100644
--- a/programs/DGStandard/gimbal/src/chassis_task.cpp
+++ b/programs/DGStandard/gimbal/src/chassis_task.cpp
@@ -52,6 +52,13 @@ void chassisTask(void* arg) {
chassis->Enable();
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
if (remote_mode == REMOTE_MODE_KILL) {
kill_chassis();
while (remote_mode == REMOTE_MODE_KILL) {
@@ -61,11 +68,11 @@ void chassisTask(void* arg) {
continue;
}
- remote::keyboard_t keyboard;
+ controller::KeyboardState keyboard{};
if (dbus->IsOnline()) {
- keyboard = dbus->keyboard;
- } else if (refereerc->IsOnline()) {
- keyboard = refereerc->vt13_packet.keyboard;
+ keyboard = dbus_state.keyboard;
+ } else if ((refereerc != nullptr && refereerc->IsOnline())) {
+ keyboard = refereerc_state.keyboard;
}
// 以云台为基准的(整车的)运动速度,范围为[-1, 1]
@@ -75,23 +82,20 @@ void chassisTask(void* arg) {
// car_vy = 0;
// car_vt = 0;
// } else
- if (dbus->ch0 || dbus->ch1 || dbus->ch2 || dbus->ch3 || dbus->ch4) {
+ if (dbus_state.channels[0] || dbus_state.channels[1] || dbus_state.channels[2] || dbus_state.channels[3] ||
+ dbus_state.channels[4]) {
// 优先使用遥控器
const float speed_scale = 0.5;
- car_vx = (float)dbus->ch0 / dbus->ROCKER_MAX * speed_scale;
- car_vy = (float)dbus->ch1 / dbus->ROCKER_MAX * speed_scale;
- car_vt = (float)dbus->ch4 / dbus->ROCKER_MAX * speed_scale;
- } else if (refereerc->vt13_packet.remote.ch0 != remote::vt13_remote_t::ROCKER_MID ||
- refereerc->vt13_packet.remote.ch1 != remote::vt13_remote_t::ROCKER_MID ||
- refereerc->vt13_packet.remote.ch4 != remote::vt13_remote_t::ROCKER_MID) {
+ car_vx = (float)dbus_state.channels[0] / 660.0f * speed_scale;
+ car_vy = (float)dbus_state.channels[1] / 660.0f * speed_scale;
+ car_vt = (float)dbus_state.channels[4] / 660.0f * speed_scale;
+ } else if (refereerc_state.channels[0] != 0 || refereerc_state.channels[1] != 0 ||
+ refereerc_state.channels[4] != 0) {
// 使用VT13遥控器
const float speed_scale = 0.5;
- car_vx = (float)(refereerc->vt13_packet.remote.ch0 - remote::vt13_remote_t::ROCKER_MID) /
- remote::vt13_remote_t::ROCKER_RANGE * speed_scale;
- car_vy = (float)(refereerc->vt13_packet.remote.ch1 - remote::vt13_remote_t::ROCKER_MID) /
- remote::vt13_remote_t::ROCKER_RANGE * speed_scale;
- car_vt = (float)(refereerc->vt13_packet.remote.ch4 - remote::vt13_remote_t::ROCKER_MID) /
- remote::vt13_remote_t::ROCKER_RANGE * speed_scale;
+ car_vx = (float)(refereerc_state.channels[0]) / 660.0f * speed_scale;
+ car_vy = (float)(refereerc_state.channels[1]) / 660.0f * speed_scale;
+ car_vt = (float)(refereerc_state.channels[4]) / 660.0f * speed_scale;
} else {
// 使用键盘
const float keyboard_speed = keyboard.bit.SHIFT ? 1 : 0.5;
diff --git a/programs/DGStandard/gimbal/src/gimbal_task.cpp b/programs/DGStandard/gimbal/src/gimbal_task.cpp
index da2d555a..7a348288 100644
--- a/programs/DGStandard/gimbal/src/gimbal_task.cpp
+++ b/programs/DGStandard/gimbal/src/gimbal_task.cpp
@@ -21,7 +21,7 @@
#include "gimbal_task.h"
#include "chassis_task.h"
-#include "dji_remote.h"
+#include "dbus.h"
#include "minipc_task.h"
osThreadId_t gimbalTaskHandle;
@@ -81,6 +81,13 @@ void gimbalTask(void* arg) {
float pitch_target = 0, yaw_target = 0;
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
// 如果遥控器处于关闭状态,关闭两个电机
check_kill();
@@ -89,7 +96,7 @@ void gimbalTask(void* arg) {
INS_Angle.yaw = ahrs->INS_angle[0];
// pitch_curr = witimu->INS_angle[0];
// yaw_curr = wrap(witimu->INS_angle[2]-yaw_offset, -PI, PI);
- // if (dbus->swr == remote::UP) {
+ // if (dbus_state.right_switch == controller::ThreePositionSwitch::Up) {
// gimbal->TargetAbs(0, 0);
// gimbal->Update();
// pitch_target = pitch_curr;
@@ -102,27 +109,24 @@ void gimbalTask(void* arg) {
const float mouse_ratio = 1;
const float remote_ratio = 0.005;
if (dbus->IsOnline()) {
- if (dbus->mouse.x != 0 || dbus->mouse.y != 0) {
- pitch_ratio = (float)dbus->mouse.y / mouse_xy_max * mouse_ratio;
- yaw_ratio = (float)dbus->mouse.x / mouse_xy_max * mouse_ratio;
- } else if (refereerc->IsOnline() &&
- (refereerc->vt13_packet.mouse.x != 0 || refereerc->vt13_packet.mouse.y != 0)) {
- pitch_ratio = (float)refereerc->remote_control.mouse.y / mouse_xy_max * mouse_ratio;
- yaw_ratio = (float)refereerc->remote_control.mouse.x / mouse_xy_max * mouse_ratio;
+ if (dbus_state.mouse.x != 0 || dbus_state.mouse.y != 0) {
+ pitch_ratio = (float)dbus_state.mouse.y / 32767.0 * mouse_ratio;
+ yaw_ratio = (float)dbus_state.mouse.x / 32767.0 * mouse_ratio;
+ } else if ((refereerc != nullptr && refereerc->IsOnline()) &&
+ (refereerc_state.mouse.x != 0 || refereerc_state.mouse.y != 0)) {
+ pitch_ratio = (float)refereerc_state.mouse.y / 32767.0 * mouse_ratio;
+ yaw_ratio = (float)refereerc_state.mouse.x / 32767.0 * mouse_ratio;
} else {
- pitch_ratio = (float)dbus->ch3 / dbus->ROCKER_MAX * remote_ratio;
- yaw_ratio = (float)dbus->ch2 / dbus->ROCKER_MAX * remote_ratio;
+ pitch_ratio = (float)dbus_state.channels[3] / 660.0f * remote_ratio;
+ yaw_ratio = (float)dbus_state.channels[2] / 660.0f * remote_ratio;
}
- } else if (refereerc->IsOnline()) {
- if (refereerc->vt13_packet.remote.ch3 != remote::vt13_remote_t::ROCKER_MID ||
- refereerc->vt13_packet.remote.ch2 != remote::vt13_remote_t::ROCKER_MID) {
- pitch_ratio = (float)(refereerc->vt13_packet.remote.ch2 - remote::vt13_remote_t::ROCKER_MID) /
- remote::vt13_remote_t::ROCKER_RANGE * remote_ratio;
- yaw_ratio = (float)(refereerc->vt13_packet.remote.ch3 - remote::vt13_remote_t::ROCKER_MID) /
- remote::vt13_remote_t::ROCKER_RANGE * remote_ratio;
+ } else if ((refereerc != nullptr && refereerc->IsOnline())) {
+ if (refereerc_state.channels[3] != 0 || refereerc_state.channels[2] != 0) {
+ pitch_ratio = (float)(refereerc_state.channels[2]) / 660.0f * remote_ratio;
+ yaw_ratio = (float)(refereerc_state.channels[3]) / 660.0f * remote_ratio;
} else {
- pitch_ratio = -refereerc->vt13_packet.mouse.y / mouse_xy_max * mouse_ratio;
- yaw_ratio = refereerc->vt13_packet.mouse.x / mouse_xy_max * mouse_ratio;
+ pitch_ratio = -refereerc_state.mouse.y / 32767.0 * mouse_ratio;
+ yaw_ratio = refereerc_state.mouse.x / 32767.0 * mouse_ratio;
}
} else {
pitch_ratio = 0;
diff --git a/programs/DGStandard/gimbal/src/main.cpp b/programs/DGStandard/gimbal/src/main.cpp
index 94fe6577..1f5b1dd3 100644
--- a/programs/DGStandard/gimbal/src/main.cpp
+++ b/programs/DGStandard/gimbal/src/main.cpp
@@ -105,6 +105,13 @@ void RM_RTOS_Default_Task(const void* arg) {
// }
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
if (referee->game_robot_status.mains_power_gimbal_output) {
gimbal_power->High();
} else {
@@ -124,17 +131,17 @@ void RM_RTOS_Default_Task(const void* arg) {
// DBUS info
print(
- "DBUS [CH0: %-4d] [CH1: %-4d] [CH2: %-4d] [CH3: %-4d] [TWL: %d] [SWL: %d] [SWR: %d]"
+ "DBUS [CH0: %-4d] [CH1: %-4d] [CH2: %-4d] [CH3: %-4d] [TWL: %d] [SWL: %s] [SWR: %s]"
"@ %d "
"ms\r\n",
- dbus->ch0,
- dbus->ch1,
- dbus->ch2,
- dbus->ch3,
- dbus->ch4,
- dbus->swl,
- dbus->swr,
- dbus->GetLastUptime()
+ dbus_state.channels[0],
+ dbus_state.channels[1],
+ dbus_state.channels[2],
+ dbus_state.channels[3],
+ dbus_state.channels[4],
+ controller::SwitchName(dbus_state.left_switch),
+ controller::SwitchName(dbus_state.right_switch),
+ dbus->GetLastValidTimeMs()
);
print("\r\n");
@@ -142,26 +149,26 @@ void RM_RTOS_Default_Task(const void* arg) {
print(
"VT13 [CH0: %-4d] [CH1: %-4d] [CH2: %-4d] [CH3: %-4d] [CH4: %-4d]"
" [Mode: %d] [SWL: %d] [SWR: %d] [Trig: %d]\r\n",
- refereerc->vt13_packet.remote.ch0,
- refereerc->vt13_packet.remote.ch1,
- refereerc->vt13_packet.remote.ch2,
- refereerc->vt13_packet.remote.ch3,
- refereerc->vt13_packet.remote.ch4,
- refereerc->vt13_packet.remote.mode_sw,
- (int)refereerc->vt13_packet.remote.swl,
- (int)refereerc->vt13_packet.remote.swr ? 1 : 0,
- (int)refereerc->vt13_packet.remote.trigger ? 1 : 0
+ refereerc_state.channels[0],
+ refereerc_state.channels[1],
+ refereerc_state.channels[2],
+ refereerc_state.channels[3],
+ refereerc_state.channels[4],
+ static_cast(refereerc_state.mode),
+ (int)refereerc_state.left_button,
+ (int)refereerc_state.right_button ? 1 : 0,
+ (int)refereerc_state.trigger ? 1 : 0
);
print("\r\n");
- auto& mouse = refereerc->vt13_packet.mouse;
+ const auto& mouse = refereerc_state.mouse;
print(
"Mouse: [X: %d] [Y: %d] [ROLL: %d] [L %d] [R %d] [MID %d]",
mouse.x,
mouse.y,
- mouse.roll,
- mouse.l,
- mouse.r,
- mouse.mid
+ mouse.z,
+ mouse.left,
+ mouse.right,
+ mouse.middle
);
print("\r\n");
@@ -202,7 +209,7 @@ void RM_RTOS_Default_Task(const void* arg) {
print("Comm Stat: ");
print_enabled("DBUS", dbus->IsOnline());
print_enabled("Referee", referee->IsOnline());
- print_enabled("Referee RC", refereerc->IsOnline());
+ print_enabled("Referee RC", (refereerc != nullptr && refereerc->IsOnline()));
print("\r\n");
print("Motor Stat: ");
print_enabled("Yaw", yaw_motor->IsOnline());
diff --git a/programs/DGStandard/gimbal/src/referee_task.cpp b/programs/DGStandard/gimbal/src/referee_task.cpp
index e08e48b3..52d776a6 100644
--- a/programs/DGStandard/gimbal/src/referee_task.cpp
+++ b/programs/DGStandard/gimbal/src/referee_task.cpp
@@ -21,9 +21,8 @@
#include "referee_task.h"
bsp::UART* referee_uart = nullptr;
-bsp::UART* refereerc_uart = nullptr;
communication::Referee* referee = nullptr;
-communication::Referee* refereerc = nullptr;
+controller::RefereeRC* refereerc = nullptr;
void init_referee() {
// 启动裁判系统
@@ -33,10 +32,5 @@ void init_referee() {
referee = new communication::Referee(referee_uart);
// 启动裁判系统图传链路
- refereerc_uart = new bsp::UART(&huart7);
- refereerc_uart->SetBaudrate(921600);
- refereerc_uart->SetupRx(300);
- // UART7没有打开DMA发送,所以这里需要将DMA发送关闭
- refereerc_uart->SetupTx(300, false);
- refereerc = new communication::Referee(refereerc_uart);
+ refereerc = new controller::RefereeRC(&huart7);
}
diff --git a/programs/DGStandard/gimbal/src/remote_task.cpp b/programs/DGStandard/gimbal/src/remote_task.cpp
index 73855c25..4a5fd4c0 100644
--- a/programs/DGStandard/gimbal/src/remote_task.cpp
+++ b/programs/DGStandard/gimbal/src/remote_task.cpp
@@ -25,7 +25,7 @@
#include "gimbal_task.h"
#include "imu_task.h"
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
RemoteMode remote_mode = REMOTE_MODE_FOLLOW;
RemoteMode last_remote_mode = REMOTE_MODE_FOLLOW;
RemoteMode available_remote_mode[] = {REMOTE_MODE_FOLLOW, REMOTE_MODE_SPIN, REMOTE_MODE_ADVANCED, REMOTE_MODE_AUTOAIM};
@@ -44,24 +44,24 @@ bool is_autoaim = false;
void init_dbus() {
// 初始化遥控器
- dbus = new remote::DBUS(&huart1);
+ dbus = new controller::DBUS(&huart1);
}
osThreadId_t remoteTaskHandle;
// #define HAS_REFEREE
void remoteTask(void* arg) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(arg);
osDelay(1000);
uint32_t shoot_burst_timestamp = 0;
- remote::switch_t state_r = remote::MID;
- remote::switch_t state_l = remote::MID;
- remote::keyboard_t keyboard;
- remote::mouse_t mouse;
+ controller::ThreePositionSwitch state_r = Mid;
+ controller::ThreePositionSwitch state_l = Mid;
+ controller::KeyboardState keyboard{};
+ controller::MouseState mouse{};
- memset(&keyboard, 0, sizeof(keyboard));
- memset(&mouse, 0, sizeof(mouse));
bool is_dbus_offline;
bool is_vt13_offline;
bool is_robot_dead;
@@ -79,10 +79,17 @@ void remoteTask(void* arg) {
BoolEdgeDetector* vt13_trigger_edge = new BoolEdgeDetector(false);
while (1) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
// 检测遥控器是否离线,或者遥控器是否在安全模式下
- is_dbus_offline = (!dbus->IsOnline()) || dbus->swr == remote::DOWN;
+ is_dbus_offline = (!dbus->IsOnline()) || dbus_state.right_switch == Down;
is_vt13_offline =
- (!refereerc->IsOnline()) || refereerc->vt13_packet.remote.mode_sw != remote::vt13_remote_t::MODE_C;
+ (!(refereerc != nullptr && refereerc->IsOnline())) || refereerc_state.mode != controller::RefereeRcMode::C;
#ifdef HAS_REFEREE
// Kill Detection
is_robot_dead = referee->game_robot_status.remain_HP == 0;
@@ -119,28 +126,28 @@ void remoteTask(void* arg) {
}
if (dbus->IsOnline()) {
- state_r = dbus->swr;
- state_l = dbus->swl;
- keyboard = dbus->keyboard;
- mouse = dbus->mouse;
- } else if (refereerc->IsOnline()) {
- keyboard = refereerc->vt13_packet.keyboard;
- mouse = (remote::mouse_t)refereerc->vt13_packet.mouse;
+ state_r = dbus_state.right_switch;
+ state_l = dbus_state.left_switch;
+ keyboard = dbus_state.keyboard;
+ mouse = dbus_state.mouse;
+ } else if ((refereerc != nullptr && refereerc->IsOnline())) {
+ keyboard = refereerc_state.keyboard;
+ mouse = refereerc_state.mouse;
}
- mouse_left_edge->input(mouse.l);
- mouse_right_edge->input(mouse.r);
+ mouse_left_edge->input(mouse.left);
+ mouse_right_edge->input(mouse.right);
keyboard_G_edge->input(keyboard.bit.G);
keyboard_B_edge->input(keyboard.bit.B);
// DT7遥控器 右摇杆切换模式
static BoolEdgeDetector* mode_switch_edge = new BoolEdgeDetector(false);
- mode_switch_edge->input(state_r == remote::UP);
+ mode_switch_edge->input(state_r == Up);
// 键盘 左CTRL切换模式
keyboard_ctrl_edge->input(keyboard.bit.CTRL);
// VT13 暂停键切换模式
- vt13_pause_edge->input(refereerc->vt13_packet.remote.pause);
+ vt13_pause_edge->input(refereerc_state.pause);
if (mode_switch_edge->posEdge() || keyboard_ctrl_edge->posEdge() || vt13_pause_edge->posEdge()) {
RemoteMode next_mode = (RemoteMode)(remote_mode + 1);
@@ -165,7 +172,7 @@ void remoteTask(void* arg) {
// }
static BoolEdgeDetector remote_swr;
- remote_swr.input(refereerc->vt13_packet.remote.swr || mouse.r);
+ remote_swr.input(refereerc_state.right_button || mouse.right);
if (remote_swr.posEdge()) {
is_autoaim = true;
}
@@ -176,7 +183,7 @@ void remoteTask(void* arg) {
/* 测试PID,摩擦轮关闭时,左摇杆下拨测试云台转动
if (shoot_flywheel_mode == SHOOT_FRIC_MODE_STOP) {
static BoolEdgeDetector* test_edge = new BoolEdgeDetector(false);
- test_edge->input(state_l == remote::DOWN);
+ test_edge->input(state_l == Down);
if (test_edge->posEdge()) {
gimbal->TargetReal(0, PI / 1.5);
}
@@ -198,11 +205,11 @@ void remoteTask(void* arg) {
// DT7 左摇杆上拨 切换摩擦轮
static BoolEdgeDetector* flywheel_switch_edge = new BoolEdgeDetector(false);
- flywheel_switch_edge->input(state_l == remote::UP);
+ flywheel_switch_edge->input(state_l == Up);
// 键盘 Z键 切换摩擦轮
keyboard_Z_edge->input(keyboard.bit.Z);
// VT13 左键 切换摩擦轮
- vt13_left_edge->input(refereerc->vt13_packet.remote.swl);
+ vt13_left_edge->input(refereerc_state.left_button);
if (flywheel_switch_edge->posEdge() || keyboard_Z_edge->posEdge() || vt13_left_edge->posEdge()) {
if (shoot_flywheel_mode == SHOOT_FRIC_MODE_STOP) { // 原来停止则开始转
@@ -217,9 +224,9 @@ void remoteTask(void* arg) {
// DT7 左摇杆下拨
static BoolEdgeDetector* shoot_switch_edge = new BoolEdgeDetector(false);
- shoot_switch_edge->input(state_l == remote::DOWN);
+ shoot_switch_edge->input(state_l == Down);
// VT13 扳机键
- vt13_trigger_edge->input(refereerc->vt13_packet.remote.trigger);
+ vt13_trigger_edge->input(refereerc_state.trigger);
if (shoot_switch_edge->posEdge() || mouse_left_edge->posEdge() || vt13_trigger_edge->posEdge()) {
shoot_load_mode = SHOOT_MODE_SINGLE;
@@ -227,7 +234,7 @@ void remoteTask(void* arg) {
}
// 连发
- if (state_l == remote::DOWN || mouse.l || refereerc->vt13_packet.remote.trigger) {
+ if (state_l == Down || mouse.left || refereerc_state.trigger) {
shoot_burst_timestamp++;
}
static BoolEdgeDetector* shoot_burst_switch_edge = new BoolEdgeDetector(false);
diff --git a/programs/DGStandard/gimbal/src/ui_task.cpp b/programs/DGStandard/gimbal/src/ui_task.cpp
index 1c0dd60f..8da09158 100644
--- a/programs/DGStandard/gimbal/src/ui_task.cpp
+++ b/programs/DGStandard/gimbal/src/ui_task.cpp
@@ -152,6 +152,13 @@ void uiTask(void* arg) {
BoolEdgeDetector* shoot_jam_edge = new BoolEdgeDetector(false);
BoolEdgeDetector* bullet_edge = new BoolEdgeDetector(false);
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
// Update chassis GUI
// 通过两个云台电机的角度
float relative_angle = yaw_motor->GetThetaDelta(gimbal_param->yaw_offset_);
@@ -351,9 +358,9 @@ void uiTask(void* arg) {
// v键清理UI
if (dbus->IsOnline())
- v_edge->input(dbus->keyboard.bit.V);
+ v_edge->input(dbus_state.keyboard.bit.V);
else
- v_edge->input(refereerc->vt13_packet.keyboard.bit.V);
+ v_edge->input(refereerc_state.keyboard.bit.V);
if (v_edge->posEdge()) {
osDelay(110);
@@ -429,9 +436,9 @@ void uiTask(void* arg) {
// c键清理消息
if (dbus->IsOnline())
- c_edge->input(dbus->keyboard.bit.C);
+ c_edge->input(dbus_state.keyboard.bit.C);
else
- c_edge->input(refereerc->vt13_packet.keyboard.bit.C);
+ c_edge->input(refereerc_state.keyboard.bit.C);
if (c_edge->posEdge()) {
diagGUI->Clear(UI_Delay);
}
diff --git a/programs/Hero/gimbal/include/referee_task.h b/programs/Hero/gimbal/include/referee_task.h
index 0446d82f..bb008599 100644
--- a/programs/Hero/gimbal/include/referee_task.h
+++ b/programs/Hero/gimbal/include/referee_task.h
@@ -22,7 +22,7 @@
#include "bsp_print.h"
#include "bsp_uart.h"
#include "cmsis_os2.h"
-#include "dji_dbus.h"
+#include "refereerc.h"
#include "main.h"
#include "protocol.h"
@@ -30,7 +30,6 @@
extern bsp::UART* referee_uart;
extern communication::Referee* referee;
-extern bsp::UART* refereerc_uart;
-extern communication::Referee* refereerc;
+extern controller::RefereeRC* refereerc;
void init_referee();
\ No newline at end of file
diff --git a/programs/Hero/gimbal/include/remote_task.h b/programs/Hero/gimbal/include/remote_task.h
index 786ec19e..be516470 100644
--- a/programs/Hero/gimbal/include/remote_task.h
+++ b/programs/Hero/gimbal/include/remote_task.h
@@ -20,12 +20,12 @@
#pragma once
#include "cmsis_os2.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
#include "referee_task.h"
#include "user_define.h"
#include "utils.h"
-extern remote::DBUS* dbus;
+extern controller::DBUS* dbus;
extern bool turbo_shoot;
/**
* @brief Dbus Init
diff --git a/programs/Hero/gimbal/src/chassis_task.cpp b/programs/Hero/gimbal/src/chassis_task.cpp
index 67ad4bf7..166ad14b 100644
--- a/programs/Hero/gimbal/src/chassis_task.cpp
+++ b/programs/Hero/gimbal/src/chassis_task.cpp
@@ -49,6 +49,13 @@ void chassisTask(void* arg) {
chassis->Enable();
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
if (remote_mode == REMOTE_MODE_KILL) {
kill_chassis();
while (remote_mode == REMOTE_MODE_KILL) {
@@ -58,32 +65,30 @@ void chassisTask(void* arg) {
continue;
}
- remote::keyboard_t keyboard;
+ controller::KeyboardState keyboard{};
if (dbus->IsOnline()) {
- keyboard = dbus->keyboard;
- } else if (refereerc->IsOnline()) {
- keyboard = refereerc->vt13_packet.keyboard;
+ keyboard = dbus_state.keyboard;
+ } else if ((refereerc != nullptr && refereerc->IsOnline())) {
+ keyboard = refereerc_state.keyboard;
}
// 以云台为基准的(整车的)运动速度,范围为[-1, 1]
float car_vx, car_vy, car_vt;
- if (dbus->ch0 || dbus->ch1 || dbus->ch2 || dbus->ch3 || dbus->ch4) {
+ if (dbus_state.channels[0] || dbus_state.channels[1] || dbus_state.channels[2] || dbus_state.channels[3] ||
+ dbus_state.channels[4]) {
// 优先使用遥控器
const float speed_scale = 0.5;
- car_vx = (float)dbus->ch0 / dbus->ROCKER_MAX * speed_scale;
- car_vy = (float)dbus->ch1 / dbus->ROCKER_MAX * speed_scale;
- car_vt = (float)dbus->ch4 / dbus->ROCKER_MAX * speed_scale;
- } else if (refereerc->IsOnline() && (refereerc->vt13_packet.remote.ch0 != remote::vt13_remote_t::ROCKER_MID ||
- refereerc->vt13_packet.remote.ch1 != remote::vt13_remote_t::ROCKER_MID ||
- refereerc->vt13_packet.remote.ch4 != remote::vt13_remote_t::ROCKER_MID)) {
+ car_vx = (float)dbus_state.channels[0] / 660.0f * speed_scale;
+ car_vy = (float)dbus_state.channels[1] / 660.0f * speed_scale;
+ car_vt = (float)dbus_state.channels[4] / 660.0f * speed_scale;
+ } else if ((refereerc != nullptr && refereerc->IsOnline()) &&
+ (refereerc_state.channels[0] != 0 || refereerc_state.channels[1] != 0 ||
+ refereerc_state.channels[4] != 0)) {
// 使用VT13遥控器摇杆
const float speed_scale = 0.5;
- car_vx = (float)(refereerc->vt13_packet.remote.ch0 - remote::vt13_remote_t::ROCKER_MID) /
- remote::vt13_remote_t::ROCKER_RANGE * speed_scale;
- car_vy = (float)(refereerc->vt13_packet.remote.ch1 - remote::vt13_remote_t::ROCKER_MID) /
- remote::vt13_remote_t::ROCKER_RANGE * speed_scale;
- car_vt = (float)(refereerc->vt13_packet.remote.ch4 - remote::vt13_remote_t::ROCKER_MID) /
- remote::vt13_remote_t::ROCKER_RANGE * speed_scale;
+ car_vx = (float)(refereerc_state.channels[0]) / 660.0f * speed_scale;
+ car_vy = (float)(refereerc_state.channels[1]) / 660.0f * speed_scale;
+ car_vt = (float)(refereerc_state.channels[4]) / 660.0f * speed_scale;
} else {
// 使用键盘
const float keyboard_speed = keyboard.bit.SHIFT ? 1 : 0.5;
diff --git a/programs/Hero/gimbal/src/gimbal_task.cpp b/programs/Hero/gimbal/src/gimbal_task.cpp
index e44ecfef..6b9096df 100644
--- a/programs/Hero/gimbal/src/gimbal_task.cpp
+++ b/programs/Hero/gimbal/src/gimbal_task.cpp
@@ -78,6 +78,13 @@ void gimbalTask(void* arg) {
float actural_chassis_turn_speed = chassis_vt / 6.0f;
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
if (remote_mode == REMOTE_MODE_KILL) {
kill_gimbal();
osDelay(GIMBAL_OS_DELAY);
@@ -91,7 +98,7 @@ void gimbalTask(void* arg) {
yaw_curr = imu->INS_angle[0];
// pitch_curr = witimu->INS_angle[0];
// yaw_curr = wrap(witimu->INS_angle[2]-yaw_offset, -PI, PI);
- // if (dbus->swr == remote::UP) {
+ // if (dbus_state.right_switch == controller::ThreePositionSwitch::Up) {
// gimbal->TargetAbs(0, 0);
// gimbal->Update();
// pitch_target = pitch_curr;
@@ -101,34 +108,31 @@ void gimbalTask(void* arg) {
// continue;
// }
if (dbus->IsOnline()) {
- if (dbus->mouse.y != 0) {
- pitch_ratio = dbus->mouse.y / 32767.0 * 7.5 / 7.0;
- } else if (refereerc->IsOnline() &&
- (refereerc->vt13_packet.mouse.x != 0 || refereerc->vt13_packet.mouse.y != 0)) {
+ if (dbus_state.mouse.y != 0) {
+ pitch_ratio = dbus_state.mouse.y / 32767.0 * 7.5 / 7.0;
+ } else if ((refereerc != nullptr && refereerc->IsOnline()) &&
+ (refereerc_state.mouse.x != 0 || refereerc_state.mouse.y != 0)) {
// DBUS在线但摇杆/鼠标无输入时,使用VT13鼠标
- pitch_ratio = refereerc->vt13_packet.mouse.y / 32767.0 * 7.5 / 7.0;
+ pitch_ratio = refereerc_state.mouse.y / 32767.0 * 7.5 / 7.0;
} else {
- pitch_ratio = -dbus->ch3 / 18000.0 / 7.0;
+ pitch_ratio = -dbus_state.channels[3] / 18000.0 / 7.0;
}
- if (dbus->mouse.x != 0) {
- yaw_ratio = -dbus->mouse.x / 32767.0 * 7.5 / 7.0;
- } else if (refereerc->IsOnline() &&
- (refereerc->vt13_packet.mouse.x != 0 || refereerc->vt13_packet.mouse.y != 0)) {
- yaw_ratio = -refereerc->vt13_packet.mouse.x / 32767.0 * 7.5 / 7.0;
+ if (dbus_state.mouse.x != 0) {
+ yaw_ratio = -dbus_state.mouse.x / 32767.0 * 7.5 / 7.0;
+ } else if ((refereerc != nullptr && refereerc->IsOnline()) &&
+ (refereerc_state.mouse.x != 0 || refereerc_state.mouse.y != 0)) {
+ yaw_ratio = -refereerc_state.mouse.x / 32767.0 * 7.5 / 7.0;
} else {
- yaw_ratio = -dbus->ch2 / 18000.0 / 7.0;
+ yaw_ratio = -dbus_state.channels[2] / 18000.0 / 7.0;
}
- } else if (refereerc->IsOnline()) {
+ } else if ((refereerc != nullptr && refereerc->IsOnline())) {
// DBUS离线时使用VT13:优先摇杆,否则鼠标
- if (refereerc->vt13_packet.remote.ch3 != remote::vt13_remote_t::ROCKER_MID ||
- refereerc->vt13_packet.remote.ch2 != remote::vt13_remote_t::ROCKER_MID) {
- pitch_ratio = (float)(refereerc->vt13_packet.remote.ch2 - remote::vt13_remote_t::ROCKER_MID) /
- remote::vt13_remote_t::ROCKER_RANGE / 18000.0 * 660.0 / 7.0;
- yaw_ratio = (float)-(refereerc->vt13_packet.remote.ch3 - remote::vt13_remote_t::ROCKER_MID) /
- remote::vt13_remote_t::ROCKER_RANGE / 18000.0 * 660.0 / 7.0;
+ if (refereerc_state.channels[3] != 0 || refereerc_state.channels[2] != 0) {
+ pitch_ratio = (float)(refereerc_state.channels[2]) / 660.0f / 18000.0 * 660.0 / 7.0;
+ yaw_ratio = (float)-(refereerc_state.channels[3]) / 660.0f / 18000.0 * 660.0 / 7.0;
} else {
- pitch_ratio = -refereerc->vt13_packet.mouse.y / 32767.0 * 7.5 / 7.0;
- yaw_ratio = -refereerc->vt13_packet.mouse.x / 32767.0 * 7.5 / 7.0;
+ pitch_ratio = -refereerc_state.mouse.y / 32767.0 * 7.5 / 7.0;
+ yaw_ratio = -refereerc_state.mouse.x / 32767.0 * 7.5 / 7.0;
}
} else {
pitch_ratio = 0;
diff --git a/programs/Hero/gimbal/src/main.cpp b/programs/Hero/gimbal/src/main.cpp
index 76d93611..0ff04e3f 100644
--- a/programs/Hero/gimbal/src/main.cpp
+++ b/programs/Hero/gimbal/src/main.cpp
@@ -96,6 +96,13 @@ void RM_RTOS_Default_Task(const void* arg) {
Buzzer_Sing(DJI);
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
set_cursor(0, 0);
clear_screen();
@@ -106,31 +113,31 @@ void RM_RTOS_Default_Task(const void* arg) {
// Movement info
print(
- "DBUS [CH0: %-4d] [CH1: %-4d] [CH2: %-4d] [CH3: %-4d] [TWL: %d] [SWL: %d] [SWR: %d]"
+ "DBUS [CH0: %-4d] [CH1: %-4d] [CH2: %-4d] [CH3: %-4d] [TWL: %d] [SWL: %s] [SWR: %s]"
"@ %d "
"ms\r\n",
- dbus->ch0,
- dbus->ch1,
- dbus->ch2,
- dbus->ch3,
- dbus->ch4,
- dbus->swl,
- dbus->swr
+ dbus_state.channels[0],
+ dbus_state.channels[1],
+ dbus_state.channels[2],
+ dbus_state.channels[3],
+ dbus_state.channels[4],
+ controller::SwitchName(dbus_state.left_switch),
+ controller::SwitchName(dbus_state.right_switch)
);
// VT13 info
print(
"VT13 [CH0: %-4d] [CH1: %-4d] [CH2: %-4d] [CH3: %-4d] [CH4: %-4d] [Mode: %d] [SWL: "
"%d] "
"[SWR: %d] [Trig: %d]\r\n",
- refereerc->vt13_packet.remote.ch0,
- refereerc->vt13_packet.remote.ch1,
- refereerc->vt13_packet.remote.ch2,
- refereerc->vt13_packet.remote.ch3,
- refereerc->vt13_packet.remote.ch4,
- refereerc->vt13_packet.remote.mode_sw,
- refereerc->vt13_packet.remote.swl,
- refereerc->vt13_packet.remote.swr,
- refereerc->vt13_packet.remote.trigger
+ refereerc_state.channels[0],
+ refereerc_state.channels[1],
+ refereerc_state.channels[2],
+ refereerc_state.channels[3],
+ refereerc_state.channels[4],
+ static_cast(refereerc_state.mode),
+ refereerc_state.left_button,
+ refereerc_state.right_button,
+ refereerc_state.trigger
);
print("Chassis %.3f %.3f %.3f\r\n", chassis->chassis_vy, chassis->chassis_vy, chassis->chassis_vt);
print(
@@ -152,7 +159,10 @@ void RM_RTOS_Default_Task(const void* arg) {
print("\r\n");
print("[Referee %s] ", referee->IsOnline() ? "\033[32mOnline\033[0m" : "\033[31mOffline\033[0m");
print("\r\n");
- print("[Referee RC %s] ", refereerc->IsOnline() ? "\033[32mOnline\033[0m" : "\033[31mOffline\033[0m");
+ print(
+ "[Referee RC %s] ",
+ (refereerc != nullptr && refereerc->IsOnline()) ? "\033[32mOnline\033[0m" : "\033[31mOffline\033[0m"
+ );
print("\r\n");
print("[Yaw %s] ", yaw_motor->IsOnline() ? "\033[32mOnline\033[0m" : "\033[31mOffline\033[0m");
print("\r\n");
diff --git a/programs/Hero/gimbal/src/referee_task.cpp b/programs/Hero/gimbal/src/referee_task.cpp
index 69548b4d..153d38b4 100644
--- a/programs/Hero/gimbal/src/referee_task.cpp
+++ b/programs/Hero/gimbal/src/referee_task.cpp
@@ -21,9 +21,8 @@
#include "referee_task.h"
bsp::UART* referee_uart = nullptr;
-bsp::UART* refereerc_uart = nullptr;
communication::Referee* referee = nullptr;
-communication::Referee* refereerc = nullptr;
+controller::RefereeRC* refereerc = nullptr;
void init_referee() {
referee_uart = new bsp::UART(&BOARD_UART1);
@@ -32,9 +31,5 @@ void init_referee() {
referee = new communication::Referee(referee_uart);
// 启动裁判系统图传链路(VT13遥控器)
- refereerc_uart = new bsp::UART(&BOARD_UART2);
- refereerc_uart->SetBaudrate(921600);
- refereerc_uart->SetupRx(300);
- refereerc_uart->SetupTx(300, false);
- refereerc = new communication::Referee(refereerc_uart);
+ refereerc = new controller::RefereeRC(&BOARD_UART2);
}
diff --git a/programs/Hero/gimbal/src/remote_task.cpp b/programs/Hero/gimbal/src/remote_task.cpp
index 0bda283a..d4288a60 100644
--- a/programs/Hero/gimbal/src/remote_task.cpp
+++ b/programs/Hero/gimbal/src/remote_task.cpp
@@ -25,7 +25,7 @@
#include "imu_task.h"
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
RemoteMode remote_mode = REMOTE_MODE_FOLLOW;
RemoteMode last_remote_mode = REMOTE_MODE_FOLLOW;
RemoteMode available_remote_mode[] = {REMOTE_MODE_FOLLOW, REMOTE_MODE_SPIN, REMOTE_MODE_ADVANCED};
@@ -37,28 +37,26 @@ bool is_killed = false;
bool turbo_shoot = false;
void init_dbus() {
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
}
osThreadId_t remoteTaskHandle;
void remoteTask(void* arg) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(arg);
osDelay(1000);
bool mode_switch = false;
bool shoot_fric_switch = false;
bool shoot_switch = false;
bool shoot_stop_switch = false;
- remote::switch_t last_state_r = remote::MID;
- remote::switch_t last_state_l = remote::MID;
- remote::keyboard_t last_keyboard;
- remote::mouse_t last_mouse;
- remote::switch_t state_r = remote::MID;
- remote::switch_t state_l = remote::MID;
- remote::keyboard_t keyboard;
- remote::mouse_t mouse;
- memset(&keyboard, 0, sizeof(keyboard));
- memset(&mouse, 0, sizeof(mouse));
- memset(&last_keyboard, 0, sizeof(last_keyboard));
- memset(&last_mouse, 0, sizeof(last_mouse));
+ controller::ThreePositionSwitch last_state_r = Mid;
+ controller::ThreePositionSwitch last_state_l = Mid;
+ controller::KeyboardState last_keyboard{};
+ controller::MouseState last_mouse{};
+ controller::ThreePositionSwitch state_r = Mid;
+ controller::ThreePositionSwitch state_l = Mid;
+ controller::KeyboardState keyboard{};
+ controller::MouseState mouse{};
bool is_dbus_offline;
bool is_vt13_offline;
bool is_robot_dead;
@@ -74,11 +72,18 @@ void remoteTask(void* arg) {
BoolEdgeDetector* vt13_trigger_edge = new BoolEdgeDetector(false);
while (1) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
// 检测遥控器是否离线,或者遥控器是否在安全模式下
- is_dbus_offline = (!dbus->IsOnline()) || dbus->swr == remote::DOWN;
+ is_dbus_offline = (!dbus->IsOnline()) || dbus_state.right_switch == Down;
// 检测VT13是否离线或不在C模式
is_vt13_offline =
- (!refereerc->IsOnline()) || refereerc->vt13_packet.remote.mode_sw != remote::vt13_remote_t::MODE_C;
+ (!(refereerc != nullptr && refereerc->IsOnline())) || refereerc_state.mode != controller::RefereeRcMode::C;
#ifdef HAS_REFEREE
is_robot_dead = referee->game_robot_status.remain_HP == 0;
is_shoot_available = (referee->game_robot_status.shooter_heat_limit -
@@ -117,22 +122,22 @@ void remoteTask(void* arg) {
last_mouse = mouse;
// Update State:优先使用DBUS,否则使用VT13
if (dbus->IsOnline()) {
- state_r = dbus->swr;
- state_l = dbus->swl;
- keyboard = dbus->keyboard;
- mouse = dbus->mouse;
- } else if (refereerc->IsOnline()) {
- state_r = remote::MID;
- state_l = remote::MID;
- keyboard = refereerc->vt13_packet.keyboard;
- mouse = (remote::mouse_t)refereerc->vt13_packet.mouse;
+ state_r = dbus_state.right_switch;
+ state_l = dbus_state.left_switch;
+ keyboard = dbus_state.keyboard;
+ mouse = dbus_state.mouse;
+ } else if ((refereerc != nullptr && refereerc->IsOnline())) {
+ state_r = Mid;
+ state_l = Mid;
+ keyboard = refereerc_state.keyboard;
+ mouse = refereerc_state.mouse;
}
// Update Edge Detectors
z_edge->input(keyboard.bit.Z);
shift_edge->input(keyboard.bit.SHIFT);
- mouse_left_edge->input(mouse.l);
- mouse_right_edge->input(mouse.r);
+ mouse_left_edge->input(mouse.left);
+ mouse_right_edge->input(mouse.right);
shoot_burst_edge->input(keyboard.bit.F);
if (shoot_burst_edge->posEdge()) {
@@ -140,25 +145,25 @@ void remoteTask(void* arg) {
}
// VT13 边沿检测
- vt13_pause_edge->input(refereerc->vt13_packet.remote.pause);
- vt13_left_edge->input(refereerc->vt13_packet.remote.swl);
- vt13_trigger_edge->input(refereerc->vt13_packet.remote.trigger);
+ vt13_pause_edge->input(refereerc_state.pause);
+ vt13_left_edge->input(refereerc_state.left_button);
+ vt13_trigger_edge->input(refereerc_state.trigger);
// ========== 模式切换 ==========
// DT7 右摇杆上拨
switch (state_r) {
- case remote::UP:
- if (last_state_r == remote::MID && dbus->IsOnline()) {
+ case Up:
+ if (last_state_r == Mid && dbus->IsOnline()) {
mode_switch = true;
}
break;
- case remote::MID:
+ case Mid:
// 键盘 SHIFT 切换模式
if (shift_edge->posEdge()) {
mode_switch = true;
}
break;
- case remote::DOWN:
+ case Down:
break;
}
// VT13 暂停键切换模式
@@ -177,24 +182,24 @@ void remoteTask(void* arg) {
// ========== 摩擦轮切换 ==========
// DT7 左摇杆上拨
switch (state_l) {
- case remote::UP:
- if (last_state_l == remote::MID && dbus->IsOnline()) {
+ case Up:
+ if (last_state_l == Mid && dbus->IsOnline()) {
shoot_fric_switch = true;
}
break;
- case remote::DOWN:
- if (last_state_l == remote::MID && dbus->IsOnline()) {
+ case Down:
+ if (last_state_l == Mid && dbus->IsOnline()) {
shoot_switch = true;
}
break;
- case remote::MID:
+ case Mid:
switch (last_state_l) {
- case remote::DOWN:
+ case Down:
shoot_stop_switch = true;
break;
- case remote::UP:
+ case Up:
break;
- case remote::MID:
+ case Mid:
// 键盘 Z键 切换摩擦轮
if (z_edge->posEdge()) {
shoot_fric_switch = true;
@@ -236,7 +241,7 @@ void remoteTask(void* arg) {
}
}
// 退弹 - 不受摩擦轮状态限制
- if (refereerc->vt13_packet.remote.ch4 < 424 || refereerc->vt13_packet.mouse.mid) {
+ if (refereerc_state.channels[4] < -600 || refereerc_state.mouse.middle) {
shoot_load_mode = SHOOT_MODE_UNLOAD;
} else if (shoot_load_mode == SHOOT_MODE_UNLOAD) {
// 退弹条件消失,根据摩擦轮状态恢复
diff --git a/programs/Hero/gimbal/src/shoot_task.cpp b/programs/Hero/gimbal/src/shoot_task.cpp
index 1dbcc134..50fce4c8 100644
--- a/programs/Hero/gimbal/src/shoot_task.cpp
+++ b/programs/Hero/gimbal/src/shoot_task.cpp
@@ -55,8 +55,8 @@ void shootTask(void* arg) {
while (!imu->DataReady() || !imu->CaliDone()) {
osDelay(SHOOT_OS_DELAY);
}
- // int last_state = remote::MID;
- // int last_state_2 = remote::MID;
+ // auto last_state = controller::ThreePositionSwitch::Mid;
+ // auto last_state_2 = controller::ThreePositionSwitch::Mid;
// uint8_t shoot_state = 0;
// int shoot_flywheel_offset = 0;
// uint8_t shoot_state_2 = 0;
diff --git a/programs/Hero/gimbal/src/ui_task.cpp b/programs/Hero/gimbal/src/ui_task.cpp
index 05d9ba4e..95689368 100644
--- a/programs/Hero/gimbal/src/ui_task.cpp
+++ b/programs/Hero/gimbal/src/ui_task.cpp
@@ -188,6 +188,13 @@ void uiTask(void* arg) {
// BoolEdgeDetector* imu_temp_edge = new BoolEdgeDetector(false);
// BoolEdgeDetector* shoot_jam_edge = new BoolEdgeDetector(false);
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
// Update chassis GUI
relative_angle = yaw_motor->GetThetaDelta(gimbal_param->yaw_offset_);
// pitch_angle = pitch_motor->GetThetaDelta(gimbal_param->pitch_offset_);
@@ -322,9 +329,9 @@ void uiTask(void* arg) {
// clear self-diagnosis messages
if (dbus->IsOnline()) {
- v_edge->input(dbus->keyboard.bit.V);
+ v_edge->input(dbus_state.keyboard.bit.V);
} else {
- v_edge->input(refereerc->vt13_packet.keyboard.bit.V);
+ v_edge->input(refereerc_state.keyboard.bit.V);
}
if (v_edge->posEdge()) {
@@ -428,9 +435,9 @@ void uiTask(void* arg) {
continue;
}
if (dbus->IsOnline()) {
- c_edge->input(dbus->keyboard.bit.C);
+ c_edge->input(dbus_state.keyboard.bit.C);
} else {
- c_edge->input(refereerc->vt13_packet.keyboard.bit.C);
+ c_edge->input(refereerc_state.keyboard.bit.C);
}
if (c_edge->posEdge()) {
diagGUI->Clear(UI_Delay);
diff --git a/programs/Neo/gimbal/include/referee_task.h b/programs/Neo/gimbal/include/referee_task.h
index 0446d82f..bb008599 100644
--- a/programs/Neo/gimbal/include/referee_task.h
+++ b/programs/Neo/gimbal/include/referee_task.h
@@ -22,7 +22,7 @@
#include "bsp_print.h"
#include "bsp_uart.h"
#include "cmsis_os2.h"
-#include "dji_dbus.h"
+#include "refereerc.h"
#include "main.h"
#include "protocol.h"
@@ -30,7 +30,6 @@
extern bsp::UART* referee_uart;
extern communication::Referee* referee;
-extern bsp::UART* refereerc_uart;
-extern communication::Referee* refereerc;
+extern controller::RefereeRC* refereerc;
void init_referee();
\ No newline at end of file
diff --git a/programs/Neo/gimbal/include/remote_task.h b/programs/Neo/gimbal/include/remote_task.h
index fd5249b5..d0eb692b 100644
--- a/programs/Neo/gimbal/include/remote_task.h
+++ b/programs/Neo/gimbal/include/remote_task.h
@@ -20,12 +20,12 @@
#pragma once
#include "cmsis_os2.h"
-#include "dji_dbus.h"
+#include "dbus.h"
#include "main.h"
#include "referee_task.h"
#include "user_define.h"
#include "utils.h"
-extern remote::DBUS* dbus;
+extern controller::DBUS* dbus;
extern bool turbo_shoot;
/**
* @brief Dbus Init
diff --git a/programs/Neo/gimbal/src/chassis_task.cpp b/programs/Neo/gimbal/src/chassis_task.cpp
index 1f4c7dd3..9c7a7a34 100644
--- a/programs/Neo/gimbal/src/chassis_task.cpp
+++ b/programs/Neo/gimbal/src/chassis_task.cpp
@@ -52,6 +52,13 @@ void chassisTask(void* arg) {
chassis->Enable();
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
if (!is_activate) {
kill_chassis();
while (!is_activate) {
@@ -61,11 +68,11 @@ void chassisTask(void* arg) {
continue;
}
- remote::keyboard_t keyboard;
+ controller::KeyboardState keyboard{};
if (dbus->IsOnline()) {
- keyboard = dbus->keyboard;
- } else if (refereerc->IsOnline()) {
- keyboard = refereerc->remote_control.keyboard;
+ keyboard = dbus_state.keyboard;
+ } else if ((refereerc != nullptr && refereerc->IsOnline())) {
+ keyboard = refereerc_state.keyboard;
}
// 以云台为基准的(整车的)运动速度,范围为[-1, 1]
@@ -80,11 +87,12 @@ void chassisTask(void* arg) {
car_vy = minipc->robot_move.target_x;
car_vx = -minipc->robot_move.target_y;
car_vt = minipc->robot_move.target_turn;
- } else if (dbus->ch0 || dbus->ch1 || dbus->ch2 || dbus->ch3 || dbus->ch4) {
+ } else if (dbus_state.channels[0] || dbus_state.channels[1] || dbus_state.channels[2] ||
+ dbus_state.channels[3] || dbus_state.channels[4]) {
// 优先使用遥控器
- car_vx = (float)dbus->ch0 / dbus->ROCKER_MAX;
- car_vy = (float)dbus->ch1 / dbus->ROCKER_MAX;
- car_vt = (float)dbus->ch4 / dbus->ROCKER_MAX;
+ car_vx = (float)dbus_state.channels[0] / 660.0f;
+ car_vy = (float)dbus_state.channels[1] / 660.0f;
+ car_vt = (float)dbus_state.channels[4] / 660.0f;
} else {
// 使用键盘
const float keyboard_speed = keyboard.bit.SHIFT ? 1 : 0.5;
diff --git a/programs/Neo/gimbal/src/gimbal_task.cpp b/programs/Neo/gimbal/src/gimbal_task.cpp
index 0ac908db..6ebcfc75 100644
--- a/programs/Neo/gimbal/src/gimbal_task.cpp
+++ b/programs/Neo/gimbal/src/gimbal_task.cpp
@@ -85,6 +85,13 @@ void gimbalTask(void* arg) {
// float actural_chassis_turn_speed = chassis_vt / 6.0f;
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
bool gimbal_en = is_activate;
#ifdef HAS_REFEREE
gimbal_en = gimbal_en && referee->game_robot_status.mains_power_gimbal_output;
@@ -118,7 +125,7 @@ void gimbalTask(void* arg) {
yaw_curr = imu->INS_angle[0];
// pitch_curr = witimu->INS_angle[0];
// yaw_curr = wrap(witimu->INS_angle[2]-yaw_offset, -PI, PI);
- // if (dbus->swr == remote::UP) {
+ // if (dbus_state.right_switch == controller::ThreePositionSwitch::Up) {
// gimbal->TargetAbs(0, 0);
// gimbal->Update();
// pitch_target = pitch_curr;
@@ -128,19 +135,19 @@ void gimbalTask(void* arg) {
// continue;
// }
if (dbus->IsOnline()) {
- if (dbus->mouse.y != 0) {
- pitch_ratio = dbus->mouse.y / 32767.0 * 7.5 / 7.0;
+ if (dbus_state.mouse.y != 0) {
+ pitch_ratio = dbus_state.mouse.y / 32767.0 * 7.5 / 7.0;
} else {
- pitch_ratio = -dbus->ch3 / 18000.0 / 7.0;
+ pitch_ratio = -dbus_state.channels[3] / 18000.0 / 7.0;
}
- if (dbus->mouse.x != 0) {
- yaw_ratio = -dbus->mouse.x / 32767.0 * 7.5 / 7.0;
+ if (dbus_state.mouse.x != 0) {
+ yaw_ratio = -dbus_state.mouse.x / 32767.0 * 7.5 / 7.0;
} else {
- yaw_ratio = -dbus->ch2 / 18000.0 / 7.0;
+ yaw_ratio = -dbus_state.channels[2] / 18000.0 / 7.0;
}
- } else if (refereerc->IsOnline()) {
- pitch_ratio = refereerc->remote_control.mouse.y / 32767.0 * 7.5 / 7.0;
- yaw_ratio = -refereerc->remote_control.mouse.x / 32767.0 * 7.5 / 7.0;
+ } else if ((refereerc != nullptr && refereerc->IsOnline())) {
+ pitch_ratio = refereerc_state.mouse.y / 32767.0 * 7.5 / 7.0;
+ yaw_ratio = -refereerc_state.mouse.x / 32767.0 * 7.5 / 7.0;
} else {
pitch_ratio = 0;
yaw_ratio = 0;
diff --git a/programs/Neo/gimbal/src/main.cpp b/programs/Neo/gimbal/src/main.cpp
index 3fe98220..37b4da86 100644
--- a/programs/Neo/gimbal/src/main.cpp
+++ b/programs/Neo/gimbal/src/main.cpp
@@ -90,6 +90,9 @@ void RM_RTOS_Default_Task(const void* arg) {
// }
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
// if (referee->game_robot_status.mains_power_gimbal_output) {
// gimbal_power->High();
// } else {
@@ -109,16 +112,16 @@ void RM_RTOS_Default_Task(const void* arg) {
// DBUS info
print(
- "DBUS [CH0: %-4d] [CH1: %-4d] [CH2: %-4d] [CH3: %-4d] [TWL: %d] [SWL: %d] [SWR: %d]"
+ "DBUS [CH0: %-4d] [CH1: %-4d] [CH2: %-4d] [CH3: %-4d] [TWL: %d] [SWL: %s] [SWR: %s]"
"@ %d "
"ms\r\n",
- dbus->ch0,
- dbus->ch1,
- dbus->ch2,
- dbus->ch3,
- dbus->ch4,
- dbus->swl,
- dbus->swr
+ dbus_state.channels[0],
+ dbus_state.channels[1],
+ dbus_state.channels[2],
+ dbus_state.channels[3],
+ dbus_state.channels[4],
+ controller::SwitchName(dbus_state.left_switch),
+ controller::SwitchName(dbus_state.right_switch)
);
print("\r\n");
diff --git a/programs/Neo/gimbal/src/referee_task.cpp b/programs/Neo/gimbal/src/referee_task.cpp
index 07f0db8c..3856cf51 100644
--- a/programs/Neo/gimbal/src/referee_task.cpp
+++ b/programs/Neo/gimbal/src/referee_task.cpp
@@ -21,9 +21,8 @@
#include "referee_task.h"
bsp::UART* referee_uart = nullptr;
-bsp::UART* refereerc_uart = nullptr;
communication::Referee* referee = nullptr;
-communication::Referee* refereerc = nullptr;
+controller::RefereeRC* refereerc = nullptr;
void init_referee() {
referee_uart = new bsp::UART(&BOARD_UART2);
@@ -32,8 +31,5 @@ void init_referee() {
referee_uart->SetupTx(300);
referee = new communication::Referee(referee_uart);
- // refereerc_uart = new bsp::UART(&huart1);
- // refereerc_uart->SetupRx(300);
- // refereerc_uart->SetupTx(300);
- // refereerc = new communication::Referee(refereerc_uart);
+ // refereerc = new controller::RefereeRC(&huart1);
}
diff --git a/programs/Neo/gimbal/src/remote_task.cpp b/programs/Neo/gimbal/src/remote_task.cpp
index 8ec61a69..485c8f32 100644
--- a/programs/Neo/gimbal/src/remote_task.cpp
+++ b/programs/Neo/gimbal/src/remote_task.cpp
@@ -23,7 +23,7 @@
#include "imu_task.h"
#include "minipc_task.h"
-remote::DBUS* dbus = nullptr;
+controller::DBUS* dbus = nullptr;
bool is_activate = true;
RemoteMode remote_mode = REMOTE_MODE_AUTOPILOT;
@@ -35,14 +35,19 @@ RemoteMode last_remote_mode = REMOTE_MODE_SPIN;
ShootMode last_shoot_mode = SHOOT_MODE_STOP;
void init_remote() {
- dbus = new remote::DBUS(&huart3);
+ dbus = new controller::DBUS(&huart3);
}
osThreadId_t remoteTaskHandle;
void remoteTask(void* arg) {
+ using enum controller::ThreePositionSwitch;
+
UNUSED(arg);
osDelay(1000);
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
bool is_referee_robot_dead = true;
bool is_referee_shoot_available = false;
@@ -51,8 +56,11 @@ void remoteTask(void* arg) {
// 使/失能(上/下电)
auto tranlogic_active_condition = TRANLOGIC {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
const auto& referee_cmd_dead = COMPONENT(0);
- return dbus->IsOnline() && dbus->swr != remote::DOWN && !referee_cmd_dead.get();
+ return dbus->IsOnline() && dbus_state.right_switch != Down && !referee_cmd_dead.get();
};
auto activate_aut = control::AutomataBuilder()
.item(is_referee_robot_dead)
@@ -64,10 +72,10 @@ void remoteTask(void* arg) {
auto tranlogic_next_remote_mode_trigger = TRANLOGIC {
const auto& swr = COMPONENT(0);
const auto& mode_change_key = COMPONENT(1);
- return (swr.downEdge() && swr.get() == remote::UP) || mode_change_key.upEdge();
+ return (swr.downEdge() && swr.get() == Up) || mode_change_key.upEdge();
};
auto remote_mode_aut = control::AutomataBuilder()
- .item(dbus->swr)
+ .item(dbus_state.right_switch)
.item(bool{}) // mode_change_key
.transition(tranlogic_next_remote_mode_trigger)
.transition(tranlogic_next_remote_mode_trigger)
@@ -82,10 +90,10 @@ void remoteTask(void* arg) {
auto tranlogic_fric_wheel_trigger = TRANLOGIC {
const auto& swl = COMPONENT(0);
const auto& fric_key = COMPONENT(1);
- return (swl.downEdge() && swl.get() == remote::UP) || fric_key.upEdge();
+ return (swl.downEdge() && swl.get() == Up) || fric_key.upEdge();
};
auto fric_wheel_aut = control::AutomataBuilder()
- .item(dbus->swl)
+ .item(dbus_state.left_switch)
.item(bool{}) // friction_key
.transition(tranlogic_fric_wheel_trigger)
.transition(tranlogic_fric_wheel_trigger)
@@ -103,13 +111,13 @@ void remoteTask(void* arg) {
const auto& referee_permit = COMPONENT(2);
const auto& shoot_key = COMPONENT(3);
const auto& remote_mode = COMPONENT(4);
- return (swl.get() == remote::DOWN || shoot_key.get()) &&
+ return (swl.get() == Down || shoot_key.get()) &&
fric_state.get() == SHOOT_FRIC_MODE_PREPARED &&
referee_permit.get() &&
(remote_mode.get() == REMOTE_MODE_AUTOPILOT ? minipc->target_angle.shoot_cmd : true);
};
auto shoot_aut = control::AutomataBuilder()
- .item(dbus->swl)
+ .item(dbus_state.left_switch)
.item(SHOOT_FRIC_MODE_STOP)
.item(is_referee_shoot_available)
.item(bool{}) // shoot_key
@@ -130,10 +138,10 @@ void remoteTask(void* arg) {
auto tranlogic_bullet_cap_trigger = TRANLOGIC {
const auto& swl = COMPONENT(0);
const auto& fric_state = COMPONENT(1);
- return swl.downEdge() && swl.get() == remote::DOWN && fric_state.get() == SHOOT_FRIC_MODE_STOP;
+ return swl.downEdge() && swl.get() == Down && fric_state.get() == SHOOT_FRIC_MODE_STOP;
};
auto bullet_cap_aut = control::AutomataBuilder()
- .item(dbus->swl)
+ .item(dbus_state.left_switch)
.item(SHOOT_FRIC_MODE_STOP)
.transition(tranlogic_bullet_cap_trigger)
.transition(tranlogic_bullet_cap_trigger)
@@ -145,6 +153,9 @@ void remoteTask(void* arg) {
while (true) {
osDelay(REMOTE_OS_DELAY);
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+
#ifdef HAS_REFEREE
// Kill Detection
is_referee_robot_dead = referee->game_robot_status.remain_HP == 0;
@@ -162,20 +173,25 @@ void remoteTask(void* arg) {
if (!is_activate || !imu->DataReady() || !imu->CaliDone())
continue;
- remote_mode_aut.input(std::make_tuple(dbus->swr, static_cast(dbus->keyboard.bit.SHIFT)));
+ remote_mode_aut.input(std::make_tuple(dbus_state.right_switch, static_cast(dbus_state.keyboard.bit.SHIFT))
+ );
last_remote_mode = remote_mode;
remote_mode = remote_mode_aut.state();
- fric_wheel_aut.input(std::make_tuple(dbus->swl, static_cast(dbus->keyboard.bit.Z)));
+ fric_wheel_aut.input(std::make_tuple(dbus_state.left_switch, static_cast(dbus_state.keyboard.bit.Z)));
shoot_fric_wheel_mode = fric_wheel_aut.state();
- shoot_aut.input(
- std::make_tuple(dbus->swl, shoot_fric_wheel_mode, is_referee_shoot_available, dbus->mouse.l, remote_mode)
- );
+ shoot_aut.input(std::make_tuple(
+ dbus_state.left_switch,
+ shoot_fric_wheel_mode,
+ is_referee_shoot_available,
+ dbus_state.mouse.left,
+ remote_mode
+ ));
last_shoot_mode = shoot_mode;
shoot_mode = shoot_aut.state();
- bullet_cap_aut.input(std::make_tuple(dbus->swl, shoot_fric_wheel_mode));
+ bullet_cap_aut.input(std::make_tuple(dbus_state.left_switch, shoot_fric_wheel_mode));
bullet_cap_mode = bullet_cap_aut.state();
}
}
diff --git a/programs/Neo/gimbal/src/shoot_task.cpp b/programs/Neo/gimbal/src/shoot_task.cpp
index 2ee1659a..b0c90bbc 100644
--- a/programs/Neo/gimbal/src/shoot_task.cpp
+++ b/programs/Neo/gimbal/src/shoot_task.cpp
@@ -57,8 +57,8 @@ void shootTask(void* arg) {
while (!imu->DataReady() || !imu->CaliDone()) {
osDelay(SHOOT_OS_DELAY);
}
- // int last_state = remote::MID;
- // int last_state_2 = remote::MID;
+ // auto last_state = controller::ThreePositionSwitch::Mid;
+ // auto last_state_2 = controller::ThreePositionSwitch::Mid;
// uint8_t shoot_state = 0;
// int shoot_flywheel_offset = 0;
// uint8_t shoot_state_2 = 0;
diff --git a/programs/Neo/gimbal/src/ui_task.cpp b/programs/Neo/gimbal/src/ui_task.cpp
index 50d21342..f050e3bd 100644
--- a/programs/Neo/gimbal/src/ui_task.cpp
+++ b/programs/Neo/gimbal/src/ui_task.cpp
@@ -134,6 +134,13 @@ void uiTask(void* arg) {
BoolEdgeDetector* imu_temp_edge = new BoolEdgeDetector(false);
BoolEdgeDetector* shoot_jam_edge = new BoolEdgeDetector(false);
while (true) {
+ controller::DbusFrame dbus_state{};
+ dbus->GetState(dbus_state);
+ controller::RefereeRcFrame refereerc_state{};
+ if (refereerc != nullptr) {
+ refereerc->GetState(refereerc_state);
+ }
+
// Update chassis GUI
relative_angle = yaw_motor->GetThetaDelta(gimbal_param->yaw_offset_);
pitch_angle = pitch_motor->GetThetaDelta(gimbal_param->pitch_offset_);
@@ -263,9 +270,9 @@ void uiTask(void* arg) {
// clear self-diagnosis messages
if (dbus->IsOnline()) {
- v_edge->input(dbus->keyboard.bit.V);
+ v_edge->input(dbus_state.keyboard.bit.V);
} else {
- v_edge->input(refereerc->remote_control.keyboard.bit.V);
+ v_edge->input(refereerc_state.keyboard.bit.V);
}
if (v_edge->posEdge()) {
@@ -337,9 +344,9 @@ void uiTask(void* arg) {
continue;
}
if (dbus->IsOnline()) {
- c_edge->input(dbus->keyboard.bit.C);
+ c_edge->input(dbus_state.keyboard.bit.C);
} else {
- c_edge->input(refereerc->remote_control.keyboard.bit.C);
+ c_edge->input(refereerc_state.keyboard.bit.C);
}
if (c_edge->posEdge()) {
diagGUI->Clear(UI_Delay);