release: 0.2.10 — tone pack 0914 (BIN3 after 2.bin), autoclose label 关闭
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
7fa2f5f1c4
commit
f8aeb4fb7c
|
|
@ -101,7 +101,7 @@ int16_t MIC_VOL_MAP[11]= {-9000,-7000,-5000,-3000,-1000,1000,3000,5000,7000,9000
|
|||
|
||||
uint8_t TOUCH_AREA_NUM = (sizeof(Touch_Areas)/sizeof(Touch_AreaTypeDef));
|
||||
|
||||
const uint8_t Version[3] = {0,2,9}; /* major.minor.patch — 0.2.9: Finger bass PC=33; HIL harness + tm1617/adc inject hooks */
|
||||
const uint8_t Version[3] = {0,2,10}; /* major.minor.patch — 0.2.10: tone 0914 (BIN3 after 2.bin); autoclose label 关闭 */
|
||||
|
||||
uint8_t Led = 8;
|
||||
bool PressFlag = 0;
|
||||
|
|
|
|||
|
|
@ -1321,9 +1321,9 @@ void Draw_System_Item_List(const LEBEL_UI *UI, GUI_SWITCH *Group)
|
|||
WHITE, c_top, c_bot, value_sz);
|
||||
}else
|
||||
{
|
||||
/* 手册「不自动」;字库无「不」,界面用稿面「关机」 */
|
||||
/* 手册「不自动」;字库无「不」,界面显示「关闭」 */
|
||||
LCD_ShowChinese_AutoAlign_Gradient(val_x1 + UI0902_TRI_L_W, val_x2 - UI0902_TRI_R_W, text_y,
|
||||
(const uint8_t*)"\xB9\xD8\xBB\xFA",
|
||||
(const uint8_t*)"\xB9\xD8\xB1\xD5",
|
||||
LCD_ALIGN_CENTER, WHITE, c_top, c_bot, value_sz);
|
||||
}
|
||||
UI_DrawTriRight((uint16_t)(val_x2 - UI0902_TRI_R_W), chev_cy);
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@
|
|||
/* Auto-generated by tools/pack_extflash_tone_0903.py — do not hand-edit. */
|
||||
/* W25Q128 absolute offsets. Boot logo display uses UI0902_BOOT_LOGO_ADDR. */
|
||||
/* Tone resource pack has no in-bin version field; release tag = EXTFLASH_TONE_RES_VER. */
|
||||
#define EXTFLASH_TONE_RES_VER "0903"
|
||||
#define EXTFLASH_TONE_RES_VER "0914"
|
||||
#define EXTFLASH_TONE_RES_VER_MAJOR 0
|
||||
#define EXTFLASH_TONE_RES_VER_MINOR 9
|
||||
#define EXTFLASH_TONE_RES_VER_PATCH 3
|
||||
#define EXTFLASH_TONE_RES_VER_PATCH 14
|
||||
|
||||
#define EXTFLASH_LOGO_ADDR 0x00000000UL
|
||||
#define EXTFLASH_LOGO_SIZE 52080UL
|
||||
|
|
@ -18,13 +18,13 @@
|
|||
#define EXTFLASH_CHARGING_H 190
|
||||
|
||||
#define EXTFLASH_BIN1_RHYTHM_ADDR 0x0001B8F0UL
|
||||
#define EXTFLASH_BIN1_RHYTHM_SIZE 530273UL
|
||||
#define EXTFLASH_BIN1_RHYTHM_SIZE 509151UL
|
||||
|
||||
#define EXTFLASH_BIN2_SONG_HAITIAN_ADDR 0x0009D07DUL
|
||||
#define EXTFLASH_BIN2_SONG_HAITIAN_SIZE 41263UL
|
||||
#define EXTFLASH_BIN2_SONG_HAITIAN_SIZE 41914UL
|
||||
|
||||
#define EXTFLASH_BIN3_UNIVERSAL_ADDR 0x000A71ACUL
|
||||
#define EXTFLASH_BIN3_UNIVERSAL_SIZE 31854UL
|
||||
#define EXTFLASH_BIN3_UNIVERSAL_ADDR 0x000A7437UL
|
||||
#define EXTFLASH_BIN3_UNIVERSAL_SIZE 33815UL
|
||||
|
||||
/* Convenience aliases used by UI ADDRESS */
|
||||
#define FLASH_ADDR_MODE_NORMAL EXTFLASH_BIN1_RHYTHM_ADDR /* 普通 */
|
||||
|
|
@ -32,11 +32,11 @@
|
|||
#define FLASH_ADDR_SONG_HAITIAN EXTFLASH_BIN2_SONG_HAITIAN_ADDR
|
||||
#define FLASH_ADDR_MODE_UNIVERSAL EXTFLASH_BIN3_UNIVERSAL_ADDR /* 万能 */
|
||||
|
||||
/* Legacy AutoBand bank — not repacked in 0903; left unchanged in firmware */
|
||||
/* Legacy AutoBand bank — not repacked; may overlap 2.bin — do not enable until remapped */
|
||||
#define FLASH_ADDR_AUTOBAND_LEGACY 0x0009EB5FUL
|
||||
|
||||
#define EXTFLASH_TONE_PACK_END 0x000AEE1AUL
|
||||
#define EXTFLASH_TONE_PACK_SIZE 716314UL
|
||||
#define EXTFLASH_TONE_PACK_END 0x000AF84EUL
|
||||
#define EXTFLASH_TONE_PACK_SIZE 718926UL
|
||||
#define UI0902_RES_BASE_SAFE_GAP (0x00100000UL - EXTFLASH_TONE_PACK_END)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
/* Auto-generated by tools/gen_git_user_fw_ver.py — do not edit.
|
||||
* git HEAD (dirty): 6da7d4d62737bd294dc42a3265e25b789b33e08c
|
||||
* git HEAD (dirty): 7fa2f5f1c43ce40fcabb0b847dedd43618ac0875
|
||||
* branch: develop → develop
|
||||
* 01 0C wire: develop_6da7d4*
|
||||
* 01 0C wire: develop_7fa2f5*
|
||||
*/
|
||||
#ifndef GIT_USER_FW_VER_H
|
||||
#define GIT_USER_FW_VER_H
|
||||
|
||||
#define GIT_COMMIT_ID_FULL "6da7d4d62737bd294dc42a3265e25b789b33e08c"
|
||||
#define GIT_COMMIT_ID_FULL "7fa2f5f1c43ce40fcabb0b847dedd43618ac0875"
|
||||
#define GIT_BRANCH_NAME "develop"
|
||||
#define GIT_COMMIT_SHORT6 "6da7d4"
|
||||
#define GIT_COMMIT_SHORT6 "7fa2f5"
|
||||
#define GIT_DIRTY (1)
|
||||
#define GIT_BUILD_ID "develop_6da7d4*"
|
||||
#define GIT_BUILD_ID "develop_7fa2f5*"
|
||||
#define GIT_BUILD_ID_LEN 15u
|
||||
|
||||
#endif /* GIT_USER_FW_VER_H */
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ from pathlib import Path
|
|||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
REPO = ROOT.parent.parent
|
||||
CSV_PATH = REPO / "Doc" / "音色文件" / "0903" / "local_songs.csv"
|
||||
CSV_PATH = REPO / "Doc" / "音色文件" / "0914" / "local_songs.csv"
|
||||
if not CSV_PATH.is_file():
|
||||
CSV_PATH = REPO / "Doc" / "音色文件" / "0903" / "local_songs.csv"
|
||||
OUT_HDR = ROOT / "project" / "inc" / "LocalSongNames.h"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Pack external W25Q128 tone/logo image for K1 (0903).
|
||||
"""Pack external W25Q128 tone/logo image for K1 (0914).
|
||||
|
||||
Layout (absolute W25Q128 offsets — BIN2/BIN3 are FIXED so FW addresses stay stable):
|
||||
Layout (absolute W25Q128 offsets):
|
||||
0x00000000 logo.bin (legacy pad; boot UI uses UI0902 full-screen logo)
|
||||
0x0000CB70 Charg.bin (legacy pad; charge UI uses UI0902_CHARGE_SCREEN full-screen)
|
||||
0x0000CB70 Charg.bin (legacy pad; charge UI uses UI0902_CHARGE_SCREEN)
|
||||
0x0001B8F0 1.bin 普通/专业 31 rhythms
|
||||
0x0009D07D 2.bin 本地曲目(变长,尾部 0xFF 填到 BIN3;<=41KB)
|
||||
0x000A71AC 3.bin 万能模式(固定;勿随 2.bin 长度漂移)
|
||||
0x0009D07D 2.bin 本地曲目(变长,<=41KB)
|
||||
after 2.bin 3.bin 万能模式(随 2.bin 长度后移;写入 ExtFlash_Tone_Addr.h)
|
||||
|
||||
Outputs:
|
||||
tools/out/extflash_tone_0903.bin
|
||||
tools/out/extflash_tone_0903.res (same bytes, .res alias)
|
||||
tools/out/extflash_ALL_tone0903_ui0902.res (tone + pad + ui0902, if ui pack present)
|
||||
tools/out/extflash_tone_0914.bin / .res
|
||||
tools/out/extflash_ALL_tone0914_ui0902.res
|
||||
project/inc/ExtFlash_Tone_Addr.h
|
||||
Doc/音色文件/0903/FLASH_MAP.txt
|
||||
Doc/音色文件/0914/FLASH_MAP.txt
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
|
|
@ -26,25 +25,28 @@ from pathlib import Path
|
|||
ROOT = Path(__file__).resolve().parents[1] # firmware project root
|
||||
REPO = ROOT.parent.parent # 一诺国际吉他
|
||||
OUT_DIR = ROOT / "tools" / "out"
|
||||
OUT_BIN = OUT_DIR / "extflash_tone_0903.bin"
|
||||
OUT_RES = OUT_DIR / "extflash_tone_0903.res"
|
||||
OUT_ALL_RES = OUT_DIR / "extflash_ALL_tone0903_ui0902.res"
|
||||
TONE_TAG = "0914"
|
||||
OUT_BIN = OUT_DIR / f"extflash_tone_{TONE_TAG}.bin"
|
||||
OUT_RES = OUT_DIR / f"extflash_tone_{TONE_TAG}.res"
|
||||
OUT_ALL_RES = OUT_DIR / f"extflash_ALL_tone{TONE_TAG}_ui0902.res"
|
||||
# Keep legacy alias names for older tools that still look for 0903
|
||||
OUT_BIN_LEGACY = OUT_DIR / "extflash_tone_0903.bin"
|
||||
OUT_RES_LEGACY = OUT_DIR / "extflash_tone_0903.res"
|
||||
OUT_ALL_LEGACY = OUT_DIR / "extflash_ALL_tone0903_ui0902.res"
|
||||
OUT_HDR = ROOT / "project" / "inc" / "ExtFlash_Tone_Addr.h"
|
||||
OUT_MAP = REPO / "Doc" / "音色文件" / "0903" / "FLASH_MAP.txt"
|
||||
OUT_MAP = REPO / "Doc" / "音色文件" / TONE_TAG / "FLASH_MAP.txt"
|
||||
UI0902_BIN = OUT_DIR / "ui0902_res.bin"
|
||||
|
||||
TONE_DIR = REPO / "Doc" / "音色文件" / "0903"
|
||||
TONE_DIR = REPO / "Doc" / "音色文件" / TONE_TAG
|
||||
|
||||
# Fixed map — must match project/inc/ExtFlash_Tone_Addr.h consumed by firmware.
|
||||
OFF_LOGO = 0x00000000
|
||||
OFF_CHARGING = 0x0000CB70
|
||||
OFF_BIN1 = 0x0001B8F0
|
||||
OFF_BIN2 = 0x0009D07D
|
||||
OFF_BIN3 = 0x000A71AC # FIXED: never place 3.bin by concatenating after variable 2.bin
|
||||
# BIN3 placed immediately after 2.bin (computed at pack time)
|
||||
UI0902_RES_BASE = 0x00100000
|
||||
DAB_MAGIC = b"\xABDAB"
|
||||
MAX_SONG_BIN_BYTES = 41 * 1024 # 曲目文件(2.bin)硬上限 41KB
|
||||
BIN2_SLOT_BYTES = OFF_BIN3 - OFF_BIN2 # 41263; must keep BIN3 fixed
|
||||
|
||||
|
||||
def find_ziliao() -> Path:
|
||||
|
|
@ -76,28 +78,31 @@ def require_region_equals(blob: bytes, off: int, src: bytes, label: str) -> None
|
|||
|
||||
|
||||
def main() -> None:
|
||||
if not TONE_DIR.is_dir():
|
||||
raise SystemExit(f"missing tone dir: {TONE_DIR}")
|
||||
|
||||
ziliao = find_ziliao()
|
||||
bin1_path = TONE_DIR / "1.bin"
|
||||
bin2_path = TONE_DIR / "2.bin"
|
||||
bin3_path = TONE_DIR / "3.bin"
|
||||
parts = [
|
||||
("LOGO", ziliao / "logo.bin", OFF_LOGO, "legacy pad; boot uses UI0902_BOOT_LOGO"),
|
||||
("CHARGING", ziliao / "Charg.bin", OFF_CHARGING, "legacy pad; UI uses UI0902_CHARGE_SCREEN"),
|
||||
("BIN1_RHYTHM", bin1_path, OFF_BIN1, "普通/专业 31 条节奏"),
|
||||
("BIN2_SONG_HAITIAN", bin2_path, OFF_BIN2, "本地曲目"),
|
||||
("BIN3_UNIVERSAL", bin3_path, OFF_BIN3, "万能模式(固定偏移)"),
|
||||
]
|
||||
for p in (bin1_path, bin2_path, bin3_path):
|
||||
if not p.is_file():
|
||||
raise SystemExit(f"missing {p}")
|
||||
|
||||
bin2_data = bin2_path.read_bytes()
|
||||
if len(bin2_data) > MAX_SONG_BIN_BYTES:
|
||||
raise SystemExit(
|
||||
f"2.bin (曲目) too large: {len(bin2_data)} bytes > {MAX_SONG_BIN_BYTES} (41KB)"
|
||||
)
|
||||
if len(bin2_data) > BIN2_SLOT_BYTES:
|
||||
raise SystemExit(
|
||||
f"2.bin too large for fixed BIN3 slot: {len(bin2_data)} > {BIN2_SLOT_BYTES} "
|
||||
f"(would shift 3.bin past 0x{OFF_BIN3:X})"
|
||||
)
|
||||
|
||||
off_bin3 = OFF_BIN2 + len(bin2_data)
|
||||
parts = [
|
||||
("LOGO", ziliao / "logo.bin", OFF_LOGO, "legacy pad; boot uses UI0902_BOOT_LOGO"),
|
||||
("CHARGING", ziliao / "Charg.bin", OFF_CHARGING, "legacy pad; UI uses UI0902_CHARGE_SCREEN"),
|
||||
("BIN1_RHYTHM", bin1_path, OFF_BIN1, "普通/专业 31 条节奏"),
|
||||
("BIN2_SONG_HAITIAN", bin2_path, OFF_BIN2, "本地曲目"),
|
||||
("BIN3_UNIVERSAL", bin3_path, off_bin3, "万能模式(紧跟 2.bin 之后)"),
|
||||
]
|
||||
|
||||
blobs: list[bytes] = []
|
||||
cursor = 0
|
||||
|
|
@ -107,7 +112,7 @@ def main() -> None:
|
|||
if cursor > force_off:
|
||||
raise SystemExit(
|
||||
f"{name}: cursor 0x{cursor:X} past forced 0x{force_off:X} "
|
||||
f"(previous blob too large; enlarge next fixed gap or shrink prior file)"
|
||||
f"(previous blob too large)"
|
||||
)
|
||||
if cursor < force_off:
|
||||
pad = force_off - cursor
|
||||
|
|
@ -122,25 +127,33 @@ def main() -> None:
|
|||
OUT_DIR.mkdir(parents=True, exist_ok=True)
|
||||
packed = b"".join(blobs)
|
||||
OUT_BIN.write_bytes(packed)
|
||||
OUT_RES.write_bytes(packed) # 总音色 .bin 同步为 .res
|
||||
OUT_RES.write_bytes(packed)
|
||||
OUT_BIN_LEGACY.write_bytes(packed)
|
||||
OUT_RES_LEGACY.write_bytes(packed)
|
||||
|
||||
by_name = {r[0]: r for r in rows if not r[0].startswith("(")}
|
||||
bin1_data = bin1_path.read_bytes()
|
||||
bin3_data = bin3_path.read_bytes()
|
||||
|
||||
# Hard integrity gates
|
||||
dab_ok(packed, OFF_BIN1, expect_cnt=31)
|
||||
dab_ok(packed, OFF_BIN2, expect_cnt=1)
|
||||
dab_ok(packed, OFF_BIN3, expect_cnt=3)
|
||||
dab_ok(packed, off_bin3, expect_cnt=3)
|
||||
if by_name["BIN1_RHYTHM"][1] != OFF_BIN1:
|
||||
raise SystemExit(f"BIN1 placed @0x{by_name['BIN1_RHYTHM'][1]:X} want 0x{OFF_BIN1:X}")
|
||||
if by_name["BIN2_SONG_HAITIAN"][1] != OFF_BIN2:
|
||||
raise SystemExit(f"BIN2 placed @0x{by_name['BIN2_SONG_HAITIAN'][1]:X} want 0x{OFF_BIN2:X}")
|
||||
if by_name["BIN3_UNIVERSAL"][1] != OFF_BIN3:
|
||||
raise SystemExit(f"BIN3 placed @0x{by_name['BIN3_UNIVERSAL'][1]:X} want 0x{OFF_BIN3:X}")
|
||||
if by_name["BIN3_UNIVERSAL"][1] != off_bin3:
|
||||
raise SystemExit(f"BIN3 placed @0x{by_name['BIN3_UNIVERSAL'][1]:X} want 0x{off_bin3:X}")
|
||||
require_region_equals(packed, OFF_LOGO, (ziliao / "logo.bin").read_bytes(), "LOGO")
|
||||
require_region_equals(packed, OFF_CHARGING, (ziliao / "Charg.bin").read_bytes(), "CHARGING")
|
||||
require_region_equals(packed, OFF_BIN1, bin1_data, "BIN1/1.bin")
|
||||
require_region_equals(packed, OFF_BIN2, bin2_data, "BIN2/2.bin")
|
||||
require_region_equals(packed, OFF_BIN3, bin3_data, "BIN3/3.bin")
|
||||
require_region_equals(packed, off_bin3, bin3_data, "BIN3/3.bin")
|
||||
|
||||
if cursor > UI0902_RES_BASE:
|
||||
raise SystemExit(
|
||||
f"ERROR: tone pack end 0x{cursor:X} overflows UI0902 @ 0x{UI0902_RES_BASE:X}"
|
||||
)
|
||||
|
||||
hdr = f"""#ifndef __EXTFLASH_TONE_ADDR_H
|
||||
#define __EXTFLASH_TONE_ADDR_H
|
||||
|
|
@ -148,10 +161,10 @@ def main() -> None:
|
|||
/* Auto-generated by tools/pack_extflash_tone_0903.py — do not hand-edit. */
|
||||
/* W25Q128 absolute offsets. Boot logo display uses UI0902_BOOT_LOGO_ADDR. */
|
||||
/* Tone resource pack has no in-bin version field; release tag = EXTFLASH_TONE_RES_VER. */
|
||||
#define EXTFLASH_TONE_RES_VER "0903"
|
||||
#define EXTFLASH_TONE_RES_VER "{TONE_TAG}"
|
||||
#define EXTFLASH_TONE_RES_VER_MAJOR 0
|
||||
#define EXTFLASH_TONE_RES_VER_MINOR 9
|
||||
#define EXTFLASH_TONE_RES_VER_PATCH 3
|
||||
#define EXTFLASH_TONE_RES_VER_PATCH 14
|
||||
|
||||
#define EXTFLASH_LOGO_ADDR 0x{by_name['LOGO'][1]:08X}UL
|
||||
#define EXTFLASH_LOGO_SIZE {by_name['LOGO'][2]}UL
|
||||
|
|
@ -167,7 +180,7 @@ def main() -> None:
|
|||
#define EXTFLASH_BIN2_SONG_HAITIAN_ADDR 0x{OFF_BIN2:08X}UL
|
||||
#define EXTFLASH_BIN2_SONG_HAITIAN_SIZE {by_name['BIN2_SONG_HAITIAN'][2]}UL
|
||||
|
||||
#define EXTFLASH_BIN3_UNIVERSAL_ADDR 0x{OFF_BIN3:08X}UL
|
||||
#define EXTFLASH_BIN3_UNIVERSAL_ADDR 0x{off_bin3:08X}UL
|
||||
#define EXTFLASH_BIN3_UNIVERSAL_SIZE {by_name['BIN3_UNIVERSAL'][2]}UL
|
||||
|
||||
/* Convenience aliases used by UI ADDRESS */
|
||||
|
|
@ -176,7 +189,7 @@ def main() -> None:
|
|||
#define FLASH_ADDR_SONG_HAITIAN EXTFLASH_BIN2_SONG_HAITIAN_ADDR
|
||||
#define FLASH_ADDR_MODE_UNIVERSAL EXTFLASH_BIN3_UNIVERSAL_ADDR /* 万能 */
|
||||
|
||||
/* Legacy AutoBand bank — not repacked in 0903; left unchanged in firmware */
|
||||
/* Legacy AutoBand bank — not repacked; may overlap 2.bin — do not enable until remapped */
|
||||
#define FLASH_ADDR_AUTOBAND_LEGACY 0x0009EB5FUL
|
||||
|
||||
#define EXTFLASH_TONE_PACK_END 0x{cursor:08X}UL
|
||||
|
|
@ -188,12 +201,13 @@ def main() -> None:
|
|||
OUT_HDR.write_text(hdr, encoding="utf-8", newline="\n")
|
||||
|
||||
map_lines = [
|
||||
"K1 external Flash map — tone pack 0903",
|
||||
f"K1 external Flash map — tone pack {TONE_TAG}",
|
||||
f"Packed file: Code/.../tools/out/{OUT_BIN.name} ({len(packed)} bytes)",
|
||||
f"Also: {OUT_RES.name}; ALL.res when ui0902_res.bin present",
|
||||
f"Ends at 0x{cursor:X}; UI0902_RES_BASE=0x00100000; free gap={0x100000 - cursor} bytes",
|
||||
f"Ends at 0x{cursor:X}; UI0902_RES_BASE=0x00100000; free gap={UI0902_RES_BASE - cursor} bytes",
|
||||
"",
|
||||
"NOTE: BIN3 is FIXED at 0x000A71AC. 2.bin must be <= 41KB and <= slot 41263 bytes.",
|
||||
f"NOTE: BIN3 follows 2.bin @ 0x{off_bin3:X} (2.bin grew past old fixed 0xA71AC).",
|
||||
" 2.bin must be <= 41KB; LOGO/CHARG/BIN1/BIN2 offsets remain fixed.",
|
||||
"",
|
||||
f"{'Name':<22} {'Offset':>10} {'Size':>10} Note",
|
||||
"-" * 72,
|
||||
|
|
@ -205,17 +219,16 @@ def main() -> None:
|
|||
"Firmware ADDRESS mapping:",
|
||||
" 普通/专业 -> FLASH_ADDR_MODE_NORMAL/EXPERT (1.bin @ 0x1B8F0)",
|
||||
" 本地曲目 -> FLASH_ADDR_SONG_HAITIAN (2.bin @ 0x9D07D, max 41KB)",
|
||||
" 万能 -> FLASH_ADDR_MODE_UNIVERSAL (3.bin @ 0xA71AC FIXED)",
|
||||
" AutoBand -> FLASH_ADDR_AUTOBAND_LEGACY 0x9EB5F (unchanged; overlaps 2.bin region — do not enable until remapped)",
|
||||
f" 万能 -> FLASH_ADDR_MODE_UNIVERSAL (3.bin @ 0x{off_bin3:X})",
|
||||
" Boot logo -> UI0902_BOOT_LOGO_ADDR (full-screen); packed logo.bin only pads 0x0..0xCB70",
|
||||
" Charging -> EXTFLASH_CHARGING_ADDR",
|
||||
" Charging -> EXTFLASH_CHARGING_ADDR (legacy pad) / UI0902_CHARGE_SCREEN",
|
||||
"",
|
||||
"Add a local song:",
|
||||
" 1. Pack the new preset into 2.bin (must stay <= 41KB / 41263 slot)",
|
||||
" 2. Append a row to local_songs.csv (index,code,name)",
|
||||
" 3. python tools/pack_extflash_tone_0903.py (also regenerates LocalSongNames.h)",
|
||||
" 4. Rebuild firmware and flash MCU + ExtFlash ALL.res",
|
||||
"Rebuild after pack:",
|
||||
" 1. python tools/pack_extflash_tone_0903.py",
|
||||
" 2. Rebuild MCU (ExtFlash_Tone_Addr.h updated)",
|
||||
" 3. Flash MCU + ExtFlash ALL.res",
|
||||
]
|
||||
OUT_MAP.parent.mkdir(parents=True, exist_ok=True)
|
||||
OUT_MAP.write_text("\n".join(map_lines) + "\n", encoding="utf-8", newline="\n")
|
||||
|
||||
print(f"Wrote {OUT_BIN} ({len(packed)} bytes)")
|
||||
|
|
@ -224,32 +237,42 @@ def main() -> None:
|
|||
print(f"Wrote {OUT_MAP}")
|
||||
for name, off, size, note in rows:
|
||||
print(f" 0x{off:08X} {size:8d} {name} {note}")
|
||||
if cursor > UI0902_RES_BASE:
|
||||
raise SystemExit("ERROR: pack overflows into UI0902_RES_BASE")
|
||||
print(f"OK: {UI0902_RES_BASE - cursor} bytes free before UI0902 @ 0x{UI0902_RES_BASE:X}")
|
||||
print("OK: BIN1/BIN2/BIN3 present at fixed addresses and match source files")
|
||||
print(f"OK: 2.bin size {len(bin2_data)} <= 41KB ({MAX_SONG_BIN_BYTES})")
|
||||
print("OK: LOGO/CHARG/BIN1/BIN2/BIN3 present and match source files")
|
||||
print(f"OK: 2.bin size {len(bin2_data)} <= 41KB; BIN3 @ 0x{off_bin3:X}")
|
||||
|
||||
if UI0902_BIN.is_file():
|
||||
ui = UI0902_BIN.read_bytes()
|
||||
all_res = packed + (b"\xFF" * (UI0902_RES_BASE - len(packed))) + ui
|
||||
require_region_equals(all_res, OFF_BIN1, bin1_data, "ALL.res BIN1")
|
||||
require_region_equals(all_res, OFF_BIN2, bin2_data, "ALL.res BIN2")
|
||||
require_region_equals(all_res, OFF_BIN3, bin3_data, "ALL.res BIN3")
|
||||
require_region_equals(all_res, off_bin3, bin3_data, "ALL.res BIN3")
|
||||
dab_ok(all_res, OFF_BIN1, 31)
|
||||
dab_ok(all_res, OFF_BIN2, 1)
|
||||
dab_ok(all_res, OFF_BIN3, 3)
|
||||
dab_ok(all_res, off_bin3, 3)
|
||||
# UI0902 magic/presence: non-empty and starts within expected region
|
||||
if len(ui) < 1024:
|
||||
raise SystemExit(f"UI0902 pack suspiciously small: {len(ui)}")
|
||||
OUT_ALL_RES.write_bytes(all_res)
|
||||
# Mirror under repo tools/out for publish/consumers
|
||||
OUT_ALL_LEGACY.write_bytes(all_res)
|
||||
repo_out = REPO / "tools" / "out"
|
||||
repo_out.mkdir(parents=True, exist_ok=True)
|
||||
(repo_out / OUT_ALL_RES.name).write_bytes(all_res)
|
||||
(repo_out / OUT_ALL_LEGACY.name).write_bytes(all_res)
|
||||
(repo_out / OUT_RES.name).write_bytes(packed)
|
||||
print(f"Wrote {OUT_ALL_RES} ({len(all_res)} bytes) — verified 1/2/3.bin")
|
||||
(repo_out / OUT_RES_LEGACY.name).write_bytes(packed)
|
||||
print(f"Wrote {OUT_ALL_RES} ({len(all_res)} bytes) — verified logo/charg/1/2/3 + UI0902")
|
||||
else:
|
||||
print(f"WARN: {UI0902_BIN} missing; skipped ALL.res")
|
||||
|
||||
# Prefer 0914 CSV; fall back to 0903
|
||||
csv_0914 = TONE_DIR / "local_songs.csv"
|
||||
gen = ROOT / "tools" / "gen_local_song_names.py"
|
||||
if not csv_0914.is_file():
|
||||
src = REPO / "Doc" / "音色文件" / "0903" / "local_songs.csv"
|
||||
if src.is_file():
|
||||
csv_0914.write_bytes(src.read_bytes())
|
||||
print(f"Copied {src.name} -> {csv_0914}")
|
||||
r = subprocess.run([sys.executable, str(gen)], check=False)
|
||||
if r.returncode != 0:
|
||||
raise SystemExit(f"gen_local_song_names.py failed ({r.returncode})")
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ Boot must also be updated so USB IAP wait screen can show UI0902_FLASH_MODE.
|
|||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import zipfile
|
||||
|
|
@ -29,14 +30,15 @@ BOOT_BIN = (
|
|||
/ "Exe"
|
||||
/ "AT32F403ARCT7_BOOT.bin"
|
||||
)
|
||||
TONE_BIN = PROJ / "tools" / "out" / "extflash_tone_0903.bin"
|
||||
TONE_RES_VER = "0914"
|
||||
TONE_BIN = PROJ / "tools" / "out" / f"extflash_tone_{TONE_RES_VER}.bin"
|
||||
UI0902_BIN = PROJ / "tools" / "out" / "ui0902_res.bin"
|
||||
MAP_TXT = REPO / "Doc" / "音色文件" / "0903" / "FLASH_MAP.txt"
|
||||
MAP_TXT = REPO / "Doc" / "音色文件" / TONE_RES_VER / "FLASH_MAP.txt"
|
||||
TONE_HDR = PROJ / "project" / "inc" / "ExtFlash_Tone_Addr.h"
|
||||
IAP_DIR = REPO / "升级" / "MCU主控升级"
|
||||
OUT_ROOT = REPO / "tools" / "out"
|
||||
|
||||
FW_VER = "0.2.9"
|
||||
TONE_RES_VER = "0903"
|
||||
FW_VER = "0.2.10"
|
||||
UI0902_RES_BASE = 0x00100000
|
||||
BOOT_FLASH_ADDR = 0x08000000
|
||||
APP_FLASH_ADDR = 0x08008000
|
||||
|
|
@ -69,31 +71,63 @@ def build_combined_extflash(tone: bytes, ui: bytes) -> bytes:
|
|||
return tone + (b"\xFF" * pad) + ui
|
||||
|
||||
|
||||
def verify_tone_layout(tone: bytes, check_sources: bool = True) -> None:
|
||||
"""Refuse to ship ALL.res if 1/2/3.bin missing, shifted, or content mismatch."""
|
||||
dab = b"\xABDAB"
|
||||
sources = {
|
||||
"BIN1": (0x0001B8F0, 31, REPO / "Doc" / "音色文件" / "0903" / "1.bin"),
|
||||
"BIN2": (0x0009D07D, 1, REPO / "Doc" / "音色文件" / "0903" / "2.bin"),
|
||||
"BIN3": (0x000A71AC, 3, REPO / "Doc" / "音色文件" / "0903" / "3.bin"),
|
||||
def read_tone_addrs() -> dict[str, int]:
|
||||
text = TONE_HDR.read_text(encoding="utf-8", errors="replace")
|
||||
def grab(name: str) -> int:
|
||||
m = re.search(rf"#define\s+{name}\s+0x([0-9A-Fa-f]+)UL", text)
|
||||
if not m:
|
||||
raise SystemExit(f"missing {name} in {TONE_HDR}")
|
||||
return int(m.group(1), 16)
|
||||
return {
|
||||
"LOGO": grab("EXTFLASH_LOGO_ADDR"),
|
||||
"CHARGING": grab("EXTFLASH_CHARGING_ADDR"),
|
||||
"BIN1": grab("EXTFLASH_BIN1_RHYTHM_ADDR"),
|
||||
"BIN2": grab("EXTFLASH_BIN2_SONG_HAITIAN_ADDR"),
|
||||
"BIN3": grab("EXTFLASH_BIN3_UNIVERSAL_ADDR"),
|
||||
}
|
||||
for name, (off, want_cnt, src_path) in sources.items():
|
||||
|
||||
|
||||
def verify_tone_layout(tone: bytes, check_sources: bool = True) -> None:
|
||||
"""Refuse to ship ALL.res if logo/charg/1/2/3.bin missing, shifted, or mismatch."""
|
||||
dab = b"\xABDAB"
|
||||
addrs = read_tone_addrs()
|
||||
tone_dir = REPO / "Doc" / "音色文件" / TONE_RES_VER
|
||||
ziliao = None
|
||||
for p in REPO.iterdir():
|
||||
if p.is_dir() and (p / "logo.bin").is_file() and (p / "Charg.bin").is_file():
|
||||
ziliao = p
|
||||
break
|
||||
if ziliao is None:
|
||||
raise SystemExit("logo.bin/Charg.bin not found under repo")
|
||||
|
||||
sources = [
|
||||
("LOGO", addrs["LOGO"], None, ziliao / "logo.bin"),
|
||||
("CHARGING", addrs["CHARGING"], None, ziliao / "Charg.bin"),
|
||||
("BIN1", addrs["BIN1"], 31, tone_dir / "1.bin"),
|
||||
("BIN2", addrs["BIN2"], 1, tone_dir / "2.bin"),
|
||||
("BIN3", addrs["BIN3"], 3, tone_dir / "3.bin"),
|
||||
]
|
||||
for name, off, want_cnt, src_path in sources:
|
||||
if off + 16 > len(tone):
|
||||
raise SystemExit(f"verify {name}: tone pack too short for 0x{off:X}")
|
||||
magic = tone[off : off + 4]
|
||||
cnt = int.from_bytes(tone[off + 12 : off + 16], "little")
|
||||
if magic != dab or cnt != want_cnt:
|
||||
raise SystemExit(
|
||||
f"verify {name} @0x{off:X} failed: magic={magic.hex()} cnt={cnt} "
|
||||
f"(want ABDAB/{want_cnt}). Re-run pack_extflash_tone_0903.py."
|
||||
)
|
||||
if want_cnt is not None:
|
||||
magic = tone[off : off + 4]
|
||||
cnt = int.from_bytes(tone[off + 12 : off + 16], "little")
|
||||
if magic != dab or cnt != want_cnt:
|
||||
raise SystemExit(
|
||||
f"verify {name} @0x{off:X} failed: magic={magic.hex()} cnt={cnt} "
|
||||
f"(want ABDAB/{want_cnt}). Re-run pack_extflash_tone_0903.py."
|
||||
)
|
||||
if check_sources and src_path.is_file():
|
||||
src = src_path.read_bytes()
|
||||
if name == "BIN2" and len(src) > 41 * 1024:
|
||||
raise SystemExit(f"verify BIN2: source 2.bin {len(src)} > 41KB")
|
||||
if tone[off : off + len(src)] != src:
|
||||
raise SystemExit(f"verify {name}: content @0x{off:X} != {src_path}")
|
||||
print("verify tone layout: BIN1/BIN2/BIN3 addresses + content OK")
|
||||
print(
|
||||
"verify tone layout: LOGO/CHARG/BIN1/BIN2/BIN3 OK "
|
||||
f"(BIN3@0x{addrs['BIN3']:X})"
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
|
|
@ -102,9 +136,17 @@ def main() -> None:
|
|||
if not EXE_BIN.is_file():
|
||||
raise SystemExit(f"missing MCU bin: {EXE_BIN}")
|
||||
if not TONE_BIN.is_file():
|
||||
raise SystemExit(f"missing tone pack: {TONE_BIN} (run pack_extflash_tone_0903.py)")
|
||||
# fallback legacy alias written by packer
|
||||
legacy = PROJ / "tools" / "out" / "extflash_tone_0903.bin"
|
||||
if legacy.is_file():
|
||||
global TONE_BIN
|
||||
TONE_BIN = legacy
|
||||
else:
|
||||
raise SystemExit(f"missing tone pack: {TONE_BIN} (run pack_extflash_tone_0903.py)")
|
||||
if not UI0902_BIN.is_file():
|
||||
raise SystemExit(f"missing UI0902 pack: {UI0902_BIN} (run gen_ui0902_assets.py)")
|
||||
if not TONE_HDR.is_file():
|
||||
raise SystemExit(f"missing {TONE_HDR}")
|
||||
|
||||
iap = IAP_DIR / "SoundWalkerIAP.exe"
|
||||
guide = IAP_DIR / "升级步骤.docx"
|
||||
|
|
@ -126,12 +168,15 @@ def main() -> None:
|
|||
tone_data = TONE_BIN.read_bytes()
|
||||
verify_tone_layout(tone_data)
|
||||
ui_data = UI0902_BIN.read_bytes()
|
||||
if len(ui_data) < 1024:
|
||||
raise SystemExit(f"UI0902 pack too small: {len(ui_data)}")
|
||||
combined = build_combined_extflash(tone_data, ui_data)
|
||||
verify_tone_layout(combined) # same offsets in ALL.res
|
||||
verify_tone_layout(combined)
|
||||
|
||||
addrs = read_tone_addrs()
|
||||
boot_name = f"AT32F403ARCT7_BOOT_v{FW_VER}_{stamp}.bin"
|
||||
mcu_name = f"YNGJ-GT1-M_MCU_v{FW_VER}_{stamp}.bin"
|
||||
comb_name = f"extflash_ALL_tone0903_ui0902_{stamp}.res"
|
||||
comb_name = f"extflash_ALL_tone{TONE_RES_VER}_ui0902_{stamp}.res"
|
||||
|
||||
boot_dst = pkg / boot_name
|
||||
mcu_dst = pkg / mcu_name
|
||||
|
|
@ -147,9 +192,8 @@ def main() -> None:
|
|||
|
||||
shutil.copy2(boot_dst, OUT_ROOT / boot_name)
|
||||
shutil.copy2(mcu_dst, OUT_ROOT / mcu_name)
|
||||
shutil.copy2(comb_dst, OUT_ROOT / "extflash_ALL_tone0903_ui0902.res")
|
||||
# Keep build intermediates under tools/out for local rebuilds; not shipped in package.
|
||||
(OUT_ROOT / "extflash_tone_0903.res").write_bytes(tone_data)
|
||||
shutil.copy2(comb_dst, OUT_ROOT / f"extflash_ALL_tone{TONE_RES_VER}_ui0902.res")
|
||||
(OUT_ROOT / f"extflash_tone_{TONE_RES_VER}.res").write_bytes(tone_data)
|
||||
(OUT_ROOT / "extflash_ui0902.res").write_bytes(ui_data)
|
||||
|
||||
readme = pkg / "README.txt"
|
||||
|
|
@ -176,7 +220,8 @@ def main() -> None:
|
|||
"",
|
||||
"外部 Flash 分区:",
|
||||
" 0x00000000 音色/充电图 (toneRes)",
|
||||
" logo pad + Charg@0xCB70 + 1.bin@0x1B8F0 + 2.bin@0x9D07D + 3.bin@0xA71AC(FIXED)",
|
||||
f" logo@0x{addrs['LOGO']:X} + Charg@0x{addrs['CHARGING']:X} + "
|
||||
f"1.bin@0x{addrs['BIN1']:X} + 2.bin@0x{addrs['BIN2']:X} + 3.bin@0x{addrs['BIN3']:X}",
|
||||
" 0x00100000 UI0902 图片 (模式选择、开机 Logo、充电、烧录模式、设置/调音台等)",
|
||||
" 0x001D2000 UI0902_FLASH_MODE 烧录模式全屏图(Boot 读取)",
|
||||
"",
|
||||
|
|
@ -189,9 +234,8 @@ def main() -> None:
|
|||
"",
|
||||
"说明:",
|
||||
" - Boot 进入 USB IAP 时显示 UI0902_FLASH_MODE;资源未烧录时白字黑底兜底。",
|
||||
" - 烧录模式图来源:K1标准界面图 0904/烧录模式.png。",
|
||||
" - 开机全屏 Logo、关机充电全屏画面在 UI0902,不在音色包里的 logo.bin/Charg.bin 占位。",
|
||||
" - AutoBand 0x9EB5F 本版未重排。",
|
||||
f" - 本包音色来源 Doc/音色文件/{TONE_RES_VER}/;BIN3 随 2.bin 长度后移。",
|
||||
"",
|
||||
"附件: SoundWalkerIAP.exe / 升级步骤.docx / FLASH_MAP.txt",
|
||||
"",
|
||||
|
|
|
|||
Loading…
Reference in New Issue