From 3274c7d4fbe49c413a8a866688caab7cf1203ea8 Mon Sep 17 00:00:00 2001 From: yuquanjun Date: Thu, 17 Sep 2026 16:18:14 +0800 Subject: [PATCH] fix(play): default pick/preamble to current-key I chord after boot Apply Accomp_ApplyDefaultIChord before SyncStart on preamble, on soft power-on/mode enter/nav switch, and on pick fallback. Reset TM1629 key edge state so soft-off residual key_last cannot stick a prior fret. Co-authored-by: Cursor --- APP/app_tm1629.c | 6 ++++++ APP/app_tm1629.h | 1 + Global/Global.c | 40 ++++++++++++++++++++++++++-------------- Global/Global.h | 2 ++ UI/UI_Idle.c | 3 +++ UI/UI_global.c | 2 ++ 6 files changed, 40 insertions(+), 14 deletions(-) diff --git a/APP/app_tm1629.c b/APP/app_tm1629.c index f18fb85..f572101 100644 --- a/APP/app_tm1629.c +++ b/APP/app_tm1629.c @@ -19,6 +19,12 @@ void app_tm1629_init(void) rt_mutex_release(TM1629_Mutex); } +void app_tm1629_reset_key_state(void) +{ + key_last = KEY_NONE; + key_hold_sticky = 0; +} + uint8_t app_tm1629_Scan_Key(void) { uint8_t key = 0; diff --git a/APP/app_tm1629.h b/APP/app_tm1629.h index 0f50565..314485c 100644 --- a/APP/app_tm1629.h +++ b/APP/app_tm1629.h @@ -3,6 +3,7 @@ void app_tm1629_init(void); +void app_tm1629_reset_key_state(void); /* 软开机清扫描边沿,避免残留 key_last */ uint8_t app_tm1629_Scan_Key(void); void app_tm1629_inject_key(uint8_t key); /* RTT/测试:绕过扫描直接注入 */ void app_tm1629_inject_hold(uint8_t key); /* RTT/测试:注入并保持(物理空扫不释放,chord key 0 解除) */ diff --git a/Global/Global.c b/Global/Global.c index 1b8bbff..77dac70 100644 --- a/Global/Global.c +++ b/Global/Global.c @@ -208,10 +208,10 @@ static void PowerOff_EmergencyReset(void) void System_PowerOn(void) { LOG_I("PWR", "power_on begin"); - /* 软关机不复位 MCU:清掉上次会话的演奏状态,保证开机拨片走当前调一级兜底 */ - KEY_ID_1629 = 0; - PressFlag = 0; - StartFlag = 0; + /* 软关机不复位 MCU:清掉上次会话演奏状态,默认当前调一级大和弦(C 调=do mi sol) */ + StartFlag = 0; + Accomp_ApplyDefaultIChord(); + app_tm1629_reset_key_state(); s_pwr_rails_cut = 0u; s_pwr_off_grace_ms = 0u; /* 本次长按已用于开机:先消耗,再置 powon,防止 TMR7 ISR 把同一按压力即判为关机 */ @@ -585,6 +585,15 @@ void MasterVolume_Reapply(void) Send_volume(vol); } +/* 当前调一级大和弦:把位1 + maj + 自然音(再经 GUI_TRANSPOSE 移调 → C调即 do mi sol) */ +void Accomp_ApplyDefaultIChord(void) +{ + KEY_ID_1629 = 1; + chord_type_index_map[1].type = 0; /* maj */ + chord_type_index_map[1].PitchOffset = 1; /* 自然,非 # */ + PressFlag = 0; +} + void Accomp_UpdatePlayingChord(void) { uint8_t midi_note_buff[4] = {0,}; @@ -594,7 +603,7 @@ void Accomp_UpdatePlayingChord(void) if (!StartFlag) return; if (KEY_ID_1629 == 0 || KEY_ID_1629 == 22 || KEY_ID_1629 == 23) - return; + Accomp_ApplyDefaultIChord(); note_cnt = GetChordNotesByType(KEY_ID_1629, chord_type_index_map[KEY_ID_1629].type, @@ -612,6 +621,9 @@ void AutoBand_StartOutro(void) uint8_t midi_note_buff[4] = {0,}; uint8_t note_cnt = 0; + if (KEY_ID_1629 == 0 || KEY_ID_1629 == 22 || KEY_ID_1629 == 23) + Accomp_ApplyDefaultIChord(); + /* 退出和弦走向 piece,再进风格尾奏舞台 */ AutoBandTop1_SetPiecePlayMode(0, 0, 0); AutoBandTop1_Postamble(0); @@ -648,22 +660,23 @@ void ADC_IN1_KEY_Handle(uint8_t key,bool on) case 0: AutoBandTop1_Preamble(1); is_preamble = 1; break; case 2: AutoBandTop1_Postamble(1); break; } + /* 前奏:须在 SyncStart 前落到当前调一级,否则前 50ms 伴奏按旧把位进 */ + if (is_preamble) + Accomp_ApplyDefaultIChord(); + else if (KEY_ID_1629 == 0 || KEY_ID_1629 == 22 || KEY_ID_1629 == 23) + Accomp_ApplyDefaultIChord(); /* 前奏/断奏起奏前补发主音量,保证与图标一致 */ MasterVolume_Reapply(); //AutoBandTop1_Start(); AutoBandTop1_SyncStart(); wk_delay_ms(50); - /* 音师:前奏起始 = 当前调一级和弦第一把位(index 1 + maj,再经移调) */ - if (is_preamble) - { - KEY_ID_1629 = 1; - chord_type_index_map[1].type = 0; - } note_cnt = GetChordNotesByType(KEY_ID_1629,chord_type_index_map[KEY_ID_1629].type,midi_note_buff); for(uint8_t i = 0;i < note_cnt;i++) { AutoBandTop1_Note_On(midi_note_buff[i],0x50); } + if (is_preamble) + StartFlag = 1; } } else @@ -1020,9 +1033,8 @@ void Pick_Handle() if (mGuiData[GUI_TAB_INDEX].Current != 2 && (chord_id == 0 || chord_id == 22 || chord_id == 23)) { - KEY_ID_1629 = 1; - chord_type_index_map[1].type = 0; - chord_id = 1; + Accomp_ApplyDefaultIChord(); + chord_id = KEY_ID_1629; } note_cnt = GetChordNotesByType(chord_id, chord_type_index_map[chord_id].type, midi_note_buff); Return_Light_buff(KEY_ID_1629); diff --git a/Global/Global.h b/Global/Global.h index bf44600..ce430aa 100644 --- a/Global/Global.h +++ b/Global/Global.h @@ -204,6 +204,8 @@ extern void (*CurrUIProcress)(DisplayTaskMessage_Type xEvent); void Stop_AutoBand(); +/* 当前调一级大和弦(把位1 + maj);开机/进模式/前奏/拨片兜底共用 */ +void Accomp_ApplyDefaultIChord(void); static void ShowPowerOn(); diff --git a/UI/UI_Idle.c b/UI/UI_Idle.c index 4bb29c1..ff73bfe 100644 --- a/UI/UI_Idle.c +++ b/UI/UI_Idle.c @@ -127,6 +127,9 @@ void Touch_Mode_Select_Action(int8_t FLAG, uint8_t ID, uint8_t areaIndex) /* ID 为 TAB 索引:0=万能(Song) 1=专业(Expert) 2=普通(Free) */ mGuiData[GUI_TAB_INDEX].Current = ID; InModeFlag = true; + /* 进模式:默认当前调一级,避免软关机残留把位影响拨片/前奏 */ + StartFlag = 0; + Accomp_ApplyDefaultIChord(); /* 进入子页后抑制残留按下,否则易误触底栏 GUI_TAB_INDEX(id=5)→设置 */ app_touch_suppress(500); /* DSP 已就绪:再下发音色 + 调音台音量(与关机前 NVM/faders 一致) */ diff --git a/UI/UI_global.c b/UI/UI_global.c index 9782364..27c7ae7 100644 --- a/UI/UI_global.c +++ b/UI/UI_global.c @@ -1014,6 +1014,8 @@ void UI_NavBar_Action(uint8_t value) app_tm1629_all_on(LED_COLOR_G); /* 底栏切模式/进设置:立即结束当前伴奏(设置页不走 ReloadTonePreset) */ Stop_AutoBand(); + /* 切模式后拨片/前奏默认当前调一级 */ + Accomp_ApplyDefaultIChord(); switch (value) {