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 <cursoragent@cursor.com>
This commit is contained in:
yuquanjun 2026-09-24 07:43:46 +08:00
parent 5c30baef89
commit e7c9cd91f1
1 changed files with 59 additions and 16 deletions

View File

@ -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)); 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; uint8_t Led = 8;
bool PressFlag = 0; bool PressFlag = 0;
@ -647,6 +647,33 @@ void Accomp_ApplyDefaultIChord(void)
PressFlag = 0; 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) void Accomp_UpdatePlayingChord(void)
{ {
uint8_t midi_note_buff[4] = {0,}; uint8_t midi_note_buff[4] = {0,};
@ -684,6 +711,7 @@ extern uint8_t m_ABSystem[];
#define AB_STAGE_POST 0x0Cu #define AB_STAGE_POST 0x0Cu
static void FreeMode_CancelEvenBeatStop(void); static void FreeMode_CancelEvenBeatStop(void);
static void FreeMode_ArmEvenBeatStop(void);
static void Accomp_FireSectionNotes(void) static void Accomp_FireSectionNotes(void)
{ {
@ -1092,6 +1120,7 @@ static void Band_AllNotesOff(void)
* 库 Stop 之后第一个 Start 必被吞,立即拨片无声。 */ * 库 Stop 之后第一个 Start 必被吞,立即拨片无声。 */
void Stop_AutoBand_Soft(void) void Stop_AutoBand_Soft(void)
{ {
Expert_RememberStopTranspose();
FreeMode_CancelEvenBeatStop(); FreeMode_CancelEvenBeatStop();
Band_CancelStartFollowup(); Band_CancelStartFollowup();
Band_TickGate = 0; Band_TickGate = 0;
@ -1107,6 +1136,7 @@ void Stop_AutoBand_Soft(void)
void Stop_AutoBand() void Stop_AutoBand()
{ {
Expert_RememberStopTranspose();
FreeMode_CancelEvenBeatStop(); FreeMode_CancelEvenBeatStop();
/* 先清播放态,再 Stop/AllNoteOff,避免处理期间其它路径误判在播 */ /* 先清播放态,再 Stop/AllNoteOff,避免处理期间其它路径误判在播 */
Band_CancelStartFollowup(); Band_CancelStartFollowup();
@ -1546,10 +1576,21 @@ void Pick_Handle()
return; 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(); Accomp_ApplyDefaultIChord();
chord_id = KEY_ID_1629; chord_id = KEY_ID_1629;
@ -1592,14 +1633,9 @@ void Pick_Handle()
break; break;
case 2: case 2:
/* 普通:左手按住指板 + 拨片起奏;松手由 TM1629 停。 /* 普通:可无指板拨片起奏(一级+专业停键调性);有指板则用当前和弦。
* 无指板起奏后若无其它操作,偶拍末停;按住指板则循环至松手再偶拍停。
* 节奏用 piece;本地曲目用 StartWithNote */ * 节奏用 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; uint8_t session_was_on = StartFlag ? 1u : 0u;
StartFlag = 1; StartFlag = 1;
@ -1617,18 +1653,24 @@ void Pick_Handle()
AutoBandTop1_SetRunVar(mGuiData[GUI_PLAY_SECTION].Current); AutoBandTop1_SetRunVar(mGuiData[GUI_PLAY_SECTION].Current);
midi = 0x3C + mGuiData[GUI_TRANSPOSE].Current; midi = 0x3C + mGuiData[GUI_TRANSPOSE].Current;
Band_StartLocalRetry(midi, midi_note_buff, note_cnt); Band_StartLocalRetry(midi, midi_note_buff, note_cnt);
LOG_I("pick", "local/normal root=%u name=%s", midi, LOG_I("pick", "local/normal root=%u name=%s noFret=%u", midi,
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?"); AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?",
(unsigned)free_pick_no_fret);
} }
else else
{ {
AutoBandTop1_SetPiecePlayMode(1, 0, 1920); AutoBandTop1_SetPiecePlayMode(1, 0, 1920);
Band_StartPieceRetry(midi_note_buff, note_cnt); Band_StartPieceRetry(midi_note_buff, note_cnt);
AutoBandTop1_SetLoopMode(0, 1); 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() : "?", 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; break;
@ -1652,6 +1694,7 @@ void Pick_Handle()
(unsigned)PressFlag, (unsigned)note_cnt, (unsigned)chord_id); (unsigned)PressFlag, (unsigned)note_cnt, (unsigned)chord_id);
break; break;
} }
}
} }