From e7c9cd91f1ee569cdf04a253b94011af266e1a43 Mon Sep 17 00:00:00 2001 From: yuquanjun Date: Thu, 24 Sep 2026 07:43:46 +0800 Subject: [PATCH] feat(free): allow pick start without fretboard using expert-stop key Normal-mode pick with no fret held applies the last expert stop transpose, starts on I, and arms even-beat stop if idle. Co-authored-by: Cursor --- Global/Global.c | 75 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 16 deletions(-) diff --git a/Global/Global.c b/Global/Global.c index 6940d6f..2ecb850 100644 --- a/Global/Global.c +++ b/Global/Global.c @@ -105,7 +105,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,23}; /* major.minor.patch — 0.2.23: 万能拨片先前奏再循环段落1 */ +const uint8_t Version[3] = {0,2,24}; /* major.minor.patch — 0.2.24: 普通无指板也可拨片起奏(用专业停键调性)+偶拍停 */ uint8_t Led = 8; bool PressFlag = 0; @@ -647,6 +647,33 @@ void Accomp_ApplyDefaultIChord(void) PressFlag = 0; } +/* 专业模式按停止键时记住当前调性,供普通模式无指板拨片起奏使用 */ +static uint8_t s_expert_stop_transpose = 0; +static uint8_t s_expert_stop_transpose_valid = 0; + +static void Expert_RememberStopTranspose(void) +{ + uint8_t tab = (uint8_t)mGuiData[GUI_TAB_INDEX].Current; + uint8_t last = (uint8_t)mGuiData[GUI_TAB_LAST_INDEX].Current; + + if (tab == 1 || (tab == 3 && last == 1)) + { + s_expert_stop_transpose = (uint8_t)mGuiData[GUI_TRANSPOSE].Current; + s_expert_stop_transpose_valid = 1; + } +} + +/* 普通无指板拨片:套用上次专业停键调性(无记录则保持当前移调) */ +static void FreeMode_ApplyExpertStopTranspose(void) +{ + if (!s_expert_stop_transpose_valid) + return; + if ((uint8_t)mGuiData[GUI_TRANSPOSE].Current == s_expert_stop_transpose) + return; + mGuiData[GUI_TRANSPOSE].Current = s_expert_stop_transpose; + UITask_Sendmsg(MSG_ID_BLE_UI_REFRESH, GUI_TRANSPOSE, 0, 0); +} + void Accomp_UpdatePlayingChord(void) { uint8_t midi_note_buff[4] = {0,}; @@ -684,6 +711,7 @@ extern uint8_t m_ABSystem[]; #define AB_STAGE_POST 0x0Cu static void FreeMode_CancelEvenBeatStop(void); +static void FreeMode_ArmEvenBeatStop(void); static void Accomp_FireSectionNotes(void) { @@ -1092,6 +1120,7 @@ static void Band_AllNotesOff(void) * 库 Stop 之后第一个 Start 必被吞,立即拨片无声。 */ void Stop_AutoBand_Soft(void) { + Expert_RememberStopTranspose(); FreeMode_CancelEvenBeatStop(); Band_CancelStartFollowup(); Band_TickGate = 0; @@ -1107,6 +1136,7 @@ void Stop_AutoBand_Soft(void) void Stop_AutoBand() { + Expert_RememberStopTranspose(); FreeMode_CancelEvenBeatStop(); /* 先清播放态,再 Stop/AllNoteOff,避免处理期间其它路径误判在播 */ Band_CancelStartFollowup(); @@ -1546,10 +1576,21 @@ void Pick_Handle() return; } - /* 左手未触发和弦板(或落在拍速/停止键)时:拨片默认发当前调一级大和弦伴奏; - * 普通模式除外——必须左手按住指板再拨,不做一级兜底(说明书需求) */ - if (mGuiData[GUI_TAB_INDEX].Current != 2 && - (chord_id == 0 || chord_id == 22 || chord_id == 23)) + /* 左手未触发和弦板(或落在拍速/停止键)时:拨片默认发当前调一级大和弦伴奏。 + * 普通模式无指板也可起奏:调性用上次专业停键时的移调,起奏后无操作则偶拍停。 */ + { + uint8_t free_pick_no_fret = + (mGuiData[GUI_TAB_INDEX].Current == 2 && + (PressFlag == 0 || chord_id == 0 || chord_id > 21)) ? 1u : 0u; + + if (free_pick_no_fret) + { + FreeMode_ApplyExpertStopTranspose(); + Accomp_ApplyDefaultIChord(); + chord_id = KEY_ID_1629; + } + else if (mGuiData[GUI_TAB_INDEX].Current != 2 && + (chord_id == 0 || chord_id == 22 || chord_id == 23)) { Accomp_ApplyDefaultIChord(); chord_id = KEY_ID_1629; @@ -1592,14 +1633,9 @@ void Pick_Handle() break; case 2: - /* 普通:左手按住指板 + 拨片起奏;松手由 TM1629 停。 + /* 普通:可无指板拨片起奏(一级+专业停键调性);有指板则用当前和弦。 + * 无指板起奏后若无其它操作,偶拍末停;按住指板则循环至松手再偶拍停。 * 节奏用 piece;本地曲目用 StartWithNote */ - if (PressFlag == 0 || chord_id == 0 || chord_id > 21) - { - LOG_I("pick", "normal skip press=%u chord=%u (need fretboard)", - (unsigned)PressFlag, (unsigned)chord_id); - break; - } { uint8_t session_was_on = StartFlag ? 1u : 0u; StartFlag = 1; @@ -1617,18 +1653,24 @@ void Pick_Handle() AutoBandTop1_SetRunVar(mGuiData[GUI_PLAY_SECTION].Current); midi = 0x3C + mGuiData[GUI_TRANSPOSE].Current; Band_StartLocalRetry(midi, midi_note_buff, note_cnt); - LOG_I("pick", "local/normal root=%u name=%s", midi, - AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?"); + LOG_I("pick", "local/normal root=%u name=%s noFret=%u", midi, + AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?", + (unsigned)free_pick_no_fret); } else { AutoBandTop1_SetPiecePlayMode(1, 0, 1920); Band_StartPieceRetry(midi_note_buff, note_cnt); AutoBandTop1_SetLoopMode(0, 1); - LOG_I("pick", "normal/rhythm piece name=%s notes=%u chord=%u", + LOG_I("pick", "normal/rhythm piece name=%s notes=%u chord=%u noFret=%u xp=%u", AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?", - (unsigned)note_cnt, (unsigned)chord_id); + (unsigned)note_cnt, (unsigned)chord_id, + (unsigned)free_pick_no_fret, + (unsigned)mGuiData[GUI_TRANSPOSE].Current); } + /* 无指板:起奏后即武装偶拍停;有指板则等松手再 Arm */ + if (free_pick_no_fret) + FreeMode_ArmEvenBeatStop(); } break; @@ -1652,6 +1694,7 @@ void Pick_Handle() (unsigned)PressFlag, (unsigned)note_cnt, (unsigned)chord_id); break; } + } }