Compare commits
No commits in common. "c1b32c035110d4a6a1b8b30665bdb267a862180a" and "f1f9520637904606e839d7d2df794ac3e48e7956" have entirely different histories.
c1b32c0351
...
f1f9520637
|
|
@ -280,12 +280,6 @@ uint8_t app_log_try_command(const char *cmd)
|
||||||
"FLASH_HAITIAN_GO", "FLASH_HAITIAN_OK\n");
|
"FLASH_HAITIAN_GO", "FLASH_HAITIAN_OK\n");
|
||||||
return 1U;
|
return 1U;
|
||||||
}
|
}
|
||||||
if (strncmp(cmd, "flash bin3 ", 11) == 0) {
|
|
||||||
uint32_t size = (uint32_t)strtoul(cmd + 11, NULL, 10);
|
|
||||||
app_log_flash_start_at(EXTFLASH_BIN3_UNIVERSAL_ADDR, size,
|
|
||||||
"FLASH_BIN3_GO", "FLASH_BIN3_OK\n");
|
|
||||||
return 1U;
|
|
||||||
}
|
|
||||||
if (strncmp(cmd, "tone status", 11) == 0) {
|
if (strncmp(cmd, "tone status", 11) == 0) {
|
||||||
uint8_t hdr[16];
|
uint8_t hdr[16];
|
||||||
uint8_t name[40];
|
uint8_t name[40];
|
||||||
|
|
@ -326,16 +320,6 @@ uint8_t app_log_try_command(const char *cmd)
|
||||||
(unsigned long)(cur_hdr[12] | (cur_hdr[13] << 8) |
|
(unsigned long)(cur_hdr[12] | (cur_hdr[13] << 8) |
|
||||||
(cur_hdr[14] << 16) | (cur_hdr[15] << 24)));
|
(cur_hdr[14] << 16) | (cur_hdr[15] << 24)));
|
||||||
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
|
||||||
{
|
|
||||||
uint8_t b3[16];
|
|
||||||
W25Q128_Read(b3, EXTFLASH_BIN3_UNIVERSAL_ADDR, 16);
|
|
||||||
snprintf(line, sizeof(line),
|
|
||||||
"TONE @BIN3 magic=%02X%02X%02X%02X cnt=%lu\n",
|
|
||||||
b3[0], b3[1], b3[2], b3[3],
|
|
||||||
(unsigned long)(b3[12] | (b3[13] << 8) |
|
|
||||||
(b3[14] << 16) | (b3[15] << 24)));
|
|
||||||
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
|
|
||||||
}
|
|
||||||
snprintf(line, sizeof(line),
|
snprintf(line, sizeof(line),
|
||||||
"TONE @BIN2 magic=%02X%02X%02X%02X max=%lu cnt=%lu name=%.16s\n",
|
"TONE @BIN2 magic=%02X%02X%02X%02X max=%lu cnt=%lu name=%.16s\n",
|
||||||
hdr[0], hdr[1], hdr[2], hdr[3],
|
hdr[0], hdr[1], hdr[2], hdr[3],
|
||||||
|
|
@ -381,20 +365,6 @@ uint8_t app_log_try_command(const char *cmd)
|
||||||
return 1U;
|
return 1U;
|
||||||
}
|
}
|
||||||
if (strncmp(cmd, "tone pick", 9) == 0) {
|
if (strncmp(cmd, "tone pick", 9) == 0) {
|
||||||
/* tone pick uni → 万能;默认仍测专业+本地曲目 */
|
|
||||||
if (cmd[9] == ' ' && (cmd[10] == 'u' || cmd[10] == 'U')) {
|
|
||||||
mGuiData[GUI_TAB_INDEX].Current = 0;
|
|
||||||
mGuiData[GUI_AUTOBAND_SW].Current = 0;
|
|
||||||
UI_ApplyToneAddress();
|
|
||||||
AutoBandTop1_Stop();
|
|
||||||
StartFlag = 0;
|
|
||||||
(void)AutoBandTop1_LoadPresetItemFromFlash(ParamGuiData[ALL_MODE_PARAM].Current);
|
|
||||||
KEY_ID_1629 = 0;
|
|
||||||
PressFlag = 0;
|
|
||||||
Pick_Handle();
|
|
||||||
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "TONE_PICK_UNI_DONE\n");
|
|
||||||
return 1U;
|
|
||||||
}
|
|
||||||
/* 模拟专业+本地曲目拨片(无和弦板) */
|
/* 模拟专业+本地曲目拨片(无和弦板) */
|
||||||
mGuiData[GUI_TAB_INDEX].Current = 1;
|
mGuiData[GUI_TAB_INDEX].Current = 1;
|
||||||
mGuiData[GUI_AUTOBAND_SW].Current = 1;
|
mGuiData[GUI_AUTOBAND_SW].Current = 1;
|
||||||
|
|
|
||||||
|
|
@ -89,11 +89,11 @@ const Touch_AreaTypeDef Touch_Areas[] =
|
||||||
{ 126, 172, UI0902_SECTION_Y, UI0902_SECTION_Y + UI0902_SECTION_BTN_H - 1, 0, 2, GUI_PLAY_SECTION, NULL },
|
{ 126, 172, UI0902_SECTION_Y, UI0902_SECTION_Y + UI0902_SECTION_BTN_H - 1, 0, 2, GUI_PLAY_SECTION, NULL },
|
||||||
{ 183, 229, UI0902_SECTION_Y, UI0902_SECTION_Y + UI0902_SECTION_BTN_H - 1, 0, 3, GUI_PLAY_SECTION, NULL },
|
{ 183, 229, UI0902_SECTION_Y, UI0902_SECTION_Y + UI0902_SECTION_BTN_H - 1, 0, 3, GUI_PLAY_SECTION, NULL },
|
||||||
|
|
||||||
/* 底栏四键:万能 | 普通 | 专业 | 设置(60×55,y265–319) */
|
/* 底栏四键:万能 | 普通 | 专业 | 设置(触区中线对齐 cx 40/100/160/210) */
|
||||||
{ UI0902_NAV_X0(0), UI0902_NAV_X1(0), UI0902_NAV_Y0, UI0902_NAV_Y1, 0, UI0902_NAV_UNIVERSAL, GUI_NAV_BAR, NULL },
|
{ 0, 69, 280, 319, 0, UI0902_NAV_UNIVERSAL, GUI_NAV_BAR, NULL },
|
||||||
{ UI0902_NAV_X0(1), UI0902_NAV_X1(1), UI0902_NAV_Y0, UI0902_NAV_Y1, 0, UI0902_NAV_NORMAL, GUI_NAV_BAR, NULL },
|
{ 70, 129, 280, 319, 0, UI0902_NAV_NORMAL, GUI_NAV_BAR, NULL },
|
||||||
{ UI0902_NAV_X0(2), UI0902_NAV_X1(2), UI0902_NAV_Y0, UI0902_NAV_Y1, 0, UI0902_NAV_EXPERT, GUI_NAV_BAR, NULL },
|
{ 130, 184, 280, 319, 0, UI0902_NAV_EXPERT, GUI_NAV_BAR, NULL },
|
||||||
{ UI0902_NAV_X0(3), UI0902_NAV_X1(3), UI0902_NAV_Y0, UI0902_NAV_Y1, 0, UI0902_NAV_SETTING, GUI_NAV_BAR, NULL },
|
{ 185, 239, 280, 319, 0, UI0902_NAV_SETTING, GUI_NAV_BAR, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 推子 0~10 共 11 档;档10 取 AW816 上限附近 */
|
/* 推子 0~10 共 11 档;档10 取 AW816 上限附近 */
|
||||||
|
|
@ -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));
|
uint8_t TOUCH_AREA_NUM = (sizeof(Touch_Areas)/sizeof(Touch_AreaTypeDef));
|
||||||
|
|
||||||
const uint8_t Version[3] = {0,2,7}; /* major.minor.patch — 0.2.7: 1.bin from Doc/音色文件/0909/31cs.bin; fixed BIN3 pack */
|
const uint8_t Version[3] = {0,2,6}; /* major.minor.patch — 0.2.6: local song 2.bin from Doc/音色文件/0908/2ss_2.bin */
|
||||||
|
|
||||||
uint8_t Led = 8;
|
uint8_t Led = 8;
|
||||||
bool PressFlag = 0;
|
bool PressFlag = 0;
|
||||||
|
|
@ -783,10 +783,15 @@ void Pick_Handle()
|
||||||
AutoBandTop1_SetLoopMode(0,1);
|
AutoBandTop1_SetLoopMode(0,1);
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
/* 设置页内沿用万能:与主路径一致,始终 loop */
|
if(PressFlag)
|
||||||
AutoBandTop1_SetPiecePlayMode(1, 0, 480);
|
{
|
||||||
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
AutoBandTop1_SetLoopMode(0,1);
|
||||||
AutoBandTop1_SetLoopMode(0, 1);
|
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
AutoBandTop1_SetPiecePlayMode(1,0,480);
|
||||||
|
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
||||||
|
}
|
||||||
StartFlag = 1;
|
StartFlag = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -837,14 +842,17 @@ void Pick_Handle()
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
/* 万能:和弦走向用 piece 模式;须 SetLoopMode,否则无循环时常听不到伴奏 */
|
|
||||||
StartFlag = 1;
|
StartFlag = 1;
|
||||||
AutoBandTop1_SetPiecePlayMode(1, 0, 480);
|
if(PressFlag)
|
||||||
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
{
|
||||||
AutoBandTop1_SetLoopMode(0, 1);
|
AutoBandTop1_SetPiecePlayMode(1,0,480);
|
||||||
LOG_I("pick", "universal piece name=%s press=%u notes=%u chord=%u",
|
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
||||||
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?",
|
AutoBandTop1_SetLoopMode(0,1);
|
||||||
(unsigned)PressFlag, (unsigned)note_cnt, (unsigned)chord_id);
|
}else
|
||||||
|
{
|
||||||
|
AutoBandTop1_SetPiecePlayMode(1,0,480);
|
||||||
|
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -148,12 +148,8 @@ void App_Auto_Init(void)
|
||||||
int ret = AutoBandTop1_LoadPresetItemFromFlash(0);
|
int ret = AutoBandTop1_LoadPresetItemFromFlash(0);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
{
|
{
|
||||||
uint8_t hdr[16];
|
LOG_E("AUTO", "LoadPreset fail ret=%d addr=0x%08X map=%s",
|
||||||
W25Q128_Read(hdr, (uint32_t)ADDRESS, 16);
|
ret, (unsigned)ADDRESS, ToneFlashMapBank((uint32_t)ADDRESS));
|
||||||
LOG_E("AUTO", "LoadPreset fail ret=%d addr=0x%08X map=%s magic=%02X%02X%02X%02X cnt=%lu",
|
|
||||||
ret, (unsigned)ADDRESS, ToneFlashMapBank((uint32_t)ADDRESS),
|
|
||||||
hdr[0], hdr[1], hdr[2], hdr[3],
|
|
||||||
(unsigned long)(hdr[12] | (hdr[13] << 8) | (hdr[14] << 16) | (hdr[15] << 24)));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,12 @@ static void UI_ModeSelect_DrawButtons(void)
|
||||||
LCD_WR_PIC_FROM_FLASH(UI0902_MODE_ROW_X, y,
|
LCD_WR_PIC_FROM_FLASH(UI0902_MODE_ROW_X, y,
|
||||||
UI0902_MODE_ROW_W, UI0902_MODE_ROW_H,
|
UI0902_MODE_ROW_W, UI0902_MODE_ROW_H,
|
||||||
s_mode_row_addr[i]);
|
s_mode_row_addr[i]);
|
||||||
|
/* 万能模式素材顶部有残留近白横线(相对行内 y=7/8),盖成行底色 */
|
||||||
|
if (i == 0) {
|
||||||
|
LCD_FillByColor(UI0902_MODE_ROW_X, (uint16_t)(y + 7),
|
||||||
|
(uint16_t)(UI0902_MODE_ROW_X + UI0902_MODE_ROW_W),
|
||||||
|
(uint16_t)(y + 9), UI0902_ROW_BG);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,11 @@ const Touch_AreaTypeDef Touch_SetingSelect_Areas[] = {
|
||||||
{ UI0902_HUB_CARD_X, (uint16_t)(UI0902_HUB_CARD_X + UI0902_HUB_CARD_W - 1),
|
{ UI0902_HUB_CARD_X, (uint16_t)(UI0902_HUB_CARD_X + UI0902_HUB_CARD_W - 1),
|
||||||
UI0902_HUB_CARD_Y1, (uint16_t)(UI0902_HUB_CARD_Y1 + UI0902_HUB_CARD_H - 1),
|
UI0902_HUB_CARD_Y1, (uint16_t)(UI0902_HUB_CARD_Y1 + UI0902_HUB_CARD_H - 1),
|
||||||
0, 0, GUI_SETING_SELECT3, NULL },
|
0, 0, GUI_SETING_SELECT3, NULL },
|
||||||
/* 底栏四键:与 Touch_Areas 共用 UI0902_NAV_* 几何 */
|
/* 底栏四键 */
|
||||||
{ UI0902_NAV_X0(0), UI0902_NAV_X1(0), UI0902_NAV_Y0, UI0902_NAV_Y1, 0, UI0902_NAV_UNIVERSAL, GUI_NAV_BAR, NULL },
|
{ 0, 69, 280, 319, 0, UI0902_NAV_UNIVERSAL, GUI_NAV_BAR, NULL },
|
||||||
{ UI0902_NAV_X0(1), UI0902_NAV_X1(1), UI0902_NAV_Y0, UI0902_NAV_Y1, 0, UI0902_NAV_NORMAL, GUI_NAV_BAR, NULL },
|
{ 70, 129, 280, 319, 0, UI0902_NAV_NORMAL, GUI_NAV_BAR, NULL },
|
||||||
{ UI0902_NAV_X0(2), UI0902_NAV_X1(2), UI0902_NAV_Y0, UI0902_NAV_Y1, 0, UI0902_NAV_EXPERT, GUI_NAV_BAR, NULL },
|
{ 130, 184, 280, 319, 0, UI0902_NAV_EXPERT, GUI_NAV_BAR, NULL },
|
||||||
{ UI0902_NAV_X0(3), UI0902_NAV_X1(3), UI0902_NAV_Y0, UI0902_NAV_Y1, 0, UI0902_NAV_SETTING, GUI_NAV_BAR, NULL },
|
{ 185, 239, 280, 319, 0, UI0902_NAV_SETTING, GUI_NAV_BAR, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TOUCH_AREA_SETING_SELECT_NUM (sizeof(Touch_SetingSelect_Areas)/sizeof(Touch_AreaTypeDef))
|
#define TOUCH_AREA_SETING_SELECT_NUM (sizeof(Touch_SetingSelect_Areas)/sizeof(Touch_AreaTypeDef))
|
||||||
|
|
|
||||||
123
UI/UI_global.c
123
UI/UI_global.c
|
|
@ -168,23 +168,10 @@ void UI_ReloadTonePreset(void)
|
||||||
if (mGuiData[GUI_TAB_INDEX].Current == 0)
|
if (mGuiData[GUI_TAB_INDEX].Current == 0)
|
||||||
{
|
{
|
||||||
int ret = AutoBandTop1_LoadPresetItemFromFlash(ParamGuiData[ALL_MODE_PARAM].Current);
|
int ret = AutoBandTop1_LoadPresetItemFromFlash(ParamGuiData[ALL_MODE_PARAM].Current);
|
||||||
if (ret != 0)
|
LOG_I("tone", "load universal idx=%d ret=%d name=%s addr=0x%08X map=BIN3@0x%08X",
|
||||||
{
|
ParamGuiData[ALL_MODE_PARAM].Current, ret,
|
||||||
uint8_t hdr[16];
|
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?",
|
||||||
W25Q128_Read(hdr, (uint32_t)ADDRESS, 16);
|
(unsigned)ADDRESS, (unsigned)EXTFLASH_BIN3_UNIVERSAL_ADDR);
|
||||||
LOG_E("tone", "load universal idx=%d ret=%d magic=%02X%02X%02X%02X cnt=%lu addr=0x%08X",
|
|
||||||
ParamGuiData[ALL_MODE_PARAM].Current, ret,
|
|
||||||
hdr[0], hdr[1], hdr[2], hdr[3],
|
|
||||||
(unsigned long)(hdr[12] | (hdr[13] << 8) | (hdr[14] << 16) | (hdr[15] << 24)),
|
|
||||||
(unsigned)ADDRESS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_I("tone", "load universal idx=%d ret=%d name=%s addr=0x%08X map=BIN3@0x%08X",
|
|
||||||
ParamGuiData[ALL_MODE_PARAM].Current, ret,
|
|
||||||
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?",
|
|
||||||
(unsigned)ADDRESS, (unsigned)EXTFLASH_BIN3_UNIVERSAL_ADDR);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* 普通/专业:本地曲目或节奏类型 */
|
/* 普通/专业:本地曲目或节奏类型 */
|
||||||
|
|
@ -456,58 +443,6 @@ void Show_Battery_Icon(uint8_t flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 中英文混排像素宽(与 LCD_GetMixedStringWidth 规则一致:CJK=sizey,ASCII=UI0902_ASCII_W) */
|
|
||||||
static uint16_t UI_MixedTextWidth(const uint8_t *str, uint8_t sizey)
|
|
||||||
{
|
|
||||||
uint16_t width = 0;
|
|
||||||
uint8_t ascii_w = UI0902_ASCII_W(sizey);
|
|
||||||
|
|
||||||
if (str == NULL)
|
|
||||||
return 0;
|
|
||||||
while (*str != '\0') {
|
|
||||||
if (*str > 0x80) {
|
|
||||||
width = (uint16_t)(width + sizey);
|
|
||||||
str += 2;
|
|
||||||
} else {
|
|
||||||
width = (uint16_t)(width + ascii_w);
|
|
||||||
str += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 曲目/音色共用:序号与名称间距(与「1.名称」拼接一致,保证两行视觉间距相同) */
|
|
||||||
#define UI0902_INDEX_NAME_GAP 0
|
|
||||||
|
|
||||||
/* 在 [x1,x2] 内整体居中绘制「N.」+ 名称(无渐变,show_Param 用) */
|
|
||||||
static void UI_DrawIndexedName_Mixed(uint16_t x1, uint16_t x2, uint16_t text_y,
|
|
||||||
const char *num, const char *name,
|
|
||||||
uint16_t fc, uint16_t bc, uint8_t sizey)
|
|
||||||
{
|
|
||||||
char line[48] = {0};
|
|
||||||
snprintf(line, sizeof(line), "%s%s", num, name);
|
|
||||||
LCD_ShowMixedString(x1, x2, text_y, (uint8_t *)line, LCD_ALIGN_CENTER,
|
|
||||||
fc, bc, sizey, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 在 [x1,x2] 内整体居中绘制「N.」+ 中文名(渐变底,音色行用);间隙与曲目行一致 */
|
|
||||||
static void UI_DrawIndexedName_Grad(uint16_t x1, uint16_t x2, uint16_t text_y,
|
|
||||||
const char *num, const uint8_t *name,
|
|
||||||
uint16_t fc, uint16_t c_top, uint16_t c_bot, uint8_t sizey)
|
|
||||||
{
|
|
||||||
uint16_t num_w = (uint16_t)(strlen(num) * UI0902_ASCII_W(sizey));
|
|
||||||
uint16_t name_w = UI_MixedTextWidth(name, sizey);
|
|
||||||
uint16_t total_w = (uint16_t)(num_w + UI0902_INDEX_NAME_GAP + name_w);
|
|
||||||
uint16_t area_w = (x2 > x1) ? (uint16_t)(x2 - x1) : 0;
|
|
||||||
uint16_t start_x = (total_w >= area_w) ? x1 : (uint16_t)(x1 + (area_w - total_w) / 2);
|
|
||||||
uint16_t name_x = (uint16_t)(start_x + num_w + UI0902_INDEX_NAME_GAP);
|
|
||||||
|
|
||||||
LCD_ShowString_AutoAlign_Gradient(start_x, (uint16_t)(start_x + num_w), text_y,
|
|
||||||
(const uint8_t *)num, LCD_ALIGN_LEFT, fc, c_top, c_bot, sizey);
|
|
||||||
LCD_ShowChinese_AutoAlign_Gradient(name_x, x2, text_y, name, LCD_ALIGN_LEFT,
|
|
||||||
fc, c_top, c_bot, sizey);
|
|
||||||
}
|
|
||||||
|
|
||||||
void show_Param(const LEBEL_UI *UI, GUI_SWITCH *Group)
|
void show_Param(const LEBEL_UI *UI, GUI_SWITCH *Group)
|
||||||
{
|
{
|
||||||
char Textstr_new[40] = {0};
|
char Textstr_new[40] = {0};
|
||||||
|
|
@ -518,7 +453,6 @@ void show_Param(const LEBEL_UI *UI, GUI_SWITCH *Group)
|
||||||
const uint16_t text_y = row_y + (row_h - UI->Text_size) / 2 + 1;
|
const uint16_t text_y = row_y + (row_h - UI->Text_size) / 2 + 1;
|
||||||
uint8_t idx = Group->Current + 1;
|
uint8_t idx = Group->Current + 1;
|
||||||
uint16_t c_top, c_bot;
|
uint16_t c_top, c_bot;
|
||||||
uint16_t x1, x2;
|
|
||||||
|
|
||||||
UI_GetFocusGrad(GUI_MODE_PARAM, &c_top, &c_bot);
|
UI_GetFocusGrad(GUI_MODE_PARAM, &c_top, &c_bot);
|
||||||
|
|
||||||
|
|
@ -530,16 +464,18 @@ void show_Param(const LEBEL_UI *UI, GUI_SWITCH *Group)
|
||||||
c_top, c_bot
|
c_top, c_bot
|
||||||
);
|
);
|
||||||
|
|
||||||
/* 序号+名称整体居中(约等于标注「右移7px」的视觉效果) */
|
// 拼接序号 1. 2. 3.
|
||||||
sprintf(NumBuf, "%d.", idx);
|
sprintf(NumBuf, "%d.", idx);
|
||||||
|
uint16_t num_w = (uint16_t)(strlen(NumBuf) * UI0902_ASCII_W(UI->Text_size));
|
||||||
if (Group->Id == EXPRESS_MODE_PARAM && Group->Current < LOCAL_SONG_COUNT)
|
if (Group->Id == EXPRESS_MODE_PARAM && Group->Current < LOCAL_SONG_COUNT)
|
||||||
strcpy(Textstr_new, LocalSongNameGbk[Group->Current]);
|
strcpy(Textstr_new, LocalSongNameGbk[Group->Current]);
|
||||||
else
|
else
|
||||||
GET_ParamNum_Str(Group->Current, 0, Textstr_new, Group->Id);
|
GET_ParamNum_Str(Group->Current, 0, Textstr_new, Group->Id);
|
||||||
x1 = (uint16_t)(UI->x + 10);
|
uint32_t string_start_x = LCD_ShowMixedString(UI->x+10, UI->x + UI->w, text_y, (uint8_t *)Textstr_new , LCD_ALIGN_CENTER, WHITE, BLACK, UI->Text_size, 1);
|
||||||
x2 = (uint16_t)(UI->x + UI->w - 10);
|
//序号X = 中文起点 - 数字宽度 - 5,间<EFBC8C>?像素
|
||||||
UI_DrawIndexedName_Mixed(x1, x2, text_y, NumBuf, Textstr_new,
|
uint16_t num_x = string_start_x - num_w;
|
||||||
WHITE, BLACK, UI->Text_size);
|
// 绘制左侧数字序号
|
||||||
|
LCD_ShowString(num_x, text_y, (const uint8_t *)NumBuf, UI->Text_fc, UI->Text_bc, UI->Text_size, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -915,17 +851,22 @@ void label_TimbreSelece_ui(const LEBEL_UI *UI, GUI_SWITCH * Group)
|
||||||
c_top, c_bot
|
c_top, c_bot
|
||||||
);
|
);
|
||||||
sprintf(NumBuf, "%d.", idx);
|
sprintf(NumBuf, "%d.", idx);
|
||||||
|
uint16_t num_w = (uint16_t)(strlen(NumBuf) * UI0902_ASCII_W(UI->Text_size));
|
||||||
GET_Num_Str(mGuiData[UI->Id].Current, 0, (char*)Textstr, UI->Id);
|
GET_Num_Str(mGuiData[UI->Id].Current, 0, (char*)Textstr, UI->Id);
|
||||||
UI_DrawIndexedName_Grad(
|
uint32_t chinese_start_x = LCD_ShowChinese_AutoAlign_Gradient(
|
||||||
(uint16_t)(UI->x + 10),
|
UI->x + num_w,
|
||||||
(uint16_t)(UI->x + UI->w - 10),
|
UI->x + UI->w,
|
||||||
text_y,
|
text_y,
|
||||||
NumBuf,
|
(const uint8_t*)Textstr,
|
||||||
Textstr,
|
UI->Text_Align,
|
||||||
UI->Text_fc,
|
UI->Text_fc,
|
||||||
c_top, c_bot,
|
c_top, c_bot,
|
||||||
UI->Text_size
|
UI->Text_size
|
||||||
);
|
);
|
||||||
|
uint16_t num_x = chinese_start_x - num_w - 5;
|
||||||
|
LCD_ShowString_AutoAlign_Gradient(num_x, num_x + num_w, text_y,
|
||||||
|
(const uint8_t *)NumBuf, LCD_ALIGN_LEFT, UI->Text_fc,
|
||||||
|
c_top, c_bot, UI->Text_size);
|
||||||
switch(Group->Id)
|
switch(Group->Id)
|
||||||
{
|
{
|
||||||
case GUI_TIMBRE_SELECT:
|
case GUI_TIMBRE_SELECT:
|
||||||
|
|
@ -1047,7 +988,7 @@ void Draw_Tab_Section_Menu(const LEBEL_UI *UI, TAB_SECTION_INDEX select_tab)
|
||||||
const uint8_t pitch = UI0902_SECTION_PITCH;
|
const uint8_t pitch = UI0902_SECTION_PITCH;
|
||||||
const uint16_t start_x = UI0902_MARGIN_X; /* 0902-04:12/69/126/183 */
|
const uint16_t start_x = UI0902_MARGIN_X; /* 0902-04:12/69/126/183 */
|
||||||
const uint16_t start_y = UI->y;
|
const uint16_t start_y = UI->y;
|
||||||
/* 0819:演奏段落数字与标题同为 13,按钮内垂直居中(视觉重心 +1);稿面数字整体右移 2px */
|
/* 0819:演奏段落数字与标题同为 13,按钮内垂直居中(视觉重心 +1) */
|
||||||
const uint16_t text_y = start_y + (tab_h - UI0902_FONT_BODY) / 2 + 1;
|
const uint16_t text_y = start_y + (tab_h - UI0902_FONT_BODY) / 2 + 1;
|
||||||
const char *nums[4] = {"1", "2", "3", "4"};
|
const char *nums[4] = {"1", "2", "3", "4"};
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
|
|
@ -1058,7 +999,7 @@ void Draw_Tab_Section_Menu(const LEBEL_UI *UI, TAB_SECTION_INDEX select_tab)
|
||||||
uint16_t bg = (select_tab == i) ? COLOR_GRAD_MID : UI0902_ROW_BG;
|
uint16_t bg = (select_tab == i) ? COLOR_GRAD_MID : UI0902_ROW_BG;
|
||||||
LCD_FillRoundRect(x, start_y, tab_w, tab_h, tab_r, bg);
|
LCD_FillRoundRect(x, start_y, tab_w, tab_h, tab_r, bg);
|
||||||
LCD_ShowString_AutoAlign(
|
LCD_ShowString_AutoAlign(
|
||||||
(uint16_t)(x + 2), (uint16_t)(x + tab_w - 1 + 2), text_y,
|
x, (uint16_t)(x + tab_w - 1), text_y,
|
||||||
(const uint8_t*)nums[i],
|
(const uint8_t*)nums[i],
|
||||||
UI->Text_Align,
|
UI->Text_Align,
|
||||||
WHITE,
|
WHITE,
|
||||||
|
|
@ -1328,12 +1269,8 @@ void Draw_System_Item_List(const LEBEL_UI *UI, GUI_SWITCH *Group)
|
||||||
(uint16_t)(UI->y + (UI->h - UI0902_ICON_SYS_RESTORE_H) / 2),
|
(uint16_t)(UI->y + (UI->h - UI0902_ICON_SYS_RESTORE_H) / 2),
|
||||||
UI0902_ICON_SYS_RESTORE_W, UI0902_ICON_SYS_RESTORE_H,
|
UI0902_ICON_SYS_RESTORE_W, UI0902_ICON_SYS_RESTORE_H,
|
||||||
UI0902_ICON_SYS_RESTORE_ADDR);
|
UI0902_ICON_SYS_RESTORE_ADDR);
|
||||||
/* 0902-07:右侧为进入下级页的细 chevron(设置图标-03),勿用实心三角 */
|
/* 右三角与蓝牙/自动关机同一右缘(val_x2) */
|
||||||
LCD_WR_PIC_FROM_FLASH_Trans(
|
UI_DrawTriRight((uint16_t)(val_x2 - UI0902_TRI_R_W), chev_cy);
|
||||||
(uint16_t)(val_x2 - UI0902_ICON_CHEVRON_W),
|
|
||||||
(uint16_t)(UI->y + (UI->h - UI0902_ICON_CHEVRON_H) / 2),
|
|
||||||
UI0902_ICON_CHEVRON_W, UI0902_ICON_CHEVRON_H,
|
|
||||||
UI0902_ICON_CHEVRON_ADDR);
|
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -173,12 +173,6 @@ void CallUI_RestoreSelect(void);
|
||||||
#define UI0902_NAV_EXPERT 2 /* 底栏:专业模式 */
|
#define UI0902_NAV_EXPERT 2 /* 底栏:专业模式 */
|
||||||
#define UI0902_NAV_SETTING 3 /* 底栏:设置 */
|
#define UI0902_NAV_SETTING 3 /* 底栏:设置 */
|
||||||
#define UI0902_NAV_NONE 0xFF
|
#define UI0902_NAV_NONE 0xFF
|
||||||
/* 底栏触区:段落钮底(y264)之下四等分全宽,各 60×55 */
|
|
||||||
#define UI0902_NAV_Y0 265
|
|
||||||
#define UI0902_NAV_Y1 319
|
|
||||||
#define UI0902_NAV_W 60
|
|
||||||
#define UI0902_NAV_X0(i) ((uint16_t)((i) * UI0902_NAV_W))
|
|
||||||
#define UI0902_NAV_X1(i) ((uint16_t)((i) * UI0902_NAV_W + UI0902_NAV_W - 1))
|
|
||||||
/* 兼容旧名(已废弃三键:设置|调音台|模式) */
|
/* 兼容旧名(已废弃三键:设置|调音台|模式) */
|
||||||
#define UI0902_NAV_MIXER UI0902_NAV_NORMAL
|
#define UI0902_NAV_MIXER UI0902_NAV_NORMAL
|
||||||
#define UI0902_NAV_MODE UI0902_NAV_EXPERT
|
#define UI0902_NAV_MODE UI0902_NAV_EXPERT
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
#define EXTFLASH_CHARGING_H 190
|
#define EXTFLASH_CHARGING_H 190
|
||||||
|
|
||||||
#define EXTFLASH_BIN1_RHYTHM_ADDR 0x0001B8F0UL
|
#define EXTFLASH_BIN1_RHYTHM_ADDR 0x0001B8F0UL
|
||||||
#define EXTFLASH_BIN1_RHYTHM_SIZE 530273UL
|
#define EXTFLASH_BIN1_RHYTHM_SIZE 530317UL
|
||||||
|
|
||||||
#define EXTFLASH_BIN2_SONG_HAITIAN_ADDR 0x0009D07DUL
|
#define EXTFLASH_BIN2_SONG_HAITIAN_ADDR 0x0009D07DUL
|
||||||
#define EXTFLASH_BIN2_SONG_HAITIAN_SIZE 41263UL
|
#define EXTFLASH_BIN2_SONG_HAITIAN_SIZE 41263UL
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
/* Auto-generated by tools/gen_git_user_fw_ver.py — do not edit.
|
/* Auto-generated by tools/gen_git_user_fw_ver.py — do not edit.
|
||||||
* git HEAD (dirty): bb6d9ae7f9987ec6cfb3ab50579951d2b58ed888
|
* git HEAD (dirty): 57448b3da8a3f912503e9d50313b5ec635888b69
|
||||||
* branch: develop → develop
|
* branch: develop → develop
|
||||||
* 01 0C wire: develop_bb6d9a*
|
* 01 0C wire: develop_57448b*
|
||||||
*/
|
*/
|
||||||
#ifndef GIT_USER_FW_VER_H
|
#ifndef GIT_USER_FW_VER_H
|
||||||
#define GIT_USER_FW_VER_H
|
#define GIT_USER_FW_VER_H
|
||||||
|
|
||||||
#define GIT_COMMIT_ID_FULL "bb6d9ae7f9987ec6cfb3ab50579951d2b58ed888"
|
#define GIT_COMMIT_ID_FULL "57448b3da8a3f912503e9d50313b5ec635888b69"
|
||||||
#define GIT_BRANCH_NAME "develop"
|
#define GIT_BRANCH_NAME "develop"
|
||||||
#define GIT_COMMIT_SHORT6 "bb6d9a"
|
#define GIT_COMMIT_SHORT6 "57448b"
|
||||||
#define GIT_DIRTY (1)
|
#define GIT_DIRTY (1)
|
||||||
#define GIT_BUILD_ID "develop_bb6d9a*"
|
#define GIT_BUILD_ID "develop_57448b*"
|
||||||
#define GIT_BUILD_ID_LEN 15u
|
#define GIT_BUILD_ID_LEN 15u
|
||||||
|
|
||||||
#endif /* GIT_USER_FW_VER_H */
|
#endif /* GIT_USER_FW_VER_H */
|
||||||
|
|
|
||||||
|
|
@ -1,195 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
"""Flash Doc/音色文件/0903/3.bin to W25Q128 @ EXTFLASH_BIN3_UNIVERSAL_ADDR via RTT.
|
|
||||||
|
|
||||||
Requires firmware that accepts RTT command: flash bin3 <size>
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
import time
|
|
||||||
|
|
||||||
DEFAULT_DEVICES = ("Cortex-M4", "AT32F403AC", "AT32F403A")
|
|
||||||
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
||||||
REPO = os.path.dirname(os.path.dirname(ROOT))
|
|
||||||
DEFAULT_BIN = os.path.join(REPO, "Doc", "音色文件", "0903", "3.bin")
|
|
||||||
EXTFLASH_BIN3_UNIVERSAL_ADDR = 0x000A71AC
|
|
||||||
DAB_MAGIC = bytes((0xAB, 0x44, 0x41, 0x42))
|
|
||||||
|
|
||||||
|
|
||||||
def connect_jlink(device: str):
|
|
||||||
import pylink
|
|
||||||
|
|
||||||
jlink = pylink.JLink()
|
|
||||||
jlink.open()
|
|
||||||
try:
|
|
||||||
jlink.exec_command("HideDeviceSelection = 1")
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
jlink.set_tif(pylink.enums.JLinkInterfaces.SWD)
|
|
||||||
|
|
||||||
last_error = None
|
|
||||||
for candidate in (device, *DEFAULT_DEVICES):
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
jlink.exec_command(f"Device = {candidate}")
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
jlink.connect(candidate)
|
|
||||||
print(f"Connected as {candidate}")
|
|
||||||
return jlink
|
|
||||||
except Exception as exc:
|
|
||||||
last_error = exc
|
|
||||||
jlink.close()
|
|
||||||
raise SystemExit(f"Failed to connect J-Link: {last_error}")
|
|
||||||
|
|
||||||
|
|
||||||
def find_rtt_control_block(jlink, ram_base: int = 0x20000000, ram_size: int = 0x18000):
|
|
||||||
needle = b"SEGGER RTT"
|
|
||||||
chunk = 0x1000
|
|
||||||
was_halted = jlink.halted()
|
|
||||||
if not was_halted:
|
|
||||||
jlink.halt()
|
|
||||||
try:
|
|
||||||
for off in range(0, ram_size, chunk):
|
|
||||||
data = bytes(jlink.memory_read8(ram_base + off, min(chunk, ram_size - off)))
|
|
||||||
idx = data.find(needle)
|
|
||||||
if idx >= 0:
|
|
||||||
return ram_base + off + idx
|
|
||||||
finally:
|
|
||||||
if not was_halted:
|
|
||||||
if hasattr(jlink, "restart"):
|
|
||||||
jlink.restart()
|
|
||||||
else:
|
|
||||||
jlink.go()
|
|
||||||
time.sleep(0.1)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def rtt_read_text(jlink, timeout_s: float = 0.2) -> str:
|
|
||||||
deadline = time.time() + timeout_s
|
|
||||||
chunks: list[bytes] = []
|
|
||||||
while time.time() < deadline:
|
|
||||||
try:
|
|
||||||
data = bytes(jlink.rtt_read(0, 512) or [])
|
|
||||||
except Exception:
|
|
||||||
data = b""
|
|
||||||
if data:
|
|
||||||
chunks.append(data)
|
|
||||||
deadline = time.time() + timeout_s
|
|
||||||
else:
|
|
||||||
time.sleep(0.02)
|
|
||||||
return b"".join(chunks).decode("ascii", errors="replace")
|
|
||||||
|
|
||||||
|
|
||||||
def wait_for(jlink, marker: str, timeout_s: float = 30.0) -> str:
|
|
||||||
deadline = time.time() + timeout_s
|
|
||||||
buf = ""
|
|
||||||
while time.time() < deadline:
|
|
||||||
buf += rtt_read_text(jlink, 0.15)
|
|
||||||
if marker in buf:
|
|
||||||
return buf
|
|
||||||
raise SystemExit(f"Timeout waiting for {marker!r}\n--- RTT ---\n{buf[-800:]}")
|
|
||||||
|
|
||||||
|
|
||||||
def send_bytes(jlink, payload: bytes) -> None:
|
|
||||||
off = 0
|
|
||||||
while off < len(payload):
|
|
||||||
try:
|
|
||||||
n = jlink.rtt_write(0, list(payload[off : off + 64]))
|
|
||||||
except Exception:
|
|
||||||
time.sleep(0.05)
|
|
||||||
continue
|
|
||||||
if n is None or n <= 0:
|
|
||||||
time.sleep(0.02)
|
|
||||||
continue
|
|
||||||
off += n
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument("--bin", default=DEFAULT_BIN)
|
|
||||||
parser.add_argument("--device", default="Cortex-M4")
|
|
||||||
parser.add_argument("--no-reset", action="store_true")
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
if not os.path.isfile(args.bin):
|
|
||||||
raise SystemExit(f"missing bin: {args.bin}")
|
|
||||||
|
|
||||||
data = open(args.bin, "rb").read()
|
|
||||||
size = len(data)
|
|
||||||
if size < 16 or data[:4] != DAB_MAGIC:
|
|
||||||
raise SystemExit(f"not a DAB bank (magic={data[:4].hex()})")
|
|
||||||
|
|
||||||
print(f"bin={args.bin} size={size} addr=0x{EXTFLASH_BIN3_UNIVERSAL_ADDR:08X}")
|
|
||||||
|
|
||||||
jlink = connect_jlink(args.device)
|
|
||||||
try:
|
|
||||||
cb = find_rtt_control_block(jlink)
|
|
||||||
if cb is None:
|
|
||||||
raise SystemExit("RTT control block not found")
|
|
||||||
print(f"RTT CB @ 0x{cb:08X}")
|
|
||||||
jlink.rtt_start(cb)
|
|
||||||
time.sleep(0.3)
|
|
||||||
_ = rtt_read_text(jlink, 0.3)
|
|
||||||
|
|
||||||
if not args.no_reset:
|
|
||||||
print("hardware reset...")
|
|
||||||
jlink.reset(halt=False)
|
|
||||||
time.sleep(3.5)
|
|
||||||
try:
|
|
||||||
jlink.rtt_stop()
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
cb = find_rtt_control_block(jlink)
|
|
||||||
if cb is None:
|
|
||||||
raise SystemExit("RTT CB missing after reset")
|
|
||||||
print(f"RTT CB @ 0x{cb:08X}")
|
|
||||||
jlink.rtt_start(cb)
|
|
||||||
time.sleep(0.5)
|
|
||||||
_ = rtt_read_text(jlink, 0.5)
|
|
||||||
|
|
||||||
cmd = f"flash bin3 {size}\n".encode("ascii")
|
|
||||||
send_bytes(jlink, cmd)
|
|
||||||
print("sent flash command, waiting GO...")
|
|
||||||
try:
|
|
||||||
log = wait_for(jlink, "FLASH_BIN3_GO", 20.0)
|
|
||||||
except SystemExit:
|
|
||||||
raise SystemExit(
|
|
||||||
"Firmware did not accept 'flash bin3'. Rebuild App with app_log.c "
|
|
||||||
"support, or temporarily flash via: concatenate 2.bin+3.bin and "
|
|
||||||
"'flash haitian <combined_size>'."
|
|
||||||
)
|
|
||||||
print(log.strip().splitlines()[-1])
|
|
||||||
time.sleep(0.2)
|
|
||||||
|
|
||||||
chunk = 256
|
|
||||||
sent = 0
|
|
||||||
t0 = time.time()
|
|
||||||
while sent < size:
|
|
||||||
end = min(sent + chunk, size)
|
|
||||||
send_bytes(jlink, data[sent:end])
|
|
||||||
sent = end
|
|
||||||
log = wait_for(jlink, "FLASH_ACK", 60.0)
|
|
||||||
if "FLASH_BIN3_OK" in log:
|
|
||||||
print(log.strip().splitlines()[-1])
|
|
||||||
print("Done. Universal bank (3.bin) updated.")
|
|
||||||
return
|
|
||||||
if sent % (4 * 1024) == 0 or sent == size:
|
|
||||||
elapsed = time.time() - t0
|
|
||||||
print(f" {sent}/{size} ({100.0 * sent / size:.1f}%) {elapsed:.1f}s")
|
|
||||||
|
|
||||||
log = wait_for(jlink, "FLASH_BIN3_OK", 60.0)
|
|
||||||
print(log.strip().splitlines()[-1])
|
|
||||||
print("Done. Universal bank (3.bin) updated.")
|
|
||||||
finally:
|
|
||||||
try:
|
|
||||||
jlink.rtt_stop()
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
jlink.close()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
|
|
@ -2,23 +2,21 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""Pack external W25Q128 tone/logo image for K1 (0903).
|
"""Pack external W25Q128 tone/logo image for K1 (0903).
|
||||||
|
|
||||||
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)
|
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 full-screen)
|
||||||
0x0001B8F0 1.bin 普通/专业 31 rhythms
|
0x0001B8F0 1.bin 普通/专业 31 rhythms
|
||||||
0x0009D07D 2.bin 本地曲目(变长,尾部 0xFF 填到 BIN3;<=41KB)
|
0x0009D07D 2.bin 海阔天空
|
||||||
0x000A71AC 3.bin 万能模式(固定;勿随 2.bin 长度漂移)
|
0x000A8607 3.bin 万能模式
|
||||||
|
|
||||||
Outputs:
|
Outputs:
|
||||||
tools/out/extflash_tone_0903.bin
|
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)
|
|
||||||
project/inc/ExtFlash_Tone_Addr.h
|
project/inc/ExtFlash_Tone_Addr.h
|
||||||
Doc/音色文件/0903/FLASH_MAP.txt
|
Doc/音色文件/0903/FLASH_MAP.txt
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import struct
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
@ -27,25 +25,11 @@ ROOT = Path(__file__).resolve().parents[1] # firmware project root
|
||||||
REPO = ROOT.parent.parent # 一诺国际吉他
|
REPO = ROOT.parent.parent # 一诺国际吉他
|
||||||
OUT_DIR = ROOT / "tools" / "out"
|
OUT_DIR = ROOT / "tools" / "out"
|
||||||
OUT_BIN = OUT_DIR / "extflash_tone_0903.bin"
|
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"
|
|
||||||
OUT_HDR = ROOT / "project" / "inc" / "ExtFlash_Tone_Addr.h"
|
OUT_HDR = ROOT / "project" / "inc" / "ExtFlash_Tone_Addr.h"
|
||||||
OUT_MAP = REPO / "Doc" / "音色文件" / "0903" / "FLASH_MAP.txt"
|
OUT_MAP = REPO / "Doc" / "音色文件" / "0903" / "FLASH_MAP.txt"
|
||||||
UI0902_BIN = OUT_DIR / "ui0902_res.bin"
|
|
||||||
|
|
||||||
TONE_DIR = REPO / "Doc" / "音色文件" / "0903"
|
TONE_DIR = REPO / "Doc" / "音色文件" / "0903"
|
||||||
|
|
||||||
# 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
|
|
||||||
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:
|
def find_ziliao() -> Path:
|
||||||
for p in REPO.iterdir():
|
for p in REPO.iterdir():
|
||||||
|
|
@ -54,66 +38,29 @@ def find_ziliao() -> Path:
|
||||||
raise FileNotFoundError("资料/logo.bin + Charg.bin not found under repo")
|
raise FileNotFoundError("资料/logo.bin + Charg.bin not found under repo")
|
||||||
|
|
||||||
|
|
||||||
def dab_ok(blob: bytes, off: int, expect_cnt: int | None = None) -> None:
|
|
||||||
if off + 16 > len(blob):
|
|
||||||
raise SystemExit(f"DAB check @0x{off:X}: past end of pack ({len(blob)})")
|
|
||||||
magic = blob[off : off + 4]
|
|
||||||
cnt = struct.unpack_from("<I", blob, off + 12)[0]
|
|
||||||
if magic != DAB_MAGIC:
|
|
||||||
raise SystemExit(
|
|
||||||
f"DAB check @0x{off:X}: bad magic {magic.hex()} (want {DAB_MAGIC.hex()})"
|
|
||||||
)
|
|
||||||
if expect_cnt is not None and cnt != expect_cnt:
|
|
||||||
raise SystemExit(f"DAB check @0x{off:X}: cnt={cnt} want {expect_cnt}")
|
|
||||||
|
|
||||||
|
|
||||||
def require_region_equals(blob: bytes, off: int, src: bytes, label: str) -> None:
|
|
||||||
end = off + len(src)
|
|
||||||
if end > len(blob):
|
|
||||||
raise SystemExit(f"{label}: pack too short for region @0x{off:X}+{len(src)}")
|
|
||||||
if blob[off:end] != src:
|
|
||||||
raise SystemExit(f"{label}: bytes @0x{off:X} do not match source file")
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
ziliao = find_ziliao()
|
ziliao = find_ziliao()
|
||||||
bin1_path = TONE_DIR / "1.bin"
|
|
||||||
bin2_path = TONE_DIR / "2.bin"
|
|
||||||
bin3_path = TONE_DIR / "3.bin"
|
|
||||||
parts = [
|
parts = [
|
||||||
("LOGO", ziliao / "logo.bin", OFF_LOGO, "legacy pad; boot uses UI0902_BOOT_LOGO"),
|
("LOGO", ziliao / "logo.bin", 0x00000000, "legacy pad; boot uses UI0902_BOOT_LOGO"),
|
||||||
("CHARGING", ziliao / "Charg.bin", OFF_CHARGING, "legacy pad; UI uses UI0902_CHARGE_SCREEN"),
|
("CHARGING", ziliao / "Charg.bin", 0x0000CB70, "legacy pad; UI uses UI0902_CHARGE_SCREEN"),
|
||||||
("BIN1_RHYTHM", bin1_path, OFF_BIN1, "普通/专业 31 条节奏"),
|
("BIN1_RHYTHM", TONE_DIR / "1.bin", 0x0001B8F0, "普通/专业 31 条节奏"),
|
||||||
("BIN2_SONG_HAITIAN", bin2_path, OFF_BIN2, "本地曲目"),
|
("BIN2_SONG_HAITIAN", TONE_DIR / "2.bin", None, "本地曲目 海阔天空"),
|
||||||
("BIN3_UNIVERSAL", bin3_path, OFF_BIN3, "万能模式(固定偏移)"),
|
("BIN3_UNIVERSAL", TONE_DIR / "3.bin", None, "万能模式"),
|
||||||
]
|
]
|
||||||
|
|
||||||
bin2_data = bin2_path.read_bytes()
|
blobs = []
|
||||||
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})"
|
|
||||||
)
|
|
||||||
|
|
||||||
blobs: list[bytes] = []
|
|
||||||
cursor = 0
|
cursor = 0
|
||||||
rows: list[tuple[str, int, int, str]] = []
|
rows = []
|
||||||
for name, path, force_off, note in parts:
|
for name, path, force_off, note in parts:
|
||||||
data = path.read_bytes()
|
data = path.read_bytes()
|
||||||
if cursor > force_off:
|
if force_off is not None:
|
||||||
raise SystemExit(
|
if cursor > force_off:
|
||||||
f"{name}: cursor 0x{cursor:X} past forced 0x{force_off:X} "
|
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)"
|
if cursor < force_off:
|
||||||
)
|
pad = force_off - cursor
|
||||||
if cursor < force_off:
|
blobs.append(b"\xFF" * pad)
|
||||||
pad = force_off - cursor
|
cursor = force_off
|
||||||
blobs.append(b"\xFF" * pad)
|
rows.append((f"(pad)", force_off - pad, pad, "gap fill 0xFF"))
|
||||||
rows.append(("(pad)", cursor, pad, "gap fill 0xFF"))
|
|
||||||
cursor = force_off
|
|
||||||
off = cursor
|
off = cursor
|
||||||
blobs.append(data)
|
blobs.append(data)
|
||||||
cursor += len(data)
|
cursor += len(data)
|
||||||
|
|
@ -122,25 +69,9 @@ def main() -> None:
|
||||||
OUT_DIR.mkdir(parents=True, exist_ok=True)
|
OUT_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
packed = b"".join(blobs)
|
packed = b"".join(blobs)
|
||||||
OUT_BIN.write_bytes(packed)
|
OUT_BIN.write_bytes(packed)
|
||||||
OUT_RES.write_bytes(packed) # 总音色 .bin 同步为 .res
|
|
||||||
|
|
||||||
|
# named lookup
|
||||||
by_name = {r[0]: r for r in rows if not r[0].startswith("(")}
|
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)
|
|
||||||
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}")
|
|
||||||
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")
|
|
||||||
|
|
||||||
hdr = f"""#ifndef __EXTFLASH_TONE_ADDR_H
|
hdr = f"""#ifndef __EXTFLASH_TONE_ADDR_H
|
||||||
#define __EXTFLASH_TONE_ADDR_H
|
#define __EXTFLASH_TONE_ADDR_H
|
||||||
|
|
@ -161,13 +92,13 @@ def main() -> None:
|
||||||
#define EXTFLASH_CHARGING_W 160
|
#define EXTFLASH_CHARGING_W 160
|
||||||
#define EXTFLASH_CHARGING_H 190
|
#define EXTFLASH_CHARGING_H 190
|
||||||
|
|
||||||
#define EXTFLASH_BIN1_RHYTHM_ADDR 0x{OFF_BIN1:08X}UL
|
#define EXTFLASH_BIN1_RHYTHM_ADDR 0x{by_name['BIN1_RHYTHM'][1]:08X}UL
|
||||||
#define EXTFLASH_BIN1_RHYTHM_SIZE {by_name['BIN1_RHYTHM'][2]}UL
|
#define EXTFLASH_BIN1_RHYTHM_SIZE {by_name['BIN1_RHYTHM'][2]}UL
|
||||||
|
|
||||||
#define EXTFLASH_BIN2_SONG_HAITIAN_ADDR 0x{OFF_BIN2:08X}UL
|
#define EXTFLASH_BIN2_SONG_HAITIAN_ADDR 0x{by_name['BIN2_SONG_HAITIAN'][1]:08X}UL
|
||||||
#define EXTFLASH_BIN2_SONG_HAITIAN_SIZE {by_name['BIN2_SONG_HAITIAN'][2]}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{by_name['BIN3_UNIVERSAL'][1]:08X}UL
|
||||||
#define EXTFLASH_BIN3_UNIVERSAL_SIZE {by_name['BIN3_UNIVERSAL'][2]}UL
|
#define EXTFLASH_BIN3_UNIVERSAL_SIZE {by_name['BIN3_UNIVERSAL'][2]}UL
|
||||||
|
|
||||||
/* Convenience aliases used by UI ADDRESS */
|
/* Convenience aliases used by UI ADDRESS */
|
||||||
|
|
@ -190,11 +121,8 @@ def main() -> None:
|
||||||
map_lines = [
|
map_lines = [
|
||||||
"K1 external Flash map — tone pack 0903",
|
"K1 external Flash map — tone pack 0903",
|
||||||
f"Packed file: Code/.../tools/out/{OUT_BIN.name} ({len(packed)} bytes)",
|
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={0x100000 - cursor} bytes",
|
||||||
"",
|
"",
|
||||||
"NOTE: BIN3 is FIXED at 0x000A71AC. 2.bin must be <= 41KB and <= slot 41263 bytes.",
|
|
||||||
"",
|
|
||||||
f"{'Name':<22} {'Offset':>10} {'Size':>10} Note",
|
f"{'Name':<22} {'Offset':>10} {'Size':>10} Note",
|
||||||
"-" * 72,
|
"-" * 72,
|
||||||
]
|
]
|
||||||
|
|
@ -203,52 +131,31 @@ def main() -> None:
|
||||||
map_lines += [
|
map_lines += [
|
||||||
"",
|
"",
|
||||||
"Firmware ADDRESS mapping:",
|
"Firmware ADDRESS mapping:",
|
||||||
" 普通/专业 -> FLASH_ADDR_MODE_NORMAL/EXPERT (1.bin @ 0x1B8F0)",
|
" 普通/专业 -> FLASH_ADDR_MODE_NORMAL/EXPERT (1.bin)",
|
||||||
" 本地曲目 -> FLASH_ADDR_SONG_HAITIAN (2.bin @ 0x9D07D, max 41KB)",
|
" 海阔天空 -> FLASH_ADDR_SONG_HAITIAN (2.bin)",
|
||||||
" 万能 -> FLASH_ADDR_MODE_UNIVERSAL (3.bin @ 0xA71AC FIXED)",
|
" 万能 -> FLASH_ADDR_MODE_UNIVERSAL (3.bin)",
|
||||||
" AutoBand -> FLASH_ADDR_AUTOBAND_LEGACY 0x9EB5F (unchanged; overlaps 2.bin region — do not enable until remapped)",
|
" AutoBand -> FLASH_ADDR_AUTOBAND_LEGACY 0x9EB5F (unchanged; overlaps 2.bin region — do not enable until remapped)",
|
||||||
" Boot logo -> UI0902_BOOT_LOGO_ADDR (full-screen); packed logo.bin only pads 0x0..0xCB70",
|
" Boot logo -> UI0902_BOOT_LOGO_ADDR (full-screen); packed logo.bin only pads 0x0..0xCB70",
|
||||||
" Charging -> EXTFLASH_CHARGING_ADDR",
|
" Charging -> EXTFLASH_CHARGING_ADDR",
|
||||||
"",
|
"",
|
||||||
"Add a local song:",
|
"Add a local song:",
|
||||||
" 1. Pack the new preset into 2.bin (must stay <= 41KB / 41263 slot)",
|
" 1. Pack the new preset into 2.bin",
|
||||||
" 2. Append a row to local_songs.csv (index,code,name)",
|
" 2. Append a row to local_songs.csv (index,code,name)",
|
||||||
" 3. python tools/pack_extflash_tone_0903.py (also regenerates LocalSongNames.h)",
|
" 3. python tools/pack_extflash_tone_0903.py (also regenerates LocalSongNames.h)",
|
||||||
" 4. Rebuild firmware and flash MCU + ExtFlash ALL.res",
|
" 4. Rebuild firmware and flash MCU + ExtFlash",
|
||||||
]
|
]
|
||||||
OUT_MAP.write_text("\n".join(map_lines) + "\n", encoding="utf-8", newline="\n")
|
OUT_MAP.write_text("\n".join(map_lines) + "\n", encoding="utf-8", newline="\n")
|
||||||
|
|
||||||
print(f"Wrote {OUT_BIN} ({len(packed)} bytes)")
|
print(f"Wrote {OUT_BIN} ({len(packed)} bytes)")
|
||||||
print(f"Wrote {OUT_RES} ({len(packed)} bytes)")
|
|
||||||
print(f"Wrote {OUT_HDR}")
|
print(f"Wrote {OUT_HDR}")
|
||||||
print(f"Wrote {OUT_MAP}")
|
print(f"Wrote {OUT_MAP}")
|
||||||
for name, off, size, note in rows:
|
for name, off, size, note in rows:
|
||||||
print(f" 0x{off:08X} {size:8d} {name} {note}")
|
print(f" 0x{off:08X} {size:8d} {name} {note}")
|
||||||
if cursor > UI0902_RES_BASE:
|
if cursor > 0x00100000:
|
||||||
raise SystemExit("ERROR: pack overflows into 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(f"OK: {0x00100000 - cursor} bytes free before UI0902 @ 0x00100000")
|
||||||
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})")
|
|
||||||
|
|
||||||
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")
|
|
||||||
dab_ok(all_res, OFF_BIN1, 31)
|
|
||||||
dab_ok(all_res, OFF_BIN2, 1)
|
|
||||||
dab_ok(all_res, OFF_BIN3, 3)
|
|
||||||
OUT_ALL_RES.write_bytes(all_res)
|
|
||||||
# Mirror under repo tools/out for publish/consumers
|
|
||||||
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_RES.name).write_bytes(packed)
|
|
||||||
print(f"Wrote {OUT_ALL_RES} ({len(all_res)} bytes) — verified 1/2/3.bin")
|
|
||||||
else:
|
|
||||||
print(f"WARN: {UI0902_BIN} missing; skipped ALL.res")
|
|
||||||
|
|
||||||
|
# Keep LocalSongNames.h in sync with Doc/.../local_songs.csv when packing tones.
|
||||||
gen = ROOT / "tools" / "gen_local_song_names.py"
|
gen = ROOT / "tools" / "gen_local_song_names.py"
|
||||||
r = subprocess.run([sys.executable, str(gen)], check=False)
|
r = subprocess.run([sys.executable, str(gen)], check=False)
|
||||||
if r.returncode != 0:
|
if r.returncode != 0:
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ MAP_TXT = REPO / "Doc" / "音色文件" / "0903" / "FLASH_MAP.txt"
|
||||||
IAP_DIR = REPO / "升级" / "MCU主控升级"
|
IAP_DIR = REPO / "升级" / "MCU主控升级"
|
||||||
OUT_ROOT = REPO / "tools" / "out"
|
OUT_ROOT = REPO / "tools" / "out"
|
||||||
|
|
||||||
FW_VER = "0.2.7"
|
FW_VER = "0.2.6"
|
||||||
TONE_RES_VER = "0903"
|
TONE_RES_VER = "0903"
|
||||||
UI0902_RES_BASE = 0x00100000
|
UI0902_RES_BASE = 0x00100000
|
||||||
BOOT_FLASH_ADDR = 0x08000000
|
BOOT_FLASH_ADDR = 0x08000000
|
||||||
|
|
@ -69,33 +69,6 @@ def build_combined_extflash(tone: bytes, ui: bytes) -> bytes:
|
||||||
return tone + (b"\xFF" * pad) + ui
|
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"),
|
|
||||||
}
|
|
||||||
for name, (off, want_cnt, src_path) in sources.items():
|
|
||||||
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 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")
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
if not BOOT_BIN.is_file():
|
if not BOOT_BIN.is_file():
|
||||||
raise SystemExit(f"missing Boot bin: {BOOT_BIN}")
|
raise SystemExit(f"missing Boot bin: {BOOT_BIN}")
|
||||||
|
|
@ -124,10 +97,8 @@ def main() -> None:
|
||||||
pkg.mkdir(parents=True)
|
pkg.mkdir(parents=True)
|
||||||
|
|
||||||
tone_data = TONE_BIN.read_bytes()
|
tone_data = TONE_BIN.read_bytes()
|
||||||
verify_tone_layout(tone_data)
|
|
||||||
ui_data = UI0902_BIN.read_bytes()
|
ui_data = UI0902_BIN.read_bytes()
|
||||||
combined = build_combined_extflash(tone_data, ui_data)
|
combined = build_combined_extflash(tone_data, ui_data)
|
||||||
verify_tone_layout(combined) # same offsets in ALL.res
|
|
||||||
|
|
||||||
boot_name = f"AT32F403ARCT7_BOOT_v{FW_VER}_{stamp}.bin"
|
boot_name = f"AT32F403ARCT7_BOOT_v{FW_VER}_{stamp}.bin"
|
||||||
mcu_name = f"YNGJ-GT1-M_MCU_v{FW_VER}_{stamp}.bin"
|
mcu_name = f"YNGJ-GT1-M_MCU_v{FW_VER}_{stamp}.bin"
|
||||||
|
|
@ -176,7 +147,7 @@ def main() -> None:
|
||||||
"",
|
"",
|
||||||
"外部 Flash 分区:",
|
"外部 Flash 分区:",
|
||||||
" 0x00000000 音色/充电图 (toneRes)",
|
" 0x00000000 音色/充电图 (toneRes)",
|
||||||
" logo pad + Charg@0xCB70 + 1.bin@0x1B8F0 + 2.bin@0x9D07D + 3.bin@0xA71AC(FIXED)",
|
" logo pad + Charg@0xCB70 + 1.bin@0x1B8F0 + 2.bin(HKTK/2s) + 3.bin",
|
||||||
" 0x00100000 UI0902 图片 (模式选择、开机 Logo、充电、烧录模式、设置/调音台等)",
|
" 0x00100000 UI0902 图片 (模式选择、开机 Logo、充电、烧录模式、设置/调音台等)",
|
||||||
" 0x001D2000 UI0902_FLASH_MODE 烧录模式全屏图(Boot 读取)",
|
" 0x001D2000 UI0902_FLASH_MODE 烧录模式全屏图(Boot 读取)",
|
||||||
"",
|
"",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue