From a68b978c084131b24f220cacd35f4df16a65ae18 Mon Sep 17 00:00:00 2001 From: yuquanjun Date: Wed, 14 Oct 2026 11:20:51 +0800 Subject: [PATCH] fix(univ): finish the universal outro so the pick can start again Keep the last 1/2/3 fill on screen, and leave neck lights all green in normal and expert unless the app is guiding them. Co-authored-by: Cursor --- Global/Global.c | 71 ++++++++++++++++++++++++++++++++++++++++------ UI/UI_ExpertMode.c | 3 ++ UI/UI_FreeMode.c | 4 ++- UI/UI_SongMode.c | 9 ++---- UI/UI_global.c | 5 ++-- 5 files changed, 74 insertions(+), 18 deletions(-) diff --git a/Global/Global.c b/Global/Global.c index f1a912e..26ec56d 100644 --- a/Global/Global.c +++ b/Global/Global.c @@ -123,7 +123,12 @@ void AppNeckLed_NoteGuide(void) void AppNeckLed_ClearGuide(void) { + uint8_t tab; s_app_neck_led = 0; + /* 断开 App 后,普通/专业回到一直全绿 */ + tab = (uint8_t)mGuiData[GUI_TAB_INDEX].Current; + if (tab == 1u || tab == 2u) + app_tm1629_all_on(LED_COLOR_G); } uint8_t AppNeckLed_IsGuide(void) @@ -944,6 +949,10 @@ void Accomp_UpdatePlayingChord(void) /* 尾奏期间冻结走向灯:保持全绿,避免 LOOP_LIGHT 按小节刷红 */ static uint8_t s_outro_led_all_green = 0; +/* bit0=等尾奏播完再停,bit1=已见到尾奏舞台 */ +static uint8_t s_outro_wait_end = 0; +#define OUTRO_WAIT_END 0x01u +#define OUTRO_SAW_STAGE 0x02u /* 万能拨片:bit0=等前奏后进 piece,bit1=已见前奏舞台(省 RAM) */ static uint8_t s_univ_preamble_flags = 0; @@ -991,7 +1000,14 @@ static void Accomp_PostambleCutNow(void) *(volatile uint32_t *)(m_ABSystem + AB_BAR_PHASE_OFF) = 0; } -/* 万能拨片起奏:退出 piece → 前奏(不循环) → 待前奏结束后切入 piece 段落1 循环。 */ +/* 万能 1/2/3 才是加花;4 号是尾奏,不占用屏幕焦点 */ +static uint8_t Univ_FillSection(void) +{ + uint8_t sec = (uint8_t)mGuiData[GUI_PLAY_SECTION].Current; + if (sec > 2u) + sec = 2u; + return sec; +} static void Univ_StartWithPreamble(uint8_t *notes, uint8_t n) { uint8_t session_was_on = StartFlag ? 1u : 0u; @@ -1001,7 +1017,8 @@ static void Univ_StartWithPreamble(uint8_t *notes, uint8_t n) StartFlag = 1; s_outro_led_all_green = 0; - mGuiData[GUI_PLAY_SECTION].Current = 0; /* 段落后续固定进段落1 */ + s_outro_wait_end = 0; + /* 再拨片按屏幕上仍选中的 1/2/3 加花,不改回段落 1 */ if (session_was_on) AutoBandTop1_Stop(); @@ -1010,7 +1027,7 @@ static void Univ_StartWithPreamble(uint8_t *notes, uint8_t n) /* 须先退出 piece,否则 Preamble 舞台切不过去(同尾奏) */ AutoBandTop1_SetPiecePlayMode(0, 0, 0); - AutoBandTop1_SetRunVar(0); + AutoBandTop1_SetRunVar(Univ_FillSection()); AutoBandTop1_SetLoopMode(0, 1); /* 循环主段落,不循环前奏 */ AutoBandTop1_Preamble(0); MasterVolume_Reapply(); @@ -1051,7 +1068,7 @@ static void Univ_PollEnterPieceAfterPreamble(void) return; s_univ_preamble_flags = 0; - AutoBandTop1_SetRunVar(0); + AutoBandTop1_SetRunVar(Univ_FillSection()); AutoBandTop1_SetPiecePlayMode(1, 0, 480); AutoBandTop1_SetLoopMode(0, 1); @@ -1070,6 +1087,35 @@ static void Univ_PollEnterPieceAfterPreamble(void) (unsigned)note_cnt, (unsigned)chord_id); } +/* 万能 4 号尾奏播完后硬停,状态与止音键一致,拨片才能再启动 */ +static void Univ_PollOutroEnd(void) +{ + uint8_t st; + uint8_t tab; + uint8_t last; + + if (!(s_outro_wait_end & OUTRO_WAIT_END) || !StartFlag) + return; + tab = (uint8_t)mGuiData[GUI_TAB_INDEX].Current; + last = (uint8_t)mGuiData[GUI_TAB_LAST_INDEX].Current; + if (tab != 0u && !(tab == 3u && last == 0u)) + { + s_outro_wait_end = 0; + return; + } + st = m_ABSystem[AB_STAGE_OFF]; + if (st == AB_STAGE_POST_WAIT || st == AB_STAGE_POST) + { + s_outro_wait_end |= OUTRO_SAW_STAGE; + return; + } + if (s_outro_wait_end & OUTRO_SAW_STAGE) + { + s_outro_wait_end = 0; + Stop_AutoBand_Request(); + } +} + /* 尾奏起奏:Postamble(0) + 同步起奏 + 当前和弦 Note_On。 * 供 ADC 独立尾奏键与万能模式第4段落键共用。 * 万能走 piece 循环,须先退出 piece,否则 Postamble 舞台切不过去; @@ -1087,9 +1133,11 @@ void AutoBand_StartOutro(void) /* 退出和弦走向 piece,再进风格尾奏舞台 */ AutoBandTop1_SetPiecePlayMode(0, 0, 0); AutoBandTop1_Postamble(0); - /* 尾奏:指板 LED 全绿(停走 LOOP 走向红灯) */ + /* 尾奏:未连 App 时指板全绿。播完后 Univ_PollOutroEnd 硬停。 */ s_outro_led_all_green = 1; - app_tm1629_all_on(LED_COLOR_G); + s_outro_wait_end = OUTRO_WAIT_END; + if (!AppNeckLed_IsGuide()) + app_tm1629_all_on(LED_COLOR_G); /* 尾奏起奏前补发主音量,保证与图标一致 */ MasterVolume_Reapply(); if (was_playing) @@ -1392,6 +1440,7 @@ void Stop_AutoBand(void) AutoBandTop1_Stop(); Band_AllNotesOff(); s_outro_led_all_green = 0; + s_outro_wait_end = 0; s_univ_preamble_flags = 0; for (uint8_t i = 0; i < 4; i++) key_toggle[i] = 0; } @@ -1889,8 +1938,11 @@ void Pick_Handle() break; case 1: - /* 专业:播放中再拨片不 Stop+Start(库会把未消费的 Start 标志清掉 → 静音); + /* 专业:未连 App 时把位灯一直全绿。App 引导中不改灯。 + * 播放中再拨片不 Stop+Start(库会把未消费的 Start 标志清掉 → 静音); * 本地曲播放中仅换和弦音续播,节奏路径 piece 重启本就安全。 */ + if (!AppNeckLed_IsGuide()) + app_tm1629_all_on(LED_COLOR_G); if (Band_IsPlaying() && mGuiData[GUI_AUTOBAND_SW].Current) { Accomp_UpdatePlayingChord(); @@ -2350,9 +2402,10 @@ void Read_Cur_Measure() Band_TrackPlayTick(); FreeMode_PollEvenBeatStop(); Univ_PollEnterPieceAfterPreamble(); + Univ_PollOutroEnd(); - /* 尾奏中保持全绿,不刷新和弦走向红灯 */ - if (loop_light_ok && StartFlag && !s_outro_led_all_green) + /* 尾奏中保持全绿。App 弹唱只显示下发灯,不走本地走向灯。 */ + if (loop_light_ok && StartFlag && !s_outro_led_all_green && !AppNeckLed_IsGuide()) { if(now - last_tick_i >= 10) { diff --git a/UI/UI_ExpertMode.c b/UI/UI_ExpertMode.c index f39d08b..85887ea 100644 --- a/UI/UI_ExpertMode.c +++ b/UI/UI_ExpertMode.c @@ -6,6 +6,9 @@ void UI_ExpertMode_Init(void) mGuiData[GUI_TAB_LAST_INDEX].Current = mGuiData[GUI_TAB_INDEX].Current; //mGuiData[GUI_AUTOBAND_SW].Current = 1; UI_ReloadTonePreset(); /* 必须在 TAB=专业 之后换库,否则仍是万能 3.bin */ + /* 未连 App 弹唱:专业把位灯一直全绿。App 引导中不改灯。 */ + if (!AppNeckLed_IsGuide()) + app_tm1629_all_on(LED_COLOR_G); if (CurrUIProcress == UI_SongMode_Process) Show_home_UI_Diff(); else diff --git a/UI/UI_FreeMode.c b/UI/UI_FreeMode.c index 207e59f..c8d498c 100644 --- a/UI/UI_FreeMode.c +++ b/UI/UI_FreeMode.c @@ -7,7 +7,9 @@ void UI_FreeMode_Init(void) mGuiData[GUI_TAB_LAST_INDEX].Current = mGuiData[GUI_TAB_INDEX].Current; //mGuiData[GUI_AUTOBAND_SW].Current = 1; UI_ReloadTonePreset(); /* TAB=普通 后再加载 1.bin */ - app_tm1629_all_on(LED_COLOR_G); /* 普通模式:全绿,不跟节奏走向灯 */ + /* 未连 App:普通一直全绿。App 引导中不改灯。 */ + if (!AppNeckLed_IsGuide()) + app_tm1629_all_on(LED_COLOR_G); if (CurrUIProcress == UI_SongMode_Process) Show_home_UI_Diff(); else diff --git a/UI/UI_SongMode.c b/UI/UI_SongMode.c index 0ca4441..78d0487 100644 --- a/UI/UI_SongMode.c +++ b/UI/UI_SongMode.c @@ -262,14 +262,10 @@ void Touch_Action(int8_t FLAG, uint8_t ID, uint8_t areaIndex,uint8_t value) } else if(ID==GUI_PLAY_SECTION) { - /* 万能模式第4键:改为尾奏播放(与独立尾奏键同路径),不走 main4 */ + /* 万能模式第4键是尾奏,不是第4加花:不改 1/2/3 焦点 */ if (mGuiData[GUI_TAB_INDEX].Current == 0 && value == 3) { - last_value = mGuiData[ID].Current; - mGuiData[ID].Current = value; AutoBand_StartOutro(); - if (!UI_SetFocus(GUI_PLAY_SECTION)) - Refresh_SectionSelect(last_value, &UI_Label[ID], &mGuiData[ID]); return; } if(mGuiData[ID].Current != value) @@ -305,7 +301,8 @@ void Touch_Action(int8_t FLAG, uint8_t ID, uint8_t areaIndex,uint8_t value) Accomp_RememberPlayContext(); mGuiData[ID].Current = value; - app_tm1629_all_on(LED_COLOR_G); + if (!AppNeckLed_IsGuide()) + app_tm1629_all_on(LED_COLOR_G); switch(mGuiData[ID].Current) { case 0: /* 万能 → 3.bin / 本地→2.bin */ diff --git a/UI/UI_global.c b/UI/UI_global.c index 66cf8b4..748798e 100644 --- a/UI/UI_global.c +++ b/UI/UI_global.c @@ -1132,8 +1132,9 @@ void Draw_Bottom_Bar(uint8_t sel, uint8_t first_back) void UI_NavBar_Action(uint8_t value) { - /* 离开万能后 LOOP_LIGHT 停更,须显式恢复全绿(旧 GUI_TAB_INDEX 路径曾做) */ - app_tm1629_all_on(LED_COLOR_G); + /* 离开万能后 LOOP_LIGHT 停更。未连 App 时普通/专业保持全绿;App 引导中不改灯。 */ + if (!AppNeckLed_IsGuide()) + app_tm1629_all_on(LED_COLOR_G); /* 先记住当前专业/普通的指板与移调,再停;勿再强制一级(会盖掉记忆供普通无指板拨片) */ Accomp_RememberPlayContext(); Stop_AutoBand();