2026-08-26 07:26:58 +08:00
|
|
|
|
#include "includes.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rt_mutex_t TM1629_Mutex = RT_NULL;
|
|
|
|
|
|
rt_mutex_t TM1617_Mutex = RT_NULL;
|
|
|
|
|
|
rt_mq_t MainTask_msg = RT_NULL;
|
|
|
|
|
|
rt_mq_t UITask_msg = RT_NULL;
|
|
|
|
|
|
rt_mq_t BLTask_msg = RT_NULL;
|
|
|
|
|
|
rt_sem_t UART4_sem = RT_NULL;
|
|
|
|
|
|
// 定义定时器ID
|
|
|
|
|
|
rt_timer_t OutTime_Stop_timer = RT_NULL;
|
|
|
|
|
|
|
|
|
|
|
|
const Touch_AreaTypeDef *pCurrentTouch_Area = Touch_ModeSelect_Areas;
|
|
|
|
|
|
|
|
|
|
|
|
GUI_SWITCH mGuiData[] = {
|
|
|
|
|
|
{ 0, 0, 11, GUI_TRANSPOSE}, // 0
|
|
|
|
|
|
{ 78, 40, 260, GUI_SPEED}, // 1
|
|
|
|
|
|
{ 0, 0, 1, GUI_MODE_PARAM}, // 2 ?? <20>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><E0BFAA> 0=<3D><> 1=<3D><>
|
|
|
|
|
|
{ 0, 0, 4, GUI_TIMBRE_SELECT}, // 3
|
|
|
|
|
|
{ 0, 0, 3, GUI_PLAY_SECTION}, // 4
|
|
|
|
|
|
{ 0, 0, 3, GUI_TAB_INDEX}, // 5
|
|
|
|
|
|
{ 0, 0, 1, GUI_AUTOBAND_SW}, // 6 ?? <20>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><E0BFAA> 0=<3D><> 1=<3D><>
|
|
|
|
|
|
{ 1, 0, 1, GUI_BL_SW},
|
|
|
|
|
|
{ 0, 0, 3, GUI_TAB_LAST_INDEX},
|
|
|
|
|
|
};
|
|
|
|
|
|
GUI_SWITCH ParamGuiData[] =
|
|
|
|
|
|
{
|
2026-09-04 17:06:02 +08:00
|
|
|
|
{ 0, 0, 30, SONG_MODE_PARAM}, // 0 节奏类型(1.bin,约 31 首)
|
2026-09-04 22:15:46 +08:00
|
|
|
|
{ 0, 0, 0, EXPRESS_MODE_PARAM}, // 1 本地曲目(2.bin;Max 由 UI_ReloadTonePreset←LOCAL_SONG_COUNT)
|
2026-08-26 07:26:58 +08:00
|
|
|
|
{ 0, 0, 2, ALL_MODE_PARAM}, // 2
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const LEBEL_UI UI_Label[] = {
|
2026-09-03 11:58:08 +08:00
|
|
|
|
/* 0819:移调/速度 标签11、主值16 */
|
|
|
|
|
|
{UI0902_MARGIN_X, UI0902_CARD_W, UI0902_CARD_Y, UI0902_CARD_H,
|
|
|
|
|
|
(const uint8_t*)"\xD2\xC6\xB5\xF7", LCD_ALIGN_CENTER, WHITE,BLACK,UI0902_FONT_LABEL,
|
|
|
|
|
|
LCD_ALIGN_CENTER,WHITE,BLACK,UI0902_FONT_HERO, GUI_TRANSPOSE},
|
|
|
|
|
|
{UI0902_MARGIN_X + UI0902_CARD_W + UI0902_CARD_GAP, UI0902_CARD_W, UI0902_CARD_Y, UI0902_CARD_H,
|
|
|
|
|
|
(const uint8_t*)"\xCB\xD9\xB6\xC8", LCD_ALIGN_CENTER, WHITE,BLACK,UI0902_FONT_LABEL,
|
|
|
|
|
|
LCD_ALIGN_CENTER,WHITE,BLACK,UI0902_FONT_HERO, GUI_SPEED},
|
|
|
|
|
|
/* 0819:TAB/行标题11、曲目正文13 */
|
|
|
|
|
|
{UI0902_MARGIN_X, UI0902_CONTENT_W, UI0902_MODE_Y, UI0902_MODE_H,
|
2026-09-07 13:48:18 +08:00
|
|
|
|
(const uint8_t*)"\xB8\xE8\xC7\xFA\xD1\xA1\xD4\xF1", LCD_ALIGN_LEFT,WHITE,BLACK,UI0902_FONT_LABEL,
|
2026-09-03 11:58:08 +08:00
|
|
|
|
LCD_ALIGN_CENTER,WHITE,BLACK,UI0902_FONT_BODY,GUI_MODE_PARAM},
|
|
|
|
|
|
{UI0902_MARGIN_X, UI0902_CONTENT_W, UI0902_TIMBRE_Y, UI0902_TIMBRE_H,
|
2026-09-07 12:14:27 +08:00
|
|
|
|
(const uint8_t*)"\xCF\xD2\xD2\xF4\xC9\xAB\xD1\xA1\xD4\xF1",LCD_ALIGN_LEFT,WHITE,BLACK,UI0902_FONT_LABEL,
|
2026-09-03 11:58:08 +08:00
|
|
|
|
LCD_ALIGN_CENTER,WHITE,BLACK,UI0902_FONT_BODY,GUI_TIMBRE_SELECT},
|
|
|
|
|
|
/* 0819:演奏段落 字号13 */
|
|
|
|
|
|
{UI0902_MARGIN_X, UI0902_CONTENT_W, UI0902_SECTION_Y, UI0902_SECTION_H,
|
|
|
|
|
|
(const uint8_t*)"\xD1\xDD\xD7\xE0\xB6\xCE\xC2\xE4",LCD_ALIGN_LEFT,WHITE,BLACK,UI0902_FONT_BODY,
|
|
|
|
|
|
LCD_ALIGN_CENTER,WHITE,BLACK,UI0902_FONT_BODY,GUI_PLAY_SECTION},
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-08-26 07:26:58 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-09-04 14:43:32 +08:00
|
|
|
|
/* 0904 / 0902-06:左→右 伴奏|弦|麦|麦混响,轨宽31 顶≈58 */
|
2026-08-26 07:26:58 +08:00
|
|
|
|
Fader_t faders[4] = {
|
2026-09-04 14:43:32 +08:00
|
|
|
|
{ 27, 58, 31, 215, 7, 0, 0, "\xB0\xE9\xD7\xE0" }, /* 0: 伴奏 */
|
|
|
|
|
|
{ 78, 58, 31, 215, 7, 1, 0, "\xCF\xD2" }, /* 1: 弦 */
|
|
|
|
|
|
{ 130, 58, 31, 215, 7, 2, 0, "\xC2\xF3" }, /* 2: 麦 */
|
|
|
|
|
|
{ 182, 58, 31, 215, 7, 3, 0, "\xC2\xF3\xBB\xEC\xCF\xEC" } /* 3: 麦混响 */
|
2026-08-26 07:26:58 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const Touch_AreaTypeDef Touch_Areas[] =
|
|
|
|
|
|
{
|
2026-09-03 11:58:08 +08:00
|
|
|
|
/* Xmin,Xmax,Ymin,Ymax, Flag, Value, ID, action — 与 UI_Label 网格同步 */
|
2026-09-04 06:39:00 +08:00
|
|
|
|
{ 12, 64, UI0902_CARD_Y, UI0902_CARD_Y + UI0902_CARD_H - 1, -1, 0, GUI_TRANSPOSE, NULL },
|
|
|
|
|
|
{ 65, 116, UI0902_CARD_Y, UI0902_CARD_Y + UI0902_CARD_H - 1, 1, 0, GUI_TRANSPOSE, NULL },
|
2026-08-26 07:26:58 +08:00
|
|
|
|
|
2026-09-04 06:39:00 +08:00
|
|
|
|
{ 125, 176, UI0902_CARD_Y, UI0902_CARD_Y + UI0902_CARD_H - 1, -1, 0, GUI_SPEED, NULL },
|
|
|
|
|
|
{ 177, 228, UI0902_CARD_Y, UI0902_CARD_Y + UI0902_CARD_H - 1, 1, 0, GUI_SPEED, NULL },
|
2026-08-26 07:26:58 +08:00
|
|
|
|
|
2026-09-03 12:43:19 +08:00
|
|
|
|
/* 节奏类型 / 本地曲目 TAB(0902:12-66 / 72-127) */
|
|
|
|
|
|
{ 12, 66, UI0902_MODE_Y, UI0902_MODE_Y + UI0902_TAB_H - 1, 0, 0, GUI_AUTOBAND_SW, NULL },
|
|
|
|
|
|
{ 72, 127, UI0902_MODE_Y, UI0902_MODE_Y + UI0902_TAB_H - 1, 0, 1, GUI_AUTOBAND_SW, NULL },
|
2026-08-26 07:26:58 +08:00
|
|
|
|
|
2026-09-03 12:43:19 +08:00
|
|
|
|
{ 13, 120, UI0902_MODE_Y + UI0902_TAB_H + 4, UI0902_MODE_Y + UI0902_MODE_H - 1, -1, 0, GUI_MODE_PARAM, NULL },
|
|
|
|
|
|
{ 121, 227, UI0902_MODE_Y + UI0902_TAB_H + 4, UI0902_MODE_Y + UI0902_MODE_H - 1, 1, 0, GUI_MODE_PARAM, NULL },
|
2026-08-26 07:26:58 +08:00
|
|
|
|
|
2026-09-03 12:43:19 +08:00
|
|
|
|
{ 13, 120, UI0902_TIMBRE_Y, UI0902_TIMBRE_Y + UI0902_TIMBRE_H - 1, -1, 0, GUI_TIMBRE_SELECT, NULL },
|
|
|
|
|
|
{ 121, 227, UI0902_TIMBRE_Y, UI0902_TIMBRE_Y + UI0902_TIMBRE_H - 1, 1, 0, GUI_TIMBRE_SELECT, NULL },
|
2026-08-26 07:26:58 +08:00
|
|
|
|
|
2026-09-04 06:39:00 +08:00
|
|
|
|
/* 演奏段落 1~4(0902-04:12/69/125/182,宽 47,步进 57) */
|
2026-09-03 12:43:19 +08:00
|
|
|
|
{ 12, 58, UI0902_SECTION_Y, UI0902_SECTION_Y + UI0902_SECTION_BTN_H - 1, 0, 0, GUI_PLAY_SECTION, NULL },
|
2026-09-04 06:39:00 +08:00
|
|
|
|
{ 69, 115, UI0902_SECTION_Y, UI0902_SECTION_Y + UI0902_SECTION_BTN_H - 1, 0, 1, GUI_PLAY_SECTION, NULL },
|
|
|
|
|
|
{ 126, 172, UI0902_SECTION_Y, UI0902_SECTION_Y + UI0902_SECTION_BTN_H - 1, 0, 2, GUI_PLAY_SECTION, NULL },
|
|
|
|
|
|
{ 183, 229, UI0902_SECTION_Y, UI0902_SECTION_Y + UI0902_SECTION_BTN_H - 1, 0, 3, GUI_PLAY_SECTION, NULL },
|
2026-09-03 11:58:08 +08:00
|
|
|
|
|
2026-09-05 07:05:23 +08:00
|
|
|
|
/* 底栏四键:万能 | 普通 | 专业 | 设置(触区中线对齐 cx 40/100/160/210) */
|
|
|
|
|
|
{ 0, 69, 280, 319, 0, UI0902_NAV_UNIVERSAL, GUI_NAV_BAR, NULL },
|
|
|
|
|
|
{ 70, 129, 280, 319, 0, UI0902_NAV_NORMAL, GUI_NAV_BAR, NULL },
|
|
|
|
|
|
{ 130, 184, 280, 319, 0, UI0902_NAV_EXPERT, GUI_NAV_BAR, NULL },
|
|
|
|
|
|
{ 185, 239, 280, 319, 0, UI0902_NAV_SETTING, GUI_NAV_BAR, NULL },
|
2026-08-26 07:26:58 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-09-05 21:56:14 +08:00
|
|
|
|
/* 推子 0~10 共 11 档;档10 取 AW816 上限附近 */
|
|
|
|
|
|
int16_t MIC_VOL_MAP[11]= {-9000,-7000,-5000,-3000,-1000,1000,3000,5000,7000,9000,1200};
|
2026-08-26 07:26:58 +08:00
|
|
|
|
|
|
|
|
|
|
uint8_t TOUCH_AREA_NUM = (sizeof(Touch_Areas)/sizeof(Touch_AreaTypeDef));
|
|
|
|
|
|
|
2026-09-07 21:48:54 +08:00
|
|
|
|
const uint8_t Version[3] = {0,2,3}; /* major.minor.patch — 0.2.3: local song HKTK load/play + tone addr logs */
|
2026-08-26 07:26:58 +08:00
|
|
|
|
|
|
|
|
|
|
uint8_t Led = 8;
|
|
|
|
|
|
bool PressFlag = 0;
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AutoCloseTime = 15;
|
|
|
|
|
|
uint16_t mAutoPowerOffCount = 15 * 60;
|
|
|
|
|
|
bool AutoCloseFlag = true;
|
|
|
|
|
|
void MainTask_Sendmsg(uint16_t ID, uint16_t ID2, uint16_t HiByte, uint16_t LoByte)
|
|
|
|
|
|
{
|
|
|
|
|
|
DisplayTaskMessage_Type msg;
|
2026-08-31 11:24:10 +08:00
|
|
|
|
rt_err_t ret;
|
2026-08-26 07:26:58 +08:00
|
|
|
|
|
|
|
|
|
|
msg.MessageType = ID; /* 业务消息 ID(MSG_ID_xxx) */
|
|
|
|
|
|
msg.ID = ID2;
|
|
|
|
|
|
msg.HiByte = HiByte;
|
|
|
|
|
|
msg.LoByte = LoByte;
|
2026-08-31 11:24:10 +08:00
|
|
|
|
ret = rt_mq_send(MainTask_msg, &msg, sizeof(DisplayTaskMessage_Type));
|
|
|
|
|
|
|
|
|
|
|
|
if (ret != RT_EOK) {
|
|
|
|
|
|
LOG_E("MSG", "send fail id=%u ret=%d", (unsigned)ID, (int)ret);
|
|
|
|
|
|
} else if (ID == MSG_ID_TOUCH || ID == MSG_ID_TOUCH_LONG_REPEAT ||
|
|
|
|
|
|
ID == MSG_ID_POWER_ON || ID == MSG_ID_POWER_OFF ||
|
|
|
|
|
|
ID == MSG_ID_BP_KEY || ID == MSG_ID_TAP_SPEED ||
|
|
|
|
|
|
ID == MSG_ID_BP_TRANSPOSE) {
|
|
|
|
|
|
LOG_I("MSG", "id=%u hi=%u lo=%u", (unsigned)ID, (unsigned)HiByte, (unsigned)LoByte);
|
|
|
|
|
|
}
|
2026-08-26 07:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UITask_Sendmsg(uint16_t ID, uint16_t ID2, uint16_t HiByte, uint16_t LoByte)
|
|
|
|
|
|
{
|
|
|
|
|
|
DisplayTaskMessage_Type msg;
|
|
|
|
|
|
|
|
|
|
|
|
msg.MessageType = ID; /* 业务消息 ID(MSG_ID_xxx) */
|
|
|
|
|
|
msg.ID = ID2;
|
|
|
|
|
|
msg.HiByte = HiByte;
|
|
|
|
|
|
msg.LoByte = LoByte;
|
|
|
|
|
|
rt_mq_send(UITask_msg, &msg, sizeof(DisplayTaskMessage_Type));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BLTask_Sendmsg(uint16_t ID, uint16_t ID2, uint16_t HiByte, uint16_t LoByte)
|
|
|
|
|
|
{
|
|
|
|
|
|
DisplayTaskMessage_Type msg;
|
|
|
|
|
|
|
|
|
|
|
|
msg.MessageType = ID; /* 业务消息 ID(MSG_ID_xxx) */
|
|
|
|
|
|
msg.ID = ID2;
|
|
|
|
|
|
msg.HiByte = HiByte;
|
|
|
|
|
|
msg.LoByte = LoByte;
|
|
|
|
|
|
rt_mq_send(BLTask_msg, &msg, sizeof(DisplayTaskMessage_Type));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define KEY_PRESS_LEVEL RESET
|
|
|
|
|
|
|
|
|
|
|
|
#define PWR_ON_HOLD_MS 3000 /* 关机态长按 3s → 开机 */
|
|
|
|
|
|
#define PWR_OFF_HOLD_MS 2000 /* 开机态长按 2s → 关机 */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef enum
|
|
|
|
|
|
{
|
|
|
|
|
|
KEY_STATE_IDLE,
|
|
|
|
|
|
KEY_STATE_PRESS,
|
|
|
|
|
|
KEY_STATE_NONE,
|
|
|
|
|
|
}PwrKeyState;
|
|
|
|
|
|
|
|
|
|
|
|
static PwrKeyState pwr_key_state = KEY_STATE_IDLE;
|
|
|
|
|
|
static uint32_t pwr_press_tick = 0;
|
|
|
|
|
|
|
|
|
|
|
|
/* 当前开关机状态(UI_Idle.c 等 extern 引用) */
|
|
|
|
|
|
bool powon = false;
|
|
|
|
|
|
|
|
|
|
|
|
/* ==================== 开机/关机动作 ==================== */
|
2026-08-31 08:20:24 +08:00
|
|
|
|
void System_PowerOn(void)
|
2026-08-26 07:26:58 +08:00
|
|
|
|
{
|
2026-08-31 11:24:10 +08:00
|
|
|
|
LOG_I("PWR", "power_on begin");
|
2026-09-07 08:26:45 +08:00
|
|
|
|
/* 控制电源硬件;蓝牙按 NVM/系统设置开关恢复,勿强制常开 */
|
2026-08-26 07:26:58 +08:00
|
|
|
|
BSP_MainPowerEnable(1);
|
|
|
|
|
|
BSP_DreamCorePowerEnable(1);
|
|
|
|
|
|
BSP_HT7178PowerEnable(1);
|
2026-09-07 08:26:45 +08:00
|
|
|
|
BSP_BlueToothPowerEnable((uint8_t)(mGuiData[GUI_BL_SW].Current ? 1 : 0));
|
2026-08-26 07:26:58 +08:00
|
|
|
|
powon = true; /* 更新开机标志 */
|
|
|
|
|
|
|
2026-09-02 12:16:05 +08:00
|
|
|
|
/* 先通知 UI 亮屏,避免外设初始化阻塞导致长时间黑屏 */
|
|
|
|
|
|
LOG_I("PWR", "send POWER_ON");
|
|
|
|
|
|
MainTask_Sendmsg(MSG_ID_POWER_ON, 0, 0, 0);
|
|
|
|
|
|
|
2026-08-26 07:26:58 +08:00
|
|
|
|
AD85020B_Init();
|
|
|
|
|
|
TM1629D_Key_LED_Init();
|
|
|
|
|
|
app_tm1617_init();
|
|
|
|
|
|
XPT2046_Init();
|
|
|
|
|
|
App_Auto_Init();
|
2026-09-02 12:16:05 +08:00
|
|
|
|
LOG_I("PWR", "periph ready");
|
2026-08-26 07:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-31 08:20:24 +08:00
|
|
|
|
static void PowerOn(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
System_PowerOn();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-26 07:26:58 +08:00
|
|
|
|
static void PowerOff(void)
|
|
|
|
|
|
{
|
2026-08-31 11:24:10 +08:00
|
|
|
|
uint8_t nvm_ret;
|
|
|
|
|
|
|
|
|
|
|
|
LOG_I("PWR", "power_off begin");
|
2026-08-26 07:26:58 +08:00
|
|
|
|
powon = false; /* 更新关机标志 */
|
|
|
|
|
|
StopFullTask();
|
2026-09-06 12:29:42 +08:00
|
|
|
|
|
2026-09-07 08:26:45 +08:00
|
|
|
|
/* 关机前把当前调音台推子与蓝牙开关写入 NVM,保证再次开机保持 */
|
2026-09-06 12:29:42 +08:00
|
|
|
|
{
|
|
|
|
|
|
NvmParam_Type *nvm = drv_nvm_param_ptr();
|
|
|
|
|
|
nvm->param.BandVol = faders[0].val;
|
|
|
|
|
|
nvm->param.StringVol = faders[1].val;
|
|
|
|
|
|
nvm->param.MIcVol = faders[2].val;
|
|
|
|
|
|
nvm->param.MicRev = faders[3].val;
|
2026-09-07 08:26:45 +08:00
|
|
|
|
nvm->param.BluetoothSW = (uint8_t)(mGuiData[GUI_BL_SW].Current ? 1 : 0);
|
2026-09-06 12:29:42 +08:00
|
|
|
|
}
|
2026-08-31 11:24:10 +08:00
|
|
|
|
nvm_ret = drv_nvm_save_to_flash();
|
|
|
|
|
|
LOG_I("PWR", "nvm_save=%u", (unsigned)nvm_ret);
|
2026-08-26 07:26:58 +08:00
|
|
|
|
|
|
|
|
|
|
LCD_FillByColor(0, 0, 240, 320, BLACK);
|
|
|
|
|
|
LCD_BLK_Clr();
|
|
|
|
|
|
|
|
|
|
|
|
app_tm1629_all_off();
|
|
|
|
|
|
|
|
|
|
|
|
app_tm1617_off();
|
2026-09-05 19:39:15 +08:00
|
|
|
|
/* 关闭电源硬件;MCU 保持运行以便长按开机 / 关机充电画面 */
|
2026-08-26 07:26:58 +08:00
|
|
|
|
BSP_MainPowerEnable(0);
|
|
|
|
|
|
BSP_DreamCorePowerEnable(0);
|
|
|
|
|
|
BSP_HT7178PowerEnable(0);
|
|
|
|
|
|
BSP_BlueToothPowerEnable(0);
|
2026-09-05 19:39:15 +08:00
|
|
|
|
CurrUIProcress = IdleProcess;
|
|
|
|
|
|
MainTask_Sendmsg(MSG_ID_POWER_OFF, 0, 0, 0);
|
|
|
|
|
|
LOG_I("PWR", "power_off done (soft-off, no reset)");
|
2026-09-05 19:58:42 +08:00
|
|
|
|
|
|
|
|
|
|
/* 关机时若已插着 Type-C,立刻进充电画面 */
|
|
|
|
|
|
{
|
|
|
|
|
|
uint8_t i;
|
|
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
app_adc_in1_scan_part(4);
|
|
|
|
|
|
if (usb_charging_state || app_adc_usb_is_plugged())
|
|
|
|
|
|
break;
|
|
|
|
|
|
rt_thread_mdelay(5);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (usb_charging_state || app_adc_usb_is_plugged())
|
|
|
|
|
|
{
|
|
|
|
|
|
usb_charging_state = 1;
|
|
|
|
|
|
usb_charging_laststate = 1;
|
|
|
|
|
|
LOG_I("PWR", "soft-off with USB → charge UI");
|
|
|
|
|
|
MainTask_Sendmsg(MSG_ID_POWOFF_CHARG, percentage, 1, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-08-26 07:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Power_Key_Scan()
|
|
|
|
|
|
{
|
|
|
|
|
|
flag_status status = BSP_GetPowerKey();
|
|
|
|
|
|
uint32_t now = rt_tick_get();
|
|
|
|
|
|
uint32_t holdtick = 0;
|
|
|
|
|
|
|
2026-09-05 19:58:42 +08:00
|
|
|
|
/* 复位/烧录后:无 USB 则自动开机一次;有 Type-C 则进关机充电画面(勿进 Logo) */
|
2026-08-31 08:20:24 +08:00
|
|
|
|
if (powon == false && pwr_key_state == KEY_STATE_IDLE && pwr_press_tick == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
static uint8_t s_auto_poweron_pending = 1;
|
|
|
|
|
|
if (s_auto_poweron_pending)
|
|
|
|
|
|
{
|
2026-09-05 19:58:42 +08:00
|
|
|
|
uint8_t i;
|
2026-08-31 08:20:24 +08:00
|
|
|
|
s_auto_poweron_pending = 0;
|
2026-09-05 19:58:42 +08:00
|
|
|
|
/* 多采几次 USB 检测,避免上电瞬间误判 */
|
|
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
app_adc_in1_scan_part(4);
|
|
|
|
|
|
if (usb_charging_state || app_adc_usb_is_plugged())
|
|
|
|
|
|
break;
|
|
|
|
|
|
rt_thread_mdelay(5);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (usb_charging_state || app_adc_usb_is_plugged())
|
|
|
|
|
|
{
|
|
|
|
|
|
usb_charging_state = 1;
|
|
|
|
|
|
usb_charging_laststate = 1;
|
|
|
|
|
|
LOG_I("PWR", "boot with USB → charge UI (no logo)");
|
|
|
|
|
|
CurrUIProcress = IdleProcess;
|
|
|
|
|
|
MainTask_Sendmsg(MSG_ID_POWOFF_CHARG, percentage, 1, 0);
|
|
|
|
|
|
pwr_key_state = KEY_STATE_NONE;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-08-31 11:24:10 +08:00
|
|
|
|
LOG_I("PWR", "auto power_on");
|
2026-08-31 08:20:24 +08:00
|
|
|
|
PowerOn();
|
|
|
|
|
|
pwr_key_state = KEY_STATE_NONE; /* 忽略开机瞬间可能残留的按键电平 */
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-26 07:26:58 +08:00
|
|
|
|
switch(pwr_key_state)
|
|
|
|
|
|
{
|
|
|
|
|
|
case KEY_STATE_IDLE:
|
|
|
|
|
|
if(status == KEY_PRESS_LEVEL)
|
|
|
|
|
|
{
|
|
|
|
|
|
pwr_press_tick = now;
|
|
|
|
|
|
pwr_key_state = KEY_STATE_PRESS;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case KEY_STATE_PRESS:
|
|
|
|
|
|
if(status != KEY_PRESS_LEVEL) /* 提前松开,放弃 */
|
|
|
|
|
|
{
|
|
|
|
|
|
pwr_press_tick = 0;
|
|
|
|
|
|
pwr_key_state = KEY_STATE_IDLE;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
holdtick = now - pwr_press_tick;
|
|
|
|
|
|
|
|
|
|
|
|
/* 用 powon 区分:关机长按 3s 开机,开机长按 2s 关机 */
|
|
|
|
|
|
if(powon == false && holdtick >= PWR_ON_HOLD_MS)
|
|
|
|
|
|
{
|
2026-08-31 11:24:10 +08:00
|
|
|
|
LOG_I("PWR", "key power_on hold=%u", (unsigned)holdtick);
|
2026-08-26 07:26:58 +08:00
|
|
|
|
PowerOn();
|
|
|
|
|
|
pwr_key_state = KEY_STATE_NONE;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if(powon == true && holdtick >= PWR_OFF_HOLD_MS)
|
|
|
|
|
|
{
|
2026-08-31 11:24:10 +08:00
|
|
|
|
LOG_I("PWR", "key power_off hold=%u", (unsigned)holdtick);
|
2026-08-26 07:26:58 +08:00
|
|
|
|
PowerOff();
|
|
|
|
|
|
pwr_key_state = KEY_STATE_NONE;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case KEY_STATE_NONE:
|
|
|
|
|
|
if(status != KEY_PRESS_LEVEL) /* 松开后复位,允许下次触发 */
|
|
|
|
|
|
{
|
|
|
|
|
|
pwr_key_state = KEY_STATE_IDLE;
|
|
|
|
|
|
pwr_press_tick = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
* 缺失符号补定义(AutoBandTop1 模块源码缺失,这些是它依赖的变量)
|
|
|
|
|
|
* ============================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
/* UI 当前处理函数指针(UI_global.c extern 引用) */
|
|
|
|
|
|
void (*CurrUIProcress)(DisplayTaskMessage_Type xEvent);
|
|
|
|
|
|
|
|
|
|
|
|
/* UI 公共全局变量 */
|
2026-09-04 11:12:22 +08:00
|
|
|
|
volatile uint32_t ADDRESS = FLASH_ADDR_MODE_UNIVERSAL;
|
2026-08-26 07:26:58 +08:00
|
|
|
|
uint8_t KEY_ID_1629 = 0;
|
|
|
|
|
|
bool StartFlag = false;
|
|
|
|
|
|
bool InModeFlag = false;
|
|
|
|
|
|
uint8_t key_toggle[4] = {0};
|
|
|
|
|
|
/* ============================================================
|
|
|
|
|
|
* UI 公共函数补定义
|
|
|
|
|
|
* ============================================================ */
|
|
|
|
|
|
|
2026-09-05 18:13:31 +08:00
|
|
|
|
/* 自动关机:有操作时复位秒计数;主循环每秒递减,到 0 关机 */
|
2026-08-26 07:26:58 +08:00
|
|
|
|
void ResetAutoPowerCount(void)
|
|
|
|
|
|
{
|
2026-09-05 18:13:31 +08:00
|
|
|
|
if (!AutoCloseFlag || AutoCloseTime == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
mAutoPowerOffCount = (uint16_t)(AutoCloseTime * 60);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AutoPowerOff_Scan(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
static uint32_t s_last_sec_tick = 0;
|
|
|
|
|
|
uint32_t now;
|
|
|
|
|
|
|
|
|
|
|
|
if (!powon || !AutoCloseFlag || AutoCloseTime == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
now = rt_tick_get();
|
|
|
|
|
|
if (s_last_sec_tick == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
s_last_sec_tick = now;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if ((now - s_last_sec_tick) < RT_TICK_PER_SECOND)
|
|
|
|
|
|
return;
|
|
|
|
|
|
s_last_sec_tick = now;
|
|
|
|
|
|
|
|
|
|
|
|
if (mAutoPowerOffCount > 0)
|
|
|
|
|
|
mAutoPowerOffCount--;
|
|
|
|
|
|
|
|
|
|
|
|
if (mAutoPowerOffCount == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
LOG_I("PWR", "auto power_off idle=%umin", (unsigned)AutoCloseTime);
|
|
|
|
|
|
PowerOff();
|
|
|
|
|
|
}
|
2026-08-26 07:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* GUI 数值调整(简单实现:更新当前值) */
|
|
|
|
|
|
uint8_t GUI_Item_AjustValue(GUI_SWITCH * Group, int8_t Dir)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint8_t ret= 0;
|
|
|
|
|
|
if (Dir > 0) {
|
|
|
|
|
|
if (Group->Current < Group->Max) {
|
|
|
|
|
|
Group->Current++;
|
|
|
|
|
|
ret = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (Dir < 0) {
|
|
|
|
|
|
if (Group->Current > Group->Min) {
|
|
|
|
|
|
Group->Current--;
|
|
|
|
|
|
ret = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GUI_Item_AjustLoopValue(GUI_SWITCH * Group, int8_t Dir)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Dir > 0) {
|
|
|
|
|
|
if (Group->Current < Group->Max) {
|
|
|
|
|
|
Group->Current++;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Group->Current = Group->Min;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (Dir < 0) {
|
|
|
|
|
|
if (Group->Current > Group->Min) {
|
|
|
|
|
|
Group->Current--;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
Group->Current = Group->Max;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
void Send_volume(uint8_t vol)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint8_t mMasterSysExVolume[12] = { 0xF0, 0x41, 0x00, 0x42, 0x12, 0x40, 0x00, 0x04, 0x00, 0x00, 0x00,0xF7};
|
|
|
|
|
|
memset(mMasterSysExVolume+8,vol,1);
|
|
|
|
|
|
SendMidiDataToDreamDSP(mMasterSysExVolume,12);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-04 17:06:02 +08:00
|
|
|
|
void Accomp_UpdatePlayingChord(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint8_t midi_note_buff[4] = {0,};
|
|
|
|
|
|
uint8_t note_cnt = 0;
|
|
|
|
|
|
uint8_t i;
|
|
|
|
|
|
|
|
|
|
|
|
if (!StartFlag)
|
|
|
|
|
|
return;
|
|
|
|
|
|
if (KEY_ID_1629 == 0 || KEY_ID_1629 == 22 || KEY_ID_1629 == 23)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
note_cnt = GetChordNotesByType(KEY_ID_1629,
|
|
|
|
|
|
chord_type_index_map[KEY_ID_1629].type,
|
|
|
|
|
|
midi_note_buff);
|
|
|
|
|
|
for (i = 0; i < note_cnt; i++)
|
|
|
|
|
|
AutoBandTop1_Note_On(midi_note_buff[i], 0x50);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-26 07:26:58 +08:00
|
|
|
|
void ADC_IN1_KEY_Handle(uint8_t key,bool on)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint8_t midi_note_buff[4] = {0,};
|
|
|
|
|
|
uint8_t note_cnt = 0;
|
2026-09-04 17:06:02 +08:00
|
|
|
|
uint8_t is_preamble = 0;
|
2026-08-26 07:26:58 +08:00
|
|
|
|
key_toggle[key] = !key_toggle[key];
|
|
|
|
|
|
if(key_toggle[key] == 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
//ResetAutoPowerCount();
|
|
|
|
|
|
switch(key)
|
|
|
|
|
|
{
|
2026-09-04 17:06:02 +08:00
|
|
|
|
case 3: AutoBandTop1_Preamble(0); is_preamble = 1; break;
|
|
|
|
|
|
case 0: AutoBandTop1_Preamble(1); is_preamble = 1; break;
|
|
|
|
|
|
case 1: AutoBandTop1_Postamble(0); break;
|
|
|
|
|
|
case 2: AutoBandTop1_Postamble(1); break;
|
2026-08-26 07:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
//AutoBandTop1_Start();
|
|
|
|
|
|
AutoBandTop1_SyncStart();
|
|
|
|
|
|
wk_delay_ms(50);
|
2026-09-04 17:06:02 +08:00
|
|
|
|
/* 音师:前奏起始 = 当前调一级和弦第一把位(index 1 + maj,再经移调) */
|
|
|
|
|
|
if (is_preamble)
|
|
|
|
|
|
{
|
|
|
|
|
|
KEY_ID_1629 = 1;
|
|
|
|
|
|
chord_type_index_map[1].type = 0;
|
|
|
|
|
|
}
|
2026-08-26 07:26:58 +08:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Stop_AutoBand();
|
|
|
|
|
|
//StartFlag = 0;
|
|
|
|
|
|
//tick_ever_positive = false;
|
|
|
|
|
|
for(uint8_t i = 0;i < 4;i++) key_toggle[i] = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void TM1617_Handle(uint8_t key)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(mGuiData[GUI_TAB_INDEX].Current == 3)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint8_t value = 0;
|
|
|
|
|
|
switch(key)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0: value = 0; break;
|
|
|
|
|
|
case 1: value = 1; break;
|
|
|
|
|
|
case 2: value = 2; break;
|
|
|
|
|
|
case 3: value = 3; break;
|
|
|
|
|
|
}
|
|
|
|
|
|
mGuiData[GUI_PLAY_SECTION].Current = value;
|
|
|
|
|
|
//AutoBandTop1_SetRunVar(mGuiData[GUI_PLAY_SECTION].Current);
|
|
|
|
|
|
//Refresh_SectionSelect(last_value, &UI_Label[GUI_PLAY_SECTION], &mGuiData[GUI_PLAY_SECTION]);
|
|
|
|
|
|
//Draw_Tab_Section_Menu(&UI_Label[GUI_PLAY_SECTION], mGuiData[GUI_PLAY_SECTION].Current);
|
|
|
|
|
|
}else
|
|
|
|
|
|
{
|
|
|
|
|
|
switch(key)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0: MainTask_Sendmsg(MSG_ID_TOUCH, 1, 40, 255); break;
|
|
|
|
|
|
case 1: MainTask_Sendmsg(MSG_ID_TOUCH, 1, 90, 255); break;
|
|
|
|
|
|
case 2: MainTask_Sendmsg(MSG_ID_TOUCH, 1, 140, 255); break;
|
|
|
|
|
|
case 3: MainTask_Sendmsg(MSG_ID_TOUCH, 1, 200, 255); break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Tap_to_Speed()
|
|
|
|
|
|
{
|
|
|
|
|
|
#define TAP_MIN_BPM 40 // 鏈€灏忛€熷害
|
|
|
|
|
|
#define TAP_MAX_BPM 260 // 鏈€澶ч€熷害
|
|
|
|
|
|
#define TAP_TIMEOUT_MS 1000 // 2绉掓病鏁插氨澶嶄綅
|
|
|
|
|
|
|
|
|
|
|
|
static int32_t tap_last_time = 0; // 涓婃鎸夐敭鏃堕棿
|
|
|
|
|
|
static uint8_t tap_state = 0; // 0=绌洪棽 1=宸叉暡涓€娆?
|
|
|
|
|
|
static uint16_t ui_tap_tempo = 120; // 鏈€缁堥€熷害 40~260
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t now = rt_tick_get();
|
|
|
|
|
|
if (now - tap_last_time > TAP_TIMEOUT_MS) {
|
|
|
|
|
|
tap_state = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (tap_state == 0) {
|
|
|
|
|
|
tap_last_time = now;
|
|
|
|
|
|
tap_state = 1;
|
|
|
|
|
|
uint8_t AllNoteOff_buff[3] = {0x99,0x3C,0x50};
|
|
|
|
|
|
SendMidiDataToDreamDSP(AllNoteOff_buff,sizeof(AllNoteOff_buff));
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
uint32_t delta = now - tap_last_time;
|
|
|
|
|
|
if (delta >= 200 && delta <= 1500)
|
|
|
|
|
|
{
|
|
|
|
|
|
ui_tap_tempo = 60000 / delta;
|
|
|
|
|
|
if (ui_tap_tempo < TAP_MIN_BPM) ui_tap_tempo = TAP_MIN_BPM;
|
|
|
|
|
|
if (ui_tap_tempo > TAP_MAX_BPM) ui_tap_tempo = TAP_MAX_BPM;
|
|
|
|
|
|
MainTask_Sendmsg(MSG_ID_TAP_SPEED, ui_tap_tempo, 0, 0);
|
|
|
|
|
|
uint8_t AllNoteOff_buff[3] = {0x99,0x3C,0x50};
|
|
|
|
|
|
SendMidiDataToDreamDSP(AllNoteOff_buff,sizeof(AllNoteOff_buff));
|
|
|
|
|
|
}
|
|
|
|
|
|
tap_state = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Stop_AutoBand()
|
|
|
|
|
|
{
|
|
|
|
|
|
AutoBandTop1_Stop();
|
|
|
|
|
|
for(uint8_t i = 0;i < 16;i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint8_t AllNoteOff_buff[3] = {0xB0,0x7B,0x00};
|
|
|
|
|
|
SendMidiDataToDreamDSP(AllNoteOff_buff,sizeof(AllNoteOff_buff));
|
|
|
|
|
|
uint8_t AllControlOff_buff[3] = {0xB0,0x79,0x00};
|
|
|
|
|
|
SendMidiDataToDreamDSP(AllControlOff_buff,sizeof(AllControlOff_buff));
|
|
|
|
|
|
}
|
|
|
|
|
|
StartFlag = 0;
|
|
|
|
|
|
//tick_ever_positive = false;
|
|
|
|
|
|
for(uint8_t i = 0;i < 4;i++) key_toggle[i] = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t BP_Transpose(uint8_t key_idx)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(pick_hold_up)
|
|
|
|
|
|
{
|
|
|
|
|
|
/* 快速移调模式:按键只用于选择移调值,不切换和弦指型 */
|
|
|
|
|
|
uint8_t new_trans = 15;
|
|
|
|
|
|
switch(key_idx)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 2: new_trans = 0; break;
|
|
|
|
|
|
case 3: new_trans = 1; break;
|
|
|
|
|
|
case 5: new_trans = 2; break;
|
|
|
|
|
|
case 6: new_trans = 3; break;
|
|
|
|
|
|
case 8: new_trans = 4; break;
|
|
|
|
|
|
case 9: new_trans = 5; break;
|
|
|
|
|
|
case 11: new_trans = 5; break;
|
|
|
|
|
|
case 12: new_trans = 6; break;
|
|
|
|
|
|
case 14: new_trans = 7; break;
|
|
|
|
|
|
case 15: new_trans = 8; break;
|
|
|
|
|
|
case 17: new_trans = 9; break;
|
|
|
|
|
|
case 18: new_trans = 10; break;
|
|
|
|
|
|
case 20: new_trans = 11; break;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(new_trans != 15)
|
|
|
|
|
|
{
|
|
|
|
|
|
MainTask_Sendmsg(MSG_ID_BP_TRANSPOSE, new_trans, 0, 0);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void TM1629_Handle(uint8_t key)
|
|
|
|
|
|
{
|
|
|
|
|
|
STRING_MIDI *MIDI;
|
|
|
|
|
|
const STRING_MIDI *ORGAN_MIDI;
|
|
|
|
|
|
static uint8_t Last_Tm1926D_Key = 0;
|
|
|
|
|
|
if(BP_Transpose(key)) return;
|
|
|
|
|
|
|
|
|
|
|
|
switch(key)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
PressFlag = 0;
|
|
|
|
|
|
if(/*StartFlag &&*/ mGuiData[GUI_TAB_INDEX].Current == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
//StartFlag = 0;
|
|
|
|
|
|
//tick_ever_positive = false;
|
|
|
|
|
|
//osTimerStart(Delay_stop_timer,1000);
|
|
|
|
|
|
rt_timer_start(OutTime_Stop_timer);
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 22:Tap_to_Speed(); break;
|
|
|
|
|
|
case 23:Stop_AutoBand(); break;
|
|
|
|
|
|
default: // 1 - 21
|
|
|
|
|
|
if (key >= 1 && key <= 21)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(mGuiData[GUI_TAB_INDEX].Current == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
PressFlag = 1;
|
|
|
|
|
|
rt_timer_stop(OutTime_Stop_timer);
|
|
|
|
|
|
//osTimerStop(Delay_stop_timer);
|
|
|
|
|
|
}
|
|
|
|
|
|
uint8_t group = (key - 1) / 3; /* 1~3→0, 4~6→1, ..., 19~21→6 */
|
|
|
|
|
|
KEY_ID_1629 = key;
|
|
|
|
|
|
MIDI = (STRING_MIDI *)Chord_Midi_Table[group];
|
|
|
|
|
|
ORGAN_MIDI = OrganChord_Midi_Table[group];
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t type = chord_type_index_map[key].type;
|
|
|
|
|
|
switch(chord_type_index_map[key].PitchOffset)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
USE_MIDI.Midi_1 = ORGAN_MIDI[type].Midi_1;
|
|
|
|
|
|
USE_MIDI.Midi_2 = ORGAN_MIDI[type].Midi_2;
|
|
|
|
|
|
USE_MIDI.Midi_3 = ORGAN_MIDI[type].Midi_3;
|
|
|
|
|
|
USE_MIDI.Midi_4 = ORGAN_MIDI[type].Midi_4;
|
|
|
|
|
|
USE_MIDI.Midi_5 = ORGAN_MIDI[type].Midi_5;
|
|
|
|
|
|
USE_MIDI.Midi_6 = ORGAN_MIDI[type].Midi_6;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
USE_MIDI.Midi_1 = MIDI[type].Midi_1;
|
|
|
|
|
|
USE_MIDI.Midi_2 = MIDI[type].Midi_2;
|
|
|
|
|
|
USE_MIDI.Midi_3 = MIDI[type].Midi_3;
|
|
|
|
|
|
USE_MIDI.Midi_4 = MIDI[type].Midi_4;
|
|
|
|
|
|
USE_MIDI.Midi_5 = MIDI[type].Midi_5;
|
|
|
|
|
|
USE_MIDI.Midi_6 = MIDI[type].Midi_6;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
USE_MIDI.Midi_1 += mGuiData[GUI_TRANSPOSE].Current;
|
|
|
|
|
|
USE_MIDI.Midi_2 += mGuiData[GUI_TRANSPOSE].Current;
|
|
|
|
|
|
USE_MIDI.Midi_3 += mGuiData[GUI_TRANSPOSE].Current;
|
|
|
|
|
|
USE_MIDI.Midi_4 += mGuiData[GUI_TRANSPOSE].Current;
|
|
|
|
|
|
USE_MIDI.Midi_5 += mGuiData[GUI_TRANSPOSE].Current;
|
|
|
|
|
|
USE_MIDI.Midi_6 += mGuiData[GUI_TRANSPOSE].Current;
|
|
|
|
|
|
|
|
|
|
|
|
if(mGuiData[GUI_TAB_INDEX].Current == 1 && StartFlag && Last_Tm1926D_Key != KEY_ID_1629)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint8_t midi_note_buff[4] = {0,};
|
|
|
|
|
|
uint8_t note_cnt = 0;
|
|
|
|
|
|
Last_Tm1926D_Key = KEY_ID_1629;
|
|
|
|
|
|
//AutoBandTop1_SetPiecePlayMode(1,0,480);
|
|
|
|
|
|
//AutoBandTop1_StartWithNotes(midi_note_buff,GetChordNotesByType(KEY_ID_1629,chord_type_index_map[KEY_ID_1629].type,midi_note_buff));
|
|
|
|
|
|
//AutoBandTop1_SetLoopMode(0,1);
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Return_Light_buff(uint8_t key_id_1629)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint8_t buff[7] = {0xF0, 0x51, 0x04, 0x01, 0x01, 0x08, 0xF7};
|
|
|
|
|
|
switch(key_id_1629)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 1: case 2: case 3: buff[3] = 0x00;break;
|
|
|
|
|
|
case 4: case 5: case 6: buff[3] = 0x01;break;
|
|
|
|
|
|
case 7: case 8: case 9: buff[3] = 0x02;break;
|
|
|
|
|
|
case 10:case 11:case 12: buff[3] = 0x03;break;
|
|
|
|
|
|
case 13:case 14:case 15: buff[3] = 0x04;break;
|
|
|
|
|
|
case 16:case 17:case 18: buff[3] = 0x05;break;
|
|
|
|
|
|
case 19:case 20:case 21: buff[3] = 0x06;break;
|
|
|
|
|
|
}
|
|
|
|
|
|
switch(chord_type_index_map[key_id_1629].type)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0:buff[5] = 0; break;
|
|
|
|
|
|
case 1:buff[5] = 8; break;
|
|
|
|
|
|
case 2:buff[5] = 2; break;
|
|
|
|
|
|
case 3:buff[5] = 13;break;
|
|
|
|
|
|
case 4:buff[5] = 10;break;
|
|
|
|
|
|
case 5:buff[5] = 31;break;
|
|
|
|
|
|
case 6:buff[5] = 30;break;
|
|
|
|
|
|
case 7:buff[5] = 4; break;
|
|
|
|
|
|
case 8:buff[5] = 11;break;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(Led == buff[3])
|
|
|
|
|
|
USART4_SendData(buff,sizeof(buff));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Pick_Handle()
|
|
|
|
|
|
{
|
|
|
|
|
|
uint8_t midi = 0;
|
|
|
|
|
|
uint8_t midi_note_buff[4] = {0,};
|
2026-09-06 07:20:08 +08:00
|
|
|
|
uint8_t note_cnt = 0;
|
|
|
|
|
|
uint8_t chord_id = KEY_ID_1629;
|
|
|
|
|
|
|
|
|
|
|
|
/* 左手未触发和弦板(或落在拍速/停止键)时:拨片默认发当前调一级大和弦伴奏 */
|
|
|
|
|
|
if (chord_id == 0 || chord_id == 22 || chord_id == 23)
|
|
|
|
|
|
{
|
|
|
|
|
|
KEY_ID_1629 = 1;
|
|
|
|
|
|
chord_type_index_map[1].type = 0;
|
|
|
|
|
|
chord_id = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
note_cnt = GetChordNotesByType(chord_id, chord_type_index_map[chord_id].type, midi_note_buff);
|
2026-08-26 07:26:58 +08:00
|
|
|
|
Return_Light_buff(KEY_ID_1629);
|
|
|
|
|
|
|
|
|
|
|
|
switch(mGuiData[GUI_TAB_INDEX].Current)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
switch(mGuiData[GUI_TAB_LAST_INDEX].Current)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
if(StartFlag == 0)//当播放了之后,拨片不再起作用
|
|
|
|
|
|
{
|
|
|
|
|
|
StartFlag = 1;
|
|
|
|
|
|
AutoBandTop1_SetLoopMode(0,1);
|
|
|
|
|
|
midi = 0x3C + mGuiData[GUI_TRANSPOSE].Current;
|
|
|
|
|
|
AutoBandTop1_StartWithNote(midi);
|
2026-09-06 07:20:08 +08:00
|
|
|
|
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
2026-08-26 07:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
StartFlag = 1;
|
|
|
|
|
|
AutoBandTop1_SetPiecePlayMode(1,0,1920);
|
2026-09-06 07:20:08 +08:00
|
|
|
|
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
2026-08-26 07:26:58 +08:00
|
|
|
|
AutoBandTop1_SetLoopMode(0,1);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
if(PressFlag)
|
|
|
|
|
|
{
|
|
|
|
|
|
AutoBandTop1_SetLoopMode(0,1);
|
2026-09-06 07:20:08 +08:00
|
|
|
|
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
2026-08-26 07:26:58 +08:00
|
|
|
|
}else
|
|
|
|
|
|
{
|
|
|
|
|
|
AutoBandTop1_SetPiecePlayMode(1,0,480);
|
2026-09-06 07:20:08 +08:00
|
|
|
|
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
2026-08-26 07:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
StartFlag = 1;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 2:
|
2026-09-07 21:48:54 +08:00
|
|
|
|
/* 普通:节奏/本地曲目均用 StartWithNote;切库后允许再次拨片起奏 */
|
|
|
|
|
|
if (StartFlag == 0 || mGuiData[GUI_AUTOBAND_SW].Current)
|
2026-08-26 07:26:58 +08:00
|
|
|
|
{
|
|
|
|
|
|
StartFlag = 1;
|
2026-09-07 21:48:54 +08:00
|
|
|
|
AutoBandTop1_Stop();
|
2026-08-26 07:26:58 +08:00
|
|
|
|
AutoBandTop1_SetLoopMode(0,1);
|
2026-09-07 21:48:54 +08:00
|
|
|
|
AutoBandTop1_SetRunVar(mGuiData[GUI_PLAY_SECTION].Current);
|
|
|
|
|
|
/* 起调必须用 0x3C+移调;勿用和弦音区 MIDI(如 48),否则本地曲目起奏异常 */
|
2026-08-26 07:26:58 +08:00
|
|
|
|
midi = 0x3C + mGuiData[GUI_TRANSPOSE].Current;
|
|
|
|
|
|
AutoBandTop1_StartWithNote(midi);
|
2026-09-06 07:20:08 +08:00
|
|
|
|
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
2026-09-07 21:48:54 +08:00
|
|
|
|
if (mGuiData[GUI_AUTOBAND_SW].Current)
|
|
|
|
|
|
LOG_I("pick", "local/normal root=%u name=%s", midi,
|
|
|
|
|
|
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?");
|
2026-08-26 07:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
2026-09-06 07:20:08 +08:00
|
|
|
|
case 1:
|
2026-08-26 07:26:58 +08:00
|
|
|
|
StartFlag = 1;
|
2026-09-07 21:48:54 +08:00
|
|
|
|
if (mGuiData[GUI_AUTOBAND_SW].Current)
|
|
|
|
|
|
{
|
|
|
|
|
|
/* 本地曲目:与普通模式同一套起奏(0x3C 根音 + 和弦音) */
|
|
|
|
|
|
AutoBandTop1_Stop();
|
|
|
|
|
|
AutoBandTop1_SetLoopMode(0,1);
|
|
|
|
|
|
AutoBandTop1_SetRunVar(mGuiData[GUI_PLAY_SECTION].Current);
|
|
|
|
|
|
midi = 0x3C + mGuiData[GUI_TRANSPOSE].Current;
|
|
|
|
|
|
AutoBandTop1_StartWithNote(midi);
|
|
|
|
|
|
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
|
|
|
|
|
LOG_I("pick", "local/expert root=%u name=%s sw=%u tab=%u",
|
|
|
|
|
|
midi,
|
|
|
|
|
|
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?",
|
|
|
|
|
|
(unsigned)mGuiData[GUI_AUTOBAND_SW].Current,
|
|
|
|
|
|
(unsigned)mGuiData[GUI_TAB_INDEX].Current);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
AutoBandTop1_SetPiecePlayMode(1,0,1920);
|
|
|
|
|
|
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
|
|
|
|
|
AutoBandTop1_SetLoopMode(0,1);
|
|
|
|
|
|
LOG_I("pick", "expert/rhythm piece name=%s",
|
|
|
|
|
|
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?");
|
|
|
|
|
|
}
|
2026-08-26 07:26:58 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
StartFlag = 1;
|
|
|
|
|
|
if(PressFlag)
|
|
|
|
|
|
{
|
|
|
|
|
|
AutoBandTop1_SetPiecePlayMode(1,0,480);
|
2026-09-06 07:20:08 +08:00
|
|
|
|
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
2026-08-26 07:26:58 +08:00
|
|
|
|
AutoBandTop1_SetLoopMode(0,1);
|
|
|
|
|
|
}else
|
|
|
|
|
|
{
|
|
|
|
|
|
AutoBandTop1_SetPiecePlayMode(1,0,480);
|
2026-09-06 07:20:08 +08:00
|
|
|
|
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
|
2026-08-26 07:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Loop_Light_Handle(uint8_t measure)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch(ParamGuiData[ALL_MODE_PARAM].Current)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
switch(measure)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 1:app_tm1629_set_led(LED_L1, LED_COLOR_R);break;
|
|
|
|
|
|
case 2:app_tm1629_set_led(LED_L6, LED_COLOR_R);break;
|
|
|
|
|
|
case 3:app_tm1629_set_led(LED_L4, LED_COLOR_R);break;
|
|
|
|
|
|
case 4:app_tm1629_set_led(LED_L5, LED_COLOR_R);break;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
switch(measure)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 1:app_tm1629_set_led(LED_L1, LED_COLOR_R);break;
|
|
|
|
|
|
case 2:app_tm1629_set_led(LED_L5, LED_COLOR_R);break;
|
|
|
|
|
|
case 3:app_tm1629_set_led(LED_L6, LED_COLOR_R);break;
|
|
|
|
|
|
case 4:app_tm1629_set_led(LED_L4, LED_COLOR_R);break;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
switch(measure)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 1:app_tm1629_set_led(LED_L1, LED_COLOR_R);break;
|
|
|
|
|
|
case 2:app_tm1629_set_led(LED_L3, LED_COLOR_R);break;
|
|
|
|
|
|
case 3:app_tm1629_set_led(LED_L6, LED_COLOR_R);break;
|
|
|
|
|
|
case 4:app_tm1629_set_led(LED_L4, LED_COLOR_R);break;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BL_Set_led(uint8_t led, uint8_t chord_type)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint8_t chord_offset;
|
|
|
|
|
|
Led = led;
|
|
|
|
|
|
switch(chord_type){
|
|
|
|
|
|
case 0x00:
|
|
|
|
|
|
chord_offset = 0;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x08:
|
|
|
|
|
|
chord_offset = 1;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x02:
|
|
|
|
|
|
chord_offset = 4;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x13:
|
|
|
|
|
|
chord_offset = 3;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x0A: //A
|
|
|
|
|
|
chord_offset = 2;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x1F: //1F
|
|
|
|
|
|
chord_offset = 7;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x1E: //1E
|
|
|
|
|
|
chord_offset = 8;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x04:
|
|
|
|
|
|
chord_offset = 5;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x0B: //B
|
|
|
|
|
|
chord_offset = 6;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch(led){
|
|
|
|
|
|
case LED_L1:
|
|
|
|
|
|
app_tm1629_set_led(LED_L1, LED_COLOR_R);
|
|
|
|
|
|
chord_type_index_map[2].type = chord_offset;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LED_L2:
|
|
|
|
|
|
app_tm1629_set_led(LED_L2, LED_COLOR_G);
|
|
|
|
|
|
chord_type_index_map[5].type = chord_offset;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LED_L3:
|
|
|
|
|
|
app_tm1629_set_led(LED_L3, LED_COLOR_B);
|
|
|
|
|
|
chord_type_index_map[8].type = chord_offset;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LED_L4:
|
|
|
|
|
|
app_tm1629_set_led(LED_L4, LED_COLOR_YELL);
|
|
|
|
|
|
chord_type_index_map[11].type = chord_offset;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LED_L5:
|
|
|
|
|
|
app_tm1629_set_led(LED_L5, LED_COLOR_PURP);
|
|
|
|
|
|
chord_type_index_map[14].type = chord_offset;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LED_L6:
|
|
|
|
|
|
app_tm1629_set_led(LED_L6, LED_COLOR_CYA);
|
|
|
|
|
|
chord_type_index_map[17].type = chord_offset;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case LED_L7:
|
|
|
|
|
|
app_tm1629_set_led(LED_L7, LED_COLOR_WHITE);
|
|
|
|
|
|
chord_type_index_map[20].type = chord_offset;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
// 鏈煡鐏彿锛屽叏閮ㄥ叧闂?
|
|
|
|
|
|
app_tm1629_all_off();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BT_Pitch_offset_map(uint8_t pos_offset,uint8_t pitch_offset)
|
|
|
|
|
|
{
|
|
|
|
|
|
//char Info[10];
|
|
|
|
|
|
//sprintf (Info, "%d %d", pos_offset,pitch_offset);
|
|
|
|
|
|
//LCD_ShowString(2, 156+16, (const uint8_t*)Info, RED, WHITE, 16, 0);
|
|
|
|
|
|
chord_type_index_map[pos_offset].PitchOffset = pitch_offset;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void BT_Chord_offset_map(uint8_t pos_offset,uint8_t chord_offset)
|
|
|
|
|
|
{
|
|
|
|
|
|
//char Info[20];
|
|
|
|
|
|
STRING_MIDI *MIDI;
|
|
|
|
|
|
const STRING_MIDI *ORGAN_MIDI;
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t group = (pos_offset - 1) / 3; /* 1~3→0, 4~6→1, ..., 19~21→6 */
|
|
|
|
|
|
uint8_t chord_APP_Local_offset = 0;
|
|
|
|
|
|
|
|
|
|
|
|
switch(chord_offset){
|
|
|
|
|
|
case 0x00:
|
|
|
|
|
|
chord_APP_Local_offset = 0;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x08:
|
|
|
|
|
|
chord_APP_Local_offset = 1;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x02:
|
|
|
|
|
|
chord_APP_Local_offset = 4;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x13:
|
|
|
|
|
|
chord_APP_Local_offset = 3;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x0A: //A
|
|
|
|
|
|
chord_APP_Local_offset = 2;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x1F: //1F
|
|
|
|
|
|
chord_APP_Local_offset = 7;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x1E: //1E
|
|
|
|
|
|
chord_APP_Local_offset = 8;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x04:
|
|
|
|
|
|
chord_APP_Local_offset = 5;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x0B: //B
|
|
|
|
|
|
chord_APP_Local_offset = 6;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//sprintf (Info, "%d %d %d %d", chord_offset,chord_APP_Local_offset,pos_offset,chord_type_index_map[pos_offset].PitchOffset);
|
|
|
|
|
|
//LCD_ShowString(2, 176+16, (const uint8_t*)Info, RED, WHITE, 16, 0);
|
|
|
|
|
|
chord_type_index_map[pos_offset].type = chord_APP_Local_offset;
|
|
|
|
|
|
|
|
|
|
|
|
MIDI = (STRING_MIDI *)Chord_Midi_Table[group];
|
|
|
|
|
|
ORGAN_MIDI = OrganChord_Midi_Table[group];
|
|
|
|
|
|
|
|
|
|
|
|
switch(chord_type_index_map[pos_offset].PitchOffset){
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
MIDI->Midi_1 = ORGAN_MIDI->Midi_1;
|
|
|
|
|
|
MIDI->Midi_2 = ORGAN_MIDI->Midi_2;
|
|
|
|
|
|
MIDI->Midi_3 = ORGAN_MIDI->Midi_3;
|
|
|
|
|
|
MIDI->Midi_4 = ORGAN_MIDI->Midi_4;
|
|
|
|
|
|
MIDI->Midi_5 = ORGAN_MIDI->Midi_5;
|
|
|
|
|
|
MIDI->Midi_6 = ORGAN_MIDI->Midi_6;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
MIDI->Midi_1 = ORGAN_MIDI->Midi_1 + 1;
|
|
|
|
|
|
MIDI->Midi_2 = ORGAN_MIDI->Midi_2 + 1;
|
|
|
|
|
|
MIDI->Midi_3 = ORGAN_MIDI->Midi_3 + 1;
|
|
|
|
|
|
MIDI->Midi_4 = ORGAN_MIDI->Midi_4 + 1;
|
|
|
|
|
|
MIDI->Midi_5 = ORGAN_MIDI->Midi_5 + 1;
|
|
|
|
|
|
MIDI->Midi_6 = ORGAN_MIDI->Midi_6 + 1;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t GetChordNotesByType(uint8_t MIDI_Index,uint8_t type,uint8_t *buff)
|
|
|
|
|
|
{
|
2026-09-04 17:06:02 +08:00
|
|
|
|
uint8_t n = 0;
|
|
|
|
|
|
uint8_t i;
|
|
|
|
|
|
uint8_t root;
|
|
|
|
|
|
|
|
|
|
|
|
buff[0] = buff[1] = buff[2] = buff[3] = 0;
|
2026-08-26 07:26:58 +08:00
|
|
|
|
switch(MIDI_Index)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 1:case 2:case 3:
|
|
|
|
|
|
switch(type)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
buff[0] = 48;buff[1] = 52;buff[2] = 55;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
buff[0] = 48;buff[1] = 51;buff[2] = 55;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
buff[0] = 48;buff[1] = 51;buff[2] = 55;buff[3] = 58;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
buff[0] = 48;buff[1] = 52;buff[2] = 55;buff[3] = 58;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 4:
|
|
|
|
|
|
buff[0] = 48;buff[1] = 52;buff[2] = 55;buff[3] = 59;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 5:
|
|
|
|
|
|
buff[0] = 48;buff[1] = 52;buff[2] = 55;buff[3] = 62;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 6:
|
|
|
|
|
|
buff[0] = 48;buff[1] = 51;buff[2] = 54;buff[3] = 58;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 7:
|
|
|
|
|
|
buff[0] = 48;buff[1] = 50;buff[2] = 55;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 8:
|
|
|
|
|
|
buff[0] = 48;buff[1] = 53;buff[2] = 55;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 4:case 5:case 6:
|
|
|
|
|
|
switch(type)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
buff[0] = 50;buff[1] = 54;buff[2] = 57;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
buff[0] = 50;buff[1] = 53;buff[2] = 57;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
buff[0] = 50;buff[1] = 53;buff[2] = 57;buff[3] = 60;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
buff[0] = 50;buff[1] = 54;buff[2] = 57;buff[3] = 60;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 4:
|
|
|
|
|
|
buff[0] = 50;buff[1] = 54;buff[2] = 57;buff[3] = 61;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 5:
|
|
|
|
|
|
buff[0] = 50;buff[1] = 54;buff[2] = 57;buff[3] = 64;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 6:
|
|
|
|
|
|
buff[0] = 50;buff[1] = 53;buff[2] = 56;buff[3] = 60;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 7:
|
|
|
|
|
|
buff[0] = 50;buff[1] = 52;buff[2] = 57;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 8:
|
|
|
|
|
|
buff[0] = 50;buff[1] = 55;buff[2] = 57;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 7:case 8:case 9:
|
|
|
|
|
|
switch(type)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
buff[0] = 52;buff[1] = 56;buff[2] = 59;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
buff[0] = 52;buff[1] = 55;buff[2] = 59;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
buff[0] = 52;buff[1] = 55;buff[2] = 59;buff[3] = 62;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
buff[0] = 52;buff[1] = 56;buff[2] = 59;buff[3] = 62;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 4:
|
|
|
|
|
|
buff[0] = 52;buff[1] = 56;buff[2] = 59;buff[3] = 63;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 5:
|
|
|
|
|
|
buff[0] = 52;buff[1] = 56;buff[2] = 59;buff[3] = 66;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 6:
|
|
|
|
|
|
buff[0] = 52;buff[1] = 55;buff[2] = 58;buff[3] = 62;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 7:
|
|
|
|
|
|
buff[0] = 52;buff[1] = 54;buff[2] = 59;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 8:
|
|
|
|
|
|
buff[0] = 52;buff[1] = 57;buff[2] = 59;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 10:case 11:case 12:
|
|
|
|
|
|
switch(type)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
buff[0] = 53;buff[1] = 57;buff[2] = 60;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
buff[0] = 53;buff[1] = 56;buff[2] = 60;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
buff[0] = 53;buff[1] = 56;buff[2] = 60;buff[3] = 63;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
buff[0] = 53;buff[1] = 57;buff[2] = 60;buff[3] = 63;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 4:
|
|
|
|
|
|
buff[0] = 53;buff[1] = 57;buff[2] = 60;buff[3] = 64;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 5:
|
|
|
|
|
|
buff[0] = 53;buff[1] = 57;buff[2] = 60;buff[3] = 67;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 6:
|
|
|
|
|
|
buff[0] = 53;buff[1] = 56;buff[2] = 59;buff[3] = 63;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 7:
|
|
|
|
|
|
buff[0] = 53;buff[1] = 55;buff[2] = 60;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 8:
|
|
|
|
|
|
buff[0] = 53;buff[1] = 58;buff[2] = 60;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 13:case 14:case 15:
|
|
|
|
|
|
switch(type)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
buff[0] = 43;buff[1] = 47;buff[2] = 50;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
buff[0] = 43;buff[1] = 46;buff[2] = 50;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
buff[0] = 43;buff[1] = 46;buff[2] = 50;buff[3] = 53;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
buff[0] = 43;buff[1] = 47;buff[2] = 50;buff[3] = 53;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 4:
|
|
|
|
|
|
buff[0] = 43;buff[1] = 47;buff[2] = 50;buff[3] = 54;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 5:
|
|
|
|
|
|
buff[0] = 43;buff[1] = 47;buff[2] = 50;buff[3] = 57;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 6:
|
|
|
|
|
|
buff[0] = 43;buff[1] = 46;buff[2] = 49;buff[3] = 53;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 7:
|
|
|
|
|
|
buff[0] = 43;buff[1] = 45;buff[2] = 50;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 8:
|
|
|
|
|
|
buff[0] = 43;buff[1] = 48;buff[2] = 50;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 16:case 17:case 18:
|
|
|
|
|
|
switch(type)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
buff[0] = 45;buff[1] = 49;buff[2] = 52;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
buff[0] = 45;buff[1] = 48;buff[2] = 52;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
buff[0] = 45;buff[1] = 48;buff[2] = 52;buff[3] = 55;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
buff[0] = 45;buff[1] = 49;buff[2] = 52;buff[3] = 55;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 4:
|
|
|
|
|
|
buff[0] = 45;buff[1] = 49;buff[2] = 52;buff[3] = 56;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 5:
|
|
|
|
|
|
buff[0] = 45;buff[1] = 49;buff[2] = 52;buff[3] = 59;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 6:
|
|
|
|
|
|
buff[0] = 45;buff[1] = 48;buff[2] = 51;buff[3] = 55;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 7:
|
|
|
|
|
|
buff[0] = 45;buff[1] = 47;buff[2] = 52;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 8:
|
|
|
|
|
|
buff[0] = 45;buff[1] = 50;buff[2] = 52;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 19:case 20:case 21:
|
|
|
|
|
|
switch(type)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
buff[0] = 47;buff[1] = 51;buff[2] = 53;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
buff[0] = 47;buff[1] = 50;buff[2] = 54;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
buff[0] = 47;buff[1] = 50;buff[2] = 54;buff[3] = 57;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
buff[0] = 47;buff[1] = 50;buff[2] = 53;buff[3] = 57;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 4:
|
|
|
|
|
|
buff[0] = 47;buff[1] = 51;buff[2] = 53;buff[3] = 57;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 5:
|
|
|
|
|
|
buff[0] = 47;buff[1] = 51;buff[2] = 54;buff[3] = 58;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 6:
|
|
|
|
|
|
buff[0] = 47;buff[1] = 51;buff[2] = 54;buff[3] = 60;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 7:
|
|
|
|
|
|
buff[0] = 47;buff[1] = 49;buff[2] = 54;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 8:
|
|
|
|
|
|
buff[0] = 47;buff[1] = 52;buff[2] = 54;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 9:
|
|
|
|
|
|
buff[0] = 47;buff[1] = 50;buff[2] = 53;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
2026-09-04 17:06:02 +08:00
|
|
|
|
default:
|
|
|
|
|
|
return 0;
|
2026-08-26 07:26:58 +08:00
|
|
|
|
}
|
2026-09-04 17:06:02 +08:00
|
|
|
|
|
|
|
|
|
|
n = (buff[3] != 0) ? 4 : 3;
|
|
|
|
|
|
switch (chord_type_index_map[MIDI_Index].PitchOffset)
|
2026-08-26 07:26:58 +08:00
|
|
|
|
{
|
2026-09-04 17:06:02 +08:00
|
|
|
|
case 2: /* # 升:整体 +1 半音 */
|
|
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
|
|
buff[i] += 1;
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
|
|
buff[i] += mGuiData[GUI_TRANSPOSE].Current;
|
|
|
|
|
|
|
2026-09-07 09:28:35 +08:00
|
|
|
|
/* 音师:仅所有调的 #四级(键 10~12 + 升)— 整组低八度,音域压在一个八度内
|
|
|
|
|
|
* 最低音 = #IV,最高音 ≤ 自然 IV。勿对六级等其它升号和弦套用。 */
|
|
|
|
|
|
if (MIDI_Index >= 10 && MIDI_Index <= 12 &&
|
|
|
|
|
|
chord_type_index_map[MIDI_Index].PitchOffset == 2)
|
2026-08-26 07:26:58 +08:00
|
|
|
|
{
|
2026-09-04 17:06:02 +08:00
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (buff[i] >= 12)
|
|
|
|
|
|
buff[i] -= 12;
|
|
|
|
|
|
}
|
|
|
|
|
|
root = buff[0];
|
|
|
|
|
|
for (i = 1; i < n; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
while (buff[i] >= (uint8_t)(root + 12))
|
|
|
|
|
|
buff[i] -= 12;
|
|
|
|
|
|
while (buff[i] < root)
|
|
|
|
|
|
buff[i] += 12;
|
|
|
|
|
|
}
|
2026-08-26 07:26:58 +08:00
|
|
|
|
}
|
2026-09-04 17:06:02 +08:00
|
|
|
|
return n;
|
2026-08-26 07:26:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Read_Cur_Measure()
|
|
|
|
|
|
{
|
|
|
|
|
|
uint32_t now = rt_tick_get();
|
2026-09-06 08:41:30 +08:00
|
|
|
|
static uint32_t last_tick_i = 0;
|
|
|
|
|
|
uint8_t tab = (uint8_t)mGuiData[GUI_TAB_INDEX].Current;
|
|
|
|
|
|
uint8_t last = (uint8_t)mGuiData[GUI_TAB_LAST_INDEX].Current;
|
|
|
|
|
|
/* 普通(2)与万能(0)均按「和弦走向」同步亮灯;设置页(3)沿用进入前模式 */
|
|
|
|
|
|
uint8_t loop_light_ok =
|
|
|
|
|
|
(tab == 0 || tab == 2) ||
|
|
|
|
|
|
(tab == 3 && (last == 0 || last == 2));
|
|
|
|
|
|
|
|
|
|
|
|
if (loop_light_ok && StartFlag)
|
2026-08-26 07:26:58 +08:00
|
|
|
|
{
|
|
|
|
|
|
if(now - last_tick_i >= 10)
|
|
|
|
|
|
{
|
|
|
|
|
|
last_tick_i = now;
|
|
|
|
|
|
uint8_t Measure = AutoBandTop1_GetCurrentRunMeasure();
|
|
|
|
|
|
MainTask_Sendmsg(MSG_ID_LOOP_LIGHT, Measure, 0, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|