From 37242f108ac58e23b5f4934506bc1d48ea0bdbe5 Mon Sep 17 00:00:00 2001 From: yuquanjun Date: Fri, 28 Aug 2026 10:07:48 +0800 Subject: [PATCH] Align status bar volume icon with UI spec. Replace the old volume bars with 5 rounded-top bars using a left-to-right brightness gradient, synced from the ADC volume pot. Co-authored-by: Cursor --- APP/app_adc.c | 4 +- UI/UI_Idle.c | 1 - UI/UI_global.c | 4 +- device/LCD_ILI9341/Drv_ILI9341_Lcd_App.c | 203 +++++++++++++++-------- 4 files changed, 142 insertions(+), 70 deletions(-) diff --git a/APP/app_adc.c b/APP/app_adc.c index 1a25af8..d3d3828 100644 --- a/APP/app_adc.c +++ b/APP/app_adc.c @@ -277,14 +277,14 @@ static void app_adc_volume_process(void) if(abs((int16_t)vol_last - (int16_t)val) > 2) { vol_last = val; - /* �� 6 �� */ + /* 5 格状态栏音量条:0=静音,5=最大 */ if (val <= 5) level = 0; else if (val <= 35) level = 1; else if (val <= 65) level = 2; else if (val <= 95) level = 3; else if (val <= 115) level = 4; else level = 5; - + MainTask_Sendmsg(MSG_ID_EC_VOL, val, level, 0); } } diff --git a/UI/UI_Idle.c b/UI/UI_Idle.c index 8d28367..2f28592 100644 --- a/UI/UI_Idle.c +++ b/UI/UI_Idle.c @@ -270,7 +270,6 @@ void IdleProcess(DisplayTaskMessage_Type msg) { //LCD_ShowString(200, 0, Num_To_String(msg.DataU16[1],buff,3), RED, WHITE, 16, 0); uint8_t vol = msg.ID; -// uint8_t level; if (vol <= 5) level = 0; else if (vol <= 35) level = 1; else if (vol <= 65) level = 2; diff --git a/UI/UI_global.c b/UI/UI_global.c index 4e94ebb..0e24f56 100644 --- a/UI/UI_global.c +++ b/UI/UI_global.c @@ -1,6 +1,6 @@ #include "includes.h" - +extern uint8_t level; // ============================================== // ����ָ�붨�� @@ -78,7 +78,7 @@ void label_top() const uint16_t btn_color = /*DARKLGRAY*/0x2988; // 深灰�????? //LCD_FillByColor(0,0,240,25,BLACK); //LCD_WR_PIC(5,0,12,20,gImage_bar); - Draw_Volume_Bar(5, 5, 3,1, WHITE,GRAY); + Draw_Volume_Bar(5, 5, level, 1, WHITE, GRAY); LCD_DrawLine(0, 26, 240, 26, btn_color); Show_BL_Icon(mGuiData[GUI_BL_SW].Current); Show_Battery_Icon(usb_charging_state); diff --git a/device/LCD_ILI9341/Drv_ILI9341_Lcd_App.c b/device/LCD_ILI9341/Drv_ILI9341_Lcd_App.c index e6d89fe..0f3614f 100644 --- a/device/LCD_ILI9341/Drv_ILI9341_Lcd_App.c +++ b/device/LCD_ILI9341/Drv_ILI9341_Lcd_App.c @@ -1706,36 +1706,116 @@ void LCD_DrawMinus_RoundBox(uint16_t x, uint16_t y, uint8_t size, uint8_t radius /** - * @brief 绘制音量条(5级,彩屏适配版) - * @param x: 音量条左上角X坐标 - * @param y: 音量条左上角Y坐标 - * @param volume_level: 音量等级(0-5,0=静音,5=最大音量) - * @param color_on: 音量条点亮颜色(彩屏RGB值,如WHITE/0xFFFF) - * @param color_off: 音量条熄灭颜色(彩屏RGB值,如BLACK/0x0000) + * @brief 仅顶部圆角、底部平齐的实心竖条 + */ +static void LCD_FillRoundTopRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t r, uint16_t color) +{ + if(w == 0 || h == 0) + { + return; + } + if(r > (w / 2)) + { + r = w / 2; + } + if(r > h) + { + r = h; + } + if(r == 0) + { + LCD_FillByColor(x, y, x + w, y + h, color); + return; + } + + LCD_FillRoundRect(x, y, w, h, r, color); + if(h > r) + { + LCD_FillByColor(x, y + h - r, x + w, y + h, color); + } +} + +/** + * @brief RGB565 两色按比例混合 + */ +static uint16_t LCD_BlendColor565(uint16_t c0, uint16_t c1, uint8_t num, uint8_t den) +{ + uint16_t r0 = (c0 >> 11) & 0x1F; + uint16_t g0 = (c0 >> 5) & 0x3F; + uint16_t b0 = c0 & 0x1F; + uint16_t r1 = (c1 >> 11) & 0x1F; + uint16_t g1 = (c1 >> 5) & 0x3F; + uint16_t b1 = c1 & 0x1F; + uint16_t r; + uint16_t g; + uint16_t b; + + if(den == 0) + { + return c1; + } + + r = r0 + (uint16_t)(r1 - r0) * num / den; + g = g0 + (uint16_t)(g1 - g0) * num / den; + b = b0 + (uint16_t)(b1 - b0) * num / den; + return (r << 11) | (g << 5) | b; +} + +/** + * @brief 绘制音量条(5格实心,从左到右亮度递增,对齐需求图) + * @param volume_level: 音量等级(0-5,0=静音,5=最大) + * @note 强度为 N 时显示前 N 格实心条;最右点亮格最亮(白),向左依次变暗 */ void Draw_Volume_Bar(uint16_t x, uint16_t y, uint8_t volume_level,uint8_t scale,uint16_t color_on, uint16_t color_off) { uint8_t i; - //const uint8_t bar_count = 5; // 音量条总数量(5挡) - uint8_t w = 5 * scale; // 单条宽度(支持缩放) - uint8_t gap = 2 * scale; // 条间距(支持缩放) - // 每条约的Y偏移和高度(按原始比例缩放) - uint8_t y_offset[5] = {8,6,4,2,0}; - uint8_t height[5] = {12,14,16,18,20}; + uint8_t bar_count = 5; + uint8_t w = 3 * scale; + uint8_t gap = 2 * scale; + uint8_t radius = 1 * scale; + uint8_t height[5] = {6, 9, 12, 15, 18}; + uint8_t max_h = height[4]; + uint16_t clear_w; + uint16_t dim_color = color_off; - // 限制音量等级范围,避免越界 - volume_level = (volume_level > 5) ? 5 : volume_level; + (void)color_on; - // 循环绘制5个音量条,按档位控制颜色 - for(i = 0; i < 5; i++) + if(volume_level > 5) { - uint16_t curr_x = x + (w + gap) * i; // 当前条的X坐标 - uint8_t curr_y = y + y_offset[i] * scale; // 当前条的Y坐标(缩放后) - uint8_t curr_h = height[i] * scale; // 当前条的高度(缩放后) - uint16_t curr_color = (i < volume_level) ? color_on : color_off; // 按档位选颜色 + volume_level = 5; + } - // 绘制圆角矩形音量条 - LCD_FillRoundRect(curr_x, curr_y, w, curr_h, 2 * scale, curr_color); + clear_w = (uint16_t)(w + gap) * bar_count - gap; + LCD_FillByColor(x, y, x + clear_w, y + max_h * scale, BLACK); + + if(volume_level == 0) + { + return; + } + + for(i = 0; i < bar_count; i++) + { + uint16_t curr_x = x + (w + gap) * i; + uint8_t curr_h = height[i] * scale; + uint8_t curr_y = y + (max_h * scale - curr_h); + uint16_t bar_color; + + if(i >= volume_level) + { + continue; + } + + if(volume_level == 1) + { + bar_color = WHITE; + } + else + { + /* 左暗右亮:第1格最暗,当前档位的最右格为全白 */ + bar_color = LCD_BlendColor565(dim_color, WHITE, i, volume_level - 1); + } + + LCD_FillRoundTopRect(curr_x, curr_y, w, curr_h, radius, bar_color); } } @@ -1755,64 +1835,57 @@ void Draw_Volume_Bar(uint16_t x, uint16_t y, uint8_t volume_level,uint8_t scale, /** - * @brief 绘制电池图标(彩屏适配版) - * @param x: 电池图标左上角X坐标 - * @param y: 电池图标左上角Y坐标 - * @param battery_percent: 电池电量百分比(0-100,超出范围自动限制) - * @param scale: 图标缩放倍数(1=原始大小,2=2倍放大,以此类推) - * @param border_color: 电池边框颜色(彩屏RGB值,如WHITE/0xFFFF) - * @param bg_color: 电池内部背景色(如BLACK/0x0000) - * @param fill_color: 电量填充颜色(如WHITE/0xFFFF) + * @brief 绘制电池图标(细线框 + 内填充 + 百分比,贴近状态栏需求图) + * @param x/y: 左上角坐标 + * @param battery_percent: 0-100,填充宽度与百分比一致 + * @param scale: 缩放倍数 + * @param border_color / bg_color / fill_color: 边框、内底、填充色 */ void Draw_Battery_Icon(uint16_t x, uint16_t y, uint8_t battery_percent,uint8_t scale, uint16_t border_color, uint16_t bg_color, uint16_t fill_color) { - // 1. 基础参数(原始尺寸,按scale缩放) - uint16_t bat_w = 25 * scale; // 电池主体宽度 - uint16_t bat_h = 15 * scale; // 电池主体高度 - uint8_t round_r = 2 * scale; // 电池圆角半径 - uint16_t inner_gap = 1 * scale; // 内部边框间隙 - uint16_t fill_gap = 2 * scale; // 电量填充区间隙 + uint16_t bat_w = 22 * scale; /* 主体宽度 */ + uint16_t bat_h = 12 * scale; /* 主体高度(更扁) */ + uint16_t fill_gap = 2 * scale; /* 填充与边框间距 */ uint8_t Info[40]; + uint16_t pole_w = 2 * scale; + uint16_t pole_h = 6 * scale; + uint16_t pole_x = x + bat_w; + uint16_t pole_y = y + (bat_h - pole_h) / 2; + uint16_t fill_w; + uint16_t fill_h; + uint16_t text_x; - LCD_FillByColor(x,y,240,y+bat_h,BLACK); + /* 清到右缘,避免百分比位数变化残留 */ + LCD_FillByColor(x, y, 240, y + ((bat_h > 16) ? bat_h : 16), BLACK); - // 2. 限制电量范围(避免负数或超过100%) if(battery_percent > 100) battery_percent = 100; - if(battery_percent == 0) battery_percent = 0; - // 3. 计算电量填充宽度(按百分比) - uint16_t fill_w = (bat_w - 2 * fill_gap) * battery_percent / 100; - // 电量填充高度(留1像素间隙,和内部区域匹配) - uint16_t fill_h = bat_h - 2 * fill_gap; + fill_w = (bat_w - 2 * fill_gap) * battery_percent / 100; + fill_h = bat_h - 2 * fill_gap; - // 4. 绘制电池外框(带圆角) - LCD_FillRoundRect(x, y, bat_w, bat_h, round_r, border_color); + /* 1px 线框外轮廓 */ + LCD_DrawRectangle(x, y, x + bat_w - 1, y + bat_h - 1, border_color); - // 5. 绘制电池内部背景(黑色底) - LCD_FillRoundRect(x + inner_gap, y + inner_gap, - bat_w - 2 * inner_gap, bat_h - 2 * inner_gap, - 0, bg_color); - - // 6. 绘制电量填充(按百分比动态显示) - if(battery_percent > 0) // 电量>0才绘制填充 + /* 内部背景 */ + if(bat_w > 2 && bat_h > 2) { - LCD_FillRoundRect(x + fill_gap, y + fill_gap, - fill_w, fill_h, - 0, fill_color); + LCD_FillByColor(x + 1, y + 1, x + bat_w - 1, y + bat_h - 1, bg_color); } - // 7. 绘制电池正极(右上角小矩形,增强视觉效果) - uint16_t pole_w = 3 * scale; // 正极宽度 - uint16_t pole_h = 7 * scale; // 正极高度 - uint16_t pole_x = x + bat_w; // 正极X坐标(电池右侧) - uint16_t pole_y = y + (bat_h - pole_h) / 2; // 正极垂直居中 - LCD_FillRoundRect(pole_x, pole_y, pole_w, pole_h, 1 * scale, border_color); - - sprintf ((char*)Info, "%d%%", battery_percent); - LCD_ShowString(x+bat_w+pole_w, y, Info, WHITE, BLACK, 16, 0); - + /* 电量填充(与百分比成比例) */ + if(battery_percent > 0 && fill_w > 0) + { + LCD_FillByColor(x + fill_gap, y + fill_gap, + x + fill_gap + fill_w, y + fill_gap + fill_h, + fill_color); + } + /* 右侧正极小凸起 */ + LCD_FillByColor(pole_x, pole_y, pole_x + pole_w, pole_y + pole_h, border_color); + sprintf((char*)Info, "%d%%", battery_percent); + text_x = pole_x + pole_w + 2 * scale; + LCD_ShowString(text_x, y, Info, WHITE, BLACK, 16, 0); } /******************************************************************************