基于安信可Ai-M61开发板的自制U盘红白机教程

2026.11.14 | 焜财商富 | 31354次围观

本文转自立创开源广场,原作者「拿了桔子跑」

原文地址:https://oshwhub.com/article/article_vcmwvopo

编者按:

手里有一块吃灰的 Ai-M61 或 Ai-M62,还能拿它做什么?

立创开源广场上有个作品给了个精彩的答案:把它做成一个打火机大小的 U 盘,插上电脑,系统认成「带麦克风的摄像头」,相机软件里直接出红白机画面。

项目叫 USB-NES。一颗 RISC-V 在片上跑 InfoNES,画面走 UVC、声音走 UAC、手柄走 HID,一根 USB 线把三件事一起做了,全程不需要板子带屏。

原理并不复杂:模拟器本来就在一帧一帧算画面,只要把算出来的画面编码成 MJPEG、当成摄像头推出去,任何带屏的设备都能当它的显示器。

「必须带屏」这条约束一去,Ai-M61 / M62 这类小板的可玩性一下就宽了。

我们觉得这个思路值得给手上正好有块吃灰板子的人看看,所以把原作者的文章整理出来。

下文为原作者正文,我们只做排版整理,技术细节与结论保留作者原意。

家人们,有没有手里吃灰的Ai-M61 / Ai-M62开发板?这些板子其实完全够跑 NES 红白机,但之前一直没个像样的玩法。

说个我自己的经历:早先用小安派 S1自己搓了个模拟器玩小霸王(参考这篇),结果是能玩,但有两个硬伤——一是那个模拟器只支持 Mapper0 格式的 NES,像魂斗罗这种非 Mapper0 的游戏根本跑不起来;二是 S1 靠触摸屏操作,手感一言难尽。更麻烦的是,那版固件必须小安派 S1 才能跑,换块板子就歇菜。

后来学 USB 的时候灵光一现:既然画面是模拟器自己算出来的,干嘛非要板子带屏幕?让电脑把模拟器画面当「摄像头」收进来不就完了——于是 UVC 视频 + UAC 音频 + HID 手柄三根线合一的复合 USB 设备就出来了,而且任何带 Ai-M61/Ai-M62 的板子都能跑。当前这版做得只有打火机大小,直接挂钥匙扣上,小巧方便。

这次咱们玩的硬核货——USB-NES:一颗 RISC-V 片上跑 InfoNES(支持多 Mapper,魂斗罗也能玩),插上 USB 电脑认成「带麦克风的摄像头」,视频、声音、手柄一根线全包,换游戏不用重编固件。妥妥的吃灰板子复活神器~

说明:本项目主体是 BL616/BL618 复合 USB 设备(UVC 视频 + UAC 音频 + HID 手柄 + 片上 InfoNES)。下面要讲的 ESP32 小手柄只是其中一种无线控制方式,手机、电脑照样能连。

01先上成品展示!

整机就是个打火机大小的 USB 小 Dongle,挂钥匙扣上都行。插上电脑,Windows 设备管理器里会依次冒出「摄像头」「麦克风」「HID 游戏设备」三类。

34c827a2-dc28-11f1-8a4b-92fbcf53809c.jpg

外壳 3D 渲染(闭合形态):打火机大小,一头 USB 接电脑、一头 TTL 串口,顶上两颗实体按键

Windows 设备管理器:「照相机」和「声音输入」里同时冒出 BL6x8_UVC_UAC_DEMO——一个设备被认成两类

35756a7a-dc28-11f1-8a4b-92fbcf53809c.jpg

USB Device Tree Viewer 再确认:同一个设备描述符里挂着 Camera, Audio, HID 三接口,标准的 USB 复合设备

02实物展示

设计再漂亮,也得看实机能不能跑。下面是通电、连电脑、出画面的实机照片——重点是这玩意儿只有打火机大。

外壳 3D 渲染(打开视图):迷你 PCB + 双 Type-C 座,Ai-M61/M62 模组焊在中央

3681805c-dc28-11f1-8a4b-92fbcf53809c.jpg

双 Type-C 特写:一头 USB(复合设备接电脑),一头 TTL(串口烧录/日志),烧完游戏拔掉 TTL 线就能挂着当 U 盘红白机

36df1cbc-dc28-11f1-8a4b-92fbcf53809c.jpg

实机效果:打开 Windows 自带「相机」,UVC 收到的就是 NES 画面(坦克大战),零驱动、零插件

373a320a-dc28-11f1-8a4b-92fbcf53809c.jpg

上电进中文游戏菜单:2048、超级玛丽、魂斗罗、马戏团、炸弹人、坦克大战、公路追逐赛、双截龙……方向键移光标、A 进入,换游戏不用重编固件

03项目卡片与硬件清单

项目 说明
核心大脑 安信可 Ai-M61 / Ai-M62 / BL616 / BL618 模组(博流 RISC-V,320MHz,4MB PSRAM)——手上有这些板子的都能跑
体积 打火机大小,可直接挂钥匙扣,小巧便携
屏幕依赖 零屏幕 ——画面走 UVC 让电脑/手机当「摄像头」显示,板子本身不用带屏
交互方式 有线 USB HID(PC 网页/小程序转发)+ 无线 UDP(板子开 SoftAP 热点,手机/电脑/ESP32 连上来玩)
视频输出 UVC 摄像头,硬件 MJPEG 编码,默认 512×480、15fps(实测编码 19fps)
音频输出 UAC 麦克风,NES APU 5 路波形混音 + 去直流,44.1kHz / 立体声 / 16-bit
手柄通道 HID(有线)+ 自定义 UDP(无线),最长支持 2 人同屏
模拟器 片上 InfoNES(6502 + PPU + APU),支持多 Mapper(不像早期 S1 那版只认 Mapper0),魂斗罗也能玩
内置游戏 9 款经典(超级玛丽、魂斗罗、坦克大战、双截龙……)
换游戏方式 flash_rom.py 一条命令写入,免重编固件
固件分发 固件 + 全部游戏拼成单文件合并镜像,一键烧录
上手难度 (会编译、会烧录、会写一条命令就行)

硬件清单

部件 具体型号/规格 说明/来源
主控 Ai-M61 / Ai-M62 / BL616 / BL618(博流 RISC-V 320MHz,4MB PSRAM) 安信可模组,吃灰板子也能用
体积 打火机大小,可挂钥匙扣 迷你 PCB,无屏幕
视频 硬件 MJPEG 编码器(RGB565→YUYV 软件转换) 片上外设,UVC 输出
音频 NES APU 5 路混音 + 去直流 经 UAC 输出 44.1k 立体声
手柄 板载按键 + USB HID + 无线 UDP 有线/无线双模,最长 2 人
存储 板载 Flash(固件 + ROM 分区) ROM 走独立目录区 + 数据区
接口 USB 2.0(DP/DN) Type-C 或 Micro-USB,供电 + 复合设备
上位机 PC 网页nes_pad_webhid.html/ 脚本nes_pad_sender.py 有线转发手柄
无线端 手机 / 电脑 / ESP32 小手柄 连板子 SoftAPBL616_NES发 UDP

04固件设计:一根 USB 线,三个设备

为什么用 UVC 而不是板子带屏?早期在小安派 S1 上玩,板子必须带屏幕才能看到画面,硬件门槛高、还得是特定板子。后来想到:模拟器画面本来就是芯片一帧帧算出来的,只要把它编码成 MJPEG 走 UVC,电脑/手机的相机软件就能直接当「摄像头」显示——板子自己完全不用带屏,任何 Ai-M61/M62 小板都能跑。这步直接把「必须有屏幕」的硬约束拿掉了,也是这个项目能「让吃灰板子玩起来」的关键。

核心思路是把 BL616/BL618 做成一个USB 复合设备(bDeviceClass=0xEFIAD 复合),一根 USB 线同时暴露三个接口:

·UVC(视频):片上 InfoNES 把 NES 画面渲染成 RGB565,软件转成 YUYV,再交给硬件 MJPEG 编码器压成视频流。电脑打开相机软件就能看,不用装任何驱动。

·UAC(音频):NES APU 的五路波形(2× 脉冲、三角波、噪声、DPCM)在片上混音,做过去直流处理,经 UAC 输出 44.1kHz 立体声。电脑录音软件能直接收到游戏原声。

·HID(手柄):板载按键通过 USB HID 回传,PC 网页/小程序读到来转发给模拟器。

385146d8-dc28-11f1-8a4b-92fbcf53809c.jpg

不用画架构图,直接上真实枚举证据——USB Tree Viewer 展开看到同一个设备下挂三个子设备:① UVC 视频设备(Camera class)② UAC 音频设备(AudioEndpoint)③ HID 设备(标准游戏手柄)。VID/PID = ABCD:1234,一根 USB 线,三个设备

视频做了BT.601 studio range + 2× 放大的色彩处理,高对比边缘没有红绿鬼影(这点是踩过坑修好的,见后面「踩坑总结」)。模拟器用InfoNES,支持多 Mapper,非 Mapper0 的游戏(如魂斗罗)也能跑——这比早期 S1 那版只认 Mapper0 强太多。

05操控方式:有线 + 无线,最长 2 人

早期 S1 靠触摸屏操作,手感一言难尽;这版回归实体操控——有线 HID + 无线 UDP,手感正常。怎么玩?两种。

A. 有线(零安装):PC 接上真手柄,打开nes_pad_webhid.html网页(WebHID,浏览器直连,不用装驱动),按键一键转发给板子。网页里还能直接预览 UVC 画面和音频——左边选设备,右边出游戏:

3903e554-dc28-11f1-8a4b-92fbcf53809c.jpg

nes_pad_webhid.html:网页读 UVC+UAC 直接出画面(坦克大战标题),下方是 NES 风格虚拟手柄,键盘 WASD/J/K 也能玩

B. 无线:板子自己开一个 WiFi 热点BL616_NES,手机、电脑、甚至一块 ESP32 小手柄连上来,发 4 字节 UDP 到192.168.4.1:5000,源端口 5001/5002区分 PAD1 / PAD2,于是能 2 人同屏。

396357aa-dc28-11f1-8a4b-92fbcf53809c.jpg

PC 端 UDP 调试工具(连 BL616_NES 热点即用):WASD + A/B/Sel/Sta 点按即发,还有「自动演示」一键跑序列;ESP32 小手柄发的也是同一套 4 字节报文

06烧录与使用

·编译固件:make CHIP=bl616 BOARD=bl616dk

·写游戏(免重编):python tools/flash_rom.py 你的rom.nes一条命令把 ROM 写进 Flash 分区

·拼合并镜像:python tools/make_merged_firmware.py把固件 + 全部游戏拼成单文件

·一键烧录:BLFlashCommand.exe --interface=uart --baudrate=2000000 --port=COMx --chipname=bl616 --cpu_id=ap --config=flash_prog_cfg.ini

·上电:插 USB,电脑识别成摄像头+麦克风,打开相机软件即出画面,上电即进中文游戏菜单

07核心代码:输入源统一

最有意思的一处设计——有线 HID 和无线 UDP 被统一成一个输入源,模拟器核心一行都不用改:

// nes/infones_port.c(节选) // 新增的输入源(无线 UDP)只改这一处,InfoNES 核心零改动 uint8_t pad1_current(void) { return pad_state // 有线 HID 写入的按键 | pad_udp_get_state(0); // 无线 PAD1(UDP server 收到的状态) }

无线端的按键映射也很直白,6 个物理键一一对应「上下左右 + A + B」,全部单键直出:

# nes_pad_udp.py(节选,ESP32 无线手柄端) BUTTON_MAP = ( ("up", BIT_UP), ("dn", BIT_DOWN), ("lt", BIT_LEFT), ("rt", BIT_RIGHT), ("a", BIT_A), ("b", BIT_B), ) # Select / Start 协议里有、物理上没有,用长按补: # b 长按松手 -> Select; a+b 同按 -> Start; b 长按 2s -> 退出

08实测效果

· 插上电脑,设备管理器同时出现摄像头 + 麦克风 + HID 三类设备

· 打开相机软件出 512×480 魂斗罗标题,实测编码 19fps(超出协议声明的 15fps)

· 录音软件收到 NES 五声道 BGM,去直流后不刺耳

· 上电进中文游戏菜单,9 款 ROM 方向键导航、A 进入

· 无线:ESP32 小手柄连BL616_NES热点,4 字节 UDP 操控,PAD1/PAD2 双人

· 换游戏:flash_rom.py一条命令,不用重编固件

实测进行中:坦克大战(非 Mapper0 之外的经典都能跑,魂斗罗同理),WebHID 网页画面 + 虚拟手柄操控,延迟肉眼无感。

09踩坑总结

坑1:画面边缘红绿鬼影

一开始 NES 画面放大后,高对比边缘出现红/绿拖影(chroma ghosting)。根因是色彩范围用了 PC 的 full range + 简单的 1× 复制。改法:用BT.601 studio range + 2× 放大,鬼影消失。现在可放心当卖点。

坑2:音频有直流偏移、低频嗡嗡声

NES APU 混音直出时带直流分量,喇叭会有「噗噗」底噪。在混音后加了一级去直流(高通/减均值),44.1k 立体声输出干净了。

10升级思路|玩出更多花样

·更多 ROM:Flash 分区还有余量,继续塞经典;

·实体手柄:使用 WB2 或者 M61做成真正能握的无线手柄;

·音频升级:APU 接板载 DAC 直推小喇叭,脱离电脑也能外放;

最后说两句

USB-NES 最爽的点在于:它把你手里吃灰的 Ai-M61/M62 板子变成了能插电脑就玩的红白机——不用屏幕、不用小安派 S1、魂斗罗也能跑,打火机大小挂钥匙扣上。从「编译固件」到「写游戏进 Flash」再到「插上电脑就能玩」全链路可控。一根 USB 线,电脑认成摄像头,里面却在跑魂斗罗——这种「骗过操作系统」的硬核浪漫,比刷一百个短视频都强。

如果你手上有块吃灰的 Ai-M61/M62 想让它复活,欢迎参考这个项目。有任何问题评论区留言,一起交流~