How to build a printer
450 points • 5 days agoArticle Link

一切始于 Xteink X3,这款可完全编程的电子墨水阅读器天然适合做各种实验。给固件加了开机动画、掷骰子等小功能后,通过浏览器热点传文件变得越来越让人抓狂。既然它外观像纸张,最直观的想法就是让它像纸一样原生支持打印。

为此的目标是让 MacBook 把它识别为一台真正的打印机,需要用到 Internet Printing Protocol (IPP),该协议通过 HTTP 通信,用于查询打印机能力和提交作业。硬件被配置为以设备名 penguin 广播自己,声明单色 300 dpi 输出及 Apple 、 PWG raster 等格式;通过实现 Bonjour discovery,在网络上宣告服务,从而把电脑"骗"成把它当成一台无驱动的通用打印机来处理。

最大的技术难题是内存管理:一张标准信纸、 300 dpi 的未压缩数据超过 8 MB,而 X3 只有 400 KB RAM 。解决办法不是把整页放进内存,而是把页面当作流来处理。构建了一条转换管道,按行解码并抖动图像,直接写入显示器预留的内存,这样可以增量地拼接页面。借助显示器现有架构的这一巧妙做法,大幅降低了内存需求,为网络栈处理传入数据腾出了空间。

做完这些优化后,MacBook 的系统对话框能成功检测到这台"打印机"。第一次测试是用 Preview 打印一页漫画,电子墨水屏上呈现出清晰锐利的图像。这个过程既实用又有成就感,把阅读器变成了能通过 Wi‑Fi 接收文档的多功能工具。

除了显示当前打印内容,系统还把每个作业以 BMP 文件归档到设备的 SD 卡上,相当于建立了一个数字输出托盘,用户可以在阅读器上直接浏览过去的打印件。包括自定义打印服务器和必要的网络配置在内的整套实现,证明了通过改造标准协议能为熟悉的硬件赋予全新的功能。

107 comments • Comments Link

- 在 `media-size-supported` 中定义精确的设备尺寸,可以让系统在不缩放的情况下把内容准确格式化到屏幕;同时使用 1-bit-per-pixel 模式和 `bi-level` 颜色设置,能显著减少数据量和传输负载。

- 管理打印堆栈往往要处理多年积累的技术债务,这通常需要深入的技术研究和定制化解决方案,因为现有标准复杂且社区支持薄弱。

- 从 VSCode 或 Obsidian 等现代桌面应用直接打印的困难,反映出现代软件生态对通用打印支持的关注在下降。

- 通过创建 CUPS backend,可以把定制硬件整合到现有打印架构中,允许用户从任何具备打印功能的应用向专用 e-ink 设备发送文档。

- 开发模拟纸张交互的打印机界面对阅读菜谱等特定场景非常有效,它省去了手动传输文件的繁琐,也避免把智能手机带入凌乱环境的风险。

- PDF 渲染计算量大且占用大量内存,对 RAM 有限的小型微控制器并不实用,这也解释了为什么此类硬件更倾向于使用更简单的直接 raster 数据流。

- Apple Raster 、 PWG Raster 和 PCLm 等打印协议通过把繁重工作交给主机来简化通信,从而保证了 AirPrint 和 Mopria 等免驱打印标准之间的兼容性。

- e-ink 爱好者把 X3 和 X4 等设备视为摆脱智能手机干扰的有价值工具,常把便携性和专注的阅读体验作为重要的生活方式优势。

- DIY 打印机项目面临的技术挑战通常被视为维护遗留系统时不可避免的副作用,虽然令人沮丧,但也催生了一个愿意分享底层优化策略的社区。

本次讨论强调了底层硬件限制与对无缝用户体验需求之间的冲突。参与者指出,尽管 IPP Everywhere 和各种 raster 格式等现代标准简化了打印流程,但在资源受限的微控制器上实现这些标准仍是一项复杂且需深厚技术专长的任务。共识是,要实现用户层面的简便(例如能直接"打印"到 e-ink 显示器),通常必须在幕后进行重大的架构创新,以规避旧协议和硬件规格的限制。