K1Guitar/Global/Global.c

1336 lines
43 KiB
C
Raw Normal View History

#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[] =
{
{ 0, 0, 30, SONG_MODE_PARAM}, // 0 节奏类型1.bin约 31 首)
{ 0, 0, 0, EXPRESS_MODE_PARAM}, // 1 本地曲目2.binMax 由 UI_ReloadTonePreset←LOCAL_SONG_COUNT
{ 0, 0, 2, ALL_MODE_PARAM}, // 2
};
const LEBEL_UI UI_Label[] = {
/* 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},
/* 0819TAB/行标题11、曲目正文13 */
{UI0902_MARGIN_X, UI0902_CONTENT_W, UI0902_MODE_Y, UI0902_MODE_H,
(const uint8_t*)"\xB8\xE8\xC7\xFA\xD1\xA1\xD4\xF1", LCD_ALIGN_LEFT,WHITE,BLACK,UI0902_FONT_LABEL,
LCD_ALIGN_CENTER,WHITE,BLACK,UI0902_FONT_BODY,GUI_MODE_PARAM},
{UI0902_MARGIN_X, UI0902_CONTENT_W, UI0902_TIMBRE_Y, UI0902_TIMBRE_H,
(const uint8_t*)"\xCF\xD2\xD2\xF4\xC9\xAB\xD1\xA1\xD4\xF1",LCD_ALIGN_LEFT,WHITE,BLACK,UI0902_FONT_LABEL,
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},
};
/* 0904 / 0902-06左→右 伴奏|弦|麦|麦混响轨宽31 顶≈58 */
Fader_t faders[4] = {
{ 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: 麦混响 */
};
const Touch_AreaTypeDef Touch_Areas[] =
{
/* Xmin,Xmax,Ymin,Ymax, Flag, Value, ID, action — 与 UI_Label 网格同步 */
{ 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 },
{ 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 },
/* 节奏类型 / 本地曲目 TAB090212-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 },
{ 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 },
{ 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 },
/* 演奏段落 1~40902-0412/69/125/182宽 47步进 57 */
{ 12, 58, UI0902_SECTION_Y, UI0902_SECTION_Y + UI0902_SECTION_BTN_H - 1, 0, 0, GUI_PLAY_SECTION, NULL },
{ 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 },
/* 底栏四键:万能 | 普通 | 专业 | 设置(触区中线对齐 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 },
};
/* 推子 0~10 共 11 档档10 取 AW816 上限附近 */
int16_t MIC_VOL_MAP[11]= {-9000,-7000,-5000,-3000,-1000,1000,3000,5000,7000,9000,1200};
uint8_t TOUCH_AREA_NUM = (sizeof(Touch_Areas)/sizeof(Touch_AreaTypeDef));
const uint8_t Version[3] = {0,2,6}; /* major.minor.patch — 0.2.6: local song 2.bin from Doc/音色文件/0908/2ss_2.bin */
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;
rt_err_t ret;
msg.MessageType = ID; /* 业务消息 IDMSG_ID_xxx */
msg.ID = ID2;
msg.HiByte = HiByte;
msg.LoByte = LoByte;
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);
}
}
void UITask_Sendmsg(uint16_t ID, uint16_t ID2, uint16_t HiByte, uint16_t LoByte)
{
DisplayTaskMessage_Type msg;
msg.MessageType = ID; /* 业务消息 IDMSG_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; /* 业务消息 IDMSG_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;
/* ==================== 开机/关机动作 ==================== */
void System_PowerOn(void)
{
LOG_I("PWR", "power_on begin");
/* 控制电源硬件;蓝牙按 NVM/系统设置开关恢复,勿强制常开 */
BSP_MainPowerEnable(1);
BSP_DreamCorePowerEnable(1);
BSP_HT7178PowerEnable(1);
/* 蓝牙按 NVM/系统设置开关恢复,勿强制常开 */
BSP_BlueToothPowerEnable((uint8_t)(mGuiData[GUI_BL_SW].Current ? 1 : 0));
powon = true; /* 更新开机标志 */
/* 先通知 UI 亮屏,避免外设初始化阻塞导致长时间黑屏 */
LOG_I("PWR", "send POWER_ON");
MainTask_Sendmsg(MSG_ID_POWER_ON, 0, 0, 0);
AD85020B_Init();
TM1629D_Key_LED_Init();
app_tm1617_init();
XPT2046_Init();
App_Auto_Init();
/* App 协议走 UART4须在开机后即解析不能等到触摸选模式才 StartTask */
StartTask();
LOG_I("PWR", "periph ready + BT UART recv started");
}
static void PowerOn(void)
{
System_PowerOn();
}
static void PowerOff(void)
{
uint8_t nvm_ret;
LOG_I("PWR", "power_off begin");
powon = false; /* 更新关机标志 */
StopFullTask();
/* 关机前把当前调音台推子与蓝牙开关写入 NVM保证再次开机保持 */
{
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;
nvm->param.BluetoothSW = (uint8_t)(mGuiData[GUI_BL_SW].Current ? 1 : 0);
}
nvm_ret = drv_nvm_save_to_flash();
LOG_I("PWR", "nvm_save=%u", (unsigned)nvm_ret);
LCD_FillByColor(0, 0, 240, 320, BLACK);
LCD_BLK_Clr();
app_tm1629_all_off();
app_tm1617_off();
/* 关闭电源硬件MCU 保持运行以便长按开机 / 关机充电画面 */
BSP_MainPowerEnable(0);
BSP_DreamCorePowerEnable(0);
BSP_HT7178PowerEnable(0);
BSP_BlueToothPowerEnable(0);
CurrUIProcress = IdleProcess;
MainTask_Sendmsg(MSG_ID_POWER_OFF, 0, 0, 0);
LOG_I("PWR", "power_off done (soft-off, no reset)");
/* 关机时若已插着 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);
}
}
}
/* App remote power-off request (BLE cmd 05 00): executed in main-loop context,
so StopFullTask() never detaches the calling BT thread itself. */
static volatile uint8_t s_sys_poweroff_req = 0;
void System_RequestPowerOff(void)
{
s_sys_poweroff_req = 1;
}
void System_PowerOff_Poll(void)
{
if (s_sys_poweroff_req)
{
s_sys_poweroff_req = 0;
if (powon)
PowerOff();
}
}
void Power_Key_Scan()
{
flag_status status = BSP_GetPowerKey();
uint32_t now = rt_tick_get();
uint32_t holdtick = 0;
/* 复位/烧录后:无 USB 则自动开机一次;有 Type-C 则进关机充电画面(勿进 Logo */
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)
{
uint8_t i;
s_auto_poweron_pending = 0;
/* 多采几次 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;
}
LOG_I("PWR", "auto power_on");
PowerOn();
pwr_key_state = KEY_STATE_NONE; /* 忽略开机瞬间可能残留的按键电平 */
return;
}
}
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)
{
LOG_I("PWR", "key power_on hold=%u", (unsigned)holdtick);
PowerOn();
pwr_key_state = KEY_STATE_NONE;
}
else if(powon == true && holdtick >= PWR_OFF_HOLD_MS)
{
LOG_I("PWR", "key power_off hold=%u", (unsigned)holdtick);
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 公共全局变量 */
volatile uint32_t ADDRESS = FLASH_ADDR_MODE_UNIVERSAL;
uint8_t KEY_ID_1629 = 0;
bool StartFlag = false;
bool InModeFlag = false;
uint8_t key_toggle[4] = {0};
/* ============================================================
* UI
* ============================================================ */
/* 自动关机:有操作时复位秒计数;主循环每秒递减,到 0 关机 */
void ResetAutoPowerCount(void)
{
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();
}
}
/* 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);
}
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);
}
void ADC_IN1_KEY_Handle(uint8_t key,bool on)
{
uint8_t midi_note_buff[4] = {0,};
uint8_t note_cnt = 0;
uint8_t is_preamble = 0;
key_toggle[key] = !key_toggle[key];
if(key_toggle[key] == 1)
{
//ResetAutoPowerCount();
switch(key)
{
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;
}
//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);
}
}
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,};
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);
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);
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
}
break;
case 1:
StartFlag = 1;
AutoBandTop1_SetPiecePlayMode(1,0,1920);
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
AutoBandTop1_SetLoopMode(0,1);
break;
case 0:
if(PressFlag)
{
AutoBandTop1_SetLoopMode(0,1);
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
}else
{
AutoBandTop1_SetPiecePlayMode(1,0,480);
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
}
StartFlag = 1;
break;
}
break;
case 2:
/* 普通:节奏/本地曲目均用 StartWithNote切库后允许再次拨片起奏 */
if (StartFlag == 0 || mGuiData[GUI_AUTOBAND_SW].Current)
{
StartFlag = 1;
AutoBandTop1_Stop();
AutoBandTop1_SetLoopMode(0,1);
AutoBandTop1_SetRunVar(mGuiData[GUI_PLAY_SECTION].Current);
/* 起调必须用 0x3C+移调;勿用和弦音区 MIDI如 48否则本地曲目起奏异常 */
midi = 0x3C + mGuiData[GUI_TRANSPOSE].Current;
AutoBandTop1_StartWithNote(midi);
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
if (mGuiData[GUI_AUTOBAND_SW].Current)
LOG_I("pick", "local/normal root=%u name=%s", midi,
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "?");
}
break;
case 1:
StartFlag = 1;
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() : "?");
}
break;
case 0:
StartFlag = 1;
if(PressFlag)
{
AutoBandTop1_SetPiecePlayMode(1,0,480);
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
AutoBandTop1_SetLoopMode(0,1);
}else
{
AutoBandTop1_SetPiecePlayMode(1,0,480);
AutoBandTop1_StartWithNotes(midi_note_buff, note_cnt);
}
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)
{
uint8_t n = 0;
uint8_t i;
uint8_t root;
buff[0] = buff[1] = buff[2] = buff[3] = 0;
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;
default:
return 0;
}
n = (buff[3] != 0) ? 4 : 3;
switch (chord_type_index_map[MIDI_Index].PitchOffset)
{
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;
/* 音师:仅所有调的 #四级(键 10~12 + 升)— 整组低八度,音域压在一个八度内
* = #IV IV */
if (MIDI_Index >= 10 && MIDI_Index <= 12 &&
chord_type_index_map[MIDI_Index].PitchOffset == 2)
{
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;
}
}
return n;
}
void Read_Cur_Measure()
{
uint32_t now = rt_tick_get();
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)
{
if(now - last_tick_i >= 10)
{
last_tick_i = now;
uint8_t Measure = AutoBandTop1_GetCurrentRunMeasure();
MainTask_Sendmsg(MSG_ID_LOOP_LIGHT, Measure, 0, 0);
}
}
}