将任何视频游戏控制器变成USB鼠标

描述

随着最新和最伟大的游戏系统每隔几年首次亮相,我的旧视频游戏控制器库存也以同样的速度增长。许多较旧的游戏机都设计有非标准的专有连接器。可悲的是,这意味着,即使它们仍然功能齐全,我的大多数旧游戏控制器也注定要在架子上积聚灰尘。然而,只需稍加修改,这些控制器就可以被赋予新的生命,并重新用作与现代计算机的漂亮接口。用旧组件和备件制造USB鼠标或键盘的专业知识既有趣又信息丰富,可以通过用户控制输入向任何嵌入式系统添加功能。

检查旧控制器

制作USB鼠标的基本要求很简单。鼠标需要两个用于左键和右键单击的按钮,以及控制水平和垂直移动的方法。

这些基本标准以各种方式实施,具有不同的组成部分和复杂性。1980 年代和 1990 年代初的游戏手柄使用连接到 8 位或 16 位闩锁的简单按钮。每隔几毫秒锁定一次数据,游戏机可以轻松地打卡并解释按下了哪些按钮。后来的控制器集成了模数转换器(ADC),以检测操纵杆从其静止位置移动的距离,从而允许不同的移动速度,而不是简单按钮的“开关”控制。更现代的控制器甚至集成了一个加速度计,通过身体运动为用户提供了更多种类的控制。无论使用哪种控制器,互联网上都应该有大量关于其数据如何编码的信息。掌握游戏控制器如何收集和存储输入后,下一步就是格式化 USB 的数据。

制作鼠标

USB是一种极其通用的协议,主机系统必须准备好接受来自所连接设备的各种数据包。首次连接终端设备时,它必须在称为“枚举”的过程中向主机描述其标识、功能和预期数据格式。幸运的是,大多数主机系统都有常用设备类(想想闪存驱动器、键盘、打印机等)的内置驱动程序。如果终端设备枚举某个类,则主机无需任何其他软件即可使用该设备。鼠标属于人体学接口设备 (HID) 类,因此在此类下枚举将使鼠标即插即用。

当设备首次连接到 USB 端口时,主机会发送 SETUP 数据,以便设备有机会枚举。终端设备必须解码 SETUP 数据包并发送设备描述符,然后发送其配置、接口、类、端点和报告描述符。描述符是包含有关设备操作的详细信息的表数据。从设备制造商、数据缓冲区大小和通信速度到功耗和数据格式,在枚举期间,各种描述符中都会报告所有内容。

报告描述符控制计算机如何接收和解释通过 USB 发送的数据。我们可以根据 HID 类中预定义的用法来识别鼠标的左键和右键功能。控制器中的两个按钮对应于两个输入,每个输入的位大小为 1,每个输入的逻辑值为 0 或 1。

USAGE_PAGE(按钮)
USAGE_MINIMUM(按钮 1)
USAGE_MAXIMUM(按钮 2)
LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM (1)
REPORT_COUNT (2)
REPORT_SIZE (1)
输入(数据、变量、绝对值)

由于我们只使用数据字节的 2 位,因此我们需要另一个 6 位的报告大小,计算机将其解释为常量。请注意,我们不包括后一位的任何用法。

REPORT_COUNT(1)
REPORT_SIZE(6)
输入(中碳纳米、变量、绝对值)

我们发送的接下来的 2 个字节分别对应于 x 轴和 y 轴数据。每个方向的数据都有自己的 8 位报告大小,对于 127 位有符号整数,逻辑值可以在 -127 到 8 的范围内。

USAGE_PAGE(通用桌面)
用法 (X)
用法(Y)
LOGICAL_MINIMUM (-127)
LOGICAL_MAXIMUM (127)
REPORT_SIZE (8)
REPORT_COUNT (2)
输入(数据、变量、相关)

由于上述报告描述符的每一行在 HID 使用情况表中都有一个预定义的值。1以下数组表示鼠标示例的总报告描述符。

 

unsigned char RepD[]=   // Report descriptor
{
0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
0x09, 0x02,                    // USAGE (Mouse)
0xA1, 0x01,                    // COLLECTION (Application)
0x09, 0x01,                    //   USAGE (Pointer)
0xA1, 0x00,                    //   COLLECTION (Physical)
0x05, 0x09,                    //     USAGE_PAGE (Button)
0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
0x29, 0x02,                    //     USAGE_MAXIMUM (Button 2)
0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
0x95, 0x02,                    //     REPORT_COUNT (2)
0x75, 0x01,                    //     REPORT_SIZE (1)
0x81, 0x02,                    //     INPUT (Data,Var,Abs)
0x95, 0x01,                    //     REPORT_COUNT (1)
0x75, 0x06,                    //     REPORT_SIZE (6)
0x81, 0x01,                    //     INPUT (Cnst,Var,Abs)
0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
0x09, 0x30,                    //     USAGE (X)
0x09, 0x31,                    //     USAGE (Y)
0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
0x25, 0x7F,                    //     LOGICAL_MAXIMUM (127)
0x75, 0x08,                    //     REPORT_SIZE (8)
0x95, 0x02,                    //     REPORT_COUNT (2)
0x81, 0x06,                    //     INPUT (Data,Var,Rel)
0xC0,                          //   END_COLLECTION
0xC0                           // END_COLLECTION
};

所以现在你要问,从这份报告描述符解释中实际得出的是什么?通过使用上面的报告描述符,我们需要做的就是将来自游戏控制器的数据格式化为以下格式(表 1),主机系统将能够正确理解输入。

表 1.USB 鼠标数据格式
 

 

  7 6 5 4 3 2 1 0
字节 0 0 0 0 0 0 0 右键单击 左键点击
字节 1 X 轴位移(带符号)
字节 2 Y 轴位移(带符号)

 

请务必注意,方向数据既有符号又相对于光标的当前位置。如果发送 -1 作为 x 轴位移,光标将向左移动一个像素。x 轴位移字节中的 +1 将光标向右移动一个像素。这同样适用于 y 轴,负值向上移动光标,正值向下移动光标。

现在可以显示创建USB接口的两种不同方法。可以使用内置USB串行接口引擎的MAXQ612或MAXQ622 16位微控制器,也可以使用带有MAX3420E或MAX3421E USB外设控制器的微控制器。图 1 显示了第一个实现。我选择的游戏控制器有一个方便的I2C 接口。使用MAXQ622用作I2C主接口与游戏控制器通信,将数据解析成上面表1所示的格式并处理USB事务。现在可以实现单芯片鼠标解决方案。

adc

图1.单芯片 USB 鼠标的示意图。本设计采用MAXQ622微控制器和MAXQ622评估(EV)板。

除外部旁路电容器外,I 上的上拉电阻2C线和晶体振荡器,此示例设计不需要额外的元件。图2所示为更通用的解决方案,使用MAX3420E USB外设控制器和配备I2C 和 SPI 函数。

adc

图2.USB鼠标示意图,现在使用MAX3420E USB外设控制器和MAX3420E评估板。而任何具有I2可以使用C和SPI功能,在这种情况下,我们继续使用MAXQ622。

MAX3420EEVKIT-2为所有接口引脚提供接头,包括用于SPI通信的MOSI、MISO、#SS和SCLK引脚,以及用于微控制器信号中断的INT引脚。MAX3420EEVKIT-2具有板载Atmel ATtiny2313微控制器,通过定制固件,可实现位砰砰®2C 总线直接连接到游戏控制器。在本例中,MAXQ622评估板具有2C和SPI外设被用作通用微控制器。

结论

现在您知道如何使用旧的视频游戏控制器和任何具有正确接口的微控制器来实现USB鼠标。该过程就像连接几个跳线并下载固件一样简单。

此处提供的代码具有多个函数。它持续监控 USB 总线是否有来自主机的任何活动或传入请求;它定期轮询游戏控制器以获取新数据,将此数据发送到主机,并闪烁 LED 作为状态/时间指示器。这两种实现都具备识别 USB 总线重置和 USB 总线挂起事件的能力。两者都执行主机的远程唤醒,并适当地响应所有主机 CONTROL 传输。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分