K1Guitar/Global/Global.c

1287 lines
41 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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\xD2\xE9", 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\xD2\xE9",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,1}; /* major.minor.patch — 0.2.1: keep mixer/master vol across power cycle */
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);
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();
LOG_I("PWR", "periph ready");
}
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);
}
}
}
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:
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:
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;
/* 音师:所有调的 #四级 — 整组和弦低八度,音域压在一个八度内 */
if (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);
}
}
}