跳到主要内容

把机型枚举砍到只剩一个

原石
原石

· 阅读约 5 分钟

先贴一行。

enum psp_model {
    PSP_1000,
    /* 2000、3000、Go —— 没写。不是漏了。 */
};

PSPi 6 拿一块自己画的板子把 PSP 1000 的主板整块替换掉,中间坐一块树莓派。仓库第一屏就把兼容性写死了:只吃 1000。我看到这行的反应是,这作者想清楚了。多数项目反过来,先画三张渲染图,兼容性留到最后“逐步适配”,适配到项目死掉为止。

只留一个机型,省下的不是一行枚举。换一代机型,屏幕排线、扬声器位置、摇杆座、螺丝柱,至少有一半要重新对一遍。多留一个 case,就是多一版 PCB、多一套结构件、多一条测试矩阵。它现在这个组合已经够大了——三种树莓派方案(Zero、Zero 2W、CM4 载板)乘上六七个发行版,就是一张表。

for board in zero zero2w cm4; do
  for os in retropie lakka ubuntu rpios batocera kali; do
    ...
  done
done

再多一个机型,这张表整个乘六。砍机型不是懒,是把测试矩阵从二维压回一维。

至于为什么是 1000——我猜是初代壳最厚、内部空间最宽松。这段我没跟作者聊过,纯属从 README 的措辞倒推,别当事实。

兼容性要分层

清单里有一句我觉得最值钱:电气上兼容所有 40 针树莓派,但只有 Zero 和 Zero 2 装得进 PSP 的壳。

struct carrier {
    int header_40pin;   /* 电气:全系都有,一排孔的事 */
    int fits_shell;     /* 机械:只有 Zero / Zero 2 */
    int thermal_ok;     /* CM4 那块,还得看载板怎么排 */
};

接口兼容是三种兼容里最便宜的一种。它就是一排 2.54 的孔,间距对了就对了,不需要你理解对面那块板子在干什么。真正贵的是机械兼容:高度、螺丝孔、排线出口、按键的行程空间。这三样里任何一样差两毫米,你手上那块板就是废的。

太多人把“接口对上了”当成“能用”。软件里也一样——两个模块的 API 签名对上了,就以为集成了,跑起来才发现一边要的是阻塞语义,一边给的是回调。40 针是签名,装不进壳是语义。

预留两个按键,这次我不批评

我平时看见“预留扩展接口”就想关页面。软件里每多一层为未来准备的抽象,今天的每个读者都要为它付一次解读成本,而那个未来多半不来。

但 PSPi 6 这块板子上预留了两个额外按键和一个额外摇杆的焊盘,我一点意见都没有。

/* 原装件:直连,一个也不重新发明 */
#define N_FACE      4
#define N_SHOULDER  2
#define N_STICK     1

/* 多出来的,空着 */
#define N_AUX_BTN   2
#define N_AUX_STICK 1

区别在成本模型。软件里加一层抽象,是持续付账:每个调用点付一次,每个新来读代码的人再付一次。硬件上多留两个焊盘,是一次性的两平方毫米铜。你不用它,它就在那儿待着,不占任何人的阅读路径。

判断标准不是“有没有预留”,是“这个预留会不会变成别人的必读路径”。不会,留着;会,删掉。

单声道不欠谁的

Zero 和 CM4 载板那两版是单声道,Universal Carrier 才补第二路。我不觉得这是妥协。掌机外放就是个巴掌大的腔体,多一路功放要多一颗芯片、多一对走线、多一个混音分支,换来的声场在一个三厘米的喇叭间距上能有多少,自己算。

真正决定体验的不是外放几声道,是那两个音量键和静音键有没有接进固件里。

struct audio_state {
    int volume;   /* 0-100,PSP 音量键直接改这个 */
    int muted;
};

这东西必须是硬键,不能是系统里的一个滑块菜单。掌机的用法是拇指盲操,眼睛盯着屏幕,手指在边上摸。你要是把它做成“打开设置 → 声音 → 调”,那这块板子就白换了。

还有一件 README 没强调,但我得说:装上完整发行版之后,它先是一台 Linux,然后才是一台掌机。开机、桌面、点图标、进游戏。想要秒进游戏,就刷 Lakka 那种只做一件事的系统。别两个都要。

电源那块最容易写歪

充电、实时电量、节能模式,听着像三个功能,其实是一个状态机。

struct power {
    int charging;
    int battery_mv;
    int battery_pct;
    int low_power;    /* 触发:降频 + 背光调暗 */
};

电量不是读一个 GPIO 就完事。ADC 采到的电压在负载下会往下掉,跑模拟器的时候掉得更凶。直接拿单次电压查表,结果就是插着电玩游戏,电量从 60% 跳到 20% 又跳回去。

这种活儿我写过。第一版读一次就判断,跑起来直接给我关机。后来改成连续采样取中位数,加一个 3% 的滞回带,才不抽风。没什么高深的,就是别信单次采样。

背光也别上什么 I2C 背光控制器。一路 PWM,一个占空比,够了。800x480 那块屏选得也是这个路子——不是因为它参数好看,是因为它到处都有、驱动现成、不用你养一份面板初始化序列。选组件的标准是“以后不用我管”。

开源硬件看 boards 目录

判断一个开源硬件项目是真是假,别看许可证写得多正式。看它有没有一个能直接丢给板厂的目录。

boards/
├── pspi6-zero/
├── pspi6-cm4/
└── universal-carrier/

每个目录里得有 Gerber、BOM、坐标文件。作者自己说他用 JLCPCB 打的板——这句话比任何“开源”标签都值钱,它说明这些文件是给人下单用的,不是给人看图用的。CC BY-SA 谁都会写一行,能下单的文件不是谁都有。

718 次提交。这个数字说明那块板子改过很多遍。我信“改三遍”,不信“一次画对”。

说句题外话。我喜欢这种换主板的思路,原因不在硬件。它没有重新发明外壳,也没有重新发明按键和那块屏幕。它复用的全是已经躺在机器上的东西,只换掉唯一该换的那一层。软件里最好的重构也是这个形状:不是重写,是把那层不该在的换掉,其余原封不动。

兼容性是拿成本换的,硬件上拿模具费换,软件上拿每个读者的脑细胞换。花之前先问一句——换来的那个机型,现在有人拿在手上吗。

原石
原石

把代码当文章写的系统工程师,以源码立论、单线程式拒绝复杂度。

查看主页 →