niazlv/nrf52-eink-price-tag
GitHub: niazlv/nrf52-eink-price-tag
该项目对无文档的廉价电子货架标签进行逆向工程,为 nRF52832 和 SSD1675A 电子纸面板开发了支持 BLE 控制与泛洪 mesh 的开源固件及可移植 C99 显示驱动库。
Stars: 0 | Forks: 0
# nRF52 电子纸标签
这是一款被重新利用的 2.9 英寸黑-白-红 (BWR) 电子货架标签的固件 —— 一颗 nRF52832 芯片,通过 BLE 驱动 SSD1675A 电子纸面板,整个开发过程没有任何厂商文档可供参考。
这些面板是从分类广告网站上花几分钱买来的一堆闲置价格标签,既没有文档、没有 SDK,也没有愿意提供解答的厂商。
这里的所有内容 —— 引脚定义、波形表、刷新模式、流媒体传输路径 —— 都是在工作台上逆向工程得出的,并记录在 [`docs/`](docs/) 中。
关于如何破解这些标签的故事(俄语):
[Как я купил кота в мешке: реверс-инжиниринг электронных ценников](https://habr.com/ru/articles/1044406/)。
## 功能说明
- 在 128×296 黑白红面板上渲染时钟 / 状态 / 屏幕保护界面
- 在经过原始全屏刷新耗时约 9 秒后,通过 BLE 以每帧约 110 ms 的速度向面板流式传输动画和视频
- 通过 Nordic UART Service 接收来自 CLI、桌面 GUI 或[在线 Web 应用](https://pwa.price-tag.sorewa.ru/)的命令
- 通过该 Web 应用进行空中升级(基于 MCUboot,支持双变体签名)
- 通过无连接的泛洪 mesh 网络在标签之间中继命令,因此只需一部手机连接即可覆盖整个标签群
## 核心亮点
- [`lib/`](lib/) —— 显示驱动和绘图代码,作为一个**可移植、无外部依赖的 C99 库**提供。不依赖 Zephyr,也不依赖 nRF SDK:它仅通过六个函数与平台隔离,并提供了针对 Zephyr、Arduino 和 STM32 HAL 的参考移植。
- [`docs/eink-lut-reference.md`](docs/eink-lut-reference.md) —— 通过实验解码出的 SSD1675A 波形表字节级格式:包含 LUT 行语义、RP 重复规则、时序计算公式,以及防止面板出现残影的 DC-balance 算术逻辑。
- [`docs/display-optimization.md`](docs/display-optimization.md) —— 记录了如何将 762 ms 的局部刷新缩短至 112 ms,包括在其中探索过的两条死胡同以及随之而来的老化问题。
## 仓库结构
```
lib/ portable library — see lib/README.md
eink/ SSD1675A driver, waveform presets, platform ports
gfx/ 1-bpp canvas, text, dithering, Game of Life
src/ this firmware (Zephyr / nRF Connect SDK)
app/ display manager, commands, mesh, auth, persistence, battery
ble/ NUS service, advertising, identity
examples/
eink_demo/ minimal app built on lib/ alone
lut_tester_host/ host tooling: LUT editor GUI, video streamer, DFU, PWA
docs/ reverse-engineering write-ups
scripts/ build and flashing helpers
boards/ board overlays
```
## 硬件说明
| 部件 | 详情 |
| ----- | ------------------------------------------------------------------ |
| MCU | nRF52832 (512 KB flash, 64 KB RAM) |
| 面板 | SSD1675A 级别, 128×296, 黑/白/红 |
| 总线 | 软件模拟的 9-bit SPI (面板将 D/C 位放在帧内部) |
| 开发板 | `nrf52dk/nrf52832` 目标平台 |
默认引脚分配(可在构建系统中覆盖 `SSD1675A_PIN_*`):
| 信号 | 引脚 |
| ------ | --- |
| BUSY | 6 |
| RST | 7 |
| CS | 8 |
| CLK | 11 |
| MOSI | 12 |
| VCC | 19 |
## 构建说明
需要 nRF Connect SDK v3.0.1。如果你的安装路径不在默认位置,请在 Makefile 中指定:
```
make # build + package an OTA image
make NCS_DIR=/opt/nordic/ncs/v3.0.1 BOARD=nrf52dk/nrf52832
make flash # west flash
make flash-retry # retry until it verifies (flaky SWD)
make clean
```
两个 OTA 变体从同一个源代码树构建 —— 详见 [`Makefile`](Makefile) 中的变体矩阵:
```
make # legacy batch: current layout, default signing key
make VARIANT=v2 # v2 batch: own signing key, factory_data partition
make release # both, merged into one manifest
```
OTA 大小校验会在发布镜像前中断构建,以防止生成 MCUboot 会接受但静默拒绝切换的镜像。
### 首次烧录
全新的标签必须通过 SWD 进行一次有线烧录 —— 在此固件刷入之前,没有任何无线访问入口。nRF52832 是一颗 Cortex-M4 芯片,因此任何 CMSIS-DAP 调试器都可以使用;处于 CMSIS-DAP 模式的 WCH-LinkE、原装 ST-Link 或 J-Link 均可胜任,且都不需要安装 Nordic 专用的烧录器。将线焊接到 SWDIO/SWCLK 焊盘上(不同批次的电路板焊盘位置可能有所不同 —— 建议先用万用表确认)。
```
make flash # west flash, for probes west knows about
make flash-openocd # openocd CLI, spawns its own session
make flash-gdb # a running OpenOCD on telnet localhost:4444
make flash-retry # keep retrying until it verifies — for flaky SWD contact
```
提供 `make flash-retry` 的原因是,此类开发板上的弹簧针 (pogo-pin) 接触不太稳定;该命令会重复执行烧录直到校验通过。完成此步骤后,所有后续更新均可通过 BLE 进行。
## 与标签通信
命令通过 Nordic UART Service 以文本行(如 `MODE:3`、`NUKE:5`、`TIME=…`)或二进制 opcode 帧的形式接收。两者均通过 [`src/app/cmd_opcodes.h`](src/app/cmd_opcodes.h) 中的同一个注册表进行分发,因此每条命令只需实现一次。运行 `HELP` 可列出当前固件支持的所有命令。
### 通过浏览器 —— 免安装
[`lut_tester_host/web/`](lut_tester_host/web/) 已部署并开放给所有人,访问地址:** **。它与本仓库中包含的应用完全相同,具备所有可用功能:支持带抖动算法的图像、文本、动画和视频流传输,内置带有实时图表和 DC-balance 柱状图的 70 字节波形编辑器,支持屏幕保护和显示模式,显示时间、电池和统计信息,以及通过 [`/dfu.html`](https://pwa.price-tag.sorewa.ru/dfu.html) 进行 OTA 升级。
它通过 Web Bluetooth 直接从浏览器与标签通信 —— 主机端无需构建或安装任何内容。**它只能搜索到已经运行了此固件的标签**,因此全新的标签需要先通过 SWD 进行一次有线烧录;标签出厂的原厂固件不会广播任何可供此应用连接的服务。它是一个 PWA,因此加载后即可安装并支持离线使用。界面语言为俄语。
Web Bluetooth 目前支持桌面端和 Android 端的 Chrome、Edge 或 Opera;Safari、iOS 和 Firefox 暂不支持。
这是一个静态资源包,因此你可以在指向它的任意主机上运行 —— `make deploy` 负责发布。
### 通过终端
```
pip install -r lut_tester_host/requirements.txt
python3 lut_tester_host/lut_tester.py # LUT editor + device control GUI
python3 lut_tester_host/vstream_player.py … # stream video to the panel
python3 lut_tester_host/dfu_upload.py … # OTA from the command line
```
## 复用显示代码
编写 `lib/` 的初衷就是使其能够从本仓库中独立提取出来。它不依赖 Zephyr、nRF SDK 或本仓库中的任何其他内容 —— 只需六个函数(`ssd1675a_port.h`)即可完成驱动程序与硬件的对接,并且 `lib/eink/port/` 目录中提供了适用于 Zephyr、Arduino 和 STM32 HAL 的可用实现。
有关移植规范和可直接复制粘贴的示例,请参阅 [`lib/README.md`](lib/README.md)。
## 许可证
本项目编写的代码采用 MIT 许可证 —— 详见 [`LICENSE`](LICENSE)。
此固件基于 Nordic `peripheral_uart` 示例开发,仍然带有 Nordic 版权声明的文件(`Kconfig`、`prj.conf`、`CMakeLists.txt` 以及 `src/ble/` 的部分内容)按照原标注保持在 `LicenseRef-Nordic-5-Clause` 许可下。`lib/` 目录为原创作品,仅采用 MIT 许可证。
标签:C99, Mesh网络, 云资产清单, 后端开发, 嵌入式固件, 物联网, 电子纸驱动, 蓝牙低功耗, 逆向工具, 逆向工程