复古游戏掌机

60 多年过去了,尽管辉光管已经停产,有很多工程师仍然对它情有独钟。我用 8 块液晶显示屏制作了一个拟辉光管时钟,感受复古元素的美感,表达对过去经典的敬意。

这是一款基于ESP32的开源复古游戏掌机,是很多年前的一个开源项目,我在开源项目基础上做了一些优化,更改了显示屏硬件,重新绘制了PCB,对原作者表示感谢!

复古游戏掌机使用Arduino IDE编程,游戏文件存放于存储卡中,支持游戏选择,理论游戏数量有很多,可以畅玩很多经典游戏,是一款儿时梦寐以求的指尖游戏机,一秒找回童年记忆。

演示视频

材料介绍

主控

复古游戏掌机主控采用 ESP32-WROVER-E 模 块( 见 图 1),ESP32-WROVER-E 采用的芯片是ESP32 系列的 ESP32-D0WD-V3。ESP32-D0WD-V3芯片具有可扩展、自适应的特点。两个 CPU 可以被单独控制。CPU 时钟频率的调节范围为 80~240 MHz,集成了丰富的外设,包括电容式触摸传感器、霍尔传感器、Micro SD 卡接口、以太网 接 口、 高 速 SPI、UART、I2S和 IPC 等。模块集成了传统蓝牙、低功耗蓝牙和 Wi-Fi,具有广泛的用途。

打开网易新闻 查看更多图片

图 1 ESP32-WROVER-E 模块

选 用 ESP32-WROVER-E 模块除了功能强大,还有一个重要原因是这个模块拥有片外内存区 —— PSRAM,对于游戏文件超过 1MB 的情况就需要片外内存区了。这个模块PSRAM 大小有 8MB,有 4MB 可用,足够 1M 大小的游戏文件运行了。

液晶显示屏

显示屏使用 3.2 英寸液晶显示屏( 见 图 2), 分 辨 率 为 320 像素 ×240 像 素, 驱 动 芯 片 型 号 为ILI9341,ILI9341 驱 动 芯 片 提 供 8位 /9 位 /16 位 /18 位的并行 MCU 数据 总 线,6 位 /16 位 /18 位 RGB 接口数据总线以及 3 线 /4 线 SPI 接口,本项目采用通信方式为 4 线 SPI,接口方式为 40Pin 插接式。

打开网易新闻 查看更多图片

图 2 3.2 英寸液晶显示屏

无声贴片开关

复古游戏掌机按键采用无声 贴 片 开 关( 见 图 3), 大 小 为6mm×6mm×5mm,这款开关按力均匀,手感柔软均匀舒适,寿命在 20万次以上。

打开网易新闻 查看更多图片

图 3 无声贴片开关

电路设计

主控部分

ESP32-WROVER-E 模 块 的引脚分配给按键、显示屏和存储卡模块,主控电路如图 4 所示。

打开网易新闻 查看更多图片

图 4 主控电路

下载电路

本项目使用 CH340C 芯片,该芯片内置晶体振荡器,可以省去晶体振荡器电路,价格便宜,电路简单,配合三极管可实现自动下载功能,下载电路如图 5 所示。

打开网易新闻 查看更多图片

图 5 下载电路

供电及稳压电路

供电电路使用了 2 个 Micro USB接口,方便后期从上下两个方向供电。稳压电路使用 LM1117S-3.3 芯片,这是一种常见的稳压芯片,价格便宜,电路简单,供电及稳压电路如图6所示。

打开网易新闻 查看更多图片

图 6 供电及稳压电路

存储电路

掌机存储电路的卡座采用的是市面上常见的 Micro SD 卡卡座,体积小,通信接口为标准 SPI 接口,通过文件系统及 SPI 接口驱动程序,单片机系统即可完成 Micro SD 卡内的文件读写,存储电路如图 7 所示。

打开网易新闻 查看更多图片

图 7 存储电路

锂电池充电电路

锂电池充电电路里使用了TP4056 芯片,TP4056 是一款完整的单节锂电池恒定电流 / 恒定电压线性充电芯片。充电电压固定在 4.2V,而充电电流可通过一个电阻进行外部设置,在充电状态时,充电指示灯 LED4(红色)亮;充满电后 LED4 灭,待机指示灯 LED3(绿色)亮。TP4056 芯片采用 ESOP8 封装,配合较少的外围元器件使其非常适用于便携式产品,并且适合给 USB 电源以及适配器电源供电,锂电池充电电路如图 8 所示。

打开网易新闻 查看更多图片

图 8 锂电池充电电路

音频电路

音频电路中使用了一个8Ω/1W、直径为 13mm 的扬声器用于播放游戏背景音乐,用一个开关控制扬声器是否工作,电路中留出两路供电电路来选择扬声器的音量,音频电路如图 9所示。这只是个简单的音频电路,俗话说“听个响”,但是这种复古音质正好和复古游戏呼应,相得益彰。

打开网易新闻 查看更多图片

图 9 音频电路

显示屏驱动电路中采用了一个0.5mm 间距 FPC 上接抽拉式贴片连接器,通过短接开关可选择 4 线SPI 连接方式,电路中还引出了两组显示屏接口,接口顺序和市面上其他常见显示屏模块的引脚顺序相同,通过修改程序,可以兼容更多 4 线SPI 驱动的显示屏,显示屏驱动电路如图 10 所示。

打开网易新闻 查看更多图片

图 10 显示屏驱动电路

PCB设计

为了方便电路板打样,我把电路板的长宽都限制在边长为 10cm 的正方形里,所以 PCB 设计时,所有元器件采用旋转 45°放置的方式,充分利用正方形的对角线长度,液晶显示屏居中放置,操作按键在显示屏两侧。PCB整体布局如图 11 所示,PCB 整体效果如图 12 所示。

打开网易新闻 查看更多图片

图 11 PCB 整体布局

打开网易新闻 查看更多图片

图 12 PCB 整体效果

程序介绍

编程环境

使用 Arduino IDE 1.8.16 版本,软件中的开发板管理器 ESP32 库版本为 1.0.6(见图 13)。

打开网易新闻 查看更多图片

图 13 Arduino IDE 版本以及 ESP32 库版本

源程序说明

源程序文件包含如下内容。

● esp32gamepad.ino :主文件。

● controller.cpp:控 制 器, 主要是按键类型和摇杆类定义。

● display.cpp:显 示 屏 驱 动文件。

● hw_config.h:文件系统定义、音频引脚及按键引脚定义。

● osd.c :操作系统处理函数。

● sound.c:音频系统函数。

一般只需要修改 esp32gamepad.ino、display.cpp、hw_config.h 这 3个文件即可。

程序编写

1. 导入库和选择开发板类型

这 个 项 目 中 使 用 了 Arduino_GFX 库 和 arduino-nofrendomaster 库,需要将下载好的库文件放置在 Arduino IDE 的 libraries 文件夹中,否则会编译失败。

Arduino 编译时,开发板类型选择 “ESP32 Wrover Module”( 见图 14)。

打开网易新闻 查看更多图片

图 14 选择开发板类型

2. 自定义按键

按照原理图对游戏掌机的按键进行定义,如程序 1 所示。

打开网易新闻 查看更多图片

显示屏移植

原 项 目 使 用 的 是 ST7789 驱 动的 2.4 英 寸 液 晶 显 示 屏, 我 这 里 改成 ILI9341 驱动的 3.2 英寸液晶显示屏,所以程序中需要修改,需要注意的是原项目中定义总线类型的语句中,IPS 是否为高清屏的内容改成Arduino_ILI9341 驱动后需要删除,因为库文件中没有相关的定义,不修改编译无法通过,原项目相关程序如程序 2 所示,移植后的程序如程序3所示。如果需要其他类型显示屏,可在 Arduino_GFX\sr\display 这个文件夹中查找,有列的就是支持的。

打开网易新闻 查看更多图片
打开网易新闻 查看更多图片
打开网易新闻 查看更多图片

复古游戏掌机的使用

(1)准备一张 Micro SD 卡,格式化成 FAT32 格式,将提前下载好的扩展名是 .nes 的游戏文件复制到存储卡根目录,游戏名用英文。

(2)开机后显示屏上如果提示“Filesystem mount failed! try to restart.”,说明存储卡挂载失败,可以尝试断电重启,若两三次重启后仍然无法使用,请检查存储卡或者电路。

(3) 开 机 存 储 卡 挂 载 成 功 后会显示一张图片,显示屏上方显示“waiting”字样。

(4)在“waiting”字样界面下,使用 left 和 right 按键可以调整亮度,立即生效,亮度最小 10,最大 255,支持重启后记住之前的设定值。

(5)在“waiting”字样界面下,按一次 A 键,则会浏览根目录文件,如果不是游戏文件,则会显示“Not a game file, please select again.”,需要继续按 A 键继续选择,直到出现.nes 的游戏文件。

(6)出现 .nes 游戏文件名显示后,按 mode 按键确认即可开始游戏。

(7)进入游戏后根据游戏中的按键提示进行操作即可。

成果展示

制作完成的复古游戏掌机如图 15所示。

打开网易新闻 查看更多图片
打开网易新闻 查看更多图片

图 15 NES 游戏掌机

复古游戏掌机做完后,我迫不及待打开了小时候玩的第一个游戏,伴随着熟悉的背景音乐,以一种老玩家从容不迫的心态无伤通过了第一关,一切都是那么熟悉,此时手里捧着的不再是一台游戏机,而是童年时期的梦想。

现在,画面震撼、玩法多样的游戏每年都会推陈出新,自制游戏机项目每年也在不断革新,我在自己能力范围内制作了属于自己的复古游戏掌机,也算是还了一个“童年债”。每次玩起这些老游戏,我总能想起那些遥远的、计算机还没普及的寒暑假,打开游戏机,选择好上次没能通关的游戏,那时候我最不缺的就是时间。