当前位置:首页 > 工业控制 > 电路设计项目集锦
[导读]最近我入手了一款M5PaperS3,它是一款形似便携式电子阅读器的ESP32-S3开发套件,配备一块4.7英寸960×540分辨率的Eink触摸屏。与其他小型Eink开发套件相比,它的特别之处在于屏幕采用了原始行/列驱动接口(在讨论Eink屏幕时,这种接口也常被称为并行接口,但与LCD屏幕上的并行接口并不相同)。这让我能够通过绕过常规波形方法来驱动该屏幕,从而实现高达60fps的高刷新率。关于这一点,稍后再详谈。这让我开始思考:除了编写电子阅读器应用程序之外,还能用它做些什么有趣的事情呢?几年前,我曾重新实现过GameBoy的FPGA版本,因此可以说我对GameBoy架构至少有一定的了解。那么,将两者结合起来会怎样呢?

引言

最近我入手了一款M5PaperS3,它是一款形似便携式电子阅读器的ESP32-S3开发套件,配备一块4.7英寸960×540分辨率的Eink触摸屏。与其他小型Eink开发套件相比,它的特别之处在于屏幕采用了原始行/列驱动接口(在讨论Eink屏幕时,这种接口也常被称为并行接口,但与LCD屏幕上的并行接口并不相同)。这让我能够通过绕过常规波形方法来驱动该屏幕,从而实现高达60fps的高刷新率。关于这一点,稍后再详谈。这让我开始思考:除了编写电子阅读器应用程序之外,还能用它做些什么有趣的事情呢?几年前,我曾重新实现过GameBoy的FPGA版本,因此可以说我对GameBoy架构至少有一定的了解。那么,将两者结合起来会怎样呢?

我在网上搜索,却从未有人尝试过制作这样的东西。因此,我非常有动力在PaperS3上创建第一个GameBoy模拟器,并让它真正能够运行起来!

Eink 驱动器

我首先着手开发的是高刷新率的Eink驱动器,因为这个组件决定了这个项目能否成功。

Eink 通常被认为响应较慢:刷新率低,响应速度慢。这通常是正确的,因为 Eink 面板内部的彩色粒子移动速度确实很慢,通常需要约 100 毫秒才能改变颜色,因此刷新频率约为 10Hz。这种缓慢的响应和较长的延迟是其副作用所致:用户可能需要等待长达 100 毫秒,屏幕才显示图像。如果操作系统使用了三重缓冲技术,则会进一步增加 100 毫秒的延迟。

许多现有的快速刷新策略本质上都是在缩短驱动时间。例如,如果仅将屏幕驱动50毫秒,就能将帧率提升至20fps,但代价是对比度降低(因为像素未能完全驱动)。然而,这种方法的极限是有限的:即使使用最新的Carta 1300屏幕并采用IGZO背板,在±24V驱动电压下,也只能将刷新率推高到30Hz,之后画面会变得过于模糊而无法使用。M5PaperS3则采用较老一代的屏幕(Carta 1000,驱动电压为±15V),其最高刷新率约为15fps。

但仍有办法让它正常工作。你看,Eink 的刷新率很慢,只有 100 毫秒。但这并不意味着你必须将帧率限制在 10Hz 才能获得 100 毫秒的驱动时间。它也可以是每 60Hz 刷新 6 帧。实际上,出于各种原因,屏幕驱动器内部的运行方式就已经如此。但控制器会每 6 帧才接收一次新图像,就像全局锁定一样,从而表现出 10Hz 的行为。但如果去掉这种锁定,让控制器每帧都接收一次新图像,我们就能解锁 60Hz 的刷新率了。

这完全有可能。但需要付出的代价是,现在你需要跟踪每个像素的时间,以确保它们总共仍能连续驱动6帧。这需要为每个像素添加一个新的状态缓冲区,用于读取和写入。而全局锁方法只需一个计数器,每帧更新一次。因此,这种方法显然并不免费。根据平台不同,这种开销可能非常高(例如在低端微控制器上,或高端微控制器但SRAM容量有限、PSRAM带宽受限的情况下)。

但我们在Eink屏幕上能获得流畅的60帧每秒,如同黄油般顺滑:

那是我在2022年做的一个FPGA演示。之后,我将这个演示改造成了一款基于FPGA的Eink显示器,名为Modos Flow。现在我们只需看看是否能在ESP32上实现同样的功能。

幸运的是,这个项目并不需要以全屏像素速率进行处理。GameBoy 只有 160x144 像素的分辨率。我需要用 3 个像素来表示 4 种灰度,通过将抖动图像复制 3 次,就能实现 3 倍像素的完美缩放,并保留抖动效果。这意味着我只需在 60Hz 下处理 160×3×144 像素,这比 960×540 在 60Hz 下的目标低得多。这也意味着我的所有缓冲区都可以完全存放在 SRAM 中,无需将数据写入速度较慢的 PSRAM。我做了一些性能测试,当前在 480×144 分辨率下运行的代码仅使用了 CPU 时间的约 50%。虽然这并不算特别优化,但也能大致反映出我们距离全分辨率还有多远。

我每像素存储4位状态,用于统计像素的状态。该状态与输入缓冲区进行比较,以决定向屏幕发送什么内容。通过LCDIF + DMA技术将像素实际输出到屏幕,使核心能够计算下一批要显示的像素。整个过程在ESP32的第二个核心上运行,每次迭代设置为约1/60秒,从而实现60Hz的刷新率。同时实现了双缓冲机制,使得第一个核心上的模拟器也具备60Hz的时间基准,使其能够支持垂直同步的图像渲染。

GameBoy 模拟器

虽然我过去曾实现过一个GameBoy模拟器,但那也是基于FPGA的。而微控制器上的GB模拟器已经被多次实现了,因此我决定使用现有的模拟器,而不是自己重新发明轮子。

Peanut GB 看起来是最受欢迎的模拟器选项,在微控制器上性能表现良好。

Walnut CGB 是 Peanut GB 的一个分支版本。它修改了模拟器,使其执行 16 位指令加载而非 8 位加载,从而可能节省内存访问时间,主要通过减少内存访问次数来优化昂贵的模拟内存映射路径。

CrankBoy 是 Playdate 项目中 Peanut GB 的一个分支,提供了专为 Playdate 设计的完整优化版 GB 模拟器。该版本在移植过程中进行了大量优化,特别是在内存映射路径方面,使得性能大幅提升,同时避免了 Walnut CGB 中较为特殊的双读取架构带来的问题。

我在ESP32-S3上试用了它们,并在多个游戏标题中测试了模拟速度。以下是测试结果:

性能以GameBoy为基准进行衡量。1表示其运行速度与GameBoy大致相同。

因此,我使用了性能最强的CrankBoy作为模拟核心。通过动态帧跳过(即当模拟器出现延迟时,仅进行模拟运算而不输出到屏幕,从而节省几毫秒以追上进度),它能在许多游戏中达到100%的速度,并以30-60帧每秒的速率进行渲染。实际帧率在很大程度上取决于运行时的具体情况。

目前的性能下,暂时启用GBC支持(可让CPU以双倍时钟频率运行)显得不太现实。我们需要更强大的技术来让GBC以合理速度运行,或使GB游戏在60帧/秒时表现更加稳定。

声音

这三个模拟器都使用 minigb-apu 作为声音模拟引擎。GB 内部集成了一个 4 通道的 PSG(可编程声音发生器),包括 2 个方波通道、1 个采样通道和 1 个噪声通道,这四个通道随后被混合以生成声音输出。在真正的 GB 中,部分混音过程发生在模拟域,但通常对于模拟器来说,最简单的方法是将所有内容直接以 32.768kHz 的采样率转换为 PCM 采样数据播放。现代所有声卡都能播放 PCM 采样数据。

然而,PaperS3的情况并非如此。PaperS3仅配备了一个蜂鸣器,当PWM驱动时只能发出单一频率的音调。一种常用的方法是利用PWM DAC输出PCM采样数据。基本做法就是直接将PCM样本发送到PWM模块中作为占空比(并将波形偏移128位以实现直流偏置)。但ESP32-S3的PWM模块无法通过DMA接收输入,必须通过轮询或在采样率时生成中断来更新占空比寄存器。这两种方式都需要我预留一些CPU周期专门用于声音输出。(注意,默认情况下,ESP32的中断处理速度较慢,这是由于上下文切换和中断调度所致。虽然可以设置32kHz中断,但成本会很高。)因此,我选择了I2S外设的PDM输出功能。该功能原本设计用于连接支持PDM的DAC/放大器,但你也可以简单地加一个RC滤波器,使其自身就成为DAC。我先实现了这个方案,立刻就能正常工作。但问题在于……声音实在太小了。如果处于非常安静的环境中,听起来还算能察觉;否则,几乎就像被静音了一样。我原以为可能是由于调制频率太高(4MHz),导致BJT进入线性区域,所以我也尝试了仅使用32kHz的PWM,但效果并无明显改善,因此我决定继续使用PDM。

但我感觉这还不够。虽然确实有声音,但如果在很多情况下听不到,那也就没什么用处了。要发出足够响亮的蜂鸣声,几乎必须使用单一频率的声音,而这正是它最初设计的目的。那么,为什么不干脆直接使用单个音调呢?要知道,在GameBoy的PSG芯片中,前两个通道是纯正的方波。采样通道也可以用方波来近似(假设游戏用它输出的是正弦波、三角波等)。如果我们把噪声也换成方波(说实话这个想法有点牵强),那就只有四个方波通道了。尽管蜂鸣器只能发出一个音调,但我们可以快速切换多个声音通道,从而产生一种伪多声部效果。这种技术在那些只配备单个蜂鸣器的平台上非常常见,比如没有声卡的IBM兼容电脑。至于效果,我觉得结果出人意料地不错,同时也有不足之处。优点是声音响亮清晰,游戏音乐依然很容易辨认,整体听起来也很有趣。缺点嘛,GameBoy本来就不该发出这样的声音。

为了确保这些操作不会占用有限的CPU资源进行模拟,我将整个PSG模拟器部署在第二核心上。根据对部分游戏的性能分析,PSG模拟器通常每帧最多运行2毫秒,具体取决于声音的复杂程度。

输入

输入方式相当简单。M5PaperS3配备触摸屏,因此在屏幕上直接显示一个触摸式摇杆是顺理成章的。

对于严肃的玩家(???),我已添加了实验性的蓝牙LE手柄支持。虽然它并未完全实现HID协议,仅对报告格式进行猜测,因此兼容性较差。我认为作为演示版本是可以接受的,但肯定还有改进空间。

JIT 2 假期

CrankBoy 的性能已经相当不错,但绝不能说是稳定可靠的 60fps。在游戏过程中,由于 CPU 模拟速度过慢,帧率经常低于 60fps。虽然听起来很奇怪——一个 240MHz 的 Xtensa LX7 无法以全速模拟 4MHz 的 GameBoy CPU,但这正是我们目前的现状。为了进一步提升性能,必须进行一些重大的优化工作。

一种选择是使用即时(JIT)动态重编译器。JIT重编译器会将GameBoy CPU的指令重新编译为Xtensa LX7的指令集,从而使ESP32能够原生执行这些指令,而无需经过解释器。

开发一个真正稳定且高效的即时编译器是一项庞大的工程。

虽然游戏兼容性尚未经过充分测试,但已能成功启动的部分游戏显示出不错的运行速度提升。这在一定程度上证明,结合60Hz屏幕驱动程序,应该能够开发出一种固件,使GameBoy游戏的运行速度接近100%。

保存数据

Game Boy 没有内置的非易失性存储,保存状态存储在卡带中。因此,要让保存的数据在重启后仍然保留,只需将其保存到 SD 卡上即可。简单对吧?其实不然。

将数据保存到SD卡上是容易的部分,问题在于什么时候保存。有些游戏会提供明确的存档菜单,但并非所有游戏都如此。游戏卡带上的硬件通常只是一个由电池供电的SRAM,甚至可能根本没有电池支持,如果游戏只是需要额外的RAM空间时就更常见了。模拟器或许可以根据卡带RAM写入模式的启发式判断,来决定何时将数据刷新到SD卡(例如最简单的形式:如果过去两秒内没有发生更新,就立即刷新)。但这听起来并不可靠:如果我在它完成刷新前关闭了它怎么办?如果游戏每秒持续向卡带RAM写入数据,导致从未触发刷新,又该怎么办?作为玩家,丢失存档数据是我最不想看到的情况之一。当然,我并不是说自动保存不可能实现。我认为这是可行的,而且如果做得恰当,效果可能会非常好。不过我还没有尝试过。

另一种选择是设置一个明确的事件来触发保存,最常见的就是关闭模拟器。但在M5PaperS3上这并不可行,因为S3的电源按钮直接切断电源,而不是尝试优雅地关机。S3甚至不知道自己即将被关闭,更不用说将保存状态刷新到SD卡了。因此我不得不在设备上添加一个保存按钮,明确要求用户按下该按钮以关闭机器。虽然看起来不太美观,但这样就解决了问题。

为了让按钮功能更实用,我添加了另一个功能:快速保存和快速加载。该功能可以存储并加载整个模拟GameBoy的游戏状态,从而快速创建存档点并返回。保存和快速保存使用同一个按钮,按下即可完成两者操作。因此,下次你拿起PaperS3时,只需使用快速加载就能立即回到游戏。

结论

总之,我认为最终成果是一款相当不错且可用的GameBoy模拟器,适用于M5PaperS3,同时也将Eink屏幕发挥到了极限。遗憾的是,PaperS3已经到达了生命周期末期,希望我们能很快得到一个真正合适的替代品!

本文编译自hackster.io

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
换一批
延伸阅读

在这个项目中,我打造了Sentra——最智能的DIY监控摄像头,这是一款基于ESP32-S3构建的全电池供电智能安防系统。Sentra将实时Wi-Fi视频流、持续的SD卡录像、运动检测、自动夜视、实时声音监测,甚至机器人...

关键字: Wi-Fi 流媒体 ESP32-S3

ESP32-S33 引入了一项许多创客忽略的功能——原生 USB 主机支持。虽然大多数项目仅将 USB USB USB 端口用于编程或串行通信,但 ESP32-S3 实际上能够作为 USB 主机,直接与键盘、鼠标、游戏手...

关键字: USB 端口 微型计算机 ESP32-S3

我们大多数人都会打开任务管理器或查看副显示器来检查电脑性能,这总是意味着盯着又一个亮着背光的屏幕。我想要的是一种不同的方式——一种能安静地放在桌面上、实时显示电脑运行状态,并且不会给工作区增添更多屏幕眩光的东西。

关键字: 显示器 ESP32-S3 PCB

该项目最初旨在通过构建一款便携式陪伴机器人,将定制硬件、嵌入式软件、娱乐功能和交互式应用整合到一个平台上,从而在现实生活中重现这一概念。

关键字: 机器人 ESP32-S3 FreeRTOS

我患有注意力缺陷多动症(ADHD),我尝试过大多数常见的提高效率的方法:应用程序、计时器、闹钟、便签纸、白板。但真正起作用的还是携带一本实体笔记本。把事情写下来,把清单直接摆在眼前,没有任何通知干扰,也没有需要打开的应用...

关键字: 任务管理器 ESP32-S3 印刷电路板

我想要更深入地了解射频系统、电源管理、印刷电路板布局以及便携式通信设备,所以我没有购买现有的 Meshtastic 节点,而是完全从零开始在 KiCad 软件中设计了自己的设备。

关键字: 射频系统 电源管理 印刷电路板 ESP32-S3

我一直乐于将“识别”这一概念拓展得更丰富——将其转化为一种能够实时响应用户的互动体验。这一次,我将格罗夫视觉人工智能 V2、XIAO ESP32-S3 和 Processing 结合在一起,创建了一个类似《水果忍者》的互...

关键字: 人工智能 ESP32-S3

“Project Aura”是一款基于 ESP32-S3 平台的开源空气质量监测设备,配备了工业级的 Sensirion 传感器、一块 4.3 英寸的 IPS 触摸屏、无焊点组装工艺,并且通过 MQTT 协议实现了与 H...

关键字: ESP32-S3 传感器 IPS 触摸屏

物联网设备智能化,TinyML(微型机器学习)技术通过将轻量级神经网络部署到资源受限的边缘设备,实现了从“感知”到“认知”的跨越。ESP32-S3作为乐鑫科技推出的旗舰级Wi-Fi/蓝牙双模芯片,凭借其双核Xtensa...

关键字: ESP32-S3 Ethos-U55

开源硬件生态以共享设计文件为核心,通过社区协作推动硬件创新。其核心特点包括设计透明性、组件互操作性和社区参与性。设计透明性使开发者能直接查看硬件工作原理,例如ESP32-S3的电路原理图和PCB布局文件完全公开,开发者可...

关键字: Arduino ESP32-S3
关闭