跳转到内容

核心接口与数据类型

Gamepad<KeysType> 是所有手柄的模板基类,负责 UDP 数据接收线程管理和回调机制。

Gamepad(int port = kDefaultPort); ///< 指定 UDP 监听端口,默认 12121
void StartDataThread(); ///< 启动数据接收线程
void StopDataThread(); ///< 停止数据接收线程
KeysType& GetKeys(); ///< 获取最新按键数据(线程安全)
void SetUpdateCallback(const std::function<void(uint32_t)>& cb); ///< 注册数据更新回调
uint16_t CalculateCrc16(const uint8_t* data, size_t length); ///< CRC-16 校验计算

每次收到有效数据并更新按键后,SDK 会调用注册的回调函数,参数为累计更新次数:

rc.SetUpdateCallback([](uint32_t count) {
// count 为自启动以来的有效数据更新次数
});

也可以直接赋值 updateCallback_ 成员:

rc.updateCallback_ = [&](uint32_t count) {
std::cout << "update count: " << count << std::endl;
};

RetroidGamepad 继承 Gamepad<RetroidKeys>,是 Retroid 手柄的具体实现。

RetroidGamepad rc(12121); ///< 创建 Retroid 手柄实例,监听 12121 端口
rc.StartDataThread(); ///< 启动数据接收
RetroidKeys keys = rc.GetKeys();
std::cout << "A button: " << keys.A << std::endl;
std::cout << "Left axis X: " << keys.left_axis_x << std::endl;

SkydroidGamepad 继承 Gamepad<SkydroidKeys>,是 Skydroid 手柄的具体实现。

SkydroidGamepad rc(12121); ///< 创建 Skydroid 手柄实例,监听 12121 端口
rc.StartDataThread(); ///< 启动数据接收
SkydroidKeys keys = rc.GetKeys();
std::cout << "A button: " << keys.A << std::endl;
std::cout << "SW1: " << keys.sw1 << std::endl;

UdpReceiver 封装了底层 UDP Socket 的创建、绑定和接收逻辑。

UdpReceiver receiver(12121); ///< 创建并绑定端口
std::vector<uint8_t> data = receiver.ReceiveData(); ///< 阻塞接收一帧数据

ReceiveData() 为阻塞调用,直到收到一个 UDP 数据包后返回原始字节流。

所有数据类型定义在 gamepad_keys.h 中。

RetroidKeys — Retroid 手柄按键数据

Section titled “RetroidKeys — Retroid 手柄按键数据”
struct RetroidKeys {
double time_stamp; ///< 时间戳(ms,相对于启动时间)
union {
uint16_t value; ///< 所有按键的位掩码
struct {
uint8_t R1 : 1;
uint8_t L1 : 1;
uint8_t start : 1;
uint8_t select : 1;
uint8_t R2 : 1;
uint8_t L2 : 1;
uint8_t A : 1;
uint8_t B : 1;
uint8_t X : 1;
uint8_t Y : 1;
uint8_t left : 1;
uint8_t right : 1;
uint8_t up : 1;
uint8_t down : 1;
uint8_t left_axis_button : 1;
uint8_t right_axis_button : 1;
};
};
union {
float axis_values[4];
struct {
float left_axis_x; ///< 左摇杆 X 轴(-1.0 ~ 1.0)
float left_axis_y; ///< 左摇杆 Y 轴(-1.0 ~ 1.0)
float right_axis_x; ///< 右摇杆 X 轴(-1.0 ~ 1.0)
float right_axis_y; ///< 右摇杆 Y 轴(-1.0 ~ 1.0)
};
};
};

SkydroidKeys — Skydroid 手柄按键数据

Section titled “SkydroidKeys — Skydroid 手柄按键数据”
struct SkydroidKeys {
double time_stamp; ///< 时间戳(ms,相对于启动时间)
union {
uint8_t keys_value;
struct {
uint8_t C : 1;
uint8_t right : 1;
uint8_t D : 1;
uint8_t E : 1;
uint8_t F : 1;
uint8_t reserved : 1;
uint8_t A : 1;
uint8_t B : 1;
};
};
union {
uint8_t switch_keys[4];
struct {
uint8_t sw1; ///< 拨动开关 1
uint8_t sw2; ///< 拨动开关 2
uint8_t sw3; ///< 拨动开关 3
uint8_t sw4; ///< 拨动开关 4
};
};
union {
float axis_values[4];
struct {
float left_axis_x; ///< 左摇杆 X 轴(-1.0 ~ 1.0)
float left_axis_y; ///< 左摇杆 Y 轴(-1.0 ~ 1.0)
float right_axis_x; ///< 右摇杆 X 轴(-1.0 ~ 1.0)
float right_axis_y; ///< 右摇杆 Y 轴(-1.0 ~ 1.0)
};
};
};
值含义
0按键松开(KeyStatus::kReleased)
1按键按下(KeyStatus::kPressed)

摇杆原始数据范围为 -1000 ~ 1000,SDK 内部除以 kJoystickRange(1000)后归一化为 -1.0 ~ 1.0 的浮点数。

方向最小值最大值
X 轴-1.0(最左)1.0(最右)
Y 轴-1.0(最下)1.0(最上)
按键说明
A / B / X / Y四动作按钮
L1 / R1左/右肩键
L2 / R2左/右扳机键
start / select开始/选择键
up / down / left / right方向键
left_axis_button / right_axis_button左/右摇杆按下
按键说明
A / B / C / D / E / F动作按钮
right方向键(右)
sw1 / sw2 / sw3 / sw4四路拨动开关
struct RetroidGamepadData {
uint8_t stx[2]; ///< 帧头 0x55 0x66
uint8_t ctrl; ///< 控制字节
uint16_t data_len; ///< 数据区长度
uint16_t seq; ///< 序列号
uint8_t id; ///< 设备 ID(1 = Retroid)
uint16_t crc16; ///< CRC-16 校验
union {
uint8_t data[32]; ///< 原始数据区
struct {
uint16_t buttons[10]; ///< 10 个按键通道
int16_t left_axis_x; ///< 左摇杆 X
int16_t left_axis_y; ///< 左摇杆 Y
int16_t right_axis_x; ///< 右摇杆 X
int16_t right_axis_y; ///< 右摇杆 Y
uint16_t axis_buttons[2]; ///< 摇杆按键
};
};
};
struct SkydroidGamepadData {
uint8_t stx[2]; ///< 帧头 0x55 0x66
uint8_t ctrl; ///< 控制字节
uint16_t data_len; ///< 数据区长度
uint16_t seq; ///< 序列号
uint8_t id; ///< 设备 ID(2 = Skydroid)
uint16_t crc16; ///< CRC-16 校验
union {
uint8_t data[32]; ///< 原始数据区
struct {
int16_t right_axis_x; ///< 右摇杆 X
int16_t right_axis_y; ///< 右摇杆 Y
int16_t left_axis_y; ///< 左摇杆 Y
int16_t left_axis_x; ///< 左摇杆 X
uint16_t switch_keys[4]; ///< 4 路拨动开关
uint16_t buttons[8]; ///< 8 个按键通道
};
};
};

注意: 两种手柄的摇杆数据在协议帧中的排列顺序不同,SDK 内部已自动处理映射。