diff --git a/APP/app_log.c b/APP/app_log.c
index 12a56c3..b569469 100644
--- a/APP/app_log.c
+++ b/APP/app_log.c
@@ -532,6 +532,18 @@ uint8_t app_log_try_command(const char *cmd)
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
return 1U;
}
+ /* mode N:进入模式选择页的第 N 项(0 万能 / 1 专业 / 2 普通),供 RTT 起奏 */
+ if (strncmp(cmd, "mode ", 5) == 0 && cmd[5] != '\0') {
+ unsigned id = (unsigned)strtoul(cmd + 5, NULL, 10);
+ extern void Touch_Mode_Select_Action(int8_t FLAG, uint8_t ID, uint8_t areaIndex);
+ if (id > 2u) {
+ SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "MODE_BAD\n");
+ return 1U;
+ }
+ Touch_Mode_Select_Action(0, (uint8_t)id, 0);
+ SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "MODE_OK\n");
+ return 1U;
+ }
/* tone start:在当前已加载音色上拨片起奏(不改 TAB/库) */
if (strncmp(cmd, "tone start", 10) == 0) {
StartFlag = 0;
diff --git a/MyCode/App_Auto.c b/MyCode/App_Auto.c
index 560ee09..245f85c 100644
--- a/MyCode/App_Auto.c
+++ b/MyCode/App_Auto.c
@@ -56,8 +56,67 @@ static uint8_t s_seq_type;
static uint8_t s_seq_xp;
static uint8_t s_seq_po;
#define SEQ_SLOTS 12
+#define ARP_CH 12 /* 逐音琶音;垫音通道同一拍会叠多个音,不参与网格 */
static uint8_t s_seq_step[16];
static struct { uint8_t ch, in, out, used; } s_seq_slot[SEQ_SLOTS];
+/* 红圈:同一拍叠上来的音向右 1 个音(图上 1 tik = 两个格子 = 一个八分音符)。 */
+static uint32_t s_grid_t0;
+static uint16_t s_grid_unit;
+static uint8_t s_grid_on;
+static uint16_t s_pending_hold_ms;
+static uint8_t s_slot_hold4[SEQ_SLOTS];
+static volatile uint16_t s_hold_report;
+static volatile uint8_t s_hold_report_ready;
+static volatile uint8_t s_hold_count;
+
+/* tmr6_ticks 没有在中断里累加,用已经在走的 1ms 时基。 */
+extern uint32_t wk_timebase_get(void);
+
+static void App_Auto_GridReset(void)
+{
+ s_grid_on = 0;
+ s_pending_hold_ms = 0;
+}
+
+/* 当前速度的八分音符,单位 ms。速度范围 40..260。 */
+static uint16_t App_Auto_EighthMs(void)
+{
+ uint16_t bpm = (uint16_t)mGuiData[GUI_SPEED].Current;
+ if (bpm < 40u)
+ bpm = 40u;
+ return (uint16_t)(30000u / bpm);
+}
+
+static void App_Auto_QueueMidi(MidiFifoItem_t *m, uint16_t hold_ms)
+{
+ if (hold_ms == 0u)
+ m->delayCounter = 0;
+ else
+ {
+ uint16_t due = (uint16_t)((uint16_t)wk_timebase_get() + hold_ms);
+ if (due == 0u)
+ due = 1u;
+ m->delayCounter = due;
+ s_hold_report = hold_ms;
+ if (s_hold_count < 255u)
+ s_hold_count++;
+ s_hold_report_ready = 1u;
+ }
+ mymidififo_InQueue(&m_MidiSendFifo, m);
+}
+
+void App_Auto_LogHeldNotes(void)
+{
+ uint16_t ms;
+ uint8_t n;
+ if (!s_hold_report_ready)
+ return;
+ ms = s_hold_report;
+ n = s_hold_count;
+ s_hold_report_ready = 0;
+ LOG_I("SEQHOLD", "dly=%u n=%u unit=%u",
+ (unsigned)ms, (unsigned)n, (unsigned)s_grid_unit);
+}
static void App_Auto_SeqRefresh(void)
{
@@ -86,6 +145,7 @@ static void App_Auto_SeqRefresh(void)
if (s_seq_on)
App_Auto_QueueAllNotesOffMelodic();
s_seq_on = 0;
+ App_Auto_GridReset();
for (i = 0u; i < SEQ_SLOTS; i++)
s_seq_slot[i].used = 0;
return;
@@ -106,7 +166,11 @@ static void App_Auto_SeqRefresh(void)
for (i = 0u; i < 16u; i++)
s_seq_step[i] = 0;
for (i = 0u; i < SEQ_SLOTS; i++)
+ {
s_seq_slot[i].used = 0;
+ s_slot_hold4[i] = 0;
+ }
+ App_Auto_GridReset();
s_seq_on = 1u;
}
@@ -116,6 +180,7 @@ static int App_Auto_MapSeq(int channel, int key, int is_on, int *out)
int ch;
int i;
+ s_pending_hold_ms = 0;
App_Auto_SeqRefresh();
if (!s_seq_on || channel == BASS_CH || channel == DRUM_CH)
return 0;
@@ -128,15 +193,32 @@ static int App_Auto_MapSeq(int channel, int key, int is_on, int *out)
&& s_seq_slot[i].in == (uint8_t)key)
{
*out = s_seq_slot[i].out;
+ s_pending_hold_ms = (uint16_t)s_slot_hold4[i] * 4u;
s_seq_slot[i].used = 0;
+ s_slot_hold4[i] = 0;
return 1;
}
}
*out = key;
return 1;
}
- *out = s_seq[s_seq_step[ch] & 7u];
- s_seq_step[ch] = (uint8_t)((s_seq_step[ch] + 1u) & 7u);
+ {
+ uint8_t step = (uint8_t)(s_seq_step[ch] & 7u);
+ uint32_t now;
+ *out = s_seq[step];
+ s_seq_step[ch] = (uint8_t)((step + 1u) & 7u);
+ /* 琶音通道同一拍里的后一个音,晚一个八分音符再发出 */
+ if (ch == ARP_CH)
+ {
+ now = wk_timebase_get();
+ if (s_grid_on && (now - s_grid_t0) < (uint32_t)(s_grid_unit / 4u))
+ s_pending_hold_ms = s_grid_unit;
+ else
+ s_grid_unit = App_Auto_EighthMs();
+ s_grid_t0 = now;
+ s_grid_on = 1u;
+ }
+ }
for (i = 0; i < SEQ_SLOTS; i++)
{
if (!s_seq_slot[i].used)
@@ -145,6 +227,7 @@ static int App_Auto_MapSeq(int channel, int key, int is_on, int *out)
s_seq_slot[i].ch = (uint8_t)ch;
s_seq_slot[i].in = (uint8_t)key;
s_seq_slot[i].out = (uint8_t)(*out);
+ s_slot_hold4[i] = (uint8_t)(s_pending_hold_ms / 4u);
return 1;
}
}
@@ -152,6 +235,7 @@ static int App_Auto_MapSeq(int channel, int key, int is_on, int *out)
s_seq_slot[0].ch = (uint8_t)ch;
s_seq_slot[0].in = (uint8_t)key;
s_seq_slot[0].out = (uint8_t)(*out);
+ s_slot_hold4[0] = (uint8_t)(s_pending_hold_ms / 4u);
return 1;
}
@@ -193,7 +277,7 @@ static uint8_t App_Auto_RegFingerprint(void)
static void App_Auto_QueueAllNotesOffMelodic(void)
{
- MidiFifoItem_t m;
+ MidiFifoItem_t m = {0};
int ch;
for (ch = 0; ch < 16; ch++)
{
@@ -202,7 +286,7 @@ static void App_Auto_QueueAllNotesOffMelodic(void)
m.msg[1] = 123; /* All Notes Off */
m.msg[2] = 0;
m.msglen = 3;
- mymidififo_InQueue(&m_MidiSendFifo, &m);
+ App_Auto_QueueMidi(&m, 0);
}
}
@@ -492,7 +576,7 @@ static int App_Auto_MapNoteOn(int channel, int key)
static void Func_CallBack_ProgramChange(int channel, int program)
{
- MidiFifoItem_t midimsg;
+ MidiFifoItem_t midimsg = {0};
uint8_t ch = (uint8_t)(channel & 0x0F);
uint8_t bank = MIDI_BANK_ACCOMP;
/* 通道 0 是硅胶弦。节奏预设常在这里放钢琴(Program 0),会盖掉弦音色。 */
@@ -510,33 +594,33 @@ static void Func_CallBack_ProgramChange(int channel, int program)
midimsg.msg[1] = 0x00; /* CC0 Bank MSB */
midimsg.msg[2] = bank;
midimsg.msglen = 3;
- mymidififo_InQueue(&m_MidiSendFifo,&midimsg);
+ App_Auto_QueueMidi(&midimsg, 0);
midimsg.msg[1] = 0x20; /* CC32 Bank LSB */
midimsg.msg[2] = 0;
- mymidififo_InQueue(&m_MidiSendFifo,&midimsg);
+ App_Auto_QueueMidi(&midimsg, 0);
midimsg.msg[0] = 0xc0 | ch;
midimsg.msg[1] = (uint8_t)program;
midimsg.msg[2] = 0;
midimsg.msglen = 2;
- mymidififo_InQueue(&m_MidiSendFifo,&midimsg);
+ App_Auto_QueueMidi(&midimsg, 0);
}
static void Func_CallBack_NoteOff(int channel,int key)
{
- MidiFifoItem_t midimsg;
+ MidiFifoItem_t midimsg = {0};
uint8_t flags = 0;
int out_key = App_Auto_MapNote(channel, key, &flags, 0);
midimsg.msg[0] = 0x80 | (channel & 0x0F);
midimsg.msg[1] = (uint8_t)out_key;
midimsg.msg[2] = 0;
midimsg.msglen = 3;
- mymidififo_InQueue(&m_MidiSendFifo,&midimsg);
+ App_Auto_QueueMidi(&midimsg, s_pending_hold_ms);
}
static void Func_CallBack_NoteOn(int channel,int key,int vel)
{
- MidiFifoItem_t midimsg;
+ MidiFifoItem_t midimsg = {0};
int out_key;
if (vel == 0)
@@ -551,7 +635,7 @@ static void Func_CallBack_NoteOn(int channel,int key,int vel)
midimsg.msg[1] = (uint8_t)out_key;
midimsg.msg[2] = (uint8_t)vel;
midimsg.msglen = 3;
- mymidififo_InQueue(&m_MidiSendFifo,&midimsg);
+ App_Auto_QueueMidi(&midimsg, s_pending_hold_ms);
}
@@ -561,23 +645,23 @@ static void Func_CallBack_CC(int channel,int cc,int value)
{
return;
}
- MidiFifoItem_t midimsg;
+ MidiFifoItem_t midimsg = {0};
midimsg.msg[0] = 0xb0 | channel;
midimsg.msg[1] = cc;
midimsg.msg[2] = value;
midimsg.msglen = 3;
- mymidififo_InQueue(&m_MidiSendFifo,&midimsg);
+ App_Auto_QueueMidi(&midimsg, 0);
}
static void Func_CallBack_PitchWheel(int channel,int cc,int value)
{
- MidiFifoItem_t midimsg;
+ MidiFifoItem_t midimsg = {0};
midimsg.msg[0] = 0xe0 | channel;
midimsg.msg[1] = cc;
midimsg.msg[2] = value;
midimsg.msglen = 3;
- mymidififo_InQueue(&m_MidiSendFifo,&midimsg);
+ App_Auto_QueueMidi(&midimsg, 0);
}
/* Flash Map 0903:对照 ExtFlash_Tone_Addr.h / Doc/.../FLASH_MAP.txt */
diff --git a/project/IAR_V7.4/YNGJ-GT1-M.ewp b/project/IAR_V7.4/YNGJ-GT1-M.ewp
index dd9c114..3a35495 100644
--- a/project/IAR_V7.4/YNGJ-GT1-M.ewp
+++ b/project/IAR_V7.4/YNGJ-GT1-M.ewp
@@ -185,7 +185,7 @@
USE_STDPERIPH_DRIVER
AT_START_F403A_V1
autoband
- DEBUG_LCD_DUMP=1
+ DEBUG_LCD_DUMP=0