Rdzleo 672506e7c7 feat(rtc-only): Phase 1 - 通过 CONFIG_BAJI_BADGE_MODE 屏蔽电子吧唧模式
按 GSD 框架 .planning/milestones/digital_human_rtc/ 规划完成 Phase 1。
源代码全部保留,通过 Kconfig 开关 + CMakeLists 条件编译 + #ifdef 调用点保护
实现"吧唧模式不进固件但代码可恢复"。

## 核心变更

### Kconfig 开关(默认关闭)
- 新增 CONFIG_BAJI_BADGE_MODE(main/Kconfig.projbuild)
- sdkconfig.defaults 默认 =n
- =y 时恢复双模式(电子吧唧 + AI 对话)
- =n 时仅 AI 数字人 RTC 模式

### CMakeLists 剥离(剥离式不重写)
- 9 个 dzbj/ 吧唧专属 + 9 个 ui/screens/ 吧唧 UI 进入 if(CONFIG_BAJI_BADGE_MODE) 条件块
- 公共保留: dzbj/lcd.c, ai_chat_ui.c, sprite_demo.c, dual_gif_demo.c,
  bg_gif_demo.c, pages_pwm.c, dzbj_init.c, fatfs.c
- 修正 PLAN 漏判:dzbj_init/fatfs 公共化(AI 模式调用 dzbj_hw_display_init/DecodeImg)

### 调用点 #ifdef 保护
- application.cc: L20 include, L63-66 background_task, L536 device_mode 分支
- movecall_moji_esp32s3.cc: dzbj headers, init_spiffs_image_list extern,
  dzbj_boot_click_handler extern, device_mode_is_badge 分支, InitializeBadgeMode,
  InitializeBadgeModeButtons, mode_switch_combo 注册, device_mode_in_switch_suppress
- 保留公共 extern: ai_chat_screen_init, ai_chat_resume_animation, pwm_init

### 整体文件级 #ifdef 包裹
- dzbj/dzbj_button.c/h
- dzbj/sleep_mgr.c
- sleep_mgr/include/sleep_mgr.h

### 6 个文件显式 #include "sdkconfig.h"
- ESP-IDF 不会 force-include,必须手动 include 才能拿到 CONFIG_* 宏

## G7 验收双向编译

- =n 模式 build:  EXIT=0(数字人 RTC 单一形态)
- =y 模式 build:  EXIT=0(双模式恢复可用)

## 固件大小变化

| 段 | =n | =y | 节省 |
|----|-----|------|------|
| .text | 2.03 MB | 2.06 MB | 27 KB |
| .rodata | 2.48 MB | 3.87 MB | 1.39 MB |
| Total | 4.63 MB | 6.05 MB | 1.45 MB |

## GSD 文档(同时提交)

- .planning/milestones/digital_human_rtc/MILESTONE.md
- .planning/milestones/digital_human_rtc/ROADMAP.md
- .planning/milestones/digital_human_rtc/INTEL.md
- .planning/milestones/digital_human_rtc/phases/phase_01_kconfig_isolation/PLAN.md
- .planning/milestones/digital_human_rtc/phases/phase_01_kconfig_isolation/SIZE_REPORT.md
- .planning/milestones/digital_human_rtc/phases/phase_01_kconfig_isolation/BADGE_MODE_ISOLATION_MAP.md
- 编译大小原始数据: size_*.txt

## 已知事项

- =n 固件 4.63 MB 仍 > 4 MB 目标,Phase 2 调整分区 + Phase 3 物理移除图片资源解决
- main/dzbj/ 下所有源文件完整保留,无任何物理删除
2026-05-13 10:22:48 +08:00

6.1 KiB
Raw Blame History

里程碑:数字人 RTC 项目(阉割版)

单一形态产品:纯 AI 对话 + Live2D 数字人显示。剥离电子吧唧模式,简化代码、释放资源。

1. 背景

主仓 Baji_Rtc_Toy 当前是"AI 对话 + 电子吧唧"双模式固件,所有共享底层(火山 RTC、Opus 编解码、BLE 配网、LCD/LVGL已稳定。Hiyori 数字人透明 GIF 显示在 Rtc_AIavatar 分支已完成 PoC背景图 + 透明 GIF 叠加方案)。

本里程碑目标:将 Rtc_AIavatar 分支演进为独立产品形态——只保留 AI 对话 + 数字人显示,移除全部电子吧唧业务,并将单一情绪 emoji 升级为多动态 GIF 表情。

2. 业务目标

# 目标 衡量
G1 屏蔽电子吧唧专属功能(不物理删除,仅条件编译排除 引入 CONFIG_BAJI_BADGE_MODE Kconfig 开关(默认 N编译固件 .text 段较双模式版减小 ≥ 80KB源代码保留以供后续借鉴
G2 数字人 GIF 替代静态 emoji 至少 3 个 hiyori 表情通过 RTC 字幕情绪标签自动切换
G3 RTC 对话字幕恢复显示 字幕实时显示在屏幕底部,不遮挡数字人
G4 资源容量满足 GIF 资源 SPIFFS ≥ 6MB装下 3 个高频表情
G5 低功耗与 RTC 联动 60s RTC 空闲自动断开连接 + 熄屏;任意键/语音唤醒
G6 保留所有必要业务 BLE 配网0xABF0/WiFi/OTA/Function Calling故事/音乐)/双向音频切换 全部可用
G7 保留吧唧代码可恢复性 在 Rtc_AIavatar 分支切换 CONFIG_BAJI_BADGE_MODE=y 后能重新编译出双模式固件

3. 范围

3.1 In Scope本里程碑做

  • 新增 Kconfig 开关 CONFIG_BAJI_BADGE_MODE(默认 N源代码不删
  • CMakeLists.txt 条件化 编译:if(CONFIG_BAJI_BADGE_MODE) 包裹吧唧 srcs/ui screens
  • 源代码加 #ifdef CONFIG_BAJI_BADGE_MODE 保护吧唧的调用点:
    • main/dzbj/ 下吧唧专属模块的调用入口device_mode/dzbj_ble/ble_transfer/dzbj_button[KEY2部分]/pages/fatfs/pages_pwm/dzbj_battery/dzbj_init
    • main/ui/screens/ 下 9 个吧唧 UI 屏幕的调用入口
    • application.cc / boards/movecall-moji-esp32s3/ 中的模式切换分支
    • BOOT+KEY2 组合键切换模式逻辑
  • 调整 partitions.csvota 双分区 4MB + SPIFFS 6MB
  • 准备 3 个 hiyori GIFm03/m06/m07gifsicle 处理 + 240×320 裁剪)
  • 实现"情绪标签 → 数字人 GIF"映射表22 情绪 → 3 GIF
  • 恢复 RTC 字幕显示在屏幕底部(半透明背景层)
  • 实现 RTC 60s 空闲超时 → 断开 + 熄屏 联动sleep_mgr 改造为 RTC 联动版,原代码用 #ifdef 保护)

关键原则:所有"屏蔽"动作 = 通过 Kconfig 关闭编译 + #ifdef 注释化调用,源代码文件全部保留在 main/dzbj/ 下作为参考

3.2 Out of Scope本里程碑不做

  • 电子吧唧模式相关任何新功能
  • Live2D 实时渲染(继续用预渲染 GIF 方案)
  • 云端 BLE OTA 推送 GIF先用 SPIFFS 预烧)
  • 数字人表情动画过渡GIF 间无淡入淡出)
  • Haru 角色(先只跑 HiyoriHaru 留作后续里程碑)
  • 主仓 main 分支的修改main 保持双模式基线不动)

4. 关键决策(已与用户对齐)

# 决策项 选择
D1 hiyori GIF 数量 精选 3 个最小m06+m07+m03约 5.7MB
D2 KEY2(GPIO4) 按键 完全删除,仅保留 BOOT 单键配网
D3 低功耗熄屏机制 RTC 空闲超时联动(复用 listening_idle_ticks_60s 断开+熄屏)
D4 字幕显示位置 屏幕底部 y=-70(半透明背景,不遮挡数字人)

5. 约束

# 约束 影响
C1 硬件不变ESP32-S3-N16R8 / 16MB Flash / 8MB PSRAM / ST77916 360×360 LCD 不能扩 Flash 解决资源问题
C2 主仓 main 保持双模式基线 本里程碑只在 Rtc_AIavatar 分支演进,不合并回 main
C3 火山 RTC 协议层不动 复用现有 protocols/volc_rtc_protocol.cc
C4 现有 BLE 配网协议不动 APP 端无需适配
C5 中文字幕字体已存在 复用 font_puhui_20_4不引入新字体

6. 成功标准(验收清单)

固件烧录后端到端验证:

  • 首次开机 → BLE 配网 APP 成功连接 → WiFi 凭据存入 NVS
  • 重启 → 自动连 WiFi → 进入 AI 对话主界面(背景图 + hiyori GIF + 状态栏)
  • 语音唤醒 AI → 字幕实时显示在屏幕底部 → 数字人 GIF 根据情绪标签切换(至少看到 3 种表情切换)
  • AI 调用 Function Call → 故事/音乐 HTTPS 播放正常
  • 任意时刻 BOOT 单击 → 中断 AI 发言
  • 60s 无对话 → 自动断 RTC + 熄屏;任意操作 → 唤醒
  • 长按 BOOT 5s → 触发 WiFi 重置 → 回到配网模式
  • OTA 升级流程可用(双分区切换)
  • 整机持续运行 30 分钟无内存泄漏、无重启

7. 风险

# 风险 缓解
R1 sleep_mgr 与 RTC 空闲超时合并可能引入回归 Phase 6 单独验证 + 旧 sleep_mgr 代码用 #ifdef CONFIG_BAJI_BADGE_MODE 保留可恢复
R2 3 个 GIF 装载切换可能与 RTC 音频争 PSRAM Phase 4 监控 heap_caps_get_free_size(MALLOC_CAP_SPIRAM)
R3 Kconfig 条件编译可能漏掉某些隐式调用导致链接错误 Phase 1 完成后开启 CONFIG_BAJI_BADGE_MODE=y 二次编译验证可恢复双模式G7 验收)
R4 字幕 z-index 与 GIF 冲突 Phase 5 用 LVGL 容器层级控制,必要时改用 layer_top
R5 分区表调整导致旧固件 OTA 兼容性 首次烧录用 esptool.py write_flashOTA 在新分区基础上启用
R6 #ifdef 散落各处后续不易维护 Phase 1 任务最后产出一份 BADGE_MODE_ISOLATION_MAP.md,列出所有 #ifdef 边界

8. 状态

阶段 状态
当前 📝 规划中(已完成调研、决策对齐)
起始分支 Rtc_AIavatarcommit eb96130
目标分支 Rtc_AIavatar(完成后 push 到 gitea + GitHub