Add full-screen 0904 charge art to UI0902 resource pack.

Charge page draws UI0902_CHARGE_SCREEN instead of legacy 160x190 Charg.bin; pack/gen/publish paths keep the asset in sync.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
yuquanjun 2026-09-05 06:27:12 +08:00
parent 8c3c14ccf8
commit 2bca0c5673
6 changed files with 51 additions and 33 deletions

View File

@ -259,8 +259,9 @@ void IdleProcess(DisplayTaskMessage_Type msg)
BSP_MainPowerEnable(1); BSP_MainPowerEnable(1);
LCD_WR_REG(0x29); //Display on LCD_WR_REG(0x29); //Display on
LCD_WR_PIC_FROM_FLASH(40, 50, EXTFLASH_CHARGING_W, EXTFLASH_CHARGING_H, /* 0904 全屏充电画面UI0902 资源包);旧 Charg.bin 160x190 仅作音色包占位 */
EXTFLASH_CHARGING_ADDR); LCD_WR_PIC_FROM_FLASH(0, 0, UI0902_CHARGE_SCREEN_W, UI0902_CHARGE_SCREEN_H,
UI0902_CHARGE_SCREEN_ADDR);
LCD_BLK_Set(); LCD_BLK_Set();
flag = 1; flag = 1;
} }
@ -268,7 +269,10 @@ void IdleProcess(DisplayTaskMessage_Type msg)
{ {
uint8_t Info[10] = {0,}; uint8_t Info[10] = {0,};
sprintf ((char*)Info, "%d%%", msg.ID); sprintf ((char*)Info, "%d%%", msg.ID);
LCD_ShowString_AutoAlign(0,240,250,Info,LCD_ALIGN_CENTER,WHITE,BLACK,0,28); /* 设计稿百分比约 y270清带避免 9%→100% 残影 */
LCD_FillByColor(40, 265, 200, 298, UI0902_BG_COLOR);
LCD_ShowString_AutoAlign(0, 240, 270, Info, LCD_ALIGN_CENTER,
WHITE, UI0902_BG_COLOR, 0, 28);
} }
//else //else
//BSP_MainPowerEnable(0); //BSP_MainPowerEnable(0);

View File

@ -280,7 +280,11 @@
#define UI0902_BOOT_LOGO_W 240 #define UI0902_BOOT_LOGO_W 240
#define UI0902_BOOT_LOGO_H 320 #define UI0902_BOOT_LOGO_H 320
#define UI0902_BTN_CANCEL_BIG_ADDR (UI0902_RES_BASE + 0x0AC000UL) /* 11872 bytes */ #define UI0902_CHARGE_SCREEN_ADDR (UI0902_RES_BASE + 0x0AC000UL) /* 153600 bytes */
#define UI0902_CHARGE_SCREEN_W 240
#define UI0902_CHARGE_SCREEN_H 320
#define UI0902_BTN_CANCEL_BIG_ADDR (UI0902_RES_BASE + 0x0D2000UL) /* 11872 bytes */
#define UI0902_BTN_CANCEL_BIG_W 106 #define UI0902_BTN_CANCEL_BIG_W 106
#define UI0902_BTN_CANCEL_BIG_H 56 #define UI0902_BTN_CANCEL_BIG_H 56

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -10,6 +10,7 @@ Outputs:
""" """
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
from pathlib import Path from pathlib import Path
import sys
ROOT = Path(__file__).resolve().parents[1] ROOT = Path(__file__).resolve().parents[1]
SRC = ROOT / "tools" / "assets_0902" SRC = ROOT / "tools" / "assets_0902"
@ -109,6 +110,9 @@ def make_cancel_button():
# ---------------- internal flash (small, high-frequency icons) ---------------- # ---------------- internal flash (small, high-frequency icons) ----------------
# NOTE: MCU-internal icon set in Drv_ILI9341_Lcd_Image_UI0902.c/.h may include
# extra hand-tuned symbols (tri/btn). Prefer --ext-only to refresh ExtFlash map
# without wiping those arrays.
INTERNAL = [ INTERNAL = [
("gImage_UI0902_Volume_20x15", "02_顶部图标/音量图标-10.png"), ("gImage_UI0902_Volume_20x15", "02_顶部图标/音量图标-10.png"),
("gImage_UI0902_Bluetooth_11x17", "02_顶部图标/蓝牙图标-10.png"), ("gImage_UI0902_Bluetooth_11x17", "02_顶部图标/蓝牙图标-10.png"),
@ -194,38 +198,45 @@ EXTERNAL = [
("TXT_RESTORE_V2", "06_控件/文字/文字-25.png"), ("TXT_RESTORE_V2", "06_控件/文字/文字-25.png"),
("TXT_RESTORE_H", "06_控件/文字/文字-26.png"), ("TXT_RESTORE_H", "06_控件/文字/文字-26.png"),
("TXT_RESTORE_CONFIRM", "06_控件/文字/文字-27.png"), ("TXT_RESTORE_CONFIRM", "06_控件/文字/文字-27.png"),
# 整屏开机 Logo(避开旧 0x0 / 充电 0xCB70 区,挂在 ui0902 资源包末尾 # 整屏开机 Logo / 充电画面(避开旧 0x0 / Charg.bin 0xCB70 区,挂在 ui0902 资源包
("BOOT_LOGO", "07_开机/开机界面-20.png"), ("BOOT_LOGO", "07_开机/开机界面-20.png"),
("CHARGE_SCREEN", "08_充电界面/充电界面-0902-09.png"), # 0904 最新全屏充电稿;百分比重叠由固件绘制
] ]
def main(): def main():
ext_only = "--ext-only" in sys.argv
# ---- internal flash C arrays ---- # ---- internal flash C arrays ----
c_lines = ['#include "Drv_ILI9341_Lcd_Image_UI0902.h"', "", if not ext_only:
"/* Auto-generated by tools/gen_ui0902_assets.py. Do not hand-edit. */", ""] c_lines = ['#include "Drv_ILI9341_Lcd_Image_UI0902.h"', "",
h_lines = ["#ifndef __DRV_ILI9341_LCD_IMAGE_UI0902_H", "/* Auto-generated by tools/gen_ui0902_assets.py. Do not hand-edit. */", ""]
"#define __DRV_ILI9341_LCD_IMAGE_UI0902_H", "", h_lines = ["#ifndef __DRV_ILI9341_LCD_IMAGE_UI0902_H",
'#include "stdint.h"', ""] "#define __DRV_ILI9341_LCD_IMAGE_UI0902_H", "",
total_int = 0 '#include "stdint.h"', ""]
total_int = 0
data, w, h = rgba_to_rgb565(make_battery_outline()) data, w, h = rgba_to_rgb565(make_battery_outline())
emit_c_array(c_lines, "gImage_UI0902_BatteryOutline_29x12", data, w, h) emit_c_array(c_lines, "gImage_UI0902_BatteryOutline_29x12", data, w, h)
h_lines.append("extern const unsigned char gImage_UI0902_BatteryOutline_29x12[];") h_lines.append("extern const unsigned char gImage_UI0902_BatteryOutline_29x12[];")
total_int += len(data)
data, w, h = rgba_to_rgb565(make_battery_fill())
emit_c_array(c_lines, "gImage_UI0902_BatteryFill_22x9", data, w, h)
h_lines.append(f"extern const unsigned char gImage_UI0902_BatteryFill_22x9[{len(data)}];")
total_int += len(data)
for name, rel in INTERNAL:
data, w, h = rgba_to_rgb565(Image.open(SRC / rel))
emit_c_array(c_lines, name, data, w, h)
h_lines.append(f"extern const unsigned char {name}[{len(data)}];")
total_int += len(data) total_int += len(data)
h_lines += ["", "#endif", ""]
OUT_H.write_text("\n".join(h_lines), encoding="utf-8") data, w, h = rgba_to_rgb565(make_battery_fill())
OUT_C.write_text("\n".join(c_lines), encoding="utf-8") emit_c_array(c_lines, "gImage_UI0902_BatteryFill_22x9", data, w, h)
h_lines.append(f"extern const unsigned char gImage_UI0902_BatteryFill_22x9[{len(data)}];")
total_int += len(data)
for name, rel in INTERNAL:
data, w, h = rgba_to_rgb565(Image.open(SRC / rel))
emit_c_array(c_lines, name, data, w, h)
h_lines.append(f"extern const unsigned char {name}[{len(data)}];")
total_int += len(data)
h_lines += ["", "#endif", ""]
OUT_H.write_text("\n".join(h_lines), encoding="utf-8")
OUT_C.write_text("\n".join(c_lines), encoding="utf-8")
print(f"internal flash payload: {total_int} bytes -> {OUT_C.name}")
else:
print("Skip internal C arrays (--ext-only)")
# ---- external flash bin ---- # ---- external flash bin ----
addr_lines = ["#ifndef __UI0902_RES_ADDR_H", "#define __UI0902_RES_ADDR_H", "", addr_lines = ["#ifndef __UI0902_RES_ADDR_H", "#define __UI0902_RES_ADDR_H", "",
@ -239,7 +250,7 @@ def main():
if name in ("ROW_UNIVERSAL_NOT", "ROW_UNIVERSAL_SEL", "ROW_NORMAL_NOT", "ROW_NORMAL_SEL", "ROW_EXPERT_NOT", "ROW_EXPERT_SEL"): if name in ("ROW_UNIVERSAL_NOT", "ROW_UNIVERSAL_SEL", "ROW_NORMAL_NOT", "ROW_NORMAL_SEL", "ROW_EXPERT_NOT", "ROW_EXPERT_SEL"):
im = im.resize(ROW_RESIZE, Image.LANCZOS) im = im.resize(ROW_RESIZE, Image.LANCZOS)
data, w, h = rgba_to_rgb565(im) data, w, h = rgba_to_rgb565(im)
elif name == "BOOT_LOGO": elif name in ("BOOT_LOGO", "CHARGE_SCREEN"):
if im.size[0] >= 241 and im.size[1] >= 321: if im.size[0] >= 241 and im.size[1] >= 321:
im = im.crop((0, 0, 240, 320)) im = im.crop((0, 0, 240, 320))
elif im.size != (240, 320): elif im.size != (240, 320):
@ -265,7 +276,6 @@ def main():
OUT_ADDR.write_text("\n".join(addr_lines), encoding="utf-8") OUT_ADDR.write_text("\n".join(addr_lines), encoding="utf-8")
OUT_BIN.write_bytes(bytes(blob)) OUT_BIN.write_bytes(bytes(blob))
print(f"internal flash payload: {total_int} bytes -> {OUT_C.name}")
print(f"external flash payload: {len(blob)} bytes ({len(entries)} images) -> {OUT_BIN.name}") print(f"external flash payload: {len(blob)} bytes ({len(entries)} images) -> {OUT_BIN.name}")
print(f"addr header -> {OUT_ADDR}") print(f"addr header -> {OUT_ADDR}")

View File

@ -4,7 +4,7 @@
Layout (absolute W25Q128 offsets): Layout (absolute W25Q128 offsets):
0x00000000 logo.bin (legacy pad; boot UI uses UI0902 full-screen logo) 0x00000000 logo.bin (legacy pad; boot UI uses UI0902 full-screen logo)
0x0000CB70 Charg.bin (160x190 RGB565 charging art) 0x0000CB70 Charg.bin (legacy pad; charge UI uses UI0902_CHARGE_SCREEN full-screen)
0x0001B8F0 1.bin 普通/专业 31 rhythms 0x0001B8F0 1.bin 普通/专业 31 rhythms
0x0009D07D 2.bin 海阔天空 0x0009D07D 2.bin 海阔天空
0x000A8607 3.bin 万能模式 0x000A8607 3.bin 万能模式
@ -42,7 +42,7 @@ def main() -> None:
ziliao = find_ziliao() ziliao = find_ziliao()
parts = [ parts = [
("LOGO", ziliao / "logo.bin", 0x00000000, "legacy pad; boot uses UI0902_BOOT_LOGO"), ("LOGO", ziliao / "logo.bin", 0x00000000, "legacy pad; boot uses UI0902_BOOT_LOGO"),
("CHARGING", ziliao / "Charg.bin", 0x0000CB70, "160x190 RGB565"), ("CHARGING", ziliao / "Charg.bin", 0x0000CB70, "legacy pad; UI uses UI0902_CHARGE_SCREEN"),
("BIN1_RHYTHM", TONE_DIR / "1.bin", 0x0001B8F0, "普通/专业 31 条节奏"), ("BIN1_RHYTHM", TONE_DIR / "1.bin", 0x0001B8F0, "普通/专业 31 条节奏"),
("BIN2_SONG_HAITIAN", TONE_DIR / "2.bin", None, "本地曲目 海阔天空"), ("BIN2_SONG_HAITIAN", TONE_DIR / "2.bin", None, "本地曲目 海阔天空"),
("BIN3_UNIVERSAL", TONE_DIR / "3.bin", None, "万能模式"), ("BIN3_UNIVERSAL", TONE_DIR / "3.bin", None, "万能模式"),

View File

@ -143,7 +143,7 @@ def main() -> None:
"说明:", "说明:",
" - 只刷音色 .res、不刷 UI0902 时,模式选择页会花屏(读图地址在 0x100000", " - 只刷音色 .res、不刷 UI0902 时,模式选择页会花屏(读图地址在 0x100000",
" - 本机开发板若早已刷过 UI0902只更新音色+MCU 仍可能正常;同事空片/整片擦除会中招。", " - 本机开发板若早已刷过 UI0902只更新音色+MCU 仍可能正常;同事空片/整片擦除会中招。",
" - 开机全屏 Logo 在 UI0902不在音色包里的 logo.bin 占位。", " - 开机全屏 Logo、关机充电全屏画面在 UI0902不在音色包里的 logo.bin/Charg.bin 占位。",
" - AutoBand 0x9EB5F 本版未重排。", " - AutoBand 0x9EB5F 本版未重排。",
"", "",
"附件: SoundWalkerIAP.exe / 升级步骤.docx / FLASH_MAP.txt", "附件: SoundWalkerIAP.exe / 升级步骤.docx / FLASH_MAP.txt",