K1Guitar/UI/UI_Mixer.c

347 lines
12 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"
extern const Touch_AreaTypeDef *pCurrentTouch_Area;
static int8_t s_mixer_focus = -1;
// ==================== <20><>ť<EFBFBD><C5A5><EFBFBD><EFBFBD> ====================
#define BTN_Y 275 // <20><>ť<EFBFBD><C5A5>ʼY
#define BTN_H 40 // <20><>ť<EFBFBD>߶<EFBFBD>
#define BTN_W 105 // <20><>ť<EFBFBD><C5A5><EFBFBD>
#define BTN_G 5 // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ť<EFBFBD>м<EFBFBD><D0BC><EFBFBD>
// ==================== <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ====================
const Touch_AreaTypeDef Touch_Btn[] = {
{ 0, 50, 0, 50, 0, 0, 0, NULL },
};
#define TOUCH_BTN_NUM (sizeof(Touch_Btn)/sizeof(Touch_AreaTypeDef))
// ============================================================
// 完整绘制推子(首次初始化 / 页面切换时调用)
// ============================================================
void DrawFader(Fader_t *f)
{
uint16_t x = f->x, y = f->y, w = f->w, h = f->h;
// 清除整个推子区域
LCD_FillByColor(x - 10, y, x + w + 10, y + h, BLACK);
// 绘制完整槽背景
DrawFaderGrooveAt(f, y + 5, y + 5 + h);
// 刻度线
for (int i = 0; i < 10; i++) {
uint16_t tick_y = y + 7 + (h * i) / 10;
LCD_DrawLine(x + w / 2 - 3, tick_y, x + w / 2 + 3, tick_y, FADER_TEXT);
}
// 底部文字
LCD_ShowChinese_AutoAlign(x + 10, x + (w / 2) - 8, y + h + 20,
(uint8_t*)f->name, LCD_ALIGN_CENTER, FADER_TEXT, BLACK, 0, 12);
// 画滑块并记录位置
uint16_t slider_y = CalcSliderY(f);
DrawFaderSlider(f, slider_y);
f->prev_slider_y = slider_y;
}
void DrawAllFaders(void)
{
NvmParam_Type * nvm = drv_nvm_param_ptr();
// 鍏堟竻鏁翠釜鎺ㄥ瓙鍖哄煙锛屽交搴曟秷闄ゆ畫锟?
//LCD_FillByColor(0, 35, 240, 320, BLACK);
for (int i = 0; i < 4; i++) {
DrawFader(&faders[i]);
}
if(nvm->param.BandVol != faders[0].val)
{
nvm->param.BandVol = faders[0].val;
}
if(nvm->param.StringVol != faders[1].val)
{
nvm->param.StringVol = faders[1].val;
}
if(nvm->param.MIcVol != faders[2].val)
{
nvm->param.MIcVol = faders[2].val;
}
if(nvm->param.MicRev != faders[3].val)
{
nvm->param.MicRev = faders[3].val;
}
drv_nvm_save_to_flash();
}
// ============================================================
// 绘制推子槽背景局部区域y_start ~ y_end 范围)
// RED/CYAN 用 FillRoundRect_Solid 自带圆角
// GREEN 覆盖 RED 底部圆角YELLOW 覆盖 CYAN 顶部圆角
// ============================================================
static void DrawFaderGrooveAt(Fader_t *f, uint16_t y_start, uint16_t y_end)
{
if (y_start >= y_end) return;
uint16_t x = f->x, y = f->y, w = f->w, h = f->h;
uint16_t groove_top = y + 5;
uint16_t groove_bot = y + 5 + h;
const uint16_t r = 15;
// 裁剪到槽边界
if (y_start < groove_top) y_start = groove_top;
if (y_end > groove_bot) y_end = groove_bot;
if (y_start >= y_end) return;
// 1. 灰色底色(纯矩形)
LCD_FillByColor(x, y_start, x + w, y_end, BLACK);
// 2. 青色段 — FillRoundRect_Solid 自带底部圆角
{ uint16_t s = groove_top + 100, e = groove_top + h;
if (y_start < e && y_end > s) {
FillRoundRect_Solid(x, s, w, e - s, r, 0x3fAE);
} }
// 3. 黄色段 — 纯矩形,覆盖青色顶部圆角
{ uint16_t s = groove_top + 100 - 33, e = groove_top + 100 + 16;
if (y_start < e && y_end > s) {
uint16_t ys = y_start > s ? y_start : s;
uint16_t ye = y_end < e ? y_end : e;
LCD_FillByColor(x, ys, x + w, ye, YELLOW);
} }
// 4. 红色段 — FillRoundRect_Solid 自带顶部圆角
{ uint16_t s = groove_top, e = groove_top + 49;
if (y_start < e && y_end > s) {
FillRoundRect_Solid(x, s, w, e - s, r, RED);
} }
// 5. 绿色段 — 纯矩形,覆盖红色底部圆角
{ uint16_t s = groove_top + 100 - 66, e = groove_top + 100 - 32;
if (y_start < e && y_end > s) {
uint16_t ys = y_start > s ? y_start : s;
uint16_t ye = y_end < e ? y_end : e;
LCD_FillByColor(x, ys, x + w, ye, RGB(21,40,7));
} }
// 6. 脏区域内的刻度线
for (int i = 0; i < 10; i++) {
uint16_t tick_y = y + 7 + (h * i) / 10;
if (tick_y >= y_start && tick_y <= y_end) {
LCD_DrawLine(x + w / 2 - 3, tick_y, x + w / 2 + 3, tick_y, FADER_TEXT);
}
}
}
// ============================================================
// 仅绘制滑块 + 数值文字(用于增量刷新)
// 滑块尺寸和文字位置与原版完全一致
// ============================================================
static void DrawFaderSlider(Fader_t *f, uint16_t slider_y)
{
uint16_t x = f->x, w = f->w, slider_h = 20;
uint16_t bg = (s_mixer_focus == (int8_t)f->id) ? COLOR_PRIMARY : COLOR_NORMAL_BG;
char buf[8];
LCD_FillRoundRect(x+5, slider_y, w-10, slider_h, 5, bg);
sprintf(buf, "%d", f->val);
LCD_ShowString_AutoAlign(x, x + w, slider_y, (uint8_t*)buf, LCD_ALIGN_CENTER, FADER_TEXT, bg, 0, 15);
}
// ============================================================
// 完整重绘滑块(槽背景 + 刻度线 + 滑块)
// ============================================================
static void UpdateFaderSlider(Fader_t *f)
{
uint16_t x = f->x, y = f->y, w = f->w, h = f->h;
uint16_t new_y = CalcSliderY(f);
if (f->prev_slider_y == new_y) return;
// 完整重绘整个推子槽区域
LCD_FillByColor(x - 10, y, x + w + 10, y + h, BLACK);
DrawFaderGrooveAt(f, y + 5, y + 5 + h);
// 刻度线
for (int i = 0; i < 10; i++) {
uint16_t tick_y = y + 7 + (h * i) / 10;
LCD_DrawLine(x + w / 2 - 3, tick_y, x + w / 2 + 3, tick_y, FADER_TEXT);
}
// 画滑块
DrawFaderSlider(f, new_y);
f->prev_slider_y = new_y;
}
void UpdateFaderByTouch(int idx, uint16_t y)
{
uint8_t val_127;
uint8_t STR_val;
if (idx < 0 || idx > 3) return;
Fader_t *f = &faders[idx];
if (s_mixer_focus != (int8_t)idx)
{
int8_t prev = s_mixer_focus;
s_mixer_focus = (int8_t)idx;
if (prev >= 0 && prev <= 3)
DrawFaderSlider(&faders[prev], faders[prev].prev_slider_y);
}
uint16_t y_min = f->y;
uint16_t y_max = f->y + f->h;
if (y < y_min + 8) { // 闈犺繎椤堕儴 鈫?鐩存帴10
f->val = 10;
}
else if (y > y_max - 8) { // 闈犺繎搴曢儴 鈫?鐩存帴0
f->val = 0;
}
else {
// 姝e父璁$畻
int32_t val_raw = 10 - ((int32_t)(y - y_min) * 10) / (y_max - y_min);
if(val_raw < 0) val_raw = 0;
if(val_raw > 10) val_raw = 10;
f->val = val_raw;
}
UpdateFaderSlider(f);
DrawFaderSlider(f, f->prev_slider_y);
// 闊抽噺杈撳嚭
switch(idx) {
case 0:
// MIX 閫氶亾
val_127 = (f->val * 127) / 10;
SendVolumeChangeMidiEvent(1,val_127);
SendVolumeChangeMidiEvent(2,val_127);
SendVolumeChangeMidiEvent(3,val_127);
SendVolumeChangeMidiEvent(4,val_127);
SendVolumeChangeMidiEvent(5,val_127);
SendVolumeChangeMidiEvent(6,val_127);
SendVolumeChangeMidiEvent(7,val_127);
SendVolumeChangeMidiEvent(8,val_127);
SendVolumeChangeMidiEvent(9,val_127);
SendVolumeChangeMidiEvent(10,val_127);
SendVolumeChangeMidiEvent(11,val_127);
SendVolumeChangeMidiEvent(12,val_127);
SendVolumeChangeMidiEvent(13,val_127);
SendVolumeChangeMidiEvent(14,val_127);
SendVolumeChangeMidiEvent(15,val_127);
break;
case 1:
// STR 寮︿箰閫氶亾
STR_val = (f->val * 127) / 10;
SendVolumeChangeMidiEvent(0,STR_val);
break;
case 2:
// MIC 楹﹀厠椋庨€氶亾
AW816_Set_Volume(MIC_VOL_MAP[f->val]);
break;
case 3:
// REV 娣峰搷閫氶亾
// 鍦ㄨ繖閲屽啓娣峰搷鎺у埗
AW816_Set_Reverb(f->val * 10);
break;
}
}
// ============================================================
// 计算滑块Y坐标根据val值 0~10
// ============================================================
static uint16_t CalcSliderY(Fader_t *f)
{
uint16_t slider_h = 16;
uint16_t fill_h = (f->val * f->h) / 10;
if (fill_h > f->h) fill_h = f->h;
uint16_t slider_y = f->y + f->h - fill_h - (slider_h / 2);
if (slider_y < f->y) slider_y = f->y;
if (slider_y > f->y + f->h - slider_h) slider_y = f->y + f->h - slider_h;
return slider_y;
}
// ============================================================
// 绘制实心圆角矩形(用 FillByColor 逐行填充圆弧区域)
// 身体填充比 LCD_FillRoundRect 多延伸 1 像素,消除缝隙
// ============================================================
static void FillRoundRect_Solid(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t r, uint16_t color)
{
if (r > w / 2) r = w / 2;
if (r > h / 2) r = h / 2;
if (r == 0) { LCD_FillByColor(x, y, x + w, y + h, color); return; }
// 身体填充(中间 + 左右两侧直边)
LCD_FillByColor(x + r, y, x + w - r, y + h, color);
LCD_FillByColor(x, y + r, x + r, y + h - r, color);
LCD_FillByColor(x + w - r, y + r, x + w, y + h - r, color);
// 4 个圆弧角:从圆心向边缘逐行填充实心行
for (uint16_t dy = 0; dy < r; dy++) {
// dx = floor(sqrt(r² - (r-dy)²)) = floor(sqrt(2*r*dy - dy²))
uint16_t d = 2 * r * dy - dy * dy;
uint16_t dx = 0;
while ((dx + 1) * (dx + 1) <= d) dx++;
// 填充从 x+r-dx 到 x+r+1+1确保dx=0时覆盖中心像素
LCD_FillByColor(x + r - dx, y + dy, x + r + 1, y + dy + 1, color); // 顶左角
LCD_FillByColor(x + w - r, y + dy, x + w - r + dx + 1, y + dy + 1, color); // 顶右角
LCD_FillByColor(x + r - dx, y + h - 1 - dy, x + r + 1, y + h - dy, color); // 底左角
LCD_FillByColor(x + w - r, y + h - 1 - dy, x + w - r + dx + 1, y + h - dy, color); // 底右角
}
}
int CheckTouchFader(uint16_t x, uint16_t y)
{
for (int i = 0; i < 4; i++) {
Fader_t *f = &faders[i];
// 鎵╁ぇ瑙︽懜鍖哄煙锛屾彁鍗囨嫋鍔ㄤ綋锟?
if (x >= f->x - 10 && x <= f->x + f->w + 10 &&
y >= f->y && y <= f->y + f->h) {
return i;
}
}
return -1;
}
// ==================== <20><>ʼ<EFBFBD><CABC> ====================
void UI_Mixer_Init(void)
{
s_mixer_focus = -1;
UI_ClearFocus();
// LCD_WR_REG(0x28); // Display OFF
UI_DrawTop_TiaoYinTai();
DrawAllFaders();
pCurrentTouch_Area = Touch_Btn;
// LCD_WR_REG(0x29); // Display ON/
}
// ==================== <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD><D6A3><EFBFBD> ====================
void UI_Mixer_Process(DisplayTaskMessage_Type msg)
{
uint16_t tx,ty;
int fader_idx;
switch(msg.MessageType)
{
case MSG_ID_TOUCH:
tx = msg.HiByte;
ty = msg.LoByte;
// 1. <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
fader_idx = CheckTouchFader(tx, ty);
if (fader_idx >= 0)
{
UpdateFaderByTouch(fader_idx, ty);
return;
}
// 2. <20>ٴ<EFBFBD><D9B4><EFBFBD> ȡ<><C8A1> / ȷ<><C8B7> <20><>ť
for(uint8_t i=0; i<TOUCH_BTN_NUM; i++)
{
if( tx >= Touch_Btn[i].x_min && tx <= Touch_Btn[i].x_max &&
ty >= Touch_Btn[i].y_min && ty <= Touch_Btn[i].y_max )
{
// <20><>ť<EFBFBD><C5A5><EFBFBD><EFBFBD>¼<EFBFBD>
if(Touch_Btn[i].ID == 0)
{
MenuPage_SystemSetting_Proc();
}
break;
}
}
ResetAutoPowerCount();
break;
case MSG_ID_EC_VOL:
// //LCD_ShowString(200, 0, Num_To_String(msg.DataU16[1],buff,3), RED, WHITE, 16, 0);
// uint8_t vol = msg.DataU16[1];
// uint8_t level;
// if (vol <= 5) level = 0;
// else if (vol <= 35) level = 1;
// else if (vol <= 65) level = 2;
// else if (vol <= 95) level = 3;
// else if (vol <= 115) level = 4;
// else level = 5;
// //Draw_Volume_Bar(5, 5, level, 1, WHITE, GRAY);
// uint8_t mMasterSysExVolume[12] = { 0xF0, 0x41, 0x00, 0x42, 0x12, 0x40, 0x00, 0x04, 0x64, 0x00, 0x00,0xF7};
// memset(mMasterSysExVolume+8,msg.DataU16[1],1);
// SendMidiDataToDreamDSP(mMasterSysExVolume,12);
//
// ResetAutoPowerCount();
break;
}
}