feat(lcd): add cached listening animation and asset guidelines
This commit is contained in:
+164
-9
@@ -8,9 +8,9 @@
|
||||
|
||||
- 底层为 ESP32-S3、ST7789P3、单线 SPI,当前像素时钟为 40 MHz,逻辑画布为 320×240。
|
||||
- 当前使用 `esp_emote_gfx` 3.0.5,由 `platform` 私有依赖。没有接入 `esp_emote_expression` 状态管理组件,也没有把当前表情绘制建立在 LVGL 上。依赖目录中存在其他库不等于当前显示链路使用它们。
|
||||
- 待机基础表情采用 GFX;其他表情仍走原 PNG 或步骤序列,不是所有资产都已经迁移。
|
||||
- 待机基础表情与 listening 采用 GFX;其他表情仍走原 PNG 或步骤序列,不是所有资产都已经迁移。listening 缓存失败时单独回退旧 PNG,不影响待机。
|
||||
- 屏幕目前未使用 TE 同步。软件预合成和连续传输能改善撕裂观感,但不能保证面板扫描与写入完全同步。
|
||||
- 用户已确认缓存与固定时间轴版本的观感满意;最后的固定时间轴版本尚未提供新的量化日志,不能写成“稳定达到 30 FPS”。
|
||||
- 用户已确认待机缓存/固定时间轴以及新 listening 版本的观感满意。两者最终版本尚无新的配套量化日志,不能写成“稳定达到 30 FPS”或“全部实机验收完成”。
|
||||
|
||||
已安装组件提供图片、网格图片、运动、动画、标签、二维码和按钮等接口。但本项目仅实际使用图片、网格、显示刷新及相关对象控制;通用中文文本、按钮、触摸和复杂布局不属于当前已实现能力。
|
||||
|
||||
@@ -53,12 +53,16 @@ esp_err_t err = domain_runtime_request_expression(&request);
|
||||
| `components/platform/src/generated/emote_gfx/idle_base.c` | 静态鼻子和胡须压缩数据 |
|
||||
| `components/platform/src/generated/emote_gfx/idle_eyes_open.c` | 原始睁眼压缩数据 |
|
||||
| `components/platform/CMakeLists.txt` | 私有组件依赖及实际参与编译的资产列表 |
|
||||
| `main/Kconfig.projbuild` | GFX 待机开关与测量日志开关 |
|
||||
| `main/Kconfig.projbuild` | GFX 待机/listening 开关与测量日志开关 |
|
||||
| `tools/split_idle_expression.py` | 从旧三帧中拆出静态底图及眼睛图层 |
|
||||
| `tools/compress_idle_expression.py` | 将底图和睁眼图层转换为压缩 C 资产,并做编码往返检查 |
|
||||
| `tools/test_lcd_status_hud.py` | 状态栏及自动回待机回归测试 |
|
||||
| `tools/test_lcd_emote_transport.py` | 离屏捕获、缓存索引、传输、闭眼弧线和统计开关回归测试 |
|
||||
| `tools/test_lcd_emote_timeline.py` | 固定时间轴、时钟粒度、迟到及取消回归测试 |
|
||||
| `components/platform/src/lcd_emote_listening.c` | listening 关键眼型的逐列几何插值,仅初始化生成缓存时运行 |
|
||||
| `components/platform/internal/lcd_emote_listening.h` | 平台私有插值接口,不向领域或控制层泄漏 GFX 类型 |
|
||||
| `tools/prepare_listening_expression.py` | 拆分旧 listening、编码往返校验、生成四个 C 资产及同算法动画预览 |
|
||||
| `tools/test_lcd_listening_gfx.py` | 实际资产、全闭合参数、缓存分配失败、GFX 对象失败、静态像素恢复与切换回归 |
|
||||
|
||||
`/tmp` 下修改过程中生成的补丁脚本不是工程运行依赖,不应提交或作为正式资源流程使用。
|
||||
|
||||
@@ -132,16 +136,56 @@ DMA 等待超时后禁止继续复用可能仍被硬件读取的缓冲,GFX 传
|
||||
|
||||
## 六、资源目录、制作和替换
|
||||
|
||||
### PNG、RLE 与运行时缓存不是同一份文件
|
||||
|
||||
PNG 是源素材格式,也是旧播放路径的压缩格式。新 GFX 路径从 PNG 生成 RLE
|
||||
数组;不存在独立 `.rle` 文件,压缩字节保存在 `generated/emote_gfx/*.c` 中。
|
||||
RLE(游程长度编码)把连续相同像素写成“数量+像素值”。本项目一条记录四字节:
|
||||
数量(1~255)、RGB565 高字节、RGB565 低字节、Alpha。例如 `0A 00 00 FF`
|
||||
表示十个不透明黑色像素,替代十份 RGB565+A8 像素的三十字节。
|
||||
颜色/透明度频繁变化时 RLE 可能压得较差,甚至膨胀;PNG 的压缩可能更紧凑。
|
||||
|
||||
| 路径 | 编辑输入 | 固件中的内容 | 运行时处理 |
|
||||
| --- | --- | --- | --- |
|
||||
| 普通 PNG 与 GFX 失败后备 | `lcd_source/*.png` | `lcd_optimized/*.png` 经素材包链接入应用 | 原 PNG 解码/缓存链路 |
|
||||
| 新待机/listening GFX | 原 PNG 与拆分图层 PNG | 六个实际参与编译的 RLE C 资产 | 初始化解压,生成 PSRAM 眼型缓存,之后切换缓存 |
|
||||
| 离线预览 | 图层与实际插值算法 | 不入固件 | 在电脑上检查造型,不能模拟 LCD 扫描 |
|
||||
|
||||
RLE 的编码往返对转换后的 RGB565+A8 数据无损,不等于原 PNG 的所有 RGB888
|
||||
像素完全不变。RGB565 转换、背景归零、裁剪及性能适配是另一层处理,须单独
|
||||
验证视觉并保留可编辑源图。九张待机与九张 listening 运行时缓存只在 PSRAM 中,
|
||||
没有对应的固件图片或磁盘缓存文件;离线 PNG/GIF 预览不能算成这些缓存的 Flash。
|
||||
|
||||
### 当前目录与准确入口
|
||||
|
||||
```text
|
||||
components/platform/assets/
|
||||
lcd_source/ 旧 PNG 源图,仍保留
|
||||
lcd_layers/jichubiaoqing/ 可编辑拆分图层、布局及预览
|
||||
lcd_source/ 原 PNG 源图,仍保留,不直接入包
|
||||
lcd_optimized/ 原 PNG 路径实际入包图片及 manifest
|
||||
audio_prompts/ 实际入包提示音
|
||||
lcd_layers/
|
||||
jichubiaoqing/ 待机可编辑拆分图层、布局及预览
|
||||
listening/ 聆听可编辑拆分图层、布局及预览
|
||||
components/platform/src/generated/emote_gfx/
|
||||
idle_base.c 实际编译的底图压缩数据
|
||||
idle_eyes_open.c 实际编译的睁眼压缩数据
|
||||
listening_base.c 实际编译的眉毛、鼻子、胡须数据
|
||||
listening_eyes_open.c 实际编译的聆听睁眼关键图
|
||||
listening_eyes_half.c 实际编译的聆听半闭关键图
|
||||
listening_eyes_closed.c 实际编译的聆听闭眼关键图
|
||||
```
|
||||
|
||||
半闭眼、闭眼源图及对应历史生成文件不代表当前参与编译;以构建列表为准,不把目录里的全部文件自动加入固件,也不擅自删除旧资源。
|
||||
这里指待机历史 `idle_eyes_half.c`、`idle_eyes_closed.c`,不是 listening 的
|
||||
半闭/闭眼 C 文件:后两者当前确实参与编译。逐文件大小、入固件分类、音频及
|
||||
源图/预览汇总见 [显示与音频资产台账](显示与音频资产台账.zh-CN.md)。
|
||||
|
||||
- 待机拆分/压缩:`tools/split_idle_expression.py`、`tools/compress_idle_expression.py`。
|
||||
- listening 拆分、压缩与预览:`tools/prepare_listening_expression.py`。
|
||||
- RLE 解码:`components/platform/src/lcd_emote_assets.c`。
|
||||
- 聆听关键图几何插值:`components/platform/src/lcd_emote_listening.c`。
|
||||
- 缓存与播放:`components/platform/src/lcd_direct.c`。
|
||||
- PNG 后备优化:`tools/optimize_lcd_assets.py`,流程见 [图片优化说明](lcd-image-asset-optimization.zh-CN.md)。
|
||||
|
||||
在仓库根目录,确认 Python 环境有 Pillow 后,可执行:
|
||||
|
||||
@@ -175,15 +219,49 @@ python3 tools/compress_idle_expression.py
|
||||
| 上述合计 | 709,654 字节 PSRAM |
|
||||
| GFX DMA 暂存区 | 10,240 字节内部 DMA 内存 |
|
||||
|
||||
此表不含对象管理、任务栈、SPI 描述符、PNG 缓存和系统其他模块。不能把表中合计当作整个显示组件的完整运行内存开销。
|
||||
此表是待机与共用缓冲的基线,不包含新增 listening。它也不含对象管理、任务栈、SPI 描述符、PNG 缓存和系统其他模块。不能把表中合计当作整个显示组件的完整运行内存开销。
|
||||
|
||||
压缩源图像像素数据为 19,336 字节,不含描述信息和组件代码。运行时眼型缓存不写入 Flash。最新本地构建应用镜像为 3,040,480 字节,OTA 槽为 4,718,592 字节;这是当次构建快照,不是后续版本承诺。
|
||||
待机压缩源图像像素数据为 19,336 字节,不含描述信息和组件代码。运行时眼型缓存不写入 Flash。接入 listening 前应用镜像为 3,040,480 字节,接入后为 3,094,176 字节,新增 53,696 字节;OTA 槽为 4,718,592 字节,剩余 1,624,416 字节。这是当次本地构建快照,不是后续版本承诺。
|
||||
|
||||
实机日志曾显示联网、唤醒同时运行时,内部内存最低只剩约十 KiB,而 PSRAM 尚有数 MiB。后续优先考虑 PSRAM 和局部复用,不能因为外部内存充足就不断扩大 DMA 或内部任务栈。
|
||||
|
||||
### 压缩优化的判定与预算限制
|
||||
|
||||
新增或替换素材必须做适合编码的压缩优化、数值比较及视觉验证,不强制 PNG 或
|
||||
RLE,不默认“接入 GFX=Flash 更小”。RLE 只是简单解压编码;当前播放快主要
|
||||
依靠初始化生成局部缓存,不能把性能收益全部归因于 RLE,也不能断言 PNG 无法
|
||||
在初始化解码后缓存。未来可评估 PNG/其他编码初始化解码生成同样缓存的成本。
|
||||
|
||||
listening 三张旧原 PNG 共 45,445 字节,已有优化 PNG 共 14,681 字节。
|
||||
新底图及三个关键图未压缩像素为 255,528 字节,RLE 载荷为 50,176 字节,
|
||||
相对未压缩像素减少约 80.4%,但比旧优化 PNG 大 35,495 字节。这几个比较对象
|
||||
并不完全相同:旧图是三个整屏画面,新图是固定底图加三个可变眼型。
|
||||
旧优化 PNG 仍作后备,因此本次没有从固件扣掉它们,完整镜像实际增加 53,696 字节。
|
||||
当前方案不是最小 Flash 方案,是用户已接受的空间换流畅度方案。
|
||||
|
||||
所有迁移应报告优化前后素材、固件增量、常驻/峰值 PSRAM、静态数据、普通堆及
|
||||
内部/DMA 增量,说明效果和测量证据。不按源码 C 文件大小推算 Flash,也不把
|
||||
PSRAM 外部内存充足当成内部 DMA 安全。当前 listening 的已接受基线是固件
|
||||
增量 53,696 字节、常驻像素 PSRAM 增量 423,234 字节,不是所有表情的硬上限。
|
||||
超出该表情已确认预算、增加内部/DMA 缓冲、或可能影响 OTA/语音/网络时,先
|
||||
给出预算、风险和替代方案并取得用户确认;新增表情尚无预算时先提出预算。
|
||||
|
||||
### 旧资源保留、整理与迁移完成条件
|
||||
|
||||
- 可编辑原 PNG 保留;离线预览和拆分 PNG 不入固件。旧待机/listening 的优化
|
||||
PNG 仍入包,提供关闭 GFX、初始化/缓存失败等后备,不是可以直接删除的重复文件。
|
||||
- 未参与编译的历史待机 C 文件、旧预览和 `defaultAudio/` 副本仅标记为待评估,
|
||||
不因“历史”标签自动删除。实际入包音频来自 `platform/assets/audio_prompts/`。
|
||||
- 迁移完成至少包括:语义入口与退出/取消一致、正常画面/状态栏验收、故障及
|
||||
关闭开关时的后备行为明确、联网/语音并行与最低内存记录、生成可重现、文档
|
||||
和台账同步。用户观感满意仅覆盖其中一项,不自动满足删除后备的条件。
|
||||
- 删除或移出固件前先列清文件、引用、回退替代方案及预计收益,取得用户授权;
|
||||
再同步构建清单/资源目录映射、相关测试和台账。保留 Git 可恢复记录并验证
|
||||
正常与故障路径。清理只是后续计划,本次没有删除资源或改变打包范围。
|
||||
|
||||
## 八、性能日志如何读
|
||||
|
||||
通过 `menuconfig` 搜索 `TQ_LCD_EMOTE_GFX_TEST` 和 `TQ_LCD_EMOTE_FPS_LOG`。前者控制 GFX 待机路径;后者控制性能统计,默认关闭,当前本地测量配置开启。关闭统计不应改变动画节奏。
|
||||
通过 `menuconfig` 搜索 `TQ_LCD_EMOTE_GFX_TEST` 和 `TQ_LCD_EMOTE_FPS_LOG`。前者控制 GFX 待机及 listening 路径;后者控制性能统计,默认关闭,当前本地测量配置开启。关闭统计不应改变动画节奏。
|
||||
|
||||
每轮完整眨眼输出一次 `emote_fps` 和 `emote_cost`,不在逐帧传输中打印:
|
||||
|
||||
@@ -192,7 +270,7 @@ python3 tools/compress_idle_expression.py
|
||||
- `eye_updates`:眼型步骤中确实完成至少一个区域传输的次数;多个 DMA 块不会重复计数。
|
||||
- `update_fps`:实际更新次数除以同一眨眼时长,不是仅运动段的瞬时频率。
|
||||
- `draw_avg_us`、`draw_max_us`:步骤绘制时间;平均包含没有传输的保持步骤。
|
||||
- `late_steps`:绘制达到或超过 34ms 的步骤数,不等于屏幕丢帧数,也不统计所有调度迟到。
|
||||
- `late_steps`:绘制达到或超过对应时间线步长的步骤数(待机 34ms、listening 30ms),不等于屏幕丢帧数,也不统计所有调度迟到。
|
||||
- `lock`:等待 GFX 锁;`compose`:眼型修改及合成、刷新处理,扣除复制和传输;`copy`:复制到 DMA;`spi`:提交并等待传输完成。
|
||||
|
||||
各项均为墙钟时间,可能包含被其他任务抢占。各项最大值可能来自不同步骤,不能相加。不能仅凭合成时间大就断言算法慢,也不能仅凭 SPI 等待大就断言线路带宽不足。
|
||||
@@ -201,6 +279,64 @@ python3 tools/compress_idle_expression.py
|
||||
|
||||
## 九、后续开发建议
|
||||
|
||||
### 已接入的 listening
|
||||
|
||||
旧实现每张停留 500ms,顺序为睁眼、半闭眼、闭眼;新实现保留三种斜眼造型,
|
||||
并固定第一张的眉毛、鼻子、胡须。背景中的细小杂色归零,旧源图和打包 PNG 全部保留。
|
||||
动态图层窗口为 `(41,87)`,尺寸 242×77,包含闭眼右端延伸及边缘余量。
|
||||
|
||||
Flash 中只保存静态底图和三个关键眼型,不保存九张缓存。初始化时按列提取两张
|
||||
相邻关键图的上下轮廓,插值出目标轮廓,再变形单张纹理,并做纵向亚像素采样。
|
||||
不是两张表情交叉淡化;避免高光双影和眼圈灰化。闭合 0、128、232 分别精确使用
|
||||
睁眼、半闭眼、闭眼关键图,232 以上共用闭眼缓存。
|
||||
|
||||
生成阶段的三张 RGB565A8 关键图共 167,706 字节 PSRAM,生成完释放。底图和九个
|
||||
局部 RGB565 缓存常驻;缓存中的黑色眼睛外区域恢复眉毛/胡须静态像素,不能任意
|
||||
叠加到不同底图。播放时没有 PNG 解码、关键图解压或逐列变形。
|
||||
|
||||
| listening 新增项 | 数值 |
|
||||
| --- | ---: |
|
||||
| 静态底图压缩数据 | 8,732 字节 Flash |
|
||||
| 睁眼、半闭眼、闭眼压缩数据 | 24,036 / 13,236 / 4,172 字节 Flash |
|
||||
| 四份压缩数据合计 | 50,176 字节 Flash |
|
||||
| 整个应用镜像实际增量,含新增代码与对齐 | 53,696 字节 Flash |
|
||||
| 静态底图解压后 | 87,822 字节 PSRAM |
|
||||
| 九个局部眼型缓存 | 335,412 字节 PSRAM |
|
||||
| 新增常驻像素合计 | 423,234 字节 PSRAM |
|
||||
| 初始化新增像素峰值,含临时关键图 | 590,940 字节 PSRAM |
|
||||
| LCD 文件静态数据/BSS 增量 | 333 字节 |
|
||||
| 新图片对象、图片状态及链表节点申请量 | 80 + 8 + 8 = 96 字节普通堆,不含分配器开销 |
|
||||
| 新 DMA 缓冲、新合成缓冲、新任务 | 0,复用原有实现 |
|
||||
|
||||
上述静态/对象字节数通过当前 ESP32-S3 编译器核对,不包含链接段对齐、堆分配
|
||||
管理、栈瞬时使用或绘制临时分配。普通堆的实际放置由 ESP-IDF 内存策略决定。
|
||||
待机加 listening 的明确常驻像素缓冲总计为 1,132,888 字节 PSRAM,仍不等于整个
|
||||
显示组件总内存。初始化峰值及联网时真实余量需要设备日志验证。
|
||||
|
||||
新时间线是 `24→80→160→232→232→192→128→64→16→0`,共十步,
|
||||
每步 30ms,锚定共同起点;目标眨眼 300ms,闭眼保持约 60ms,睁眼停留约 2.4 秒。
|
||||
同一闭眼缓存重复保持不触发新传输。目标步骤频率不是实测 FPS,也不是面板扫描率。
|
||||
`emote_fps` 日志新增 `face=idle/listening` 区分后端,仍由原测量开关控制。
|
||||
|
||||
领域目录和控制层监听状态不变:按键/本地唤醒进入时展示 listening,直到新请求
|
||||
或停止;它不严格等于录音已经开始。眨眼结束不自动回待机。退出后下一次待机请求
|
||||
恢复待机静态层与眼型;切换时完整刷新一次,之后只刷新眼睛及变化的状态栏。
|
||||
缓存失败释放未绑定像素并保留旧 PNG;极端解锁错误下已绑定对象的像素保留到重启,
|
||||
不能释放后仍被渲染线程引用。GFX 总开关关闭时仍使用原 PNG。
|
||||
|
||||
生成资源与预览(需要 Pillow 和 Clang,覆盖本次生成的 listening 图层与资产):
|
||||
|
||||
```bash
|
||||
python3 tools/prepare_listening_expression.py
|
||||
python3 tools/test_lcd_listening_gfx.py
|
||||
```
|
||||
|
||||
可编辑 PNG、布局和预览在 `components/platform/assets/lcd_layers/listening/`;
|
||||
实际编译的四个 `listening_*.c` 在 `components/platform/src/generated/emote_gfx/`。
|
||||
动画预览 `preview.gif` 调用实际 C 插值生成,但没有模拟 LCD 扫描与语音负载。
|
||||
固定窗口/锚点变化需同步脚本与测试。需要手工保留眉毛等素材编辑时,不要直接重新
|
||||
拆分覆盖;当前生成脚本不是所有角色通用的热替换工具。
|
||||
|
||||
### 接入更多表情
|
||||
|
||||
先逐个迁移,保留未迁移 PNG 路径。每个表情准备静态层、动态图层、锚点、时间线、缓存预算及结束行为。固定短动作适合预生成缓存;大量不同动作或连续交互需要考虑按需生成、共享缓存和生命周期,不应给每个表情无上限常驻一份整屏缓存。
|
||||
@@ -231,6 +367,7 @@ python3 tools/compress_idle_expression.py
|
||||
python3 tools/test_lcd_status_hud.py
|
||||
python3 tools/test_lcd_emote_transport.py
|
||||
python3 tools/test_lcd_emote_timeline.py
|
||||
python3 tools/test_lcd_listening_gfx.py
|
||||
```
|
||||
|
||||
这些脚本在电脑上从实际源码提取 C 函数,使用 Clang 与内存、未定义行为检查器。需要 Python 和 Clang;不是固件代码,不占设备 Flash 或 RAM。测试使用模拟接口,不能证明屏幕无撕裂、实时帧率或设备像素完全一致。
|
||||
@@ -248,3 +385,21 @@ python3 tools/test_lcd_emote_timeline.py
|
||||
7. 新增停止或资源释放功能时的取消、超时和反复启动测试。
|
||||
|
||||
交付时分别报告源码检查、主机测试、编译和实机证据。不能把“编译通过”写成“设备已验证”,也不能只用目标帧率或一次录像承诺持续性能。
|
||||
|
||||
### 对话需求与验证记录
|
||||
|
||||
| 需求或反馈 | 当前结果与边界 |
|
||||
| --- | --- |
|
||||
| 不需要触摸/复杂 GUI,精致流畅为主 | 局部 GFX 图层,不迁移完整 LVGL GUI |
|
||||
| 拆分原表情,允许性能适配但整体保持 | 待机/listening 拆分与固定静态层;后续延续原画风,大幅变化需确认 |
|
||||
| 眼睛向中间闭合,避免重影和撕裂 | 单一轮廓、闭眼弧线、缓存和连续传输;没有 TE,不能承诺零撕裂 |
|
||||
| 统一所有返回待机入口、补时间电量 | 已实现统一后端及 HUD;不能覆盖新 pending;数字点阵不代表任意中文文字 |
|
||||
| 增加可开关日志、计算具体帧数 | 已有 emote_fps/emote_cost;区分步骤/实际更新/面板扫描率 |
|
||||
| 全中文开发说明与 AI 注意事项 | 本指南、资产台账及 AGENTS.md 中文 GFX 约束;原有仓库架构规范保留 |
|
||||
| listening 也迁移为流畅表情并报告开销 | 已接入,开销见上表;保持业务监听生命周期与旧 PNG 后备 |
|
||||
| 用户确认待机与 listening 效果满意 | 2026-10-09 对话中确认;没有据此声称最终量化 FPS/最低内存及全部场景合格 |
|
||||
| 素材需要压缩优化与成本限制 | 已补通用强制流程、PNG/RLE 权衡与先确认预算规则 |
|
||||
|
||||
此前缓存/时序及中文指南提交为 `89e8e3a`、`c0770ac`;本次基线包含 listening
|
||||
接入及补充文档。完整状态机、任意中文字体、其他表情批量迁移、
|
||||
资源清理/热替换是后续方向,不标成已经实现,也不推断用户已要求立即实施。
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
# 待机恢复与时间 / 电量状态栏
|
||||
|
||||
完整现行说明见 [GFX 表情显示应用与开发指南](GFX表情显示应用与开发指南.md)。
|
||||
本文保留待机、状态栏和历次优化记录;旧 lcd-expressions.md 中的测试图案、
|
||||
本文保留待机、状态栏和历次优化记录;以下历史数字主要针对待机,listening 的
|
||||
独立资源/时间线见新指南。旧 lcd-expressions.md 中的测试图案、
|
||||
优先级仲裁描述不代表当前运行行为。正常播放现在是缓存图像,不是逐帧网格。
|
||||
|
||||
## 返回待机
|
||||
|
||||
- 开机 / 默认空闲、显式 IDLE 请求、有限动画 return_to_idle、缺失素材回退和
|
||||
非取消的播放错误都进入同一个待机后端。
|
||||
- CONFIG_TQ_LCD_EMOTE_GFX_TEST 启用且初始化成功时使用单纹理网格眨眼;
|
||||
- CONFIG_TQ_LCD_EMOTE_GFX_TEST 启用且初始化成功时优先播放初始化生成的眼型缓存;
|
||||
待机缓存失败保留实时网格。网格与闭眼弧线通常只用于待机缓存生成。
|
||||
禁用或初始化失败才使用历史三帧 PNG 安全后备。
|
||||
- 历史 jichubiaoqing 请求(duration_ms=0)也适配到 GFX。
|
||||
有限播放保留 repeat_count,每轮为 frame_ms 睁眼停留 + 12 个 34ms 眨眼步骤;
|
||||
不承诺与旧 PNG 完全相同的持续时间。服务错误因此不再临时退回三帧。
|
||||
- 自动恢复只在没有 pending 请求且未停止时排入 IDLE,不能覆盖新来的请求。
|
||||
- 其他表情仍为 PNG / step sequence,未改动其图像或动画顺序。
|
||||
- listening 也已迁移为 GFX 局部缓存,复用引擎/传输/HUD,缓存失败回退旧 PNG;
|
||||
保持睁眼约 2.4 秒、眨眼目标 300ms,直到业务新请求或停止,不自行回待机。
|
||||
- 除待机/listening 外,其他表情仍为 PNG / step sequence,未改动其图像或动画顺序。
|
||||
pending 仍是单槽替换,不是完整优先级状态机。
|
||||
|
||||
## 状态栏
|
||||
@@ -23,7 +27,8 @@
|
||||
- 右上百分比和电池;未知值显示 --%,充电绿色并带闪电缺口,低电量红色。
|
||||
- SOC、有效性和充电状态来自现有 domain battery 服务,不从 ADC 重算。
|
||||
- GFX 顶部 320x40 RGB565 图层,常驻 25,600 B PSRAM;只在分钟或电池状态
|
||||
改变时使图层失效并刷新,眨眼主要改变眼睛网格,接近闭合时切换为程序绘制的抗锯齿弧线,不解码新 PNG。
|
||||
改变时使图层失效并刷新。正常待机/listening 眨眼切换缓存,不重新解码 PNG;
|
||||
实时网格与程序闭眼弧线属于待机缓存生成或缓存失败后备路径。
|
||||
- PNG 表情复用相同点阵 / 电池绘制器,在每帧合成时更新;二维码和 LCD
|
||||
边界测试页面不显示状态栏。PNG 无限等待期间不会独立重绘状态栏。
|
||||
- 不需要字体包或新图片。旧 PNG 低电量底部告警保留;旧充电 PNG 不再自动
|
||||
@@ -61,7 +66,8 @@ AddressSanitizer / UndefinedBehaviorSanitizer 检查 808 组有效性、充电
|
||||
|
||||
主机传输/闭眼回归:`python3 tools/test_lcd_emote_transport.py`,检查 320 种
|
||||
区域宽度、DMA 分块/数据顺序、错误/超时处理及闭眼对称性。当前 RTOS tick
|
||||
为 10ms,实际眨眼间隔仍有 tick 量化及任务调度抖动,日志不是实测 FPS。
|
||||
为 10ms,实际眨眼间隔仍有 tick 量化及任务调度抖动;日志测量步骤/图像更新
|
||||
吞吐率,不是面板扫描率。
|
||||
|
||||
## 可开关的实测帧率日志
|
||||
|
||||
@@ -73,13 +79,14 @@ menuconfig 的屏幕配置中 `Log measured GFX blink FPS` 对应
|
||||
|
||||
- blink_us:实际整轮眨眼墙钟耗时,包含计算、SPI、等待和任务调度,
|
||||
不包含此前约 2 秒的静止睁眼时间,也不包含该条日志输出时间。
|
||||
- step_fps:12 个时序步骤 / 实测眨眼秒数,闭眼保持也算步骤。
|
||||
- step_fps:本轮步骤数 / 实测眨眼秒数(待机 12 步、listening 10 步),闭眼保持也算步骤。
|
||||
- eye_updates:步骤的刷新调用确实完成至少一个区域传输才计一次;
|
||||
一帧多个区域/多个 DMA 块不会重复计数,保持帧和等待期间的 HUD 更新不计。
|
||||
- update_fps:eye_updates / 相同的 blink_us,是本轮眼睛画面更新吞吐率,
|
||||
不是面板扫描率,也不是仅统计运动段的瞬时 FPS。
|
||||
- draw_avg_us / draw_max_us:步骤绘制及锁等待耗时,平均包含无需传输的保持步骤。
|
||||
- late_steps:绘制耗时达到或超过 34ms 帧预算的步骤数。
|
||||
- late_steps:绘制耗时达到或超过相应步长预算的步骤数(待机 34ms、listening 30ms)。
|
||||
- face:idle/listening,区分当前表情。
|
||||
|
||||
示例:blink_us=570000 steps=12,则 step_fps=21.05;如果 eye_updates=9,
|
||||
update_fps=15.78。没有 TE,这些指标不测量屏幕实际扫描或保证无撕裂。
|
||||
@@ -87,7 +94,7 @@ update_fps=15.78。没有 TE,这些指标不测量屏幕实际扫描或保证
|
||||
### 分项耗时 emote_cost
|
||||
|
||||
同一开关下,每轮 emote_fps 后追加一条 emote_cost,各项均输出 avg_us / max_us。
|
||||
平均按 12 个步骤计算,包含不传输的闭眼保持步骤;各项最大值可能来自不同步骤,
|
||||
平均按本轮步骤数计算(待机 12、listening 10),包含不传输的闭眼保持步骤;各项最大值可能来自不同步骤,
|
||||
不能相加。累计计数和快照都在 GFX 渲染锁内,不计静止/HUD 更新的耗时。
|
||||
|
||||
- lock:调用 gfx_emote_lock 到获取锁的墙钟耗时。
|
||||
|
||||
@@ -0,0 +1,388 @@
|
||||
# 显示与音频资产台账
|
||||
|
||||
## 范围、日期与计量口径
|
||||
|
||||
这是 2026-10-09 lucky-cat 工作区的只读核对快照;采集时包含尚未提交的 listening
|
||||
素材以及两个未跟踪的历史待机 C 资产。它不是构建输入或自动生成的实时报告。
|
||||
新增、替换、移出固件或经授权清理资产时,应同步更新此表及指南。
|
||||
|
||||
范围包含平台图片/图层/音频、生成 GFX C 文件、旧音频副本、领域内嵌网页和项目
|
||||
显示预览;不逐个列第三方库的内部样例/字体、ESP-IDF 文件或 build 缓存。
|
||||
语音模型作为独立构建产物在后文单列,不冒充项目图片资产。
|
||||
|
||||
- 文件字节为文件逻辑长度;分配字节来自本机 stat 的 st_blocks×512,可能随文件
|
||||
系统、压缩、克隆共享而改变,不能当作唯一物理磁盘成本或固件占用。
|
||||
- C 文件是十六进制数组的文本,文本长度不等于 Flash。Flash 载荷必须按数组
|
||||
字节统计;描述结构、代码、对齐和其他数据最终以应用镜像为准。
|
||||
- 源图、图层、预览、manifest、旧副本不因出现在仓库中就自动进入固件。
|
||||
- PNG/Opus 素材包与六份 GFX RLE 都已包含在应用镜像里,不能重复加算。
|
||||
- 本文只记录分类,不授权删除任何文件。后备保留与清理条件见
|
||||
[GFX 开发指南](GFX表情显示应用与开发指南.md#旧资源保留整理与迁移完成条件)。
|
||||
|
||||
## 目录汇总
|
||||
|
||||
| 类别 | 文件数 | 文件字节合计 | 本机分配字节合计 | 当前用途 |
|
||||
| --- | ---: | ---: | ---: | --- |
|
||||
| 原始 LCD 图片 | 76 | 1,168,722 | 1,290,240 | 源图/历史 GIF,不直接入固件 |
|
||||
| 优化 PNG 与清单 | 76 | 465,933 | 593,920 | 按 PNG 白名单入包;manifest 不入包 |
|
||||
| 提示音 | 32 | 385,758 | 450,560 | 本目录 Opus 入包 |
|
||||
| 待机拆分图层及预览 | 8 | 74,585 | 94,208 | 制作输入/预览,不入包 |
|
||||
| 聆听拆分图层及预览 | 16 | 272,605 | 303,104 | 制作输入/预览,不入包 |
|
||||
| GFX 压缩 C 资产 | 8 | 1,232,250 | 1,253,376 | 六份参与编译;历史两份未参与 |
|
||||
| 旧音频副本 | 30 | 378,918 | 442,368 | 本目录不入包,不自动删除 |
|
||||
| 领域网页资源 | 1 | 5,373 | 8,192 | user_config.html 单独 EMBED_TXTFILES,不在素材包 |
|
||||
| 文档中的独立显示预览 | 2 | 98,302 | 102,400 | 仅电脑预览,不入固件 |
|
||||
|
||||
以下同名文件跨目录是不同用途,不应直接合并或重复计入 Flash。当前没有独立中文字体包;数字 HUD 使用代码内置点阵,不意味着已支持任意中文字形。
|
||||
|
||||
## 原始 LCD 图片
|
||||
|
||||
目录:`components/platform/assets/lcd_source/`。源图/历史 GIF,不直接入固件。
|
||||
|
||||
| 文件 | 文件字节 | 本机分配字节 | 尺寸 | 固件用途 |
|
||||
| --- | ---: | ---: | --- | --- |
|
||||
| `OTA.gif` | 40,441 | 40,960 | 320×240 | 不直接入固件 |
|
||||
| `buyunqian1.png` | 20,467 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `charging.png` | 3,018 | 4,096 | 50×70 | 不直接入固件 |
|
||||
| `chouqian_buyun0.png` | 16,883 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_buyun1.png` | 20,467 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_buyun2.png` | 27,971 | 28,672 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_heping0.png` | 17,146 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_heping1.png` | 20,975 | 24,576 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_heping2.png` | 28,152 | 28,672 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_qianzhi0.png` | 13,739 | 16,384 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_qianzhi1.png` | 16,425 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_qianzhi2.png` | 15,559 | 16,384 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_shangshang0.png` | 17,377 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_shangshang1.png` | 20,582 | 24,576 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_shangshang2.png` | 28,046 | 28,672 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_xiaoji0.png` | 17,071 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_xiaoji1.png` | 20,313 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_xiaoji2.png` | 27,354 | 28,672 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_zhongshang0.png` | 16,995 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_zhongshang1.png` | 19,968 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `chouqian_zhongshang2.png` | 26,989 | 28,672 | 320×240 | 不直接入固件 |
|
||||
| `east0.png` | 19,981 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `huo0.png` | 19,143 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `huo1.png` | 19,706 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `icon_huo0.png` | 2,028 | 4,096 | 56×58 | 不直接入固件 |
|
||||
| `icon_jin0.png` | 2,369 | 4,096 | 65×44 | 不直接入固件 |
|
||||
| `icon_mu0.png` | 3,741 | 4,096 | 86×50 | 不直接入固件 |
|
||||
| `icon_shui0.png` | 2,239 | 4,096 | 60×56 | 不直接入固件 |
|
||||
| `icon_tu0.png` | 2,873 | 4,096 | 75×42 | 不直接入固件 |
|
||||
| `jichubiaoqing0.png` | 20,645 | 24,576 | 320×240 | 不直接入固件 |
|
||||
| `jichubiaoqing1.png` | 16,355 | 16,384 | 320×240 | 不直接入固件 |
|
||||
| `jichubiaoqing2.png` | 14,340 | 16,384 | 320×240 | 不直接入固件 |
|
||||
| `jin0.png` | 17,398 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `jin1.png` | 19,311 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `lcdtest00.png` | 3,321 | 4,096 | 320×240 | 不直接入固件 |
|
||||
| `lcdtest01.png` | 3,574 | 4,096 | 320×240 | 不直接入固件 |
|
||||
| `lcdtest02.png` | 3,767 | 4,096 | 320×240 | 不直接入固件 |
|
||||
| `lcdtest03.png` | 3,903 | 4,096 | 320×240 | 不直接入固件 |
|
||||
| `lcdtest04.png` | 3,579 | 4,096 | 320×240 | 不直接入固件 |
|
||||
| `lcdtest05.png` | 3,996 | 4,096 | 320×240 | 不直接入固件 |
|
||||
| `lcdtest06.png` | 4,089 | 4,096 | 320×240 | 不直接入固件 |
|
||||
| `lcdtest07.png` | 3,753 | 4,096 | 320×240 | 不直接入固件 |
|
||||
| `lcdtest08.png` | 3,860 | 4,096 | 320×240 | 不直接入固件 |
|
||||
| `lcdtest09.png` | 4,008 | 4,096 | 320×240 | 不直接入固件 |
|
||||
| `lcdtest10.png` | 3,545 | 4,096 | 320×240 | 不直接入固件 |
|
||||
| `lcdtest11.png` | 3,169 | 4,096 | 320×240 | 不直接入固件 |
|
||||
| `lcdtest12.png` | 3,453 | 4,096 | 320×240 | 不直接入固件 |
|
||||
| `lcdtest13.png` | 3,710 | 4,096 | 320×240 | 不直接入固件 |
|
||||
| `lcdtest14.png` | 3,443 | 4,096 | 320×240 | 不直接入固件 |
|
||||
| `lcdtest15.png` | 3,646 | 4,096 | 320×240 | 不直接入固件 |
|
||||
| `listening0.png` | 19,615 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `listening1.png` | 15,072 | 16,384 | 320×240 | 不直接入固件 |
|
||||
| `listening2.png` | 10,758 | 12,288 | 320×240 | 不直接入固件 |
|
||||
| `lowbat.png` | 10,222 | 12,288 | 232×36 | 不直接入固件 |
|
||||
| `mu0.png` | 19,742 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `mu1.png` | 19,483 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `muyu0.png` | 17,340 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `muyu1.png` | 21,462 | 24,576 | 320×240 | 不直接入固件 |
|
||||
| `muyu2.png` | 34,079 | 36,864 | 320×240 | 不直接入固件 |
|
||||
| `north0.png` | 19,314 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `northeast0.png` | 21,808 | 24,576 | 320×240 | 不直接入固件 |
|
||||
| `northwest0.png` | 19,143 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `ota1.png` | 25,911 | 28,672 | 320×240 | 不直接入固件 |
|
||||
| `ota2.png` | 22,397 | 24,576 | 320×240 | 不直接入固件 |
|
||||
| `ota3.png` | 22,079 | 24,576 | 320×240 | 不直接入固件 |
|
||||
| `qianzhiwuxing0.png` | 16,670 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `qrcode.png` | 18,971 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `shui0.png` | 18,086 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `shui1.png` | 18,478 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `south0.png` | 22,767 | 24,576 | 320×240 | 不直接入固件 |
|
||||
| `southeast0.png` | 24,902 | 28,672 | 320×240 | 不直接入固件 |
|
||||
| `southwest0.png` | 22,298 | 24,576 | 320×240 | 不直接入固件 |
|
||||
| `spin0.png` | 17,071 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `tu0.png` | 18,101 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `tu1.png` | 20,059 | 20,480 | 320×240 | 不直接入固件 |
|
||||
| `west0.png` | 18,011 | 20,480 | 320×240 | 不直接入固件 |
|
||||
|
||||
## 优化 PNG 与清单
|
||||
|
||||
目录:`components/platform/assets/lcd_optimized/`。按 PNG 白名单入包;manifest 不入包。
|
||||
|
||||
| 文件 | 文件字节 | 本机分配字节 | 尺寸 | 固件用途 |
|
||||
| --- | ---: | ---: | --- | --- |
|
||||
| `buyunqian1.png` | 7,598 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `charging.png` | 1,254 | 4,096 | 50×70 | 入包 PNG |
|
||||
| `chouqian_buyun0.png` | 6,536 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `chouqian_buyun1.png` | 7,598 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `chouqian_buyun2.png` | 9,986 | 12,288 | 320×240 | 入包 PNG |
|
||||
| `chouqian_heping0.png` | 6,590 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `chouqian_heping1.png` | 7,701 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `chouqian_heping2.png` | 10,120 | 12,288 | 320×240 | 入包 PNG |
|
||||
| `chouqian_qianzhi0.png` | 5,203 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `chouqian_qianzhi1.png` | 6,119 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `chouqian_qianzhi2.png` | 5,984 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `chouqian_shangshang0.png` | 6,578 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `chouqian_shangshang1.png` | 7,519 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `chouqian_shangshang2.png` | 9,804 | 12,288 | 320×240 | 入包 PNG |
|
||||
| `chouqian_xiaoji0.png` | 6,447 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `chouqian_xiaoji1.png` | 7,424 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `chouqian_xiaoji2.png` | 9,715 | 12,288 | 320×240 | 入包 PNG |
|
||||
| `chouqian_zhongshang0.png` | 6,291 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `chouqian_zhongshang1.png` | 7,224 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `chouqian_zhongshang2.png` | 9,387 | 12,288 | 320×240 | 入包 PNG |
|
||||
| `east0.png` | 5,681 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `huo0.png` | 7,023 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `huo1.png` | 7,269 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `icon_huo0.png` | 1,422 | 4,096 | 56×58 | 入包 PNG |
|
||||
| `icon_jin0.png` | 1,509 | 4,096 | 65×44 | 入包 PNG |
|
||||
| `icon_mu0.png` | 1,866 | 4,096 | 86×50 | 入包 PNG |
|
||||
| `icon_shui0.png` | 1,457 | 4,096 | 60×56 | 入包 PNG |
|
||||
| `icon_tu0.png` | 1,643 | 4,096 | 75×42 | 入包 PNG |
|
||||
| `jichubiaoqing0.png` | 6,467 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `jichubiaoqing1.png` | 5,306 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `jichubiaoqing2.png` | 4,482 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `jin0.png` | 6,488 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `jin1.png` | 7,077 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `lcdtest00.png` | 2,885 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `lcdtest01.png` | 2,965 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `lcdtest02.png` | 2,982 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `lcdtest03.png` | 3,043 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `lcdtest04.png` | 2,949 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `lcdtest05.png` | 3,225 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `lcdtest06.png` | 3,431 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `lcdtest07.png` | 3,369 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `lcdtest08.png` | 3,299 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `lcdtest09.png` | 3,458 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `lcdtest10.png` | 3,229 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `lcdtest11.png` | 2,966 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `lcdtest12.png` | 2,921 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `lcdtest13.png` | 3,020 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `lcdtest14.png` | 2,986 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `lcdtest15.png` | 3,033 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `listening0.png` | 6,165 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `listening1.png` | 4,939 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `listening2.png` | 3,577 | 4,096 | 320×240 | 入包 PNG |
|
||||
| `lowbat.png` | 3,527 | 4,096 | 232×36 | 入包 PNG |
|
||||
| `manifest.json` | 34,788 | 36,864 | — | 不入包,校验清单/非白名单 |
|
||||
| `mu0.png` | 7,270 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `mu1.png` | 7,208 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `muyu0.png` | 6,924 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `muyu1.png` | 8,325 | 12,288 | 320×240 | 入包 PNG |
|
||||
| `muyu2.png` | 12,523 | 16,384 | 320×240 | 入包 PNG |
|
||||
| `north0.png` | 5,527 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `northeast0.png` | 6,276 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `northwest0.png` | 5,496 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `ota1.png` | 8,745 | 12,288 | 320×240 | 入包 PNG |
|
||||
| `ota2.png` | 7,585 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `ota3.png` | 7,525 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `qianzhiwuxing0.png` | 5,811 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `qrcode.png` | 11,039 | 12,288 | 320×240 | 入包 PNG |
|
||||
| `shui0.png` | 6,640 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `shui1.png` | 6,932 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `south0.png` | 6,609 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `southeast0.png` | 7,354 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `southwest0.png` | 6,599 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `spin0.png` | 6,447 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `tu0.png` | 7,028 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `tu1.png` | 7,381 | 8,192 | 320×240 | 入包 PNG |
|
||||
| `west0.png` | 5,164 | 8,192 | 320×240 | 入包 PNG |
|
||||
|
||||
## 提示音
|
||||
|
||||
目录:`components/platform/assets/audio_prompts/`。本目录 Opus 入包。
|
||||
|
||||
| 文件 | 文件字节 | 本机分配字节 | 尺寸 | 固件用途 |
|
||||
| --- | ---: | ---: | --- | --- |
|
||||
| `battery_checking.opus` | 4,366 | 8,192 | — | 入包 Opus |
|
||||
| `battery_low_20.opus` | 6,582 | 8,192 | — | 入包 Opus |
|
||||
| `battery_low_energy_warning.opus` | 26,369 | 28,672 | — | 入包 Opus |
|
||||
| `boot.opus` | 2,296 | 4,096 | — | 入包 Opus |
|
||||
| `button_interrupt_listening.opus` | 2,911 | 4,096 | — | 入包 Opus |
|
||||
| `charge_complete.opus` | 22,329 | 24,576 | — | 入包 Opus |
|
||||
| `daily_first_wake.opus` | 14,798 | 16,384 | — | 入包 Opus |
|
||||
| `daily_wake.opus` | 7,111 | 8,192 | — | 入包 Opus |
|
||||
| `enter_provisioning.opus` | 6,701 | 8,192 | — | 入包 Opus |
|
||||
| `intro_first_setup_success.opus` | 23,813 | 24,576 | — | 入包 Opus |
|
||||
| `local_wake_response.opus` | 3,680 | 4,096 | — | 入包 Opus |
|
||||
| `luck_flow_lost_help_find.opus` | 14,658 | 16,384 | — | 入包 Opus |
|
||||
| `muyu.opus` | 3,160 | 4,096 | — | 入包 Opus |
|
||||
| `network_connect_failed.opus` | 4,388 | 8,192 | — | 入包 Opus |
|
||||
| `network_connect_success.opus` | 4,778 | 8,192 | — | 入包 Opus |
|
||||
| `network_connecting.opus` | 2,836 | 4,096 | — | 入包 Opus |
|
||||
| `network_interrupted_repairing.opus` | 13,887 | 16,384 | — | 入包 Opus |
|
||||
| `network_unstable.opus` | 13,910 | 16,384 | — | 入包 Opus |
|
||||
| `server_abnormal_interrupted.opus` | 24,764 | 28,672 | — | 入包 Opus |
|
||||
| `server_connect_failed.opus` | 5,690 | 8,192 | — | 入包 Opus |
|
||||
| `server_connect_success.opus` | 6,302 | 8,192 | — | 入包 Opus |
|
||||
| `server_repair_wait_open.opus` | 17,193 | 20,480 | — | 入包 Opus |
|
||||
| `server_repair_wait_reopen.opus` | 17,829 | 20,480 | — | 入包 Opus |
|
||||
| `shutdown.opus` | 3,160 | 4,096 | — | 入包 Opus |
|
||||
| `shutdown_normal_goodbye.opus` | 6,396 | 8,192 | — | 入包 Opus |
|
||||
| `shutdown_power_empty.opus` | 19,970 | 20,480 | — | 入包 Opus |
|
||||
| `signal_restored_business_resume.opus` | 10,996 | 12,288 | — | 入包 Opus |
|
||||
| `standby_5min.opus` | 21,429 | 24,576 | — | 入包 Opus |
|
||||
| `system_update_complete.opus` | 12,396 | 16,384 | — | 入包 Opus |
|
||||
| `system_upgrading.opus` | 23,754 | 24,576 | — | 入包 Opus |
|
||||
| `welcome_luck_ready.opus` | 25,325 | 28,672 | — | 入包 Opus |
|
||||
| `wifi_password_wrong.opus` | 11,981 | 12,288 | — | 入包 Opus |
|
||||
|
||||
## 待机拆分图层及预览
|
||||
|
||||
目录:`components/platform/assets/lcd_layers/jichubiaoqing/`。制作输入/预览,不入包。
|
||||
|
||||
| 文件 | 文件字节 | 本机分配字节 | 尺寸 | 固件用途 |
|
||||
| --- | ---: | ---: | --- | --- |
|
||||
| `idle_base.png` | 5,321 | 8,192 | 320×240 | 不直接入固件 |
|
||||
| `idle_eyes_closed.png` | 5,896 | 8,192 | 238×93 | 不直接入固件 |
|
||||
| `idle_eyes_half.png` | 8,791 | 12,288 | 238×93 | 不直接入固件 |
|
||||
| `idle_eyes_open.png` | 12,161 | 12,288 | 238×93 | 不直接入固件 |
|
||||
| `layout.json` | 387 | 4,096 | — | 不直接入固件 |
|
||||
| `preview_closed.png` | 10,881 | 12,288 | 320×240 | 不直接入固件 |
|
||||
| `preview_half.png` | 13,832 | 16,384 | 320×240 | 不直接入固件 |
|
||||
| `preview_open.png` | 17,316 | 20,480 | 320×240 | 不直接入固件 |
|
||||
|
||||
## 聆听拆分图层及预览
|
||||
|
||||
目录:`components/platform/assets/lcd_layers/listening/`。制作输入/预览,不入包。
|
||||
|
||||
| 文件 | 文件字节 | 本机分配字节 | 尺寸 | 固件用途 |
|
||||
| --- | ---: | ---: | --- | --- |
|
||||
| `layout.json` | 346 | 4,096 | — | 不直接入固件 |
|
||||
| `listening_base.png` | 6,234 | 8,192 | 320×240 | 不直接入固件 |
|
||||
| `listening_eyes_closed.png` | 2,875 | 4,096 | 242×77 | 不直接入固件 |
|
||||
| `listening_eyes_half.png` | 6,460 | 8,192 | 242×77 | 不直接入固件 |
|
||||
| `listening_eyes_open.png` | 9,866 | 12,288 | 242×77 | 不直接入固件 |
|
||||
| `preview.gif` | 53,952 | 57,344 | 320×240 | 不直接入固件 |
|
||||
| `preview_000.png` | 13,633 | 16,384 | 320×240 | 不直接入固件 |
|
||||
| `preview_016.png` | 15,577 | 16,384 | 320×240 | 不直接入固件 |
|
||||
| `preview_024.png` | 15,540 | 16,384 | 320×240 | 不直接入固件 |
|
||||
| `preview_064.png` | 14,802 | 16,384 | 320×240 | 不直接入固件 |
|
||||
| `preview_080.png` | 14,347 | 16,384 | 320×240 | 不直接入固件 |
|
||||
| `preview_128.png` | 10,641 | 12,288 | 320×240 | 不直接入固件 |
|
||||
| `preview_160.png` | 10,937 | 12,288 | 320×240 | 不直接入固件 |
|
||||
| `preview_192.png` | 9,820 | 12,288 | 320×240 | 不直接入固件 |
|
||||
| `preview_232.png` | 7,674 | 8,192 | 320×240 | 不直接入固件 |
|
||||
| `preview_sheet.png` | 79,901 | 81,920 | 960×720 | 不直接入固件 |
|
||||
|
||||
## GFX 压缩 C 资产
|
||||
|
||||
目录:`components/platform/src/generated/emote_gfx/`。六份参与编译;历史两份未参与。
|
||||
|
||||
| 文件 | 文本文件字节 | 本机分配字节 | 图层尺寸 | 数组载荷字节 | RGB565+A8 像素字节 | 参与编译 |
|
||||
| --- | ---: | ---: | --- | ---: | ---: | --- |
|
||||
| `idle_base.c` | 29,698 | 32,768 | 284×37 | 4,764(RLE) | 31,524 | 是,GFX 开关开启时 |
|
||||
| `idle_eyes_closed.c` | 400,750 | 401,408 | 238×93 | 66,402(历史未压缩像素) | 66,402 | 否,历史文件,仅保留 |
|
||||
| `idle_eyes_half.c` | 400,744 | 401,408 | 238×93 | 66,402(历史未压缩像素) | 66,402 | 否,历史文件,仅保留 |
|
||||
| `idle_eyes_open.c` | 90,201 | 94,208 | 238×93 | 14,572(RLE) | 66,402 | 是,GFX 开关开启时 |
|
||||
| `listening_base.c` | 54,190 | 57,344 | 287×102 | 8,732(RLE) | 87,822 | 是,GFX 开关开启时 |
|
||||
| `listening_eyes_closed.c` | 26,097 | 28,672 | 242×77 | 4,172(RLE) | 55,902 | 是,GFX 开关开启时 |
|
||||
| `listening_eyes_half.c` | 81,985 | 86,016 | 242×77 | 13,236(RLE) | 55,902 | 是,GFX 开关开启时 |
|
||||
| `listening_eyes_open.c` | 148,585 | 151,552 | 242×77 | 24,036(RLE) | 55,902 | 是,GFX 开关开启时 |
|
||||
|
||||
## 旧音频副本
|
||||
|
||||
目录:`defaultAudio/`。本目录不入包,不自动删除。
|
||||
|
||||
| 文件 | 文件字节 | 本机分配字节 | 尺寸 | 固件用途 |
|
||||
| --- | ---: | ---: | --- | --- |
|
||||
| `battery_checking.opus` | 4,366 | 8,192 | — | 不直接入固件 |
|
||||
| `battery_low_20.opus` | 6,582 | 8,192 | — | 不直接入固件 |
|
||||
| `battery_low_energy_warning.opus` | 26,369 | 28,672 | — | 不直接入固件 |
|
||||
| `boot.opus` | 2,296 | 4,096 | — | 不直接入固件 |
|
||||
| `button_interrupt_listening.opus` | 2,911 | 4,096 | — | 不直接入固件 |
|
||||
| `charge_complete.opus` | 22,329 | 24,576 | — | 不直接入固件 |
|
||||
| `daily_first_wake.opus` | 14,798 | 16,384 | — | 不直接入固件 |
|
||||
| `daily_wake.opus` | 7,111 | 8,192 | — | 不直接入固件 |
|
||||
| `enter_provisioning.opus` | 6,701 | 8,192 | — | 不直接入固件 |
|
||||
| `intro_first_setup_success.opus` | 23,813 | 24,576 | — | 不直接入固件 |
|
||||
| `luck_flow_lost_help_find.opus` | 14,658 | 16,384 | — | 不直接入固件 |
|
||||
| `network_connect_failed.opus` | 4,388 | 8,192 | — | 不直接入固件 |
|
||||
| `network_connect_success.opus` | 4,778 | 8,192 | — | 不直接入固件 |
|
||||
| `network_connecting.opus` | 2,836 | 4,096 | — | 不直接入固件 |
|
||||
| `network_interrupted_repairing.opus` | 13,887 | 16,384 | — | 不直接入固件 |
|
||||
| `network_unstable.opus` | 13,910 | 16,384 | — | 不直接入固件 |
|
||||
| `server_abnormal_interrupted.opus` | 24,764 | 28,672 | — | 不直接入固件 |
|
||||
| `server_connect_failed.opus` | 5,690 | 8,192 | — | 不直接入固件 |
|
||||
| `server_connect_success.opus` | 6,302 | 8,192 | — | 不直接入固件 |
|
||||
| `server_repair_wait_open.opus` | 17,193 | 20,480 | — | 不直接入固件 |
|
||||
| `server_repair_wait_reopen.opus` | 17,829 | 20,480 | — | 不直接入固件 |
|
||||
| `shutdown.opus` | 3,160 | 4,096 | — | 不直接入固件 |
|
||||
| `shutdown_normal_goodbye.opus` | 6,396 | 8,192 | — | 不直接入固件 |
|
||||
| `shutdown_power_empty.opus` | 19,970 | 20,480 | — | 不直接入固件 |
|
||||
| `signal_restored_business_resume.opus` | 10,996 | 12,288 | — | 不直接入固件 |
|
||||
| `standby_5min.opus` | 21,429 | 24,576 | — | 不直接入固件 |
|
||||
| `system_update_complete.opus` | 12,396 | 16,384 | — | 不直接入固件 |
|
||||
| `system_upgrading.opus` | 23,754 | 24,576 | — | 不直接入固件 |
|
||||
| `welcome_luck_ready.opus` | 25,325 | 28,672 | — | 不直接入固件 |
|
||||
| `wifi_password_wrong.opus` | 11,981 | 12,288 | — | 不直接入固件 |
|
||||
|
||||
## 领域网页资源
|
||||
|
||||
目录:`components/domain/assets/`。user_config.html 单独 EMBED_TXTFILES,不在素材包。
|
||||
|
||||
| 文件 | 文件字节 | 本机分配字节 | 尺寸 | 固件用途 |
|
||||
| --- | ---: | ---: | --- | --- |
|
||||
| `user_config.html` | 5,373 | 8,192 | — | 单独嵌入应用,文本尾部追加 NUL |
|
||||
|
||||
## 独立显示预览
|
||||
|
||||
| 文件 | 文件字节 | 本机分配字节 | 用途 |
|
||||
| --- | ---: | ---: | --- |
|
||||
| `docs/cat-face-screen-preview.html` | 5,225 | 8,192 | 文档/浏览器预览,不入固件 |
|
||||
| `docs/lcd-boundary-test-preview.gif` | 93,077 | 94,208 | 文档/浏览器预览,不入固件 |
|
||||
|
||||
## 实际入固件与构建快照
|
||||
|
||||
当前 PNG 白名单为 75 项,提示音为 32 项;已逐项对照
|
||||
现有素材包名称及字节,确认本次台账快照与该包一致。资源变化后需重新核对构建,
|
||||
不能只改本文数字。
|
||||
|
||||
| 项目 | 字节 | 计量说明 |
|
||||
| --- | ---: | --- |
|
||||
| 白名单优化 PNG 载荷 | 431,145 | 素材包内部像素文件 |
|
||||
| Opus 提示音载荷 | 385,758 | 素材包内部音频文件 |
|
||||
| 包头、条目头及名称 | 3,222 | 打包元数据 |
|
||||
| platform_assets.pack | 820,125 | 上述三项之和,包含于应用 |
|
||||
| 六份在用 RLE 载荷 | 69,512 | 独立 C 数组链接入应用,不在素材包内 |
|
||||
| 应用镜像 | 3,094,176 | 已包含 PNG、Opus、RLE、网页、代码及其他链接数据 |
|
||||
| 单个 OTA 槽 | 4,718,592 | 应用余量 1,624,416 字节;不能把两个槽余量合并供一次 OTA 使用 |
|
||||
| 独立语音模型镜像 | 2,681,351 | model 分区容量 3,145,728 字节,不属于应用内图片包 |
|
||||
|
||||
文件总大小不能当作“当前整个 Flash 用量”;NVS、分区表、引导程序、模型和
|
||||
其他分区另计,设备内容还取决于实际烧录/OTA。临时构建产物不应提交。
|
||||
|
||||
## listening 压缩与旧方案对照
|
||||
|
||||
旧三张原 PNG 共 45,445 字节;旧优化 PNG 共 14,681 字节;新四份图层原始
|
||||
RGB565+A8 像素共 255,528 字节,新 RLE 载荷共 50,176 字节。相对原始像素
|
||||
减少约 80.4%,但比旧优化 PNG 多 35,495 字节,不能称为“比旧方案省 Flash”。
|
||||
原旧 PNG 后备没有移出素材包,所以实际固件增量为 53,696 字节,不是仅比较
|
||||
新旧素材大小的差。九张局部缓存共 335,412 字节 PSRAM,静态底图 87,822 字节,
|
||||
常驻像素共 423,234 字节;初始化额外关键图 167,706 字节,随后释放。
|
||||
当前没有新增 DMA 暂存区、合成缓冲或任务。它是用户已接受的空间换流畅度方案。
|
||||
|
||||
## 维护与后续清理
|
||||
|
||||
1. PNG 新增/替换按 [图片优化流程](lcd-image-asset-optimization.zh-CN.md) 生成并验证,
|
||||
不能编辑优化产物代替修改源图。GFX 新增/替换使用对应压缩脚本和编码往返测试。
|
||||
2. 改白名单、图层、生成 C、音频或预览时更新分类、文件字节及载荷;重新构建时
|
||||
同步镜像/包快照,记录常驻与峰值内存。不要把本文静态表当自动一致性校验。
|
||||
3. 当前后备 PNG 全保留;历史 C 与旧副本只标记,未授权不删。删除前核对引用、
|
||||
GFX 关闭/故障后备以及收益,经过用户确认并完成迁移验收后再修改构建及资源表。
|
||||
4. 清理优先区分“不再入固件”与“删除可编辑源文件”。前者有 Flash 收益,后者
|
||||
可能仅省开发机空间,不能混为一谈。保留 Git 可恢复记录,并验证正常/故障路径。
|
||||
5. 这里没有安排立即清理、批量迁移所有表情或新增字体;这些需要单独确定范围。
|
||||
Reference in New Issue
Block a user