diff --git a/AGENTS.md b/AGENTS.md index 06c8444..72db302 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -298,8 +298,11 @@ Use a clear conventional format: ### 状态、测量与验收 17. 时间沿用现有同步与时区服务;电量来自领域状态,不在显示层用电压重算。 - 保留未知值和二维码/边界测试不叠加规则。当前点阵仅满足数字状态,不能 - 声称已支持任意中文文字。 + 保留未知值和二维码/边界测试不叠加规则。当前字形子集仅满足数字状态,不能 + 声称已支持任意中文文字。当前时间使用 Montserrat 14 数字子集直接合成, + 电量只显示 40×20 电池素材,不创建 GFX label 或运行 LVGL GUI。 + `tools/prepare_status_hud_assets.py --check` 验证字形提取及调色板游程往返; + HUD 资源 C 不手改,Alpha 不丢弃,不重复加入 PNG 素材包。 18. 性能测量沿用 `CONFIG_TQ_LCD_EMOTE_FPS_LOG`,不逐帧打印。区分步骤频率、 实际图像更新、DMA 块次数与面板扫描率;不将 30 FPS 配置写成实测 30 FPS。 19. 分项都是墙钟时间,含任务抢占;平均包含保持帧,各项最大值可能不在同一帧。 diff --git a/components/platform/CMakeLists.txt b/components/platform/CMakeLists.txt index 222429b..094f592 100644 --- a/components/platform/CMakeLists.txt +++ b/components/platform/CMakeLists.txt @@ -15,6 +15,7 @@ set(platform_srcs "src/platform_digital_input_driver.c" "src/platform_io_effects.c" "src/lcd_direct.c" + "src/generated/lcd_status_assets.c" "src/lcd_direct_assets.c" "src/platform_asset_bundle.c" "third_party/lodepng/lodepng.cpp" diff --git a/components/platform/assets/status_hud/LVGL-LICENSE.txt b/components/platform/assets/status_hud/LVGL-LICENSE.txt new file mode 100644 index 0000000..690d2df --- /dev/null +++ b/components/platform/assets/status_hud/LVGL-LICENSE.txt @@ -0,0 +1,8 @@ +MIT licence +Copyright (c) 2025 LVGL Kft + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/components/platform/assets/status_hud/battery_optimized/battery_1.png b/components/platform/assets/status_hud/battery_optimized/battery_1.png new file mode 100644 index 0000000..69b3b14 Binary files /dev/null and b/components/platform/assets/status_hud/battery_optimized/battery_1.png differ diff --git a/components/platform/assets/status_hud/battery_optimized/battery_100.png b/components/platform/assets/status_hud/battery_optimized/battery_100.png new file mode 100644 index 0000000..78a5afa Binary files /dev/null and b/components/platform/assets/status_hud/battery_optimized/battery_100.png differ diff --git a/components/platform/assets/status_hud/battery_optimized/battery_25.png b/components/platform/assets/status_hud/battery_optimized/battery_25.png new file mode 100644 index 0000000..29105fc Binary files /dev/null and b/components/platform/assets/status_hud/battery_optimized/battery_25.png differ diff --git a/components/platform/assets/status_hud/battery_optimized/battery_50.png b/components/platform/assets/status_hud/battery_optimized/battery_50.png new file mode 100644 index 0000000..9cafd04 Binary files /dev/null and b/components/platform/assets/status_hud/battery_optimized/battery_50.png differ diff --git a/components/platform/assets/status_hud/battery_optimized/battery_75.png b/components/platform/assets/status_hud/battery_optimized/battery_75.png new file mode 100644 index 0000000..5beee14 Binary files /dev/null and b/components/platform/assets/status_hud/battery_optimized/battery_75.png differ diff --git a/components/platform/assets/status_hud/battery_optimized/battery_charging_1.png b/components/platform/assets/status_hud/battery_optimized/battery_charging_1.png new file mode 100644 index 0000000..e8fe088 Binary files /dev/null and b/components/platform/assets/status_hud/battery_optimized/battery_charging_1.png differ diff --git a/components/platform/assets/status_hud/battery_optimized/battery_charging_100.png b/components/platform/assets/status_hud/battery_optimized/battery_charging_100.png new file mode 100644 index 0000000..04e4b07 Binary files /dev/null and b/components/platform/assets/status_hud/battery_optimized/battery_charging_100.png differ diff --git a/components/platform/assets/status_hud/battery_optimized/battery_charging_25.png b/components/platform/assets/status_hud/battery_optimized/battery_charging_25.png new file mode 100644 index 0000000..c6a525c Binary files /dev/null and b/components/platform/assets/status_hud/battery_optimized/battery_charging_25.png differ diff --git a/components/platform/assets/status_hud/battery_optimized/battery_charging_50.png b/components/platform/assets/status_hud/battery_optimized/battery_charging_50.png new file mode 100644 index 0000000..9f6e072 Binary files /dev/null and b/components/platform/assets/status_hud/battery_optimized/battery_charging_50.png differ diff --git a/components/platform/assets/status_hud/battery_optimized/battery_charging_75.png b/components/platform/assets/status_hud/battery_optimized/battery_charging_75.png new file mode 100644 index 0000000..e490480 Binary files /dev/null and b/components/platform/assets/status_hud/battery_optimized/battery_charging_75.png differ diff --git a/components/platform/assets/status_hud/battery_source/battery_1.png b/components/platform/assets/status_hud/battery_source/battery_1.png new file mode 100644 index 0000000..4e988c5 Binary files /dev/null and b/components/platform/assets/status_hud/battery_source/battery_1.png differ diff --git a/components/platform/assets/status_hud/battery_source/battery_100.png b/components/platform/assets/status_hud/battery_source/battery_100.png new file mode 100644 index 0000000..ccfdb3f Binary files /dev/null and b/components/platform/assets/status_hud/battery_source/battery_100.png differ diff --git a/components/platform/assets/status_hud/battery_source/battery_25.png b/components/platform/assets/status_hud/battery_source/battery_25.png new file mode 100644 index 0000000..d87920c Binary files /dev/null and b/components/platform/assets/status_hud/battery_source/battery_25.png differ diff --git a/components/platform/assets/status_hud/battery_source/battery_50.png b/components/platform/assets/status_hud/battery_source/battery_50.png new file mode 100644 index 0000000..0f47b5c Binary files /dev/null and b/components/platform/assets/status_hud/battery_source/battery_50.png differ diff --git a/components/platform/assets/status_hud/battery_source/battery_75.png b/components/platform/assets/status_hud/battery_source/battery_75.png new file mode 100644 index 0000000..13c587d Binary files /dev/null and b/components/platform/assets/status_hud/battery_source/battery_75.png differ diff --git a/components/platform/assets/status_hud/battery_source/battery_charging_1.png b/components/platform/assets/status_hud/battery_source/battery_charging_1.png new file mode 100644 index 0000000..ccd3885 Binary files /dev/null and b/components/platform/assets/status_hud/battery_source/battery_charging_1.png differ diff --git a/components/platform/assets/status_hud/battery_source/battery_charging_100.png b/components/platform/assets/status_hud/battery_source/battery_charging_100.png new file mode 100644 index 0000000..1095f6d Binary files /dev/null and b/components/platform/assets/status_hud/battery_source/battery_charging_100.png differ diff --git a/components/platform/assets/status_hud/battery_source/battery_charging_25.png b/components/platform/assets/status_hud/battery_source/battery_charging_25.png new file mode 100644 index 0000000..1ed18a2 Binary files /dev/null and b/components/platform/assets/status_hud/battery_source/battery_charging_25.png differ diff --git a/components/platform/assets/status_hud/battery_source/battery_charging_50.png b/components/platform/assets/status_hud/battery_source/battery_charging_50.png new file mode 100644 index 0000000..8acd12c Binary files /dev/null and b/components/platform/assets/status_hud/battery_source/battery_charging_50.png differ diff --git a/components/platform/assets/status_hud/battery_source/battery_charging_75.png b/components/platform/assets/status_hud/battery_source/battery_charging_75.png new file mode 100644 index 0000000..c285328 Binary files /dev/null and b/components/platform/assets/status_hud/battery_source/battery_charging_75.png differ diff --git a/components/platform/internal/lcd_status_assets.h b/components/platform/internal/lcd_status_assets.h new file mode 100644 index 0000000..5c73988 --- /dev/null +++ b/components/platform/internal/lcd_status_assets.h @@ -0,0 +1,18 @@ +#pragma once +#include + +/* Montserrat 14 原始 4-bit Alpha;仅保留 0..9、冒号、横线。 */ +typedef struct { + uint16_t offset; + uint8_t advance, width, height; + int8_t x, y; +} lcd_status_glyph_t; +typedef struct { + const uint8_t *palette; /* RGB565 高字节、低字节、A8。 */ + const uint8_t *runs; /* 数量、调色板索引。 */ + uint16_t run_bytes; +} lcd_status_icon_t; +extern const uint8_t lcd_status_font_bitmap[]; +extern const lcd_status_glyph_t lcd_status_font_glyphs[12]; +/* 1、25、50、75、100;后五项为对应的充电图标。 */ +extern const lcd_status_icon_t lcd_status_battery_icons[10]; diff --git a/components/platform/src/generated/lcd_status_assets.c b/components/platform/src/generated/lcd_status_assets.c new file mode 100644 index 0000000..fb3bcc9 --- /dev/null +++ b/components/platform/src/generated/lcd_status_assets.c @@ -0,0 +1,580 @@ +/* Generated by tools/prepare_status_hud_assets.py; do not edit. + * Font subset derived from LVGL Montserrat 14, Copyright (c) 2025 LVGL Kft. + * See components/platform/assets/status_hud/LVGL-LICENSE.txt. */ +#include "lcd_status_assets.h" + +const uint8_t lcd_status_font_bitmap[] = { + 0x00, 0x4c, 0xfe, 0x70, 0x00, 0x4f, 0xb6, 0x8f, 0x90, 0x0d, 0xb0, 0x00, 0x5f, 0x32, 0xf4, 0x00, 0x00, 0xe7, 0x4f, 0x20, 0x00, 0x0c, 0xa4, 0xf2, + 0x00, 0x00, 0xca, 0x2f, 0x40, 0x00, 0x0e, 0x70, 0xdb, 0x00, 0x05, 0xf2, 0x04, 0xfb, 0x68, 0xf9, 0x00, 0x04, 0xcf, 0xe7, 0x00, 0xef, 0xfb, 0x44, + 0xcb, 0x00, 0xab, 0x00, 0xab, 0x00, 0xab, 0x00, 0xab, 0x00, 0xab, 0x00, 0xab, 0x00, 0xab, 0x00, 0xab, 0x07, 0xdf, 0xea, 0x10, 0x8e, 0x85, 0x7e, + 0xc0, 0x01, 0x00, 0x06, 0xf1, 0x00, 0x00, 0x06, 0xf0, 0x00, 0x00, 0x0d, 0x90, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x1c, 0xc0, 0x00, 0x01, 0xdb, 0x00, + 0x00, 0x1d, 0xe5, 0x44, 0x42, 0x7f, 0xff, 0xff, 0xf9, 0x7f, 0xff, 0xff, 0xf0, 0x24, 0x44, 0x5f, 0x90, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x09, 0xe1, + 0x00, 0x00, 0x3f, 0xd8, 0x10, 0x00, 0x04, 0x6d, 0xd0, 0x00, 0x00, 0x02, 0xf4, 0x10, 0x00, 0x02, 0xf4, 0xbd, 0x75, 0x7d, 0xd0, 0x19, 0xdf, 0xea, + 0x10, 0x00, 0x00, 0x0d, 0xa0, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x07, 0xe1, 0x00, 0x00, 0x00, 0x4f, 0x40, 0x10, 0x00, 0x02, 0xf6, 0x00, + 0xf5, 0x00, 0x1d, 0xa0, 0x00, 0xf5, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xf3, 0x13, 0x33, 0x33, 0xf7, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x00, 0x00, + 0x00, 0xf5, 0x00, 0x09, 0xff, 0xff, 0xf0, 0x0a, 0xb4, 0x44, 0x40, 0x0c, 0x80, 0x00, 0x00, 0x0e, 0x70, 0x00, 0x00, 0x0f, 0xff, 0xfc, 0x40, 0x03, + 0x34, 0x5c, 0xf2, 0x00, 0x00, 0x00, 0xf7, 0x10, 0x00, 0x00, 0xf7, 0x8e, 0x85, 0x6c, 0xf1, 0x08, 0xdf, 0xfb, 0x30, 0x00, 0x2a, 0xef, 0xd5, 0x00, + 0x3f, 0xd6, 0x57, 0x40, 0x0c, 0xc0, 0x00, 0x00, 0x02, 0xf4, 0x00, 0x00, 0x00, 0x4f, 0x5b, 0xff, 0xa1, 0x04, 0xfe, 0x84, 0x5d, 0xd0, 0x3f, 0x80, + 0x00, 0x3f, 0x30, 0xe8, 0x00, 0x03, 0xf2, 0x06, 0xf8, 0x45, 0xdc, 0x00, 0x05, 0xdf, 0xe9, 0x10, 0x9f, 0xff, 0xff, 0xfd, 0x9d, 0x44, 0x44, 0xe9, + 0x9c, 0x00, 0x04, 0xf2, 0x00, 0x00, 0x0b, 0xb0, 0x00, 0x00, 0x2f, 0x40, 0x00, 0x00, 0xad, 0x00, 0x00, 0x01, 0xf6, 0x00, 0x00, 0x08, 0xe0, 0x00, + 0x00, 0x0e, 0x80, 0x00, 0x00, 0x6f, 0x10, 0x00, 0x01, 0x9e, 0xfe, 0x91, 0x00, 0xbe, 0x63, 0x6e, 0xc0, 0x0f, 0x60, 0x00, 0x6f, 0x00, 0xcc, 0x20, + 0x2b, 0xc0, 0x02, 0xef, 0xff, 0xe2, 0x00, 0xdc, 0x42, 0x4c, 0xd0, 0x5f, 0x20, 0x00, 0x1f, 0x55, 0xf2, 0x00, 0x02, 0xf5, 0x0e, 0xd5, 0x35, 0xde, + 0x00, 0x1a, 0xef, 0xea, 0x10, 0x03, 0xbf, 0xea, 0x20, 0x2f, 0xa4, 0x4b, 0xe1, 0x8e, 0x00, 0x00, 0xe9, 0x9d, 0x00, 0x00, 0xdd, 0x4f, 0x71, 0x29, + 0xff, 0x07, 0xff, 0xfc, 0x9e, 0x00, 0x02, 0x10, 0xac, 0x00, 0x00, 0x02, 0xf6, 0x07, 0x65, 0x8f, 0xb0, 0x0a, 0xef, 0xd7, 0x00, 0x2e, 0x53, 0xf5, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x52, 0xe4, 0x00, 0x00, 0x03, 0xff, 0xf9, 0x03, 0x33, 0x10, +}; +const lcd_status_glyph_t lcd_status_font_glyphs[12] = { + {0, 9, 9, 10, 0, 0}, /* 0 */ + {45, 5, 4, 10, 0, 0}, /* 1 */ + {65, 8, 8, 10, 0, 0}, /* 2 */ + {105, 8, 8, 10, 0, 0}, /* 3 */ + {145, 9, 10, 10, 0, 0}, /* 4 */ + {195, 8, 8, 10, 0, 0}, /* 5 */ + {235, 9, 9, 10, 0, 0}, /* 6 */ + {280, 8, 8, 10, 0, 0}, /* 7 */ + {320, 9, 9, 10, 0, 0}, /* 8 */ + {365, 9, 8, 10, 0, 0}, /* 9 */ + {405, 3, 3, 8, 0, 0}, /* : */ + {417, 5, 5, 3, 0, 3}, /* - */ +}; +static const uint8_t battery_palette_0[] = { + 0x00, 0x00, 0x00, 0xf8, 0x00, 0x01, 0xf9, 0xe7, 0x04, 0xf9, 0x86, 0x05, 0xfa, 0xaa, 0x03, 0xf8, 0x00, 0x02, 0xf9, 0xc4, 0x0d, 0xf9, 0xe6, 0x5b, + 0xf9, 0xe6, 0x82, 0xf9, 0xc6, 0x84, 0xf9, 0xc5, 0x85, 0xf9, 0xe6, 0x78, 0xf9, 0xe5, 0x36, 0xfb, 0xe0, 0x02, 0xf9, 0xc5, 0x34, 0xf9, 0xe6, 0xe4, + 0xfa, 0x06, 0xff, 0xf9, 0xc6, 0xff, 0xf9, 0xe6, 0xff, 0xf9, 0xc6, 0x98, 0xf9, 0xc7, 0x0d, 0xf9, 0xe6, 0xe5, 0xf9, 0xe6, 0xe1, 0xf9, 0xc5, 0x40, + 0xf9, 0xe5, 0x10, 0xf9, 0xa6, 0x0e, 0xfa, 0x26, 0x0f, 0xf9, 0xe6, 0x19, 0xf9, 0xc5, 0x80, 0xf9, 0xc5, 0x75, 0xf9, 0xc5, 0x5b, 0xf9, 0xc5, 0x3b, + 0xf9, 0xc6, 0xbf, 0xf9, 0xc5, 0x6b, 0xf9, 0xc6, 0xb7, 0xf9, 0xc6, 0xed, 0xf9, 0xc6, 0xfc, 0xf9, 0xe6, 0x94, 0xf9, 0x45, 0x06, 0xfa, 0xa0, 0x03, + 0xf9, 0xc6, 0x79, 0xf9, 0x84, 0x0f, 0xf9, 0x65, 0x0b, 0xf9, 0xc6, 0x83, 0xf9, 0xc6, 0xfd, 0xf9, 0xc6, 0x1a, 0xf9, 0xc5, 0xfa, 0xf9, 0xe6, 0x8c, + 0xf9, 0xc5, 0x7c, 0xf9, 0xe6, 0xfe, 0xf9, 0xc5, 0x9b, 0xf9, 0xc6, 0x3e, 0xf9, 0xc5, 0xfc, 0xf9, 0xc6, 0x8d, 0xf9, 0xc6, 0x24, 0xf9, 0xc6, 0x8a, + 0xf9, 0xc6, 0xe2, 0xfa, 0x06, 0xfd, 0xf9, 0xe6, 0x83, 0xfa, 0x06, 0xfe, 0xf9, 0xa6, 0x25, 0xf9, 0xa4, 0x0e, 0xf9, 0xc5, 0xa1, 0xfa, 0x06, 0xe9, + 0xf9, 0xc5, 0x42, 0xf9, 0xc6, 0x93, 0xf9, 0xc6, 0x78, 0xf9, 0x86, 0x0f, 0xf9, 0xc6, 0x5e, 0xf9, 0xc5, 0x38, 0xf9, 0xc5, 0xc6, 0xf9, 0xc5, 0x70, + 0xf9, 0xc6, 0xb4, 0xf9, 0xc6, 0xef, 0xf9, 0xe6, 0xe9, 0xf9, 0xe6, 0xdc, 0xf9, 0xc5, 0x3c, 0xf9, 0x86, 0x0a, 0xf9, 0xc7, 0x09, 0xf9, 0xe6, 0x14, + 0xf9, 0xc6, 0x7a, 0xf9, 0xc5, 0x39, 0xf9, 0xe6, 0xea, 0xf9, 0xc5, 0xfb, 0xf9, 0xc6, 0x9f, 0xf9, 0xe5, 0x11, 0xf9, 0xe6, 0x64, 0xf9, 0xe6, 0x8b, + 0xf9, 0xc6, 0x8e, 0xf9, 0xe6, 0x80, 0xf9, 0xc6, 0x3d, +}; +static const uint8_t battery_runs_0[] = { + 0x03, 0x00, 0x01, 0x01, 0x02, 0x02, 0x18, 0x03, 0x02, 0x02, 0x01, 0x04, 0x09, 0x00, 0x01, 0x05, 0x1e, 0x00, 0x01, 0x05, 0x07, 0x00, 0x01, 0x05, + 0x01, 0x00, 0x01, 0x06, 0x01, 0x07, 0x01, 0x08, 0x02, 0x09, 0x15, 0x0a, 0x02, 0x09, 0x01, 0x0b, 0x01, 0x0c, 0x01, 0x00, 0x01, 0x01, 0x05, 0x00, + 0x01, 0x0d, 0x01, 0x00, 0x01, 0x0e, 0x01, 0x0f, 0x01, 0x10, 0x1a, 0x11, 0x01, 0x12, 0x01, 0x10, 0x01, 0x13, 0x01, 0x0d, 0x01, 0x05, 0x01, 0x01, + 0x03, 0x00, 0x01, 0x01, 0x01, 0x14, 0x01, 0x15, 0x01, 0x16, 0x01, 0x17, 0x01, 0x18, 0x01, 0x19, 0x16, 0x06, 0x01, 0x19, 0x01, 0x1a, 0x01, 0x1b, + 0x01, 0x1c, 0x01, 0x10, 0x01, 0x1d, 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, 0x03, 0x00, 0x01, 0x1e, 0x01, 0x10, 0x01, 0x1f, 0x01, 0x20, 0x01, 0x21, + 0x1b, 0x00, 0x01, 0x22, 0x01, 0x23, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00, 0x01, 0x05, 0x02, 0x00, 0x01, 0x09, 0x01, 0x24, 0x01, 0x1b, 0x01, 0x12, + 0x01, 0x25, 0x01, 0x01, 0x01, 0x03, 0x17, 0x01, 0x01, 0x26, 0x01, 0x27, 0x01, 0x28, 0x01, 0x12, 0x01, 0x29, 0x01, 0x00, 0x01, 0x2a, 0x03, 0x00, + 0x01, 0x2b, 0x01, 0x2c, 0x01, 0x2d, 0x01, 0x2e, 0x01, 0x2f, 0x01, 0x00, 0x01, 0x02, 0x17, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x30, 0x01, 0x31, + 0x01, 0x06, 0x01, 0x32, 0x01, 0x0f, 0x01, 0x33, 0x02, 0x00, 0x01, 0x2b, 0x01, 0x2c, 0x01, 0x2d, 0x01, 0x34, 0x01, 0x35, 0x01, 0x00, 0x01, 0x02, + 0x17, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x30, 0x01, 0x11, 0x01, 0x36, 0x01, 0x23, 0x01, 0x10, 0x01, 0x37, 0x02, 0x00, 0x01, 0x2b, 0x01, 0x2c, + 0x01, 0x2d, 0x01, 0x34, 0x01, 0x35, 0x01, 0x00, 0x01, 0x02, 0x17, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x30, 0x01, 0x11, 0x01, 0x36, 0x01, 0x38, + 0x01, 0x39, 0x01, 0x3a, 0x02, 0x00, 0x01, 0x2b, 0x01, 0x2c, 0x01, 0x2d, 0x01, 0x34, 0x01, 0x35, 0x01, 0x00, 0x01, 0x02, 0x17, 0x00, 0x01, 0x02, + 0x01, 0x00, 0x01, 0x30, 0x01, 0x11, 0x01, 0x36, 0x01, 0x38, 0x01, 0x3b, 0x01, 0x3a, 0x02, 0x00, 0x01, 0x2b, 0x01, 0x2c, 0x01, 0x2d, 0x01, 0x34, + 0x01, 0x35, 0x01, 0x00, 0x01, 0x02, 0x17, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x30, 0x01, 0x11, 0x01, 0x3c, 0x01, 0x23, 0x01, 0x10, 0x01, 0x37, + 0x02, 0x00, 0x01, 0x2b, 0x01, 0x2c, 0x01, 0x2d, 0x01, 0x2e, 0x01, 0x2f, 0x01, 0x00, 0x01, 0x02, 0x17, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x30, + 0x01, 0x31, 0x01, 0x3d, 0x01, 0x3e, 0x01, 0x3f, 0x01, 0x40, 0x02, 0x00, 0x01, 0x09, 0x01, 0x24, 0x01, 0x2d, 0x01, 0x12, 0x01, 0x41, 0x01, 0x01, + 0x01, 0x03, 0x17, 0x01, 0x01, 0x26, 0x01, 0x27, 0x01, 0x42, 0x01, 0x12, 0x01, 0x29, 0x01, 0x00, 0x01, 0x43, 0x03, 0x00, 0x01, 0x44, 0x01, 0x10, + 0x01, 0x45, 0x01, 0x46, 0x01, 0x47, 0x1b, 0x00, 0x01, 0x48, 0x01, 0x49, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, + 0x01, 0x1a, 0x01, 0x4a, 0x01, 0x4b, 0x01, 0x4c, 0x01, 0x14, 0x01, 0x4d, 0x17, 0x4e, 0x01, 0x2a, 0x01, 0x4f, 0x01, 0x42, 0x01, 0x10, 0x01, 0x50, + 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, 0x01, 0x0d, 0x01, 0x00, 0x01, 0x51, 0x01, 0x52, 0x01, 0x10, 0x1a, 0x53, 0x01, 0x12, 0x01, 0x10, + 0x01, 0x54, 0x01, 0x02, 0x01, 0x05, 0x01, 0x01, 0x04, 0x00, 0x01, 0x05, 0x01, 0x00, 0x01, 0x55, 0x01, 0x56, 0x01, 0x57, 0x01, 0x35, 0x16, 0x58, + 0x02, 0x35, 0x01, 0x59, 0x01, 0x5a, 0x09, 0x00, 0x01, 0x05, 0x1e, 0x00, 0x01, 0x01, 0x09, 0x00, 0x01, 0x01, 0x03, 0x02, 0x17, 0x03, 0x02, 0x02, + 0x01, 0x04, 0x07, 0x00, +}; +static const uint8_t battery_palette_1[] = { + 0x00, 0x00, 0x00, 0xf8, 0x00, 0x01, 0xf9, 0xe7, 0x04, 0xf9, 0x86, 0x05, 0xfa, 0xaa, 0x03, 0xf8, 0x00, 0x02, 0xf9, 0xc4, 0x0d, 0xf9, 0xe6, 0x5b, + 0xf9, 0xe6, 0x83, 0xf9, 0xc5, 0x85, 0xf9, 0xc5, 0x86, 0xf9, 0xc6, 0x84, 0xf9, 0xe6, 0x78, 0xf9, 0xe5, 0x36, 0xfb, 0xe0, 0x02, 0xf9, 0xc5, 0x34, + 0xf9, 0xe6, 0xe3, 0xfa, 0x06, 0xff, 0xf9, 0xc6, 0xfd, 0xf9, 0xc5, 0xfc, 0xf9, 0xe6, 0xff, 0xf9, 0xc6, 0xff, 0xf9, 0xc6, 0x98, 0xf9, 0xc7, 0x0d, + 0xf9, 0xe6, 0xe5, 0xf9, 0xe6, 0xe4, 0xf9, 0xc5, 0x32, 0xf9, 0xc5, 0x1b, 0xf9, 0xe5, 0x20, 0xf9, 0xc6, 0x1e, 0xf9, 0xc6, 0x1f, 0xf9, 0xe6, 0x19, + 0xf9, 0xa6, 0x0e, 0xfa, 0x26, 0x0f, 0xf9, 0xc5, 0x80, 0xf9, 0xc5, 0x75, 0xf9, 0xc5, 0x5b, 0xf9, 0xc5, 0x2d, 0xf9, 0xe6, 0x54, 0xf9, 0xe6, 0xe1, + 0xf9, 0xc6, 0xe7, 0xf9, 0xc6, 0xe8, 0xf9, 0xc5, 0x6c, 0xf9, 0xc6, 0xb7, 0xf9, 0xc6, 0xed, 0xf9, 0xe6, 0x15, 0xf9, 0xc6, 0xf6, 0xf9, 0xe5, 0x10, + 0xf9, 0x45, 0x06, 0xfa, 0xa0, 0x03, 0xf9, 0xc6, 0x79, 0xf9, 0x84, 0x0f, 0xf9, 0x65, 0x0b, 0xf9, 0xc6, 0x83, 0xf9, 0xa5, 0x21, 0xf9, 0xc6, 0xfe, + 0xf9, 0xe6, 0xfe, 0xf9, 0xc6, 0xf1, 0xf9, 0xa5, 0x17, 0xf9, 0xc5, 0x7c, 0xf9, 0xc5, 0x9b, 0xf9, 0xc6, 0x3e, 0xf9, 0xc6, 0xe9, 0xf9, 0xc6, 0xf2, + 0xf9, 0xc5, 0x16, 0xf9, 0xc6, 0x24, 0xf9, 0xc6, 0x8a, 0xf9, 0xc6, 0xe2, 0xfa, 0x06, 0xfd, 0xfa, 0x06, 0xfe, 0xf9, 0xa6, 0x25, 0xf9, 0xa4, 0x0e, + 0xf9, 0xc5, 0xa1, 0xfa, 0x06, 0xe9, 0xf9, 0xc5, 0x42, 0xf9, 0xc6, 0xee, 0xf9, 0xc6, 0xf7, 0xf9, 0xe5, 0x11, 0xf9, 0xc6, 0x78, 0xf9, 0x86, 0x0f, + 0xf9, 0xe6, 0x5d, 0xf9, 0xa5, 0x29, 0xf9, 0xe6, 0xe7, 0xf9, 0xc6, 0xec, 0xf9, 0xe6, 0xe8, 0xf9, 0xc6, 0x73, 0xf9, 0xc6, 0xb4, 0xf9, 0xc6, 0xef, + 0xf9, 0xe6, 0xe9, 0xf9, 0xe6, 0xdf, 0xf9, 0xc5, 0x2c, 0xf9, 0xc7, 0x09, 0xf9, 0xe7, 0x08, 0xf9, 0xe6, 0x14, 0xf9, 0xc6, 0x7a, 0xf9, 0xc5, 0x39, + 0xf9, 0xc6, 0xf8, 0xf9, 0xc5, 0xf6, 0xf9, 0xc5, 0xfb, 0xf9, 0xc6, 0x9f, 0xf9, 0xe6, 0x63, 0xf9, 0xe6, 0x8c, 0xf9, 0xc6, 0x8e, 0xf9, 0xc6, 0x8f, + 0xf9, 0xc6, 0x8d, 0xf9, 0xe6, 0x80, 0xf9, 0xc6, 0x3d, +}; +static const uint8_t battery_runs_1[] = { + 0x03, 0x00, 0x01, 0x01, 0x02, 0x02, 0x18, 0x03, 0x02, 0x02, 0x01, 0x04, 0x09, 0x00, 0x01, 0x05, 0x1e, 0x00, 0x01, 0x05, 0x07, 0x00, 0x01, 0x05, + 0x01, 0x00, 0x01, 0x06, 0x01, 0x07, 0x01, 0x08, 0x01, 0x09, 0x03, 0x0a, 0x13, 0x09, 0x02, 0x0b, 0x01, 0x0c, 0x01, 0x0d, 0x01, 0x00, 0x01, 0x01, + 0x05, 0x00, 0x01, 0x0e, 0x01, 0x00, 0x01, 0x0f, 0x01, 0x10, 0x01, 0x11, 0x01, 0x12, 0x03, 0x13, 0x01, 0x12, 0x01, 0x14, 0x14, 0x15, 0x01, 0x14, + 0x01, 0x11, 0x01, 0x16, 0x01, 0x0e, 0x01, 0x05, 0x01, 0x01, 0x03, 0x00, 0x01, 0x01, 0x01, 0x17, 0x01, 0x18, 0x01, 0x19, 0x01, 0x1a, 0x01, 0x1b, + 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x1e, 0x01, 0x1f, 0x01, 0x04, 0x01, 0x17, 0x11, 0x06, 0x01, 0x20, 0x01, 0x21, 0x01, 0x1f, 0x01, 0x22, 0x01, 0x11, + 0x01, 0x23, 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, 0x03, 0x00, 0x01, 0x24, 0x01, 0x11, 0x01, 0x25, 0x01, 0x26, 0x01, 0x27, 0x01, 0x28, 0x01, 0x29, + 0x01, 0x28, 0x01, 0x27, 0x01, 0x2a, 0x16, 0x00, 0x01, 0x2b, 0x01, 0x2c, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00, 0x01, 0x05, 0x02, 0x00, 0x01, 0x0b, + 0x01, 0x12, 0x01, 0x2d, 0x01, 0x2c, 0x05, 0x14, 0x01, 0x2e, 0x01, 0x2f, 0x01, 0x01, 0x01, 0x05, 0x11, 0x01, 0x01, 0x30, 0x01, 0x31, 0x01, 0x32, + 0x01, 0x14, 0x01, 0x33, 0x01, 0x00, 0x01, 0x34, 0x03, 0x00, 0x01, 0x35, 0x01, 0x12, 0x01, 0x36, 0x01, 0x29, 0x01, 0x37, 0x01, 0x12, 0x01, 0x37, + 0x01, 0x12, 0x01, 0x38, 0x01, 0x39, 0x01, 0x3a, 0x01, 0x00, 0x01, 0x01, 0x11, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x3b, 0x01, 0x38, 0x01, 0x06, + 0x01, 0x3c, 0x01, 0x19, 0x01, 0x3d, 0x02, 0x00, 0x01, 0x35, 0x01, 0x12, 0x01, 0x1e, 0x01, 0x3e, 0x01, 0x14, 0x01, 0x37, 0x01, 0x15, 0x01, 0x37, + 0x01, 0x14, 0x01, 0x3f, 0x01, 0x40, 0x01, 0x00, 0x01, 0x01, 0x11, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x3b, 0x01, 0x15, 0x01, 0x41, 0x01, 0x2c, + 0x01, 0x11, 0x01, 0x42, 0x02, 0x00, 0x01, 0x35, 0x01, 0x12, 0x01, 0x1e, 0x01, 0x3e, 0x01, 0x14, 0x01, 0x37, 0x01, 0x15, 0x01, 0x37, 0x01, 0x14, + 0x01, 0x3f, 0x01, 0x40, 0x01, 0x00, 0x01, 0x01, 0x11, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x3b, 0x01, 0x15, 0x01, 0x41, 0x01, 0x43, 0x01, 0x44, + 0x01, 0x08, 0x02, 0x00, 0x01, 0x35, 0x01, 0x12, 0x01, 0x1e, 0x01, 0x3e, 0x01, 0x14, 0x01, 0x37, 0x01, 0x15, 0x01, 0x37, 0x01, 0x14, 0x01, 0x3f, + 0x01, 0x40, 0x01, 0x00, 0x01, 0x01, 0x11, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x3b, 0x01, 0x15, 0x01, 0x41, 0x01, 0x43, 0x01, 0x45, 0x01, 0x08, + 0x02, 0x00, 0x01, 0x35, 0x01, 0x12, 0x01, 0x1e, 0x01, 0x3e, 0x01, 0x14, 0x01, 0x37, 0x01, 0x15, 0x01, 0x37, 0x01, 0x14, 0x01, 0x3f, 0x01, 0x40, + 0x01, 0x00, 0x01, 0x01, 0x11, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x3b, 0x01, 0x15, 0x01, 0x46, 0x01, 0x2c, 0x01, 0x11, 0x01, 0x42, 0x02, 0x00, + 0x01, 0x35, 0x01, 0x12, 0x01, 0x36, 0x01, 0x29, 0x01, 0x38, 0x01, 0x12, 0x01, 0x37, 0x01, 0x12, 0x01, 0x38, 0x01, 0x39, 0x01, 0x3a, 0x01, 0x00, + 0x01, 0x01, 0x11, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x3b, 0x01, 0x38, 0x01, 0x47, 0x01, 0x48, 0x01, 0x49, 0x01, 0x4a, 0x02, 0x00, 0x01, 0x0b, + 0x01, 0x12, 0x01, 0x40, 0x01, 0x4b, 0x05, 0x14, 0x01, 0x4c, 0x01, 0x4d, 0x01, 0x01, 0x01, 0x05, 0x11, 0x01, 0x01, 0x30, 0x01, 0x31, 0x01, 0x4e, + 0x01, 0x14, 0x01, 0x33, 0x01, 0x00, 0x01, 0x4f, 0x03, 0x00, 0x01, 0x50, 0x01, 0x11, 0x01, 0x51, 0x01, 0x24, 0x01, 0x52, 0x01, 0x53, 0x01, 0x4b, + 0x01, 0x53, 0x01, 0x54, 0x01, 0x55, 0x16, 0x00, 0x01, 0x56, 0x01, 0x57, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, + 0x01, 0x21, 0x01, 0x58, 0x01, 0x59, 0x01, 0x5a, 0x01, 0x1b, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x1e, 0x01, 0x1f, 0x01, 0x00, 0x02, 0x5b, 0x01, 0x5c, + 0x10, 0x5b, 0x01, 0x34, 0x01, 0x5d, 0x01, 0x4e, 0x01, 0x11, 0x01, 0x5e, 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, 0x01, 0x0e, 0x01, 0x00, + 0x01, 0x5f, 0x01, 0x58, 0x01, 0x11, 0x01, 0x60, 0x03, 0x61, 0x01, 0x4c, 0x01, 0x12, 0x14, 0x62, 0x01, 0x14, 0x01, 0x11, 0x01, 0x63, 0x01, 0x02, + 0x01, 0x05, 0x01, 0x01, 0x04, 0x00, 0x01, 0x05, 0x01, 0x00, 0x01, 0x4d, 0x01, 0x64, 0x01, 0x65, 0x01, 0x66, 0x03, 0x67, 0x13, 0x66, 0x02, 0x68, + 0x01, 0x69, 0x01, 0x6a, 0x09, 0x00, 0x01, 0x05, 0x1e, 0x00, 0x01, 0x01, 0x09, 0x00, 0x01, 0x01, 0x03, 0x02, 0x17, 0x03, 0x02, 0x02, 0x01, 0x04, + 0x07, 0x00, +}; +static const uint8_t battery_palette_2[] = { + 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0xff, 0xff, 0x04, 0xff, 0xff, 0x05, 0xff, 0xff, 0x03, 0xff, 0xff, 0x02, 0xff, 0xff, 0x0d, 0xff, 0xff, 0x5b, + 0xff, 0xff, 0x83, 0xff, 0xff, 0x85, 0xff, 0xff, 0x86, 0xff, 0xff, 0x84, 0xff, 0xff, 0x78, 0xff, 0xff, 0x36, 0xff, 0xff, 0x34, 0xff, 0xff, 0xe3, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfc, 0xff, 0xff, 0x98, 0xff, 0xff, 0xe5, 0xff, 0xff, 0xe4, 0xff, 0xff, 0x32, 0xff, 0xff, 0x1b, + 0xff, 0xff, 0x20, 0xff, 0xff, 0x1e, 0xff, 0xff, 0x1f, 0xff, 0xff, 0x19, 0xff, 0xff, 0x0e, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x80, 0xff, 0xff, 0x75, + 0xff, 0xff, 0x2d, 0xff, 0xff, 0x54, 0xff, 0xff, 0xe1, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xe9, 0xff, 0xff, 0x6c, 0xff, 0xff, 0xb7, 0xff, 0xff, 0xed, + 0xff, 0xff, 0x15, 0xff, 0xff, 0xf6, 0xff, 0xff, 0x10, 0xff, 0xff, 0x06, 0xff, 0xff, 0x79, 0xff, 0xff, 0x0b, 0xff, 0xff, 0x21, 0xff, 0xff, 0xe8, + 0xff, 0xff, 0xfe, 0xff, 0xff, 0xf1, 0xff, 0xff, 0x17, 0xff, 0xff, 0x7c, 0xff, 0xff, 0x9b, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xf2, 0xff, 0xff, 0x16, + 0xff, 0xff, 0x24, 0xff, 0xff, 0x8a, 0xff, 0xff, 0xe2, 0xff, 0xff, 0x25, 0xff, 0xff, 0xa1, 0xff, 0xff, 0x42, 0xff, 0xff, 0xee, 0xff, 0xff, 0xf7, + 0xff, 0xff, 0x11, 0xff, 0xff, 0x5d, 0xff, 0xff, 0x29, 0xff, 0xff, 0xec, 0xff, 0xff, 0xef, 0xff, 0xff, 0x73, 0xff, 0xff, 0xb4, 0xff, 0xff, 0xdf, + 0xff, 0xff, 0x2c, 0xff, 0xff, 0x09, 0xff, 0xff, 0x08, 0xff, 0xff, 0x14, 0xff, 0xff, 0x7a, 0xff, 0xff, 0x39, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xfb, + 0xff, 0xff, 0x9f, 0xff, 0xff, 0x63, 0xff, 0xff, 0x8c, 0xff, 0xff, 0x8e, 0xff, 0xff, 0x8f, 0xff, 0xff, 0x8d, 0xff, 0xff, 0x3d, +}; +static const uint8_t battery_runs_2[] = { + 0x03, 0x00, 0x01, 0x01, 0x02, 0x02, 0x18, 0x03, 0x02, 0x02, 0x01, 0x04, 0x09, 0x00, 0x01, 0x05, 0x1e, 0x00, 0x01, 0x05, 0x07, 0x00, 0x01, 0x05, + 0x01, 0x00, 0x01, 0x06, 0x01, 0x07, 0x01, 0x08, 0x01, 0x09, 0x0a, 0x0a, 0x0c, 0x09, 0x02, 0x0b, 0x01, 0x0c, 0x01, 0x0d, 0x01, 0x00, 0x01, 0x01, + 0x05, 0x00, 0x01, 0x05, 0x01, 0x00, 0x01, 0x0e, 0x01, 0x0f, 0x01, 0x10, 0x01, 0x11, 0x0a, 0x12, 0x01, 0x11, 0x10, 0x10, 0x01, 0x13, 0x02, 0x05, + 0x01, 0x01, 0x03, 0x00, 0x01, 0x01, 0x01, 0x06, 0x01, 0x14, 0x01, 0x15, 0x01, 0x16, 0x01, 0x17, 0x01, 0x18, 0x01, 0x19, 0x06, 0x1a, 0x01, 0x19, + 0x01, 0x1a, 0x01, 0x1b, 0x01, 0x04, 0x0b, 0x06, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x1b, 0x01, 0x1e, 0x01, 0x10, 0x01, 0x1f, 0x01, 0x00, 0x01, 0x02, + 0x01, 0x01, 0x03, 0x00, 0x01, 0x07, 0x01, 0x10, 0x01, 0x20, 0x01, 0x21, 0x01, 0x22, 0x01, 0x23, 0x08, 0x24, 0x01, 0x23, 0x01, 0x22, 0x01, 0x25, + 0x0f, 0x00, 0x01, 0x26, 0x01, 0x27, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00, 0x01, 0x05, 0x02, 0x00, 0x01, 0x0b, 0x01, 0x11, 0x01, 0x28, 0x01, 0x27, + 0x0c, 0x10, 0x01, 0x29, 0x01, 0x2a, 0x01, 0x01, 0x01, 0x05, 0x0a, 0x01, 0x01, 0x2b, 0x01, 0x04, 0x01, 0x2c, 0x01, 0x10, 0x01, 0x1d, 0x01, 0x00, + 0x01, 0x2d, 0x03, 0x00, 0x01, 0x08, 0x01, 0x11, 0x01, 0x2e, 0x01, 0x2f, 0x01, 0x30, 0x01, 0x11, 0x08, 0x30, 0x01, 0x11, 0x01, 0x30, 0x01, 0x31, + 0x01, 0x32, 0x01, 0x00, 0x01, 0x01, 0x0a, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x33, 0x01, 0x30, 0x01, 0x06, 0x01, 0x34, 0x01, 0x15, 0x01, 0x35, + 0x02, 0x00, 0x01, 0x08, 0x01, 0x11, 0x01, 0x1a, 0x01, 0x24, 0x01, 0x10, 0x01, 0x30, 0x08, 0x10, 0x01, 0x30, 0x01, 0x10, 0x01, 0x36, 0x01, 0x37, + 0x01, 0x00, 0x01, 0x01, 0x0a, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x33, 0x01, 0x10, 0x01, 0x38, 0x01, 0x27, 0x01, 0x10, 0x01, 0x39, 0x02, 0x00, + 0x01, 0x08, 0x01, 0x11, 0x01, 0x1a, 0x01, 0x24, 0x01, 0x10, 0x01, 0x30, 0x08, 0x10, 0x01, 0x30, 0x01, 0x10, 0x01, 0x36, 0x01, 0x37, 0x01, 0x00, + 0x01, 0x01, 0x0a, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x33, 0x01, 0x10, 0x01, 0x38, 0x01, 0x3a, 0x01, 0x11, 0x01, 0x08, 0x02, 0x00, 0x01, 0x08, + 0x01, 0x11, 0x01, 0x1a, 0x01, 0x24, 0x01, 0x10, 0x01, 0x30, 0x08, 0x10, 0x01, 0x30, 0x01, 0x10, 0x01, 0x36, 0x01, 0x37, 0x01, 0x00, 0x01, 0x01, + 0x0a, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x33, 0x01, 0x10, 0x01, 0x38, 0x01, 0x3a, 0x01, 0x30, 0x01, 0x08, 0x02, 0x00, 0x01, 0x08, 0x01, 0x11, + 0x01, 0x1a, 0x01, 0x24, 0x01, 0x10, 0x01, 0x30, 0x08, 0x10, 0x01, 0x30, 0x01, 0x10, 0x01, 0x36, 0x01, 0x37, 0x01, 0x00, 0x01, 0x01, 0x0a, 0x00, + 0x01, 0x02, 0x01, 0x00, 0x01, 0x33, 0x01, 0x10, 0x01, 0x3b, 0x01, 0x27, 0x01, 0x10, 0x01, 0x39, 0x02, 0x00, 0x01, 0x08, 0x01, 0x11, 0x01, 0x2e, + 0x01, 0x2f, 0x01, 0x30, 0x01, 0x11, 0x08, 0x30, 0x01, 0x11, 0x01, 0x30, 0x01, 0x31, 0x01, 0x32, 0x01, 0x00, 0x01, 0x01, 0x0a, 0x00, 0x01, 0x02, + 0x01, 0x00, 0x01, 0x33, 0x01, 0x30, 0x01, 0x1c, 0x01, 0x3c, 0x01, 0x24, 0x01, 0x3d, 0x02, 0x00, 0x01, 0x0b, 0x01, 0x11, 0x01, 0x37, 0x01, 0x3e, + 0x0c, 0x10, 0x01, 0x3f, 0x01, 0x40, 0x01, 0x01, 0x01, 0x05, 0x0a, 0x01, 0x01, 0x2b, 0x01, 0x04, 0x01, 0x0c, 0x01, 0x10, 0x01, 0x1d, 0x01, 0x00, + 0x01, 0x1d, 0x03, 0x00, 0x01, 0x41, 0x01, 0x10, 0x01, 0x42, 0x01, 0x07, 0x01, 0x23, 0x01, 0x43, 0x01, 0x3e, 0x07, 0x44, 0x01, 0x43, 0x01, 0x2f, + 0x01, 0x45, 0x0f, 0x00, 0x01, 0x46, 0x01, 0x44, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x1d, 0x01, 0x24, + 0x01, 0x47, 0x01, 0x48, 0x01, 0x17, 0x01, 0x18, 0x09, 0x1a, 0x01, 0x1b, 0x01, 0x00, 0x02, 0x49, 0x01, 0x4a, 0x09, 0x49, 0x01, 0x2d, 0x01, 0x4b, + 0x01, 0x0c, 0x01, 0x10, 0x01, 0x4c, 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, 0x01, 0x05, 0x01, 0x00, 0x01, 0x4d, 0x01, 0x24, 0x01, 0x10, + 0x01, 0x4e, 0x0a, 0x29, 0x01, 0x3f, 0x01, 0x11, 0x0d, 0x4f, 0x02, 0x10, 0x01, 0x50, 0x01, 0x02, 0x01, 0x05, 0x01, 0x01, 0x04, 0x00, 0x01, 0x05, + 0x01, 0x00, 0x01, 0x40, 0x01, 0x51, 0x01, 0x52, 0x01, 0x53, 0x0a, 0x54, 0x0c, 0x53, 0x02, 0x55, 0x01, 0x1e, 0x01, 0x56, 0x09, 0x00, 0x01, 0x05, + 0x1e, 0x00, 0x01, 0x01, 0x09, 0x00, 0x01, 0x01, 0x03, 0x02, 0x17, 0x03, 0x02, 0x02, 0x01, 0x04, 0x07, 0x00, +}; +static const uint8_t battery_palette_3[] = { + 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0xff, 0xff, 0x04, 0xff, 0xff, 0x05, 0xff, 0xff, 0x03, 0xff, 0xff, 0x02, 0xff, 0xff, 0x0d, 0xff, 0xff, 0x5b, + 0xff, 0xff, 0x83, 0xff, 0xff, 0x85, 0xff, 0xff, 0x86, 0xff, 0xff, 0x84, 0xff, 0xff, 0x78, 0xff, 0xff, 0x36, 0xff, 0xff, 0x34, 0xff, 0xff, 0xe3, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfc, 0xff, 0xff, 0x98, 0xff, 0xff, 0xe5, 0xff, 0xff, 0xe4, 0xff, 0xff, 0x32, 0xff, 0xff, 0x1b, + 0xff, 0xff, 0x20, 0xff, 0xff, 0x1e, 0xff, 0xff, 0x1f, 0xff, 0xff, 0x0a, 0xff, 0xff, 0x08, 0xff, 0xff, 0x0e, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x19, + 0xff, 0xff, 0x80, 0xff, 0xff, 0x75, 0xff, 0xff, 0x2d, 0xff, 0xff, 0x54, 0xff, 0xff, 0xe1, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xe8, + 0xff, 0xff, 0xc0, 0xff, 0xff, 0x18, 0xff, 0xff, 0xb7, 0xff, 0xff, 0xed, 0xff, 0xff, 0x15, 0xff, 0xff, 0x06, 0xff, 0xff, 0x79, 0xff, 0xff, 0x0b, + 0xff, 0xff, 0x21, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfa, 0xff, 0xff, 0x88, 0xff, 0xff, 0x7c, 0xff, 0xff, 0x9b, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xfb, + 0xff, 0xff, 0x24, 0xff, 0xff, 0x8a, 0xff, 0xff, 0x87, 0xff, 0xff, 0xe2, 0xff, 0xff, 0x25, 0xff, 0xff, 0xa1, 0xff, 0xff, 0x42, 0xff, 0xff, 0x16, + 0xff, 0xff, 0xee, 0xff, 0xff, 0x82, 0xff, 0xff, 0x5d, 0xff, 0xff, 0x29, 0xff, 0xff, 0xec, 0xff, 0xff, 0xef, 0xff, 0xff, 0xc7, 0xff, 0xff, 0x1c, + 0xff, 0xff, 0xb4, 0xff, 0xff, 0xdf, 0xff, 0xff, 0x2c, 0xff, 0xff, 0x09, 0xff, 0xff, 0x14, 0xff, 0xff, 0x7a, 0xff, 0xff, 0x39, 0xff, 0xff, 0xf8, + 0xff, 0xff, 0xf6, 0xff, 0xff, 0x9f, 0xff, 0xff, 0x11, 0xff, 0xff, 0x63, 0xff, 0xff, 0x8c, 0xff, 0xff, 0x8e, 0xff, 0xff, 0x8f, 0xff, 0xff, 0x8d, + 0xff, 0xff, 0x3d, +}; +static const uint8_t battery_runs_3[] = { + 0x03, 0x00, 0x01, 0x01, 0x02, 0x02, 0x18, 0x03, 0x02, 0x02, 0x01, 0x04, 0x09, 0x00, 0x01, 0x05, 0x1e, 0x00, 0x01, 0x05, 0x07, 0x00, 0x01, 0x05, + 0x01, 0x00, 0x01, 0x06, 0x01, 0x07, 0x01, 0x08, 0x01, 0x09, 0x11, 0x0a, 0x05, 0x09, 0x02, 0x0b, 0x01, 0x0c, 0x01, 0x0d, 0x01, 0x00, 0x01, 0x01, + 0x05, 0x00, 0x01, 0x05, 0x01, 0x00, 0x01, 0x0e, 0x01, 0x0f, 0x01, 0x10, 0x01, 0x11, 0x12, 0x12, 0x09, 0x10, 0x01, 0x13, 0x02, 0x05, 0x01, 0x01, + 0x03, 0x00, 0x01, 0x01, 0x01, 0x06, 0x01, 0x14, 0x01, 0x15, 0x01, 0x16, 0x01, 0x17, 0x01, 0x18, 0x01, 0x19, 0x0e, 0x1a, 0x02, 0x19, 0x01, 0x1b, + 0x01, 0x1c, 0x01, 0x1d, 0x02, 0x06, 0x01, 0x1d, 0x01, 0x1e, 0x01, 0x1f, 0x01, 0x20, 0x01, 0x10, 0x01, 0x21, 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, + 0x03, 0x00, 0x01, 0x07, 0x01, 0x10, 0x01, 0x22, 0x01, 0x23, 0x01, 0x24, 0x01, 0x25, 0x0f, 0x26, 0x02, 0x27, 0x01, 0x28, 0x01, 0x29, 0x07, 0x00, + 0x01, 0x2a, 0x01, 0x2b, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00, 0x01, 0x05, 0x02, 0x00, 0x01, 0x0b, 0x01, 0x11, 0x01, 0x2c, 0x01, 0x2b, 0x14, 0x10, + 0x01, 0x20, 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x2d, 0x01, 0x04, 0x01, 0x2e, 0x01, 0x10, 0x01, 0x1e, 0x01, 0x00, 0x01, 0x2f, 0x03, 0x00, + 0x01, 0x08, 0x01, 0x11, 0x01, 0x30, 0x01, 0x27, 0x01, 0x31, 0x01, 0x11, 0x10, 0x31, 0x01, 0x32, 0x01, 0x12, 0x01, 0x33, 0x01, 0x00, 0x01, 0x02, + 0x03, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x34, 0x01, 0x31, 0x01, 0x06, 0x01, 0x35, 0x01, 0x15, 0x01, 0x36, 0x02, 0x00, 0x01, 0x08, 0x01, 0x11, + 0x01, 0x1a, 0x01, 0x26, 0x01, 0x10, 0x01, 0x31, 0x10, 0x10, 0x01, 0x37, 0x01, 0x10, 0x01, 0x0a, 0x01, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, + 0x01, 0x00, 0x01, 0x34, 0x01, 0x10, 0x01, 0x38, 0x01, 0x2b, 0x01, 0x10, 0x01, 0x39, 0x02, 0x00, 0x01, 0x08, 0x01, 0x11, 0x01, 0x1a, 0x01, 0x26, + 0x01, 0x10, 0x01, 0x31, 0x10, 0x10, 0x01, 0x37, 0x01, 0x10, 0x01, 0x3a, 0x01, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x34, + 0x01, 0x10, 0x01, 0x38, 0x01, 0x3b, 0x01, 0x11, 0x01, 0x08, 0x02, 0x00, 0x01, 0x08, 0x01, 0x11, 0x01, 0x1a, 0x01, 0x26, 0x01, 0x10, 0x01, 0x31, + 0x10, 0x10, 0x01, 0x37, 0x01, 0x10, 0x01, 0x3a, 0x01, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x34, 0x01, 0x10, 0x01, 0x38, + 0x01, 0x3b, 0x01, 0x31, 0x01, 0x08, 0x02, 0x00, 0x01, 0x08, 0x01, 0x11, 0x01, 0x1a, 0x01, 0x26, 0x01, 0x10, 0x01, 0x31, 0x10, 0x10, 0x01, 0x37, + 0x01, 0x10, 0x01, 0x0a, 0x01, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x34, 0x01, 0x10, 0x01, 0x3c, 0x01, 0x2b, 0x01, 0x10, + 0x01, 0x39, 0x02, 0x00, 0x01, 0x08, 0x01, 0x11, 0x01, 0x30, 0x01, 0x27, 0x01, 0x31, 0x01, 0x11, 0x10, 0x31, 0x01, 0x32, 0x01, 0x11, 0x01, 0x33, + 0x01, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x34, 0x01, 0x31, 0x01, 0x1d, 0x01, 0x3d, 0x01, 0x26, 0x01, 0x3e, 0x02, 0x00, + 0x01, 0x0b, 0x01, 0x11, 0x01, 0x3f, 0x01, 0x40, 0x14, 0x10, 0x01, 0x41, 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x2d, 0x01, 0x04, 0x01, 0x0c, + 0x01, 0x10, 0x01, 0x1e, 0x01, 0x00, 0x01, 0x1e, 0x03, 0x00, 0x01, 0x42, 0x01, 0x10, 0x01, 0x43, 0x01, 0x07, 0x01, 0x25, 0x01, 0x44, 0x01, 0x40, + 0x0e, 0x45, 0x02, 0x40, 0x01, 0x46, 0x01, 0x47, 0x07, 0x00, 0x01, 0x48, 0x01, 0x45, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, + 0x01, 0x01, 0x01, 0x1e, 0x01, 0x26, 0x01, 0x49, 0x01, 0x4a, 0x01, 0x17, 0x01, 0x18, 0x0f, 0x1a, 0x01, 0x19, 0x01, 0x1a, 0x01, 0x4b, 0x01, 0x04, + 0x01, 0x4b, 0x01, 0x1c, 0x02, 0x4b, 0x01, 0x2f, 0x01, 0x4c, 0x01, 0x0c, 0x01, 0x10, 0x01, 0x4d, 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, + 0x01, 0x05, 0x01, 0x00, 0x01, 0x4e, 0x01, 0x26, 0x01, 0x10, 0x01, 0x4f, 0x12, 0x50, 0x01, 0x37, 0x01, 0x12, 0x05, 0x37, 0x02, 0x10, 0x01, 0x51, + 0x01, 0x02, 0x01, 0x05, 0x01, 0x01, 0x04, 0x00, 0x01, 0x05, 0x01, 0x00, 0x01, 0x52, 0x01, 0x53, 0x01, 0x54, 0x01, 0x55, 0x11, 0x56, 0x05, 0x55, + 0x02, 0x57, 0x01, 0x20, 0x01, 0x58, 0x09, 0x00, 0x01, 0x05, 0x1e, 0x00, 0x01, 0x01, 0x09, 0x00, 0x01, 0x01, 0x03, 0x02, 0x17, 0x03, 0x02, 0x02, + 0x01, 0x04, 0x07, 0x00, +}; +static const uint8_t battery_palette_4[] = { + 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0xff, 0xff, 0x04, 0xff, 0xff, 0x05, 0xff, 0xff, 0x03, 0xff, 0xff, 0x02, 0xff, 0xff, 0x0d, 0xff, 0xff, 0x5b, + 0xff, 0xff, 0x83, 0xff, 0xff, 0x85, 0xff, 0xff, 0x86, 0xff, 0xff, 0x78, 0xff, 0xff, 0x36, 0xff, 0xff, 0x34, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfd, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xfb, 0xff, 0xff, 0x97, 0xff, 0xff, 0xe5, 0xff, 0xff, 0xe4, 0xff, 0xff, 0x32, 0xff, 0xff, 0x1b, + 0xff, 0xff, 0x20, 0xff, 0xff, 0x1e, 0xff, 0xff, 0x1f, 0xff, 0xff, 0x17, 0xff, 0xff, 0x7c, 0xff, 0xff, 0x75, 0xff, 0xff, 0x2d, 0xff, 0xff, 0x54, + 0xff, 0xff, 0xe1, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xe9, 0xff, 0xff, 0xe8, 0xff, 0xff, 0xbe, 0xff, 0xff, 0x06, 0xff, 0xff, 0xb2, 0xff, 0xff, 0xee, + 0xff, 0xff, 0x84, 0xff, 0xff, 0x15, 0xff, 0xff, 0xed, 0xff, 0xff, 0x6d, 0xff, 0xff, 0x65, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0b, 0xff, 0xff, 0x21, + 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfa, 0xff, 0xff, 0x76, 0xff, 0xff, 0x69, 0xff, 0xff, 0x9b, 0xff, 0xff, 0x3e, 0xff, 0xff, 0x73, 0xff, 0xff, 0x6a, + 0xff, 0xff, 0x24, 0xff, 0xff, 0x8a, 0xff, 0xff, 0x74, 0xff, 0xff, 0xe2, 0xff, 0xff, 0x25, 0xff, 0xff, 0x0e, 0xff, 0xff, 0xa1, 0xff, 0xff, 0x42, + 0xff, 0xff, 0x16, 0xff, 0xff, 0x6e, 0xff, 0xff, 0x5d, 0xff, 0xff, 0x29, 0xff, 0xff, 0xec, 0xff, 0xff, 0xef, 0xff, 0xff, 0xc5, 0xff, 0xff, 0x08, + 0xff, 0xff, 0xae, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xdf, 0xff, 0xff, 0x2c, 0xff, 0xff, 0x14, 0xff, 0xff, 0x7a, 0xff, 0xff, 0x39, 0xff, 0xff, 0xf8, + 0xff, 0xff, 0xf6, 0xff, 0xff, 0xf5, 0xff, 0xff, 0x9e, 0xff, 0xff, 0x11, 0xff, 0xff, 0x63, 0xff, 0xff, 0x8c, 0xff, 0xff, 0x8e, 0xff, 0xff, 0x8f, + 0xff, 0xff, 0x81, 0xff, 0xff, 0x3d, +}; +static const uint8_t battery_runs_4[] = { + 0x03, 0x00, 0x01, 0x01, 0x02, 0x02, 0x18, 0x03, 0x02, 0x02, 0x01, 0x04, 0x09, 0x00, 0x01, 0x05, 0x1e, 0x00, 0x01, 0x05, 0x07, 0x00, 0x01, 0x05, + 0x01, 0x00, 0x01, 0x06, 0x01, 0x07, 0x01, 0x08, 0x01, 0x09, 0x16, 0x0a, 0x02, 0x09, 0x01, 0x0b, 0x01, 0x0c, 0x01, 0x00, 0x01, 0x01, 0x05, 0x00, + 0x01, 0x05, 0x01, 0x00, 0x01, 0x0d, 0x01, 0x0e, 0x01, 0x0f, 0x01, 0x10, 0x18, 0x11, 0x01, 0x12, 0x02, 0x0f, 0x01, 0x13, 0x02, 0x05, 0x01, 0x01, + 0x03, 0x00, 0x01, 0x01, 0x01, 0x06, 0x01, 0x14, 0x01, 0x15, 0x01, 0x16, 0x01, 0x17, 0x01, 0x18, 0x01, 0x19, 0x16, 0x1a, 0x01, 0x18, 0x01, 0x1b, + 0x01, 0x1c, 0x01, 0x0f, 0x01, 0x1d, 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, 0x03, 0x00, 0x01, 0x07, 0x01, 0x0f, 0x01, 0x1e, 0x01, 0x1f, 0x01, 0x20, + 0x01, 0x21, 0x16, 0x22, 0x02, 0x23, 0x01, 0x24, 0x01, 0x25, 0x01, 0x26, 0x01, 0x27, 0x01, 0x02, 0x01, 0x01, 0x01, 0x00, 0x01, 0x05, 0x02, 0x00, + 0x01, 0x28, 0x01, 0x10, 0x01, 0x29, 0x01, 0x2a, 0x1b, 0x0f, 0x01, 0x2b, 0x01, 0x2c, 0x01, 0x0f, 0x01, 0x2d, 0x01, 0x00, 0x01, 0x2e, 0x03, 0x00, + 0x01, 0x08, 0x01, 0x10, 0x01, 0x2f, 0x01, 0x23, 0x01, 0x30, 0x01, 0x10, 0x17, 0x30, 0x01, 0x31, 0x01, 0x11, 0x01, 0x32, 0x01, 0x33, 0x01, 0x30, + 0x01, 0x06, 0x01, 0x34, 0x01, 0x15, 0x01, 0x35, 0x02, 0x00, 0x01, 0x08, 0x01, 0x10, 0x01, 0x1a, 0x01, 0x22, 0x01, 0x0f, 0x01, 0x30, 0x17, 0x0f, + 0x01, 0x12, 0x01, 0x0f, 0x01, 0x36, 0x01, 0x37, 0x01, 0x0f, 0x01, 0x38, 0x01, 0x2a, 0x01, 0x0f, 0x01, 0x39, 0x02, 0x00, 0x01, 0x08, 0x01, 0x10, + 0x01, 0x1a, 0x01, 0x22, 0x01, 0x0f, 0x01, 0x30, 0x17, 0x0f, 0x01, 0x12, 0x01, 0x0f, 0x01, 0x3a, 0x01, 0x37, 0x01, 0x0f, 0x01, 0x38, 0x01, 0x3b, + 0x01, 0x10, 0x01, 0x08, 0x02, 0x00, 0x01, 0x08, 0x01, 0x10, 0x01, 0x1a, 0x01, 0x22, 0x01, 0x0f, 0x01, 0x30, 0x17, 0x0f, 0x01, 0x12, 0x01, 0x0f, + 0x01, 0x3a, 0x01, 0x37, 0x01, 0x0f, 0x01, 0x38, 0x01, 0x3b, 0x01, 0x30, 0x01, 0x08, 0x02, 0x00, 0x01, 0x08, 0x01, 0x10, 0x01, 0x1a, 0x01, 0x22, + 0x01, 0x0f, 0x01, 0x30, 0x17, 0x0f, 0x01, 0x12, 0x01, 0x0f, 0x01, 0x36, 0x01, 0x37, 0x01, 0x0f, 0x01, 0x3c, 0x01, 0x2a, 0x01, 0x0f, 0x01, 0x39, + 0x02, 0x00, 0x01, 0x08, 0x01, 0x10, 0x01, 0x2f, 0x01, 0x23, 0x01, 0x30, 0x01, 0x10, 0x17, 0x30, 0x01, 0x31, 0x01, 0x10, 0x01, 0x32, 0x01, 0x33, + 0x01, 0x30, 0x01, 0x3d, 0x01, 0x3e, 0x01, 0x22, 0x01, 0x3f, 0x02, 0x00, 0x01, 0x28, 0x01, 0x10, 0x01, 0x40, 0x01, 0x27, 0x1b, 0x0f, 0x01, 0x41, + 0x01, 0x2c, 0x01, 0x0f, 0x01, 0x2d, 0x01, 0x00, 0x01, 0x2d, 0x03, 0x00, 0x01, 0x42, 0x01, 0x0f, 0x01, 0x43, 0x01, 0x07, 0x01, 0x21, 0x01, 0x44, + 0x01, 0x27, 0x15, 0x45, 0x02, 0x27, 0x01, 0x46, 0x01, 0x47, 0x01, 0x48, 0x01, 0x49, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, + 0x01, 0x01, 0x01, 0x2d, 0x01, 0x22, 0x01, 0x4a, 0x01, 0x4b, 0x01, 0x17, 0x01, 0x18, 0x17, 0x1a, 0x01, 0x2f, 0x01, 0x4c, 0x01, 0x3a, 0x01, 0x0f, + 0x01, 0x4d, 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, 0x01, 0x05, 0x01, 0x00, 0x01, 0x4e, 0x01, 0x22, 0x01, 0x0f, 0x01, 0x4f, 0x18, 0x50, + 0x01, 0x51, 0x02, 0x0f, 0x01, 0x52, 0x01, 0x02, 0x01, 0x05, 0x01, 0x01, 0x04, 0x00, 0x01, 0x05, 0x01, 0x00, 0x01, 0x53, 0x01, 0x54, 0x01, 0x55, + 0x01, 0x56, 0x17, 0x57, 0x01, 0x56, 0x01, 0x58, 0x01, 0x59, 0x09, 0x00, 0x01, 0x05, 0x1e, 0x00, 0x01, 0x01, 0x09, 0x00, 0x01, 0x01, 0x03, 0x02, + 0x17, 0x03, 0x02, 0x02, 0x01, 0x04, 0x07, 0x00, +}; +static const uint8_t battery_palette_5[] = { + 0x00, 0x00, 0x00, 0x07, 0xe0, 0x01, 0x3d, 0xe7, 0x04, 0x3f, 0xef, 0x04, 0x36, 0x6c, 0x05, 0x55, 0x4a, 0x03, 0x07, 0xef, 0x02, 0x03, 0xef, 0x02, + 0x03, 0xe0, 0x02, 0x25, 0x89, 0x0d, 0x36, 0x6b, 0x5b, 0x36, 0x6b, 0x82, 0x36, 0x2b, 0x84, 0x36, 0x2b, 0x85, 0x36, 0x2b, 0x86, 0x2e, 0x2a, 0x83, + 0x36, 0x4b, 0x84, 0x36, 0x6b, 0x78, 0x36, 0x4b, 0x36, 0x00, 0x00, 0x01, 0x7f, 0xef, 0x02, 0x35, 0xeb, 0x34, 0x36, 0x6b, 0xe4, 0x3e, 0xcc, 0xff, + 0x36, 0x4b, 0xff, 0x36, 0x2a, 0xfa, 0x46, 0x8d, 0xff, 0x36, 0x6b, 0xff, 0x3e, 0xec, 0xff, 0x36, 0x2b, 0x98, 0x3e, 0x2c, 0x0d, 0x36, 0x6b, 0xe5, + 0x36, 0x8b, 0xe1, 0x36, 0x0a, 0x40, 0x2d, 0xeb, 0x10, 0x36, 0x4b, 0x0e, 0x3e, 0x29, 0x0d, 0x6e, 0x90, 0x11, 0x01, 0xe0, 0x04, 0xef, 0xdd, 0x70, + 0xef, 0xde, 0x45, 0x26, 0x29, 0x0d, 0x56, 0x6e, 0x0f, 0x36, 0x6a, 0x0f, 0x36, 0x0b, 0x19, 0x36, 0x4b, 0x80, 0x3f, 0x0c, 0xff, 0x36, 0x2b, 0x75, + 0x36, 0x2b, 0x5b, 0x35, 0xea, 0x3b, 0x36, 0x4b, 0xbf, 0x36, 0x4b, 0x6b, 0xff, 0xff, 0x4b, 0xff, 0xff, 0xd2, 0xff, 0xff, 0x02, 0x36, 0x4b, 0xb7, + 0x36, 0x2b, 0xed, 0x3d, 0xef, 0x04, 0x36, 0x2b, 0xfc, 0x36, 0xab, 0x19, 0x36, 0x2a, 0x94, 0x36, 0x66, 0x05, 0xbf, 0xf7, 0x04, 0xff, 0xdf, 0x2c, + 0xff, 0xff, 0xfc, 0xff, 0xff, 0x86, 0xe7, 0xff, 0x09, 0x2d, 0x4a, 0x06, 0x36, 0x2b, 0x79, 0x2d, 0xc8, 0x0b, 0x36, 0x2b, 0x83, 0x36, 0x2b, 0xfd, + 0x36, 0x6b, 0x1a, 0x36, 0x2b, 0xfa, 0x36, 0x2b, 0x8c, 0xff, 0xff, 0x19, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xf6, 0xff, 0xff, 0x12, 0x36, 0x2b, 0x7c, + 0x36, 0x6b, 0xfe, 0x36, 0x2b, 0x9b, 0x3e, 0xac, 0xe4, 0x36, 0x2b, 0x3e, 0x36, 0x2b, 0x8d, 0xff, 0xff, 0x0b, 0xff, 0xff, 0xcb, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xe8, 0xff, 0xff, 0x80, 0xff, 0xff, 0x7c, 0xff, 0xff, 0x88, 0xff, 0xff, 0x28, 0x36, 0x2a, 0x24, 0x36, 0x2b, 0x8a, 0xff, 0xff, 0x01, + 0xff, 0xff, 0xaf, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xb7, 0xff, 0xff, 0x0c, 0x36, 0x2b, 0xe2, 0x3e, 0xcc, 0xfd, 0xff, 0xff, 0x09, 0xff, 0xff, 0xab, + 0xff, 0xff, 0xb9, 0x3e, 0xcc, 0xfe, 0xff, 0xff, 0x26, 0xff, 0xff, 0x90, 0xff, 0xff, 0x84, 0xff, 0xff, 0x95, 0xff, 0xff, 0xfa, 0xff, 0xff, 0x0f, + 0x36, 0x2a, 0x25, 0xff, 0xff, 0x46, 0xff, 0xff, 0xe2, 0xff, 0xff, 0x1e, 0xff, 0xff, 0x03, 0x36, 0x2b, 0xa1, 0x3e, 0xcc, 0xe9, 0x36, 0x2b, 0x42, + 0x36, 0x2b, 0x93, 0xff, 0xff, 0x07, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x30, 0xff, 0xff, 0x04, 0x36, 0x2b, 0x78, 0x35, 0xca, 0x0f, + 0x36, 0x2b, 0x5e, 0x35, 0xea, 0x38, 0x36, 0x2b, 0xc6, 0x36, 0x2b, 0x70, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xfd, 0xff, 0xff, 0x48, 0x36, 0x2b, 0xb4, + 0x36, 0x2b, 0xef, 0x07, 0xff, 0x01, 0x36, 0x6b, 0xe9, 0x36, 0x8b, 0xdc, 0x36, 0x0b, 0x3c, 0x36, 0x69, 0x0a, 0x3e, 0x2a, 0x09, 0x6e, 0xb2, 0x0c, + 0x1d, 0x47, 0x09, 0xff, 0xff, 0x7e, 0xf7, 0xfe, 0x7a, 0x76, 0xb1, 0x0d, 0x3e, 0xeb, 0x08, 0x2d, 0xcb, 0x0b, 0x35, 0xeb, 0x14, 0x36, 0x4b, 0x78, + 0x36, 0x2b, 0x7a, 0x36, 0x0a, 0x39, 0x36, 0x6b, 0xea, 0x36, 0x2b, 0xfb, 0x3e, 0x4b, 0xfb, 0x76, 0xf1, 0xff, 0x2e, 0x2a, 0xf5, 0x36, 0x4b, 0x9f, + 0x2d, 0xa9, 0x11, 0x36, 0x6b, 0x64, 0x36, 0x4b, 0x8b, 0x36, 0x2a, 0x8e, 0x36, 0x2b, 0x8e, 0x2e, 0x0a, 0x8a, 0x36, 0x2b, 0x8f, 0x36, 0x4b, 0x8d, + 0x36, 0x6b, 0x80, 0x36, 0x4b, 0x3d, +}; +static const uint8_t battery_runs_5[] = { + 0x03, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x03, 0x18, 0x04, 0x02, 0x03, 0x01, 0x05, 0x09, 0x00, 0x01, 0x06, 0x1e, 0x00, 0x01, 0x07, 0x07, 0x00, + 0x01, 0x08, 0x01, 0x00, 0x01, 0x09, 0x01, 0x0a, 0x01, 0x0b, 0x02, 0x0c, 0x0c, 0x0d, 0x01, 0x0e, 0x01, 0x0f, 0x01, 0x0d, 0x01, 0x0c, 0x05, 0x0d, + 0x01, 0x0c, 0x01, 0x10, 0x01, 0x11, 0x01, 0x12, 0x01, 0x00, 0x01, 0x13, 0x05, 0x00, 0x01, 0x14, 0x01, 0x00, 0x01, 0x15, 0x01, 0x16, 0x01, 0x17, + 0x0f, 0x18, 0x01, 0x19, 0x01, 0x1a, 0x09, 0x18, 0x01, 0x1b, 0x01, 0x1c, 0x01, 0x1d, 0x01, 0x14, 0x01, 0x07, 0x01, 0x13, 0x03, 0x00, 0x01, 0x01, + 0x01, 0x1e, 0x01, 0x1f, 0x01, 0x20, 0x01, 0x21, 0x01, 0x22, 0x01, 0x23, 0x0a, 0x1e, 0x01, 0x24, 0x01, 0x25, 0x01, 0x26, 0x01, 0x27, 0x01, 0x28, + 0x01, 0x29, 0x01, 0x2a, 0x05, 0x1e, 0x01, 0x23, 0x01, 0x2b, 0x01, 0x2c, 0x01, 0x2d, 0x01, 0x2e, 0x01, 0x2f, 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, + 0x03, 0x00, 0x01, 0x30, 0x01, 0x17, 0x01, 0x31, 0x01, 0x32, 0x01, 0x33, 0x0d, 0x00, 0x01, 0x34, 0x01, 0x35, 0x01, 0x36, 0x0b, 0x00, 0x01, 0x37, + 0x01, 0x38, 0x01, 0x39, 0x01, 0x01, 0x01, 0x00, 0x01, 0x07, 0x02, 0x00, 0x01, 0x0c, 0x01, 0x3a, 0x01, 0x3b, 0x01, 0x1b, 0x01, 0x3c, 0x01, 0x01, + 0x01, 0x3d, 0x08, 0x01, 0x01, 0x3e, 0x01, 0x00, 0x01, 0x3f, 0x01, 0x40, 0x01, 0x41, 0x01, 0x3e, 0x01, 0x42, 0x01, 0x14, 0x07, 0x01, 0x01, 0x43, + 0x01, 0x05, 0x01, 0x44, 0x01, 0x1b, 0x01, 0x2b, 0x01, 0x00, 0x01, 0x45, 0x03, 0x00, 0x01, 0x46, 0x01, 0x47, 0x01, 0x48, 0x01, 0x49, 0x01, 0x4a, + 0x01, 0x00, 0x01, 0x02, 0x07, 0x00, 0x01, 0x36, 0x01, 0x00, 0x01, 0x4b, 0x01, 0x4c, 0x01, 0x4d, 0x01, 0x4e, 0x0a, 0x00, 0x01, 0x02, 0x01, 0x00, + 0x01, 0x4f, 0x01, 0x50, 0x01, 0x24, 0x01, 0x51, 0x01, 0x52, 0x01, 0x53, 0x02, 0x00, 0x01, 0x46, 0x01, 0x47, 0x01, 0x48, 0x01, 0x3a, 0x01, 0x54, + 0x01, 0x00, 0x01, 0x02, 0x06, 0x00, 0x02, 0x36, 0x01, 0x55, 0x01, 0x56, 0x01, 0x57, 0x01, 0x58, 0x01, 0x59, 0x01, 0x5a, 0x01, 0x5b, 0x01, 0x5c, + 0x01, 0x00, 0x01, 0x36, 0x05, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x4f, 0x01, 0x18, 0x01, 0x5d, 0x01, 0x38, 0x01, 0x2e, 0x01, 0x5e, 0x02, 0x00, + 0x01, 0x46, 0x01, 0x47, 0x01, 0x48, 0x01, 0x3a, 0x01, 0x54, 0x01, 0x00, 0x01, 0x02, 0x05, 0x00, 0x01, 0x5f, 0x02, 0x00, 0x01, 0x60, 0x01, 0x57, + 0x01, 0x61, 0x03, 0x57, 0x01, 0x62, 0x01, 0x63, 0x01, 0x36, 0x01, 0x5f, 0x05, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x4f, 0x01, 0x18, 0x01, 0x5d, + 0x01, 0x64, 0x01, 0x65, 0x01, 0x46, 0x02, 0x00, 0x01, 0x46, 0x01, 0x47, 0x01, 0x48, 0x01, 0x3a, 0x01, 0x54, 0x01, 0x00, 0x01, 0x02, 0x04, 0x00, + 0x01, 0x5f, 0x01, 0x36, 0x01, 0x66, 0x01, 0x67, 0x03, 0x57, 0x01, 0x61, 0x01, 0x57, 0x01, 0x68, 0x02, 0x00, 0x01, 0x5f, 0x06, 0x00, 0x01, 0x02, + 0x01, 0x00, 0x01, 0x4f, 0x01, 0x18, 0x01, 0x5d, 0x01, 0x64, 0x01, 0x69, 0x01, 0x46, 0x02, 0x00, 0x01, 0x46, 0x01, 0x47, 0x01, 0x48, 0x01, 0x3a, + 0x01, 0x54, 0x01, 0x00, 0x01, 0x02, 0x04, 0x00, 0x01, 0x36, 0x01, 0x00, 0x01, 0x6a, 0x01, 0x6b, 0x01, 0x6c, 0x01, 0x6d, 0x01, 0x6e, 0x01, 0x57, + 0x01, 0x35, 0x01, 0x6f, 0x01, 0x5f, 0x01, 0x36, 0x07, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x4f, 0x01, 0x18, 0x01, 0x70, 0x01, 0x38, 0x01, 0x2e, + 0x01, 0x5e, 0x02, 0x00, 0x01, 0x46, 0x01, 0x47, 0x01, 0x48, 0x01, 0x49, 0x01, 0x4a, 0x01, 0x00, 0x01, 0x02, 0x09, 0x00, 0x01, 0x71, 0x01, 0x57, + 0x01, 0x72, 0x01, 0x73, 0x01, 0x00, 0x01, 0x74, 0x08, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x4f, 0x01, 0x50, 0x01, 0x23, 0x01, 0x75, 0x01, 0x76, + 0x01, 0x77, 0x02, 0x00, 0x01, 0x0c, 0x01, 0x3a, 0x01, 0x48, 0x01, 0x1b, 0x01, 0x78, 0x01, 0x01, 0x01, 0x3d, 0x06, 0x01, 0x01, 0x14, 0x01, 0x79, + 0x01, 0x5f, 0x01, 0x7a, 0x01, 0x7b, 0x01, 0x7c, 0x01, 0x00, 0x01, 0x7d, 0x01, 0x13, 0x08, 0x01, 0x01, 0x43, 0x01, 0x05, 0x01, 0x7e, 0x01, 0x1b, + 0x01, 0x7f, 0x01, 0x00, 0x01, 0x7f, 0x03, 0x00, 0x01, 0x80, 0x01, 0x17, 0x01, 0x81, 0x01, 0x82, 0x01, 0x83, 0x0a, 0x00, 0x01, 0x84, 0x01, 0x85, + 0x01, 0x86, 0x01, 0x00, 0x01, 0x5f, 0x0c, 0x00, 0x01, 0x87, 0x01, 0x88, 0x01, 0x04, 0x01, 0x13, 0x01, 0x00, 0x01, 0x89, 0x01, 0x00, 0x01, 0x01, + 0x01, 0x2b, 0x01, 0x8a, 0x01, 0x8b, 0x01, 0x8c, 0x01, 0x24, 0x01, 0x8d, 0x07, 0x8e, 0x01, 0x8f, 0x01, 0x90, 0x01, 0x91, 0x01, 0x92, 0x01, 0x00, + 0x01, 0x93, 0x01, 0x94, 0x09, 0x8e, 0x01, 0x95, 0x01, 0x96, 0x01, 0x97, 0x01, 0x2e, 0x01, 0x98, 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, + 0x01, 0x14, 0x01, 0x00, 0x01, 0x99, 0x01, 0x9a, 0x01, 0x17, 0x0a, 0x9b, 0x01, 0x9c, 0x01, 0x9d, 0x01, 0x9e, 0x01, 0x47, 0x0c, 0x9b, 0x01, 0x18, + 0x01, 0x1c, 0x01, 0x9f, 0x01, 0x02, 0x01, 0x07, 0x01, 0x13, 0x04, 0x00, 0x01, 0x07, 0x01, 0x00, 0x01, 0xa0, 0x01, 0xa1, 0x01, 0xa2, 0x01, 0x54, + 0x08, 0xa3, 0x01, 0xa4, 0x01, 0xa5, 0x01, 0xa6, 0x01, 0xa4, 0x0a, 0xa3, 0x01, 0x54, 0x01, 0xa7, 0x01, 0xa8, 0x01, 0xa9, 0x09, 0x00, 0x01, 0x06, + 0x1e, 0x00, 0x01, 0x89, 0x09, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x03, 0x17, 0x04, 0x01, 0x39, 0x01, 0x03, 0x01, 0x05, 0x07, 0x00, +}; +static const uint8_t battery_palette_6[] = { + 0x00, 0x00, 0x00, 0x07, 0xe0, 0x01, 0x3d, 0xe7, 0x04, 0x3f, 0xef, 0x04, 0x36, 0x6c, 0x05, 0x55, 0x4a, 0x03, 0x07, 0xef, 0x02, 0x03, 0xef, 0x02, + 0x03, 0xe0, 0x02, 0x25, 0x89, 0x0d, 0x36, 0x6b, 0x5b, 0x36, 0x6b, 0x83, 0x36, 0x2b, 0x85, 0x36, 0x2b, 0x86, 0x2e, 0x2a, 0x83, 0x36, 0x2b, 0x84, + 0x36, 0x4b, 0x84, 0x36, 0x6b, 0x78, 0x36, 0x4b, 0x36, 0x00, 0x00, 0x01, 0x7f, 0xef, 0x02, 0x35, 0xeb, 0x34, 0x36, 0x6b, 0xe3, 0x3e, 0xec, 0xff, + 0x36, 0x2b, 0xfd, 0x36, 0x2b, 0xfc, 0x36, 0x4b, 0xff, 0x36, 0x2a, 0xfa, 0x46, 0x8d, 0xff, 0x36, 0x6b, 0xff, 0x36, 0x2b, 0x98, 0x3e, 0x2c, 0x0d, + 0x36, 0x6b, 0xe5, 0x36, 0x8b, 0xe4, 0x36, 0x0a, 0x32, 0x2e, 0x2a, 0x1b, 0x36, 0x6b, 0x20, 0x36, 0x0a, 0x1e, 0x36, 0x6b, 0x1f, 0x36, 0x0a, 0x19, + 0x3e, 0xac, 0x0d, 0x3e, 0x29, 0x0d, 0x6e, 0x90, 0x11, 0x01, 0xe0, 0x04, 0xef, 0xdd, 0x70, 0xef, 0xde, 0x45, 0x26, 0x29, 0x0d, 0x56, 0x6e, 0x0f, + 0x36, 0x4b, 0x0e, 0x36, 0x6a, 0x0f, 0x36, 0x0b, 0x19, 0x36, 0x4b, 0x80, 0x3f, 0x0c, 0xff, 0x36, 0x2b, 0x75, 0x36, 0x2b, 0x5b, 0x35, 0xca, 0x2d, + 0x36, 0x4b, 0x54, 0x36, 0x8b, 0xe1, 0x36, 0x2b, 0xe7, 0x36, 0x2b, 0xe8, 0x36, 0x2a, 0x6c, 0xff, 0xff, 0x4b, 0xff, 0xff, 0xd2, 0xff, 0xff, 0x02, + 0x36, 0x4b, 0xb7, 0x36, 0x2b, 0xed, 0x3d, 0xef, 0x04, 0x36, 0x6c, 0x15, 0x36, 0x8b, 0xff, 0x36, 0x2b, 0xf6, 0x3e, 0x6b, 0x10, 0x07, 0xe0, 0x02, + 0xbf, 0xf7, 0x04, 0xff, 0xdf, 0x2c, 0xff, 0xff, 0xfc, 0xff, 0xff, 0x86, 0xe7, 0xff, 0x09, 0x2d, 0x4a, 0x06, 0x36, 0x2b, 0x79, 0x2d, 0xc8, 0x0b, + 0x36, 0x2b, 0x83, 0x2e, 0x4b, 0x21, 0x36, 0x4b, 0xe8, 0x36, 0x4b, 0xfe, 0x36, 0x2b, 0xfe, 0x36, 0x2b, 0xf1, 0x36, 0x2b, 0x17, 0xff, 0xff, 0x19, + 0xff, 0xff, 0xe0, 0xff, 0xff, 0xf6, 0xff, 0xff, 0x12, 0x36, 0x2b, 0x7c, 0x36, 0x6b, 0xfe, 0x36, 0x2b, 0x9b, 0x3e, 0xac, 0xe4, 0x36, 0x2b, 0x3e, + 0x36, 0x2b, 0x1f, 0x36, 0x2b, 0xe9, 0x36, 0x2b, 0xff, 0x36, 0x2b, 0xf2, 0x3e, 0x2b, 0x16, 0xff, 0xff, 0x0b, 0xff, 0xff, 0xcb, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xe8, 0xff, 0xff, 0x80, 0xff, 0xff, 0x7c, 0xff, 0xff, 0x88, 0xff, 0xff, 0x28, 0x36, 0x2a, 0x24, 0x36, 0x2b, 0x8a, 0xff, 0xff, 0xaf, + 0xff, 0xff, 0xfb, 0xff, 0xff, 0xb7, 0xff, 0xff, 0x0c, 0xff, 0xff, 0x01, 0x36, 0x2b, 0xe2, 0x3e, 0xcc, 0xfd, 0xff, 0xff, 0x03, 0xff, 0xff, 0x09, + 0xff, 0xff, 0xab, 0xff, 0xff, 0xb9, 0x3e, 0xcc, 0xfe, 0xff, 0xff, 0x26, 0xff, 0xff, 0x90, 0xff, 0xff, 0x84, 0xff, 0xff, 0x95, 0xff, 0xff, 0xfa, + 0xff, 0xff, 0x0f, 0x36, 0x2a, 0x25, 0xff, 0xff, 0x46, 0xff, 0xff, 0xe2, 0xff, 0xff, 0x1e, 0x36, 0x2b, 0xa1, 0x3e, 0xcc, 0xe9, 0x36, 0x2b, 0x42, + 0x2e, 0x8b, 0x16, 0x36, 0x2b, 0xee, 0x36, 0x2b, 0xf7, 0x3e, 0x0b, 0x11, 0xff, 0xff, 0x07, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x30, + 0xff, 0xff, 0x04, 0x36, 0x2b, 0x78, 0x35, 0xca, 0x0f, 0x36, 0x4a, 0x5d, 0x36, 0x0a, 0x29, 0x36, 0x8b, 0xe7, 0x36, 0x4b, 0xec, 0x36, 0x6b, 0xe8, + 0x36, 0x2b, 0x73, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xfd, 0xff, 0xff, 0x48, 0x36, 0x2b, 0xb4, 0x36, 0x2b, 0xef, 0x07, 0xff, 0x01, 0x36, 0x6b, 0xe9, + 0x36, 0x8b, 0xdf, 0x35, 0xea, 0x2c, 0x36, 0x6b, 0x1e, 0x3e, 0x6b, 0x1f, 0x3e, 0x2a, 0x09, 0x3e, 0xeb, 0x08, 0x6e, 0xb2, 0x0c, 0x1d, 0x47, 0x09, + 0xff, 0xff, 0x7e, 0xf7, 0xfe, 0x7a, 0x76, 0xb1, 0x0d, 0x2d, 0xcb, 0x0b, 0x35, 0xeb, 0x14, 0x36, 0x4b, 0x78, 0x36, 0x2b, 0x7a, 0x36, 0x0a, 0x39, + 0x3e, 0xcc, 0xff, 0x36, 0x2b, 0xf8, 0x36, 0x2b, 0xfb, 0x3e, 0x4b, 0xfb, 0x76, 0xf1, 0xff, 0x2e, 0x2a, 0xf5, 0x36, 0x4b, 0x9f, 0x2d, 0xa9, 0x11, + 0x36, 0x6b, 0x63, 0x36, 0x6b, 0x8c, 0x36, 0x2b, 0x8e, 0x36, 0x2b, 0x8f, 0x36, 0x2a, 0x8e, 0x2e, 0x0a, 0x8a, 0x36, 0x2b, 0x8d, 0x36, 0x4b, 0x8d, + 0x36, 0x6b, 0x80, 0x36, 0x4b, 0x3d, +}; +static const uint8_t battery_runs_6[] = { + 0x03, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x03, 0x18, 0x04, 0x02, 0x03, 0x01, 0x05, 0x09, 0x00, 0x01, 0x06, 0x1e, 0x00, 0x01, 0x07, 0x07, 0x00, + 0x01, 0x08, 0x01, 0x00, 0x01, 0x09, 0x01, 0x0a, 0x01, 0x0b, 0x01, 0x0c, 0x03, 0x0d, 0x0a, 0x0c, 0x01, 0x0d, 0x01, 0x0e, 0x01, 0x0c, 0x01, 0x0f, + 0x05, 0x0c, 0x01, 0x0f, 0x01, 0x10, 0x01, 0x11, 0x01, 0x12, 0x01, 0x00, 0x01, 0x13, 0x05, 0x00, 0x01, 0x14, 0x01, 0x00, 0x01, 0x15, 0x01, 0x16, + 0x01, 0x17, 0x01, 0x18, 0x03, 0x19, 0x01, 0x18, 0x0a, 0x1a, 0x01, 0x1b, 0x01, 0x1c, 0x09, 0x1a, 0x01, 0x1d, 0x01, 0x17, 0x01, 0x1e, 0x01, 0x14, + 0x01, 0x07, 0x01, 0x13, 0x03, 0x00, 0x01, 0x01, 0x01, 0x1f, 0x01, 0x20, 0x01, 0x21, 0x01, 0x22, 0x01, 0x23, 0x01, 0x24, 0x01, 0x25, 0x01, 0x26, + 0x01, 0x27, 0x01, 0x05, 0x01, 0x28, 0x05, 0x1f, 0x01, 0x29, 0x01, 0x2a, 0x01, 0x2b, 0x01, 0x2c, 0x01, 0x2d, 0x01, 0x2e, 0x01, 0x2f, 0x05, 0x1f, + 0x01, 0x30, 0x01, 0x31, 0x01, 0x32, 0x01, 0x33, 0x01, 0x34, 0x01, 0x35, 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, 0x03, 0x00, 0x01, 0x36, 0x01, 0x17, + 0x01, 0x37, 0x01, 0x38, 0x01, 0x39, 0x01, 0x3a, 0x01, 0x3b, 0x01, 0x3a, 0x01, 0x39, 0x01, 0x3c, 0x08, 0x00, 0x01, 0x3d, 0x01, 0x3e, 0x01, 0x3f, + 0x0b, 0x00, 0x01, 0x40, 0x01, 0x41, 0x01, 0x42, 0x01, 0x01, 0x01, 0x00, 0x01, 0x07, 0x02, 0x00, 0x01, 0x0f, 0x01, 0x18, 0x01, 0x43, 0x01, 0x41, + 0x01, 0x44, 0x01, 0x1a, 0x01, 0x1d, 0x01, 0x1a, 0x01, 0x44, 0x01, 0x45, 0x01, 0x46, 0x01, 0x01, 0x01, 0x47, 0x02, 0x01, 0x01, 0x48, 0x01, 0x00, + 0x01, 0x49, 0x01, 0x4a, 0x01, 0x4b, 0x01, 0x48, 0x01, 0x4c, 0x01, 0x14, 0x07, 0x01, 0x01, 0x4d, 0x01, 0x05, 0x01, 0x4e, 0x01, 0x1d, 0x01, 0x31, + 0x01, 0x00, 0x01, 0x4f, 0x03, 0x00, 0x01, 0x50, 0x01, 0x18, 0x01, 0x51, 0x01, 0x52, 0x01, 0x53, 0x01, 0x18, 0x01, 0x54, 0x01, 0x18, 0x01, 0x53, + 0x01, 0x55, 0x01, 0x56, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x3f, 0x01, 0x00, 0x01, 0x57, 0x01, 0x58, 0x01, 0x59, 0x01, 0x5a, 0x0a, 0x00, + 0x01, 0x02, 0x01, 0x00, 0x01, 0x5b, 0x01, 0x5c, 0x01, 0x29, 0x01, 0x5d, 0x01, 0x5e, 0x01, 0x5f, 0x02, 0x00, 0x01, 0x50, 0x01, 0x18, 0x01, 0x60, + 0x01, 0x61, 0x01, 0x1a, 0x01, 0x54, 0x01, 0x62, 0x01, 0x54, 0x01, 0x1a, 0x01, 0x63, 0x01, 0x64, 0x01, 0x00, 0x01, 0x01, 0x02, 0x3f, 0x01, 0x65, + 0x01, 0x66, 0x01, 0x67, 0x01, 0x68, 0x01, 0x69, 0x01, 0x6a, 0x01, 0x6b, 0x01, 0x6c, 0x01, 0x00, 0x01, 0x3f, 0x05, 0x00, 0x01, 0x02, 0x01, 0x00, + 0x01, 0x5b, 0x01, 0x1a, 0x01, 0x6d, 0x01, 0x41, 0x01, 0x34, 0x01, 0x6e, 0x02, 0x00, 0x01, 0x50, 0x01, 0x18, 0x01, 0x60, 0x01, 0x61, 0x01, 0x1a, + 0x01, 0x54, 0x01, 0x62, 0x01, 0x54, 0x01, 0x1a, 0x01, 0x63, 0x01, 0x64, 0x01, 0x00, 0x01, 0x14, 0x02, 0x00, 0x01, 0x6f, 0x01, 0x67, 0x01, 0x70, + 0x03, 0x67, 0x01, 0x71, 0x01, 0x72, 0x01, 0x3f, 0x01, 0x73, 0x05, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x5b, 0x01, 0x1a, 0x01, 0x6d, 0x01, 0x74, + 0x01, 0x75, 0x01, 0x50, 0x02, 0x00, 0x01, 0x50, 0x01, 0x18, 0x01, 0x60, 0x01, 0x61, 0x01, 0x1a, 0x01, 0x54, 0x01, 0x62, 0x01, 0x54, 0x01, 0x1a, + 0x01, 0x63, 0x01, 0x64, 0x01, 0x00, 0x01, 0x76, 0x01, 0x77, 0x01, 0x78, 0x03, 0x67, 0x01, 0x70, 0x01, 0x67, 0x01, 0x79, 0x02, 0x00, 0x01, 0x73, + 0x06, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x5b, 0x01, 0x1a, 0x01, 0x6d, 0x01, 0x74, 0x01, 0x7a, 0x01, 0x50, 0x02, 0x00, 0x01, 0x50, 0x01, 0x18, + 0x01, 0x60, 0x01, 0x61, 0x01, 0x1a, 0x01, 0x54, 0x01, 0x62, 0x01, 0x54, 0x01, 0x1a, 0x01, 0x63, 0x01, 0x64, 0x02, 0x00, 0x01, 0x7b, 0x01, 0x7c, + 0x01, 0x7d, 0x01, 0x7e, 0x01, 0x7f, 0x01, 0x67, 0x01, 0x3e, 0x01, 0x80, 0x01, 0x73, 0x01, 0x3f, 0x07, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x5b, + 0x01, 0x1a, 0x01, 0x81, 0x01, 0x41, 0x01, 0x34, 0x01, 0x6e, 0x02, 0x00, 0x01, 0x50, 0x01, 0x18, 0x01, 0x51, 0x01, 0x3b, 0x01, 0x53, 0x01, 0x18, + 0x01, 0x54, 0x01, 0x18, 0x01, 0x53, 0x01, 0x55, 0x01, 0x56, 0x01, 0x00, 0x01, 0x01, 0x03, 0x00, 0x01, 0x82, 0x01, 0x67, 0x01, 0x83, 0x01, 0x84, + 0x01, 0x00, 0x01, 0x76, 0x08, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x5b, 0x01, 0x5c, 0x01, 0x30, 0x01, 0x85, 0x01, 0x86, 0x01, 0x87, 0x02, 0x00, + 0x01, 0x0f, 0x01, 0x18, 0x01, 0x88, 0x01, 0x89, 0x01, 0x44, 0x03, 0x1a, 0x01, 0x44, 0x01, 0x8a, 0x01, 0x8b, 0x01, 0x01, 0x01, 0x47, 0x01, 0x14, + 0x01, 0x8c, 0x01, 0x73, 0x01, 0x8d, 0x01, 0x8e, 0x01, 0x8f, 0x01, 0x00, 0x01, 0x90, 0x01, 0x13, 0x08, 0x01, 0x01, 0x4d, 0x01, 0x05, 0x01, 0x91, + 0x01, 0x1d, 0x01, 0x92, 0x01, 0x00, 0x01, 0x92, 0x03, 0x00, 0x01, 0x93, 0x01, 0x17, 0x01, 0x94, 0x01, 0x36, 0x01, 0x95, 0x01, 0x96, 0x01, 0x89, + 0x01, 0x96, 0x01, 0x97, 0x01, 0x98, 0x05, 0x00, 0x01, 0x99, 0x01, 0x9a, 0x01, 0x9b, 0x01, 0x00, 0x01, 0x73, 0x0c, 0x00, 0x01, 0x9c, 0x01, 0x9d, + 0x01, 0x04, 0x01, 0x13, 0x01, 0x00, 0x01, 0x9e, 0x01, 0x00, 0x01, 0x01, 0x01, 0x31, 0x01, 0x9f, 0x01, 0xa0, 0x01, 0xa1, 0x01, 0x23, 0x01, 0x24, + 0x01, 0xa2, 0x01, 0xa3, 0x01, 0x27, 0x01, 0x00, 0x02, 0xa4, 0x01, 0xa5, 0x01, 0xa6, 0x01, 0xa7, 0x01, 0xa8, 0x01, 0xa9, 0x01, 0x00, 0x01, 0xaa, + 0x01, 0xa5, 0x09, 0xa4, 0x01, 0xab, 0x01, 0xac, 0x01, 0xad, 0x01, 0x34, 0x01, 0xae, 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, 0x01, 0x14, + 0x01, 0x00, 0x01, 0xaf, 0x01, 0x9f, 0x01, 0xb0, 0x01, 0xb1, 0x03, 0x45, 0x01, 0x8a, 0x01, 0x18, 0x04, 0xb2, 0x01, 0xb3, 0x01, 0xb4, 0x01, 0xb5, + 0x01, 0x18, 0x0c, 0xb2, 0x01, 0x1a, 0x01, 0x17, 0x01, 0xb6, 0x01, 0x02, 0x01, 0x07, 0x01, 0x13, 0x04, 0x00, 0x01, 0x07, 0x01, 0x00, 0x01, 0xb7, + 0x01, 0xb8, 0x01, 0xb9, 0x01, 0xba, 0x03, 0xbb, 0x05, 0xbc, 0x01, 0xba, 0x01, 0xbd, 0x01, 0xbb, 0x01, 0xba, 0x0a, 0xbc, 0x01, 0xbe, 0x01, 0xbf, + 0x01, 0xc0, 0x01, 0xc1, 0x09, 0x00, 0x01, 0x06, 0x1e, 0x00, 0x01, 0x9e, 0x09, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x03, 0x17, 0x04, 0x01, 0x42, + 0x01, 0x03, 0x01, 0x05, 0x07, 0x00, +}; +static const uint8_t battery_palette_7[] = { + 0x00, 0x00, 0x00, 0x07, 0xe0, 0x01, 0x3d, 0xe7, 0x04, 0x3f, 0xef, 0x04, 0x36, 0x6c, 0x05, 0x55, 0x4a, 0x03, 0x07, 0xef, 0x02, 0x03, 0xef, 0x02, + 0x03, 0xe0, 0x02, 0x25, 0x89, 0x0d, 0x36, 0x6b, 0x5b, 0x36, 0x6b, 0x83, 0x36, 0x2b, 0x85, 0x36, 0x2b, 0x86, 0x2e, 0x2a, 0x83, 0x36, 0x2b, 0x84, + 0x36, 0x4b, 0x84, 0x36, 0x6b, 0x78, 0x36, 0x4b, 0x36, 0x00, 0x00, 0x01, 0x7f, 0xef, 0x02, 0x35, 0xeb, 0x34, 0x36, 0x6b, 0xe3, 0x3e, 0xec, 0xff, + 0x36, 0x2b, 0xfd, 0x36, 0x2b, 0xfc, 0x36, 0x4b, 0xff, 0x36, 0x2a, 0xfa, 0x46, 0x8d, 0xff, 0x36, 0x6b, 0xff, 0x36, 0x2b, 0x98, 0x3e, 0x2c, 0x0d, + 0x36, 0x6b, 0xe5, 0x36, 0x8b, 0xe4, 0x36, 0x0a, 0x32, 0x2e, 0x2a, 0x1b, 0x36, 0x6b, 0x20, 0x36, 0x6b, 0x1e, 0x36, 0x2b, 0x1f, 0x36, 0x6b, 0x1f, + 0x36, 0x0a, 0x19, 0x66, 0xaf, 0x12, 0x03, 0x20, 0x05, 0xef, 0xdd, 0x70, 0xef, 0xde, 0x45, 0x26, 0x29, 0x0d, 0x56, 0x6e, 0x0f, 0x36, 0x4b, 0x0e, + 0x36, 0x6a, 0x0f, 0x36, 0x0b, 0x19, 0x36, 0x4b, 0x80, 0x3f, 0x0c, 0xff, 0x36, 0x2b, 0x75, 0x36, 0x2b, 0x5b, 0x35, 0xca, 0x2d, 0x36, 0x4b, 0x54, + 0x36, 0x8b, 0xe1, 0x36, 0x2b, 0xe7, 0x36, 0x2b, 0xe9, 0x3e, 0x4b, 0x70, 0xff, 0xff, 0x4e, 0xff, 0xff, 0xd2, 0xff, 0xff, 0x02, 0x36, 0x4b, 0xb7, + 0x36, 0x2b, 0xed, 0x3d, 0xef, 0x04, 0x36, 0x6c, 0x15, 0x36, 0x8b, 0xff, 0x3e, 0xac, 0xff, 0x2e, 0x09, 0xed, 0xc7, 0x7a, 0x3c, 0xff, 0xff, 0xfc, + 0xff, 0xff, 0x87, 0xbf, 0xf7, 0x04, 0xe7, 0xff, 0x09, 0x2d, 0x4a, 0x06, 0x36, 0x2b, 0x79, 0x2d, 0xc8, 0x0b, 0x36, 0x2b, 0x83, 0x2e, 0x4b, 0x21, + 0x36, 0x4b, 0xe8, 0x36, 0x4b, 0xfe, 0x36, 0x2b, 0xfe, 0x2e, 0x2a, 0xfe, 0x46, 0x4c, 0xf2, 0xf7, 0xfe, 0xed, 0xff, 0xff, 0xf7, 0xf7, 0xfe, 0x13, + 0x36, 0x2b, 0x7c, 0x36, 0x6b, 0xfe, 0x3e, 0x29, 0x0d, 0x36, 0x2b, 0x9b, 0x3e, 0xac, 0xe4, 0x36, 0x2b, 0x3e, 0x36, 0x2b, 0xff, 0x36, 0x2a, 0xff, + 0xd7, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xea, 0xff, 0xff, 0x80, 0xff, 0xff, 0x7c, 0xff, 0xff, 0x88, 0xff, 0xff, 0x28, 0x36, 0x2a, 0x24, + 0x36, 0x2b, 0x8a, 0x2e, 0x2a, 0xff, 0xc7, 0x79, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xb7, 0xff, 0xff, 0x0c, 0xff, 0xff, 0x01, 0x36, 0x2b, 0xe2, + 0x3e, 0xcc, 0xfd, 0xbf, 0x79, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xb9, 0x3e, 0xcc, 0xfe, 0x56, 0x6e, 0xff, 0xa7, 0x36, 0xff, 0x9f, 0x15, 0xff, + 0xaf, 0x57, 0xff, 0xff, 0xff, 0xd3, 0xff, 0xff, 0x0f, 0x36, 0x2a, 0x25, 0x36, 0x2b, 0xe8, 0x36, 0x2a, 0xfe, 0x26, 0x09, 0xfe, 0x1d, 0xe8, 0xff, + 0x6e, 0xb0, 0xfd, 0xff, 0xff, 0xe5, 0xf7, 0xbe, 0x1f, 0xff, 0xff, 0x03, 0x36, 0x2b, 0xa1, 0x3e, 0xcc, 0xe9, 0x36, 0x2b, 0x42, 0x2e, 0x8b, 0x16, + 0x36, 0x2b, 0xee, 0x3e, 0x6b, 0xff, 0xcf, 0x9a, 0xff, 0xff, 0xff, 0xf4, 0xf7, 0xde, 0x33, 0xff, 0xff, 0x04, 0x36, 0x2b, 0x78, 0x35, 0xca, 0x0f, + 0x36, 0x4a, 0x5d, 0x36, 0x0a, 0x29, 0x36, 0x8b, 0xe7, 0x36, 0x4b, 0xec, 0x36, 0x2b, 0xef, 0x2e, 0x2a, 0xef, 0x4e, 0x8d, 0xf0, 0xff, 0xff, 0xfa, + 0xff, 0xff, 0x45, 0x36, 0x2b, 0xb4, 0x07, 0xff, 0x01, 0x36, 0x6b, 0xe9, 0x36, 0x8b, 0xdf, 0x35, 0xea, 0x2c, 0x4e, 0x4d, 0x22, 0x25, 0xe9, 0x1f, + 0xf7, 0xde, 0x8a, 0xf7, 0xde, 0x79, 0x76, 0xb1, 0x0d, 0x3e, 0xeb, 0x08, 0x3e, 0x2a, 0x09, 0x2d, 0xcb, 0x0b, 0x35, 0xeb, 0x14, 0x36, 0x4b, 0x78, + 0x36, 0x2b, 0x7a, 0x36, 0x0a, 0x39, 0x3e, 0xcc, 0xff, 0x36, 0x2b, 0xf8, 0x36, 0x2b, 0xf6, 0x3e, 0x4b, 0xf6, 0x6e, 0xf1, 0xff, 0x2e, 0x2a, 0xf5, + 0x36, 0x2b, 0xfb, 0x36, 0x4b, 0x9f, 0x2d, 0xa9, 0x11, 0x36, 0x6b, 0x63, 0x36, 0x6b, 0x8c, 0x36, 0x2b, 0x8e, 0x36, 0x2b, 0x8f, 0x2e, 0x2a, 0x8b, + 0x36, 0x2a, 0x8e, 0x36, 0x2b, 0x8d, 0x36, 0x4b, 0x8d, 0x36, 0x6b, 0x80, 0x36, 0x4b, 0x3d, +}; +static const uint8_t battery_runs_7[] = { + 0x03, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x03, 0x18, 0x04, 0x02, 0x03, 0x01, 0x05, 0x09, 0x00, 0x01, 0x06, 0x1e, 0x00, 0x01, 0x07, 0x07, 0x00, + 0x01, 0x08, 0x01, 0x00, 0x01, 0x09, 0x01, 0x0a, 0x01, 0x0b, 0x01, 0x0c, 0x0a, 0x0d, 0x03, 0x0c, 0x01, 0x0d, 0x01, 0x0e, 0x01, 0x0c, 0x01, 0x0f, + 0x05, 0x0c, 0x01, 0x0f, 0x01, 0x10, 0x01, 0x11, 0x01, 0x12, 0x01, 0x00, 0x01, 0x13, 0x05, 0x00, 0x01, 0x14, 0x01, 0x00, 0x01, 0x15, 0x01, 0x16, + 0x01, 0x17, 0x01, 0x18, 0x0a, 0x19, 0x01, 0x18, 0x03, 0x1a, 0x01, 0x1b, 0x01, 0x1c, 0x09, 0x1a, 0x01, 0x1d, 0x01, 0x17, 0x01, 0x1e, 0x01, 0x14, + 0x01, 0x07, 0x01, 0x13, 0x03, 0x00, 0x01, 0x01, 0x01, 0x1f, 0x01, 0x20, 0x01, 0x21, 0x01, 0x22, 0x01, 0x23, 0x01, 0x24, 0x01, 0x25, 0x06, 0x26, + 0x01, 0x25, 0x01, 0x27, 0x01, 0x28, 0x01, 0x06, 0x01, 0x29, 0x01, 0x2a, 0x01, 0x2b, 0x01, 0x2c, 0x01, 0x2d, 0x01, 0x2e, 0x05, 0x1f, 0x01, 0x2f, + 0x01, 0x30, 0x01, 0x31, 0x01, 0x32, 0x01, 0x33, 0x01, 0x34, 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, 0x03, 0x00, 0x01, 0x35, 0x01, 0x17, 0x01, 0x36, + 0x01, 0x37, 0x01, 0x38, 0x01, 0x39, 0x08, 0x3a, 0x01, 0x39, 0x01, 0x38, 0x01, 0x3b, 0x01, 0x00, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0x3e, 0x0b, 0x00, + 0x01, 0x3f, 0x01, 0x40, 0x01, 0x41, 0x01, 0x01, 0x01, 0x00, 0x01, 0x07, 0x02, 0x00, 0x01, 0x0f, 0x01, 0x18, 0x01, 0x42, 0x01, 0x40, 0x01, 0x43, + 0x0a, 0x1a, 0x01, 0x44, 0x01, 0x45, 0x01, 0x46, 0x01, 0x47, 0x01, 0x48, 0x01, 0x49, 0x01, 0x4a, 0x01, 0x14, 0x07, 0x01, 0x01, 0x4b, 0x01, 0x05, + 0x01, 0x4c, 0x01, 0x1d, 0x01, 0x30, 0x01, 0x00, 0x01, 0x4d, 0x03, 0x00, 0x01, 0x4e, 0x01, 0x18, 0x01, 0x4f, 0x01, 0x50, 0x01, 0x51, 0x01, 0x18, + 0x09, 0x52, 0x01, 0x53, 0x01, 0x54, 0x01, 0x55, 0x01, 0x56, 0x01, 0x57, 0x0a, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x58, 0x01, 0x59, 0x01, 0x5a, + 0x01, 0x5b, 0x01, 0x5c, 0x01, 0x5d, 0x02, 0x00, 0x01, 0x4e, 0x01, 0x18, 0x01, 0x26, 0x01, 0x3a, 0x01, 0x1a, 0x01, 0x52, 0x08, 0x5e, 0x01, 0x5f, + 0x01, 0x5e, 0x01, 0x60, 0x01, 0x61, 0x01, 0x62, 0x01, 0x63, 0x01, 0x64, 0x01, 0x65, 0x01, 0x66, 0x01, 0x00, 0x01, 0x3e, 0x05, 0x00, 0x01, 0x02, + 0x01, 0x00, 0x01, 0x58, 0x01, 0x1a, 0x01, 0x67, 0x01, 0x40, 0x01, 0x33, 0x01, 0x68, 0x02, 0x00, 0x01, 0x4e, 0x01, 0x18, 0x01, 0x26, 0x01, 0x3a, + 0x01, 0x1a, 0x01, 0x52, 0x07, 0x5e, 0x01, 0x5f, 0x01, 0x69, 0x01, 0x6a, 0x01, 0x61, 0x01, 0x6b, 0x03, 0x61, 0x01, 0x6c, 0x01, 0x6d, 0x01, 0x3e, + 0x01, 0x6e, 0x05, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x58, 0x01, 0x1a, 0x01, 0x67, 0x01, 0x6f, 0x01, 0x70, 0x01, 0x4e, 0x02, 0x00, 0x01, 0x4e, + 0x01, 0x18, 0x01, 0x26, 0x01, 0x3a, 0x01, 0x1a, 0x01, 0x52, 0x08, 0x5e, 0x01, 0x71, 0x03, 0x61, 0x01, 0x72, 0x01, 0x61, 0x01, 0x73, 0x02, 0x00, + 0x01, 0x6e, 0x06, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x58, 0x01, 0x1a, 0x01, 0x67, 0x01, 0x6f, 0x01, 0x74, 0x01, 0x4e, 0x02, 0x00, 0x01, 0x4e, + 0x01, 0x18, 0x01, 0x26, 0x01, 0x3a, 0x01, 0x1a, 0x01, 0x52, 0x06, 0x5e, 0x01, 0x69, 0x01, 0x75, 0x01, 0x76, 0x01, 0x77, 0x01, 0x78, 0x01, 0x47, + 0x01, 0x61, 0x01, 0x79, 0x01, 0x7a, 0x01, 0x6e, 0x01, 0x3e, 0x07, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x58, 0x01, 0x1a, 0x01, 0x7b, 0x01, 0x40, + 0x01, 0x33, 0x01, 0x68, 0x02, 0x00, 0x01, 0x4e, 0x01, 0x18, 0x01, 0x4f, 0x01, 0x7c, 0x01, 0x51, 0x01, 0x18, 0x07, 0x52, 0x01, 0x7d, 0x01, 0x7e, + 0x01, 0x7f, 0x01, 0x80, 0x01, 0x61, 0x01, 0x81, 0x01, 0x82, 0x01, 0x00, 0x01, 0x83, 0x08, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x58, 0x01, 0x59, + 0x01, 0x2f, 0x01, 0x84, 0x01, 0x85, 0x01, 0x86, 0x02, 0x00, 0x01, 0x0f, 0x01, 0x18, 0x01, 0x87, 0x01, 0x88, 0x01, 0x43, 0x09, 0x1a, 0x01, 0x89, + 0x01, 0x69, 0x01, 0x8a, 0x01, 0x8b, 0x01, 0x8c, 0x01, 0x00, 0x01, 0x8d, 0x01, 0x13, 0x08, 0x01, 0x01, 0x4b, 0x01, 0x05, 0x01, 0x8e, 0x01, 0x1d, + 0x01, 0x8f, 0x01, 0x00, 0x01, 0x8f, 0x03, 0x00, 0x01, 0x90, 0x01, 0x17, 0x01, 0x91, 0x01, 0x35, 0x01, 0x92, 0x01, 0x93, 0x01, 0x88, 0x07, 0x94, + 0x01, 0x95, 0x01, 0x96, 0x01, 0x97, 0x01, 0x98, 0x01, 0x00, 0x01, 0x6e, 0x0c, 0x00, 0x01, 0x99, 0x01, 0x94, 0x01, 0x04, 0x01, 0x13, 0x01, 0x00, + 0x01, 0x9a, 0x01, 0x00, 0x01, 0x01, 0x01, 0x30, 0x01, 0x9b, 0x01, 0x9c, 0x01, 0x9d, 0x01, 0x23, 0x01, 0x24, 0x07, 0x26, 0x01, 0x9e, 0x01, 0x9f, + 0x01, 0xa0, 0x01, 0xa1, 0x01, 0x00, 0x01, 0xa2, 0x01, 0xa3, 0x09, 0xa4, 0x01, 0xa5, 0x01, 0xa6, 0x01, 0xa7, 0x01, 0x33, 0x01, 0xa8, 0x01, 0x00, + 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, 0x01, 0x14, 0x01, 0x00, 0x01, 0xa9, 0x01, 0x9b, 0x01, 0xaa, 0x01, 0xab, 0x09, 0xac, 0x01, 0xad, 0x01, 0xae, + 0x01, 0xaf, 0x01, 0x18, 0x0c, 0xb0, 0x01, 0x1a, 0x01, 0x17, 0x01, 0xb1, 0x01, 0x02, 0x01, 0x07, 0x01, 0x13, 0x04, 0x00, 0x01, 0x07, 0x01, 0x00, + 0x01, 0xb2, 0x01, 0xb3, 0x01, 0xb4, 0x01, 0xb5, 0x09, 0xb6, 0x01, 0xb7, 0x01, 0xb6, 0x01, 0xb5, 0x0a, 0xb8, 0x01, 0xb9, 0x01, 0xba, 0x01, 0xbb, + 0x01, 0xbc, 0x09, 0x00, 0x01, 0x06, 0x1e, 0x00, 0x01, 0x9a, 0x09, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x03, 0x17, 0x04, 0x01, 0x41, 0x01, 0x03, + 0x01, 0x05, 0x07, 0x00, +}; +static const uint8_t battery_palette_8[] = { + 0x00, 0x00, 0x00, 0x07, 0xe0, 0x01, 0x3d, 0xe7, 0x04, 0x3f, 0xef, 0x04, 0x36, 0x6c, 0x05, 0x55, 0x4a, 0x03, 0x07, 0xef, 0x02, 0x03, 0xef, 0x02, + 0x03, 0xe0, 0x02, 0x25, 0x89, 0x0d, 0x36, 0x6b, 0x5b, 0x36, 0x6b, 0x83, 0x36, 0x2b, 0x85, 0x36, 0x2b, 0x86, 0x2e, 0x2a, 0x84, 0x36, 0x2b, 0x84, + 0x36, 0x4b, 0x84, 0x36, 0x6b, 0x78, 0x36, 0x4b, 0x36, 0x00, 0x00, 0x01, 0x7f, 0xef, 0x02, 0x35, 0xeb, 0x34, 0x36, 0x6b, 0xe3, 0x3e, 0xec, 0xff, + 0x36, 0x2b, 0xfd, 0x36, 0x2b, 0xfc, 0x36, 0x2a, 0xf9, 0x46, 0x6d, 0xff, 0x36, 0x4b, 0xff, 0x36, 0x6b, 0xff, 0x36, 0x2b, 0x98, 0x3e, 0x2c, 0x0d, + 0x36, 0x6b, 0xe5, 0x36, 0x8b, 0xe4, 0x36, 0x0a, 0x32, 0x2e, 0x2a, 0x1b, 0x36, 0x6b, 0x20, 0x36, 0x6b, 0x1e, 0x36, 0x2b, 0x1f, 0x36, 0x2a, 0x1f, + 0x56, 0x8e, 0x21, 0x05, 0xa5, 0x1f, 0xe7, 0xdd, 0x74, 0xcf, 0x7a, 0x54, 0x2e, 0x0a, 0x1e, 0x46, 0xac, 0x20, 0x36, 0x69, 0x0a, 0x3d, 0xeb, 0x08, + 0x36, 0x4b, 0x0e, 0x36, 0x6a, 0x0f, 0x36, 0x0b, 0x19, 0x36, 0x4b, 0x80, 0x3f, 0x0c, 0xff, 0x36, 0x2b, 0x75, 0x36, 0x2b, 0x5b, 0x35, 0xca, 0x2d, + 0x36, 0x4b, 0x54, 0x36, 0x8b, 0xe1, 0x36, 0x2b, 0xe7, 0x36, 0x2b, 0xe9, 0x3e, 0x4b, 0xe9, 0x26, 0x09, 0xe9, 0x7e, 0xd2, 0xe9, 0xdf, 0xbc, 0xfd, + 0x36, 0x2a, 0xec, 0x36, 0x2b, 0xe8, 0x36, 0x4b, 0xe8, 0x36, 0x4b, 0xc0, 0x36, 0x4a, 0x18, 0x36, 0x4b, 0xb7, 0x36, 0x2b, 0xed, 0x3d, 0xef, 0x04, + 0x36, 0x6c, 0x15, 0x36, 0x8b, 0xff, 0x3e, 0x6b, 0xff, 0x2e, 0x4a, 0xff, 0x56, 0xae, 0xff, 0xff, 0xff, 0xff, 0x9f, 0x36, 0xff, 0x26, 0x29, 0xff, + 0x3e, 0x6c, 0xff, 0x36, 0x2b, 0x80, 0x36, 0x66, 0x05, 0x2d, 0x4a, 0x06, 0x36, 0x2b, 0x79, 0x2d, 0xc8, 0x0b, 0x36, 0x2b, 0x83, 0x2e, 0x4b, 0x21, + 0x36, 0x4b, 0xfe, 0x36, 0x2b, 0xfe, 0x2e, 0x2a, 0xfe, 0x46, 0x4c, 0xfe, 0xe7, 0xbd, 0xfe, 0xff, 0xff, 0xfe, 0x46, 0x4c, 0xff, 0x1e, 0x08, 0xfe, + 0x26, 0x09, 0xfe, 0x2e, 0x2a, 0xfa, 0x3e, 0xac, 0xfc, 0x36, 0x4b, 0x88, 0x36, 0x2b, 0x7c, 0x36, 0x6b, 0xfe, 0x3e, 0x29, 0x0d, 0x36, 0x2b, 0x9b, + 0x3e, 0xac, 0xe4, 0x36, 0x2b, 0x3e, 0x36, 0x2b, 0xff, 0x36, 0x2a, 0xff, 0xd7, 0xbb, 0xff, 0xef, 0xde, 0xff, 0x9f, 0x15, 0xff, 0x97, 0x15, 0xff, + 0xa7, 0x36, 0xff, 0x56, 0x8e, 0xfb, 0x36, 0xab, 0xff, 0x36, 0x4b, 0x86, 0x36, 0x2a, 0x24, 0x36, 0x2b, 0x8a, 0x2e, 0x2a, 0xff, 0xc7, 0x79, 0xff, + 0xc7, 0x7a, 0xff, 0x36, 0x2b, 0xfb, 0x3e, 0xab, 0xff, 0x36, 0x4b, 0x87, 0x36, 0x2b, 0xe2, 0x3e, 0xcc, 0xfd, 0xbf, 0x79, 0xff, 0xcf, 0x9a, 0xff, + 0x2e, 0x2a, 0xfb, 0x3e, 0xac, 0xff, 0x3e, 0xcc, 0xfe, 0x56, 0x6e, 0xff, 0xaf, 0x57, 0xff, 0xdf, 0xbc, 0xff, 0x3e, 0x4b, 0xff, 0x36, 0x2a, 0x25, + 0x36, 0x2a, 0xfe, 0x1d, 0xe8, 0xfe, 0x6e, 0xb0, 0xff, 0xef, 0xdd, 0xfe, 0x4e, 0x6d, 0xfe, 0x36, 0x2b, 0xfa, 0x3e, 0xab, 0xfd, 0x36, 0x2b, 0xa1, + 0x3e, 0xcc, 0xe9, 0x36, 0x2b, 0x42, 0x2e, 0x8b, 0x16, 0x36, 0x2b, 0xee, 0x36, 0x2b, 0x82, 0x36, 0x2b, 0x78, 0x35, 0xca, 0x0f, 0x36, 0x4a, 0x5d, + 0x36, 0x0a, 0x29, 0x36, 0x8b, 0xe7, 0x36, 0x4b, 0xec, 0x36, 0x2b, 0xef, 0x2e, 0x2a, 0xef, 0x4e, 0x6d, 0xf3, 0x76, 0xd1, 0xef, 0x26, 0x09, 0xef, + 0x3e, 0x4b, 0xef, 0x36, 0x4b, 0xee, 0x36, 0x4b, 0xc7, 0x36, 0x4b, 0x1c, 0x36, 0x2b, 0xb4, 0x07, 0xff, 0x01, 0x36, 0x6b, 0xe9, 0x36, 0x8b, 0xdf, + 0x35, 0xea, 0x2c, 0x4e, 0x4d, 0x22, 0x26, 0x29, 0x1f, 0xf7, 0xde, 0x8a, 0xef, 0xde, 0x7e, 0x05, 0xa4, 0x1f, 0x3e, 0x6b, 0x1f, 0x3d, 0x4a, 0x09, + 0x57, 0xea, 0x03, 0x3e, 0x2a, 0x09, 0x2d, 0xcb, 0x0b, 0x35, 0xeb, 0x14, 0x36, 0x4b, 0x78, 0x36, 0x2b, 0x7a, 0x36, 0x0a, 0x39, 0x3e, 0xcc, 0xff, + 0x36, 0x2b, 0xf8, 0x36, 0x2b, 0xf6, 0x3e, 0x4b, 0xf6, 0x6e, 0xf1, 0xff, 0x2e, 0x2a, 0xf4, 0x36, 0x4b, 0x9f, 0x2d, 0xa9, 0x11, 0x36, 0x6b, 0x63, + 0x36, 0x6b, 0x8c, 0x36, 0x2b, 0x8e, 0x36, 0x2b, 0x8f, 0x2e, 0x2a, 0x8b, 0x36, 0x2a, 0x8e, 0x36, 0x2b, 0x8d, 0x36, 0x4b, 0x8d, 0x36, 0x6b, 0x80, + 0x36, 0x4b, 0x3d, +}; +static const uint8_t battery_runs_8[] = { + 0x03, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x03, 0x18, 0x04, 0x02, 0x03, 0x01, 0x05, 0x09, 0x00, 0x01, 0x06, 0x1e, 0x00, 0x01, 0x07, 0x07, 0x00, + 0x01, 0x08, 0x01, 0x00, 0x01, 0x09, 0x01, 0x0a, 0x01, 0x0b, 0x01, 0x0c, 0x0e, 0x0d, 0x01, 0x0e, 0x02, 0x0d, 0x05, 0x0c, 0x01, 0x0f, 0x01, 0x10, + 0x01, 0x11, 0x01, 0x12, 0x01, 0x00, 0x01, 0x13, 0x05, 0x00, 0x01, 0x14, 0x01, 0x00, 0x01, 0x15, 0x01, 0x16, 0x01, 0x17, 0x01, 0x18, 0x0e, 0x19, + 0x01, 0x1a, 0x01, 0x1b, 0x02, 0x19, 0x07, 0x1c, 0x01, 0x1d, 0x01, 0x17, 0x01, 0x1e, 0x01, 0x14, 0x01, 0x07, 0x01, 0x13, 0x03, 0x00, 0x01, 0x01, + 0x01, 0x1f, 0x01, 0x20, 0x01, 0x21, 0x01, 0x22, 0x01, 0x23, 0x01, 0x24, 0x01, 0x25, 0x09, 0x26, 0x01, 0x27, 0x01, 0x28, 0x01, 0x29, 0x01, 0x2a, + 0x01, 0x2b, 0x01, 0x2c, 0x01, 0x2d, 0x01, 0x2e, 0x01, 0x2f, 0x01, 0x30, 0x02, 0x1f, 0x01, 0x30, 0x01, 0x31, 0x01, 0x32, 0x01, 0x33, 0x01, 0x34, + 0x01, 0x35, 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, 0x03, 0x00, 0x01, 0x36, 0x01, 0x17, 0x01, 0x37, 0x01, 0x38, 0x01, 0x39, 0x01, 0x3a, 0x0a, 0x3b, + 0x01, 0x3c, 0x01, 0x3d, 0x01, 0x3e, 0x01, 0x3f, 0x01, 0x40, 0x01, 0x41, 0x01, 0x42, 0x01, 0x43, 0x01, 0x44, 0x07, 0x00, 0x01, 0x45, 0x01, 0x46, + 0x01, 0x47, 0x01, 0x01, 0x01, 0x00, 0x01, 0x07, 0x02, 0x00, 0x01, 0x0f, 0x01, 0x18, 0x01, 0x48, 0x01, 0x46, 0x01, 0x49, 0x0a, 0x1c, 0x01, 0x4a, + 0x01, 0x4b, 0x01, 0x4c, 0x01, 0x4d, 0x01, 0x4e, 0x01, 0x4f, 0x01, 0x50, 0x01, 0x1c, 0x01, 0x17, 0x01, 0x51, 0x01, 0x01, 0x01, 0x52, 0x03, 0x01, + 0x01, 0x53, 0x01, 0x05, 0x01, 0x54, 0x01, 0x1d, 0x01, 0x31, 0x01, 0x00, 0x01, 0x55, 0x03, 0x00, 0x01, 0x56, 0x01, 0x18, 0x01, 0x57, 0x01, 0x42, + 0x01, 0x58, 0x01, 0x18, 0x09, 0x59, 0x01, 0x5a, 0x01, 0x5b, 0x01, 0x5c, 0x01, 0x5d, 0x01, 0x5e, 0x01, 0x5f, 0x01, 0x60, 0x01, 0x61, 0x01, 0x62, + 0x01, 0x63, 0x01, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x64, 0x01, 0x65, 0x01, 0x66, 0x01, 0x67, 0x01, 0x68, 0x01, 0x69, + 0x02, 0x00, 0x01, 0x56, 0x01, 0x18, 0x01, 0x26, 0x01, 0x3b, 0x01, 0x1c, 0x01, 0x59, 0x08, 0x6a, 0x01, 0x6b, 0x01, 0x1c, 0x01, 0x6c, 0x01, 0x4d, + 0x01, 0x6d, 0x01, 0x6e, 0x01, 0x6f, 0x01, 0x70, 0x01, 0x71, 0x01, 0x72, 0x01, 0x73, 0x01, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x01, 0x00, + 0x01, 0x64, 0x01, 0x1c, 0x01, 0x74, 0x01, 0x46, 0x01, 0x34, 0x01, 0x75, 0x02, 0x00, 0x01, 0x56, 0x01, 0x18, 0x01, 0x26, 0x01, 0x3b, 0x01, 0x1c, + 0x01, 0x59, 0x07, 0x6a, 0x01, 0x6b, 0x01, 0x76, 0x01, 0x77, 0x05, 0x4d, 0x01, 0x78, 0x01, 0x79, 0x01, 0x7a, 0x01, 0x7b, 0x01, 0x00, 0x01, 0x02, + 0x03, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x64, 0x01, 0x1c, 0x01, 0x74, 0x01, 0x7c, 0x01, 0x7d, 0x01, 0x56, 0x02, 0x00, 0x01, 0x56, 0x01, 0x18, + 0x01, 0x26, 0x01, 0x3b, 0x01, 0x1c, 0x01, 0x59, 0x08, 0x6a, 0x01, 0x7e, 0x05, 0x4d, 0x01, 0x7f, 0x01, 0x76, 0x01, 0x80, 0x01, 0x81, 0x01, 0x7b, + 0x01, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x64, 0x01, 0x1c, 0x01, 0x74, 0x01, 0x7c, 0x01, 0x82, 0x01, 0x56, 0x02, 0x00, + 0x01, 0x56, 0x01, 0x18, 0x01, 0x26, 0x01, 0x3b, 0x01, 0x1c, 0x01, 0x59, 0x06, 0x6a, 0x01, 0x76, 0x01, 0x83, 0x01, 0x70, 0x01, 0x6e, 0x01, 0x84, + 0x02, 0x4d, 0x01, 0x85, 0x01, 0x86, 0x01, 0x6b, 0x01, 0x79, 0x01, 0x7a, 0x01, 0x73, 0x01, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x01, 0x00, + 0x01, 0x64, 0x01, 0x1c, 0x01, 0x87, 0x01, 0x46, 0x01, 0x34, 0x01, 0x75, 0x02, 0x00, 0x01, 0x56, 0x01, 0x18, 0x01, 0x57, 0x01, 0x41, 0x01, 0x58, + 0x01, 0x18, 0x07, 0x59, 0x01, 0x88, 0x01, 0x60, 0x01, 0x89, 0x01, 0x8a, 0x01, 0x5d, 0x01, 0x8b, 0x01, 0x8c, 0x01, 0x5a, 0x01, 0x59, 0x01, 0x8d, + 0x01, 0x8e, 0x01, 0x63, 0x01, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x01, 0x00, 0x01, 0x64, 0x01, 0x65, 0x01, 0x30, 0x01, 0x8f, 0x01, 0x90, + 0x01, 0x91, 0x02, 0x00, 0x01, 0x0f, 0x01, 0x18, 0x01, 0x92, 0x01, 0x93, 0x01, 0x49, 0x09, 0x1c, 0x01, 0x4a, 0x01, 0x76, 0x01, 0x7f, 0x01, 0x4d, + 0x01, 0x4c, 0x01, 0x76, 0x01, 0x86, 0x01, 0x1c, 0x01, 0x6a, 0x01, 0x17, 0x01, 0x94, 0x01, 0x01, 0x01, 0x52, 0x03, 0x01, 0x01, 0x53, 0x01, 0x05, + 0x01, 0x95, 0x01, 0x1d, 0x01, 0x96, 0x01, 0x00, 0x01, 0x96, 0x03, 0x00, 0x01, 0x97, 0x01, 0x17, 0x01, 0x98, 0x01, 0x36, 0x01, 0x99, 0x01, 0x9a, + 0x01, 0x93, 0x07, 0x9b, 0x01, 0x9c, 0x01, 0x9d, 0x01, 0x4d, 0x01, 0x9e, 0x01, 0x9f, 0x01, 0xa0, 0x01, 0x9b, 0x01, 0x93, 0x01, 0xa1, 0x01, 0xa2, + 0x01, 0xa3, 0x07, 0x00, 0x01, 0xa4, 0x01, 0x9b, 0x01, 0x04, 0x01, 0x13, 0x01, 0x00, 0x01, 0xa5, 0x01, 0x00, 0x01, 0x01, 0x01, 0x31, 0x01, 0xa6, + 0x01, 0xa7, 0x01, 0xa8, 0x01, 0x23, 0x01, 0x24, 0x07, 0x26, 0x01, 0xa9, 0x01, 0xaa, 0x01, 0xab, 0x01, 0xac, 0x01, 0xad, 0x01, 0x28, 0x02, 0x26, + 0x01, 0x25, 0x01, 0xae, 0x01, 0xaf, 0x01, 0xb0, 0x01, 0xb1, 0x01, 0x2f, 0x02, 0xb1, 0x01, 0xb2, 0x01, 0xb3, 0x01, 0xb4, 0x01, 0x34, 0x01, 0xb5, + 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, 0x01, 0x14, 0x01, 0x00, 0x01, 0xb6, 0x01, 0xa6, 0x01, 0xb7, 0x01, 0xb8, 0x09, 0xb9, 0x01, 0xba, + 0x01, 0xbb, 0x01, 0xbc, 0x06, 0xb9, 0x01, 0x79, 0x01, 0x19, 0x05, 0x79, 0x01, 0x1c, 0x01, 0x17, 0x01, 0xbd, 0x01, 0x02, 0x01, 0x07, 0x01, 0x13, + 0x04, 0x00, 0x01, 0x07, 0x01, 0x00, 0x01, 0xbe, 0x01, 0xbf, 0x01, 0xc0, 0x01, 0xc1, 0x09, 0xc2, 0x01, 0xc3, 0x07, 0xc2, 0x01, 0xc1, 0x04, 0xc4, + 0x01, 0xc5, 0x01, 0xc6, 0x01, 0xc7, 0x01, 0xc8, 0x09, 0x00, 0x01, 0x06, 0x1e, 0x00, 0x01, 0xa5, 0x09, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x03, + 0x17, 0x04, 0x01, 0x47, 0x01, 0x03, 0x01, 0x05, 0x07, 0x00, +}; +static const uint8_t battery_palette_9[] = { + 0x00, 0x00, 0x00, 0x07, 0xe0, 0x01, 0x3d, 0xe7, 0x04, 0x3f, 0xef, 0x04, 0x36, 0x6c, 0x05, 0x55, 0x4a, 0x03, 0x07, 0xef, 0x02, 0x03, 0xef, 0x02, + 0x03, 0xe0, 0x02, 0x25, 0x89, 0x0d, 0x36, 0x6b, 0x5b, 0x36, 0x6b, 0x83, 0x36, 0x2b, 0x85, 0x36, 0x2b, 0x86, 0x2e, 0x2a, 0x84, 0x36, 0x4b, 0x85, + 0x36, 0x6b, 0x78, 0x36, 0x4b, 0x36, 0x00, 0x00, 0x01, 0x7f, 0xef, 0x02, 0x35, 0xeb, 0x34, 0x36, 0x6b, 0xe3, 0x3e, 0xec, 0xff, 0x36, 0x2b, 0xfd, + 0x36, 0x2b, 0xfc, 0x36, 0x2a, 0xf9, 0x46, 0x6d, 0xff, 0x36, 0x2b, 0xfb, 0x36, 0x6b, 0xff, 0x36, 0x4b, 0x97, 0x3e, 0x2c, 0x0d, 0x36, 0x6b, 0xe5, + 0x36, 0x8b, 0xe4, 0x36, 0x0a, 0x32, 0x2e, 0x2a, 0x1b, 0x36, 0x6b, 0x20, 0x36, 0x6b, 0x1e, 0x36, 0x2b, 0x1f, 0x36, 0x2a, 0x1f, 0x56, 0x8e, 0x21, + 0x05, 0xa5, 0x1f, 0xe7, 0xdd, 0x74, 0xcf, 0x7a, 0x54, 0x2d, 0xea, 0x1f, 0x46, 0x4c, 0x21, 0x36, 0xab, 0x20, 0x2d, 0xe9, 0x17, 0x36, 0x4b, 0x7c, + 0x3f, 0x0c, 0xff, 0x36, 0x2b, 0x75, 0x36, 0x2b, 0x5b, 0x35, 0xca, 0x2d, 0x36, 0x4b, 0x54, 0x36, 0x8b, 0xe1, 0x36, 0x2b, 0xe7, 0x36, 0x2b, 0xe9, + 0x3e, 0x4b, 0xe9, 0x26, 0x09, 0xe9, 0x7e, 0xd2, 0xe9, 0xdf, 0xbc, 0xfd, 0x36, 0x2a, 0xec, 0x36, 0x2b, 0xe8, 0x36, 0x6b, 0xe8, 0x36, 0x6b, 0xbe, + 0x2d, 0x4a, 0x06, 0x36, 0x4b, 0xb2, 0x36, 0x2b, 0xee, 0x3d, 0xef, 0x04, 0x36, 0x2b, 0x84, 0x36, 0x6c, 0x15, 0x36, 0x2b, 0xed, 0x36, 0x8b, 0xff, + 0x36, 0x4b, 0xff, 0x3e, 0x6b, 0xff, 0x2e, 0x4a, 0xff, 0x56, 0xae, 0xff, 0xff, 0xff, 0xff, 0x9f, 0x36, 0xff, 0x26, 0x29, 0xff, 0x3e, 0x6c, 0xff, + 0x36, 0x2b, 0x6d, 0x36, 0x2b, 0x65, 0x36, 0x6a, 0x0f, 0x2d, 0xc8, 0x0b, 0x36, 0x2b, 0x83, 0x2e, 0x4b, 0x21, 0x36, 0x4b, 0xe8, 0x36, 0x4b, 0xfe, + 0x36, 0x2b, 0xfe, 0x2e, 0x2a, 0xfe, 0x46, 0x4c, 0xfe, 0xe7, 0xbd, 0xfe, 0xff, 0xff, 0xfe, 0x46, 0x4c, 0xff, 0x1e, 0x08, 0xfe, 0x26, 0x09, 0xfe, + 0x36, 0x2a, 0xfe, 0x36, 0x2b, 0xfa, 0x3e, 0xcc, 0xfc, 0x36, 0x4b, 0x76, 0x36, 0x2b, 0x69, 0x36, 0x6b, 0xfe, 0x3e, 0x29, 0x0d, 0x36, 0x2b, 0x9b, + 0x3e, 0xac, 0xe4, 0x36, 0x2b, 0x3e, 0x36, 0x2b, 0xff, 0x36, 0x2a, 0xff, 0xd7, 0xbb, 0xff, 0xef, 0xde, 0xff, 0x9f, 0x15, 0xff, 0x97, 0x15, 0xff, + 0xa7, 0x36, 0xff, 0x56, 0x8e, 0xff, 0x2e, 0x2a, 0xff, 0x3e, 0xcc, 0xff, 0x36, 0x4b, 0x73, 0x36, 0x2b, 0x6a, 0x36, 0x2a, 0x24, 0x36, 0x2b, 0x8a, + 0xc7, 0x79, 0xff, 0xc7, 0x7a, 0xff, 0x36, 0x4a, 0x74, 0x36, 0x2b, 0xe2, 0x3e, 0xcc, 0xfd, 0xbf, 0x79, 0xff, 0xcf, 0x9a, 0xff, 0x3e, 0xcc, 0xfe, + 0x56, 0x6e, 0xff, 0xaf, 0x57, 0xff, 0xdf, 0xbc, 0xff, 0x3e, 0x4b, 0xff, 0x36, 0x2a, 0x25, 0x1d, 0xe8, 0xfe, 0x6e, 0xb0, 0xff, 0xef, 0xdd, 0xfe, + 0x4e, 0x6d, 0xfe, 0x36, 0x2b, 0x76, 0x36, 0x4b, 0x0e, 0x36, 0x2b, 0xa1, 0x3e, 0xcc, 0xe9, 0x36, 0x2b, 0x42, 0x2e, 0x8b, 0x16, 0x36, 0x2b, 0x6e, + 0x35, 0xca, 0x0f, 0x36, 0x4a, 0x5d, 0x36, 0x0a, 0x29, 0x36, 0x8b, 0xe7, 0x36, 0x4b, 0xec, 0x36, 0x2b, 0xef, 0x2e, 0x2a, 0xef, 0x4e, 0x6d, 0xf3, + 0x76, 0xd1, 0xef, 0x26, 0x09, 0xef, 0x3e, 0x4b, 0xef, 0x36, 0x4b, 0xee, 0x36, 0x6b, 0xc5, 0x3d, 0xeb, 0x08, 0x36, 0x2b, 0xae, 0x36, 0x2b, 0xf0, + 0x07, 0xff, 0x01, 0x36, 0x6b, 0xe9, 0x36, 0x8b, 0xdf, 0x35, 0xea, 0x2c, 0x4e, 0x4d, 0x22, 0x26, 0x29, 0x1f, 0xf7, 0xde, 0x8a, 0xef, 0xde, 0x7e, + 0x05, 0xa4, 0x1f, 0x36, 0x8b, 0x21, 0x35, 0xeb, 0x14, 0x36, 0x4b, 0x74, 0x36, 0x2a, 0x7a, 0x36, 0x0a, 0x39, 0x36, 0x2b, 0xf8, 0x36, 0x2b, 0xf6, + 0x3e, 0x4b, 0xf6, 0x6e, 0xf1, 0xff, 0x2e, 0x2a, 0xf4, 0x36, 0x2b, 0xf5, 0x36, 0x4b, 0x9e, 0x2d, 0xa9, 0x11, 0x36, 0x6b, 0x63, 0x36, 0x6b, 0x8c, + 0x36, 0x2b, 0x8e, 0x36, 0x2b, 0x8f, 0x2e, 0x2a, 0x8b, 0x36, 0x4b, 0x8e, 0x36, 0x6b, 0x81, 0x36, 0x4b, 0x3d, +}; +static const uint8_t battery_runs_9[] = { + 0x03, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x03, 0x18, 0x04, 0x02, 0x03, 0x01, 0x05, 0x09, 0x00, 0x01, 0x06, 0x1e, 0x00, 0x01, 0x07, 0x07, 0x00, + 0x01, 0x08, 0x01, 0x00, 0x01, 0x09, 0x01, 0x0a, 0x01, 0x0b, 0x01, 0x0c, 0x0e, 0x0d, 0x01, 0x0e, 0x07, 0x0d, 0x01, 0x0c, 0x01, 0x0f, 0x01, 0x10, + 0x01, 0x11, 0x01, 0x00, 0x01, 0x12, 0x05, 0x00, 0x01, 0x13, 0x01, 0x00, 0x01, 0x14, 0x01, 0x15, 0x01, 0x16, 0x01, 0x17, 0x0e, 0x18, 0x01, 0x19, + 0x01, 0x1a, 0x08, 0x18, 0x01, 0x1b, 0x01, 0x1c, 0x01, 0x16, 0x01, 0x1d, 0x01, 0x13, 0x01, 0x07, 0x01, 0x12, 0x03, 0x00, 0x01, 0x01, 0x01, 0x1e, + 0x01, 0x1f, 0x01, 0x20, 0x01, 0x21, 0x01, 0x22, 0x01, 0x23, 0x01, 0x24, 0x09, 0x25, 0x01, 0x26, 0x01, 0x27, 0x01, 0x28, 0x01, 0x29, 0x01, 0x2a, + 0x01, 0x2b, 0x01, 0x2c, 0x06, 0x25, 0x01, 0x2d, 0x01, 0x2e, 0x01, 0x2f, 0x01, 0x30, 0x01, 0x31, 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, 0x03, 0x00, + 0x01, 0x32, 0x01, 0x16, 0x01, 0x33, 0x01, 0x34, 0x01, 0x35, 0x01, 0x36, 0x0a, 0x37, 0x01, 0x38, 0x01, 0x39, 0x01, 0x3a, 0x01, 0x3b, 0x01, 0x3c, + 0x07, 0x37, 0x01, 0x3d, 0x01, 0x3e, 0x01, 0x3f, 0x01, 0x40, 0x01, 0x41, 0x01, 0x42, 0x01, 0x43, 0x01, 0x01, 0x01, 0x00, 0x01, 0x07, 0x02, 0x00, + 0x01, 0x44, 0x01, 0x17, 0x01, 0x45, 0x01, 0x46, 0x01, 0x47, 0x0a, 0x48, 0x01, 0x49, 0x01, 0x4a, 0x01, 0x4b, 0x01, 0x4c, 0x01, 0x4d, 0x01, 0x4e, + 0x01, 0x4f, 0x01, 0x1c, 0x07, 0x48, 0x01, 0x30, 0x01, 0x50, 0x01, 0x51, 0x01, 0x47, 0x01, 0x52, 0x01, 0x00, 0x01, 0x53, 0x03, 0x00, 0x01, 0x54, + 0x01, 0x17, 0x01, 0x55, 0x01, 0x56, 0x01, 0x57, 0x01, 0x17, 0x09, 0x58, 0x01, 0x59, 0x01, 0x5a, 0x01, 0x5b, 0x01, 0x5c, 0x01, 0x5d, 0x01, 0x5e, + 0x01, 0x5f, 0x01, 0x60, 0x06, 0x58, 0x01, 0x61, 0x01, 0x62, 0x01, 0x63, 0x01, 0x64, 0x01, 0x65, 0x01, 0x66, 0x01, 0x67, 0x01, 0x68, 0x01, 0x69, + 0x02, 0x00, 0x01, 0x54, 0x01, 0x17, 0x01, 0x25, 0x01, 0x37, 0x01, 0x48, 0x01, 0x58, 0x08, 0x6a, 0x01, 0x6b, 0x01, 0x48, 0x01, 0x6c, 0x01, 0x4c, + 0x01, 0x6d, 0x01, 0x6e, 0x01, 0x6f, 0x01, 0x70, 0x01, 0x71, 0x01, 0x72, 0x05, 0x6a, 0x01, 0x1b, 0x01, 0x73, 0x01, 0x74, 0x01, 0x75, 0x01, 0x48, + 0x01, 0x76, 0x01, 0x46, 0x01, 0x30, 0x01, 0x77, 0x02, 0x00, 0x01, 0x54, 0x01, 0x17, 0x01, 0x25, 0x01, 0x37, 0x01, 0x48, 0x01, 0x58, 0x07, 0x6a, + 0x01, 0x6b, 0x01, 0x72, 0x01, 0x78, 0x05, 0x4c, 0x01, 0x79, 0x07, 0x6a, 0x01, 0x1b, 0x01, 0x73, 0x01, 0x7a, 0x01, 0x75, 0x01, 0x48, 0x01, 0x76, + 0x01, 0x7b, 0x01, 0x7c, 0x01, 0x54, 0x02, 0x00, 0x01, 0x54, 0x01, 0x17, 0x01, 0x25, 0x01, 0x37, 0x01, 0x48, 0x01, 0x58, 0x08, 0x6a, 0x01, 0x7d, + 0x05, 0x4c, 0x01, 0x7e, 0x01, 0x72, 0x01, 0x6b, 0x06, 0x6a, 0x01, 0x1b, 0x01, 0x73, 0x01, 0x7a, 0x01, 0x75, 0x01, 0x48, 0x01, 0x76, 0x01, 0x7b, + 0x01, 0x7f, 0x01, 0x54, 0x02, 0x00, 0x01, 0x54, 0x01, 0x17, 0x01, 0x25, 0x01, 0x37, 0x01, 0x48, 0x01, 0x58, 0x06, 0x6a, 0x01, 0x72, 0x01, 0x80, + 0x01, 0x70, 0x01, 0x6e, 0x01, 0x81, 0x02, 0x4c, 0x01, 0x82, 0x01, 0x83, 0x01, 0x6b, 0x01, 0x48, 0x06, 0x6a, 0x01, 0x1b, 0x01, 0x73, 0x01, 0x74, + 0x01, 0x75, 0x01, 0x48, 0x01, 0x84, 0x01, 0x46, 0x01, 0x30, 0x01, 0x77, 0x02, 0x00, 0x01, 0x54, 0x01, 0x17, 0x01, 0x55, 0x01, 0x3d, 0x01, 0x57, + 0x01, 0x17, 0x07, 0x58, 0x01, 0x60, 0x01, 0x5f, 0x01, 0x85, 0x01, 0x86, 0x01, 0x5c, 0x01, 0x87, 0x01, 0x88, 0x01, 0x59, 0x08, 0x58, 0x01, 0x61, + 0x01, 0x7c, 0x01, 0x89, 0x01, 0x64, 0x01, 0x65, 0x01, 0x8a, 0x01, 0x8b, 0x01, 0x8c, 0x01, 0x8d, 0x02, 0x00, 0x01, 0x44, 0x01, 0x17, 0x01, 0x8e, + 0x01, 0x42, 0x01, 0x47, 0x09, 0x48, 0x01, 0x49, 0x01, 0x72, 0x01, 0x7e, 0x01, 0x4c, 0x01, 0x4b, 0x01, 0x72, 0x01, 0x83, 0x08, 0x48, 0x01, 0x6a, + 0x01, 0x30, 0x01, 0x8f, 0x01, 0x51, 0x01, 0x47, 0x01, 0x90, 0x01, 0x00, 0x01, 0x90, 0x03, 0x00, 0x01, 0x91, 0x01, 0x16, 0x01, 0x92, 0x01, 0x32, + 0x01, 0x93, 0x01, 0x94, 0x01, 0x42, 0x07, 0x95, 0x01, 0x96, 0x01, 0x97, 0x01, 0x4c, 0x01, 0x98, 0x01, 0x99, 0x01, 0x9a, 0x08, 0x95, 0x01, 0x42, + 0x01, 0x9b, 0x01, 0x9c, 0x01, 0x9d, 0x01, 0x9e, 0x01, 0x9f, 0x01, 0x04, 0x01, 0x12, 0x01, 0x00, 0x01, 0xa0, 0x01, 0x00, 0x01, 0x01, 0x01, 0x52, + 0x01, 0xa1, 0x01, 0xa2, 0x01, 0xa3, 0x01, 0x22, 0x01, 0x23, 0x07, 0x25, 0x01, 0xa4, 0x01, 0xa5, 0x01, 0xa6, 0x01, 0xa7, 0x01, 0xa8, 0x01, 0x27, + 0x0a, 0x25, 0x01, 0xa9, 0x01, 0xaa, 0x01, 0xab, 0x01, 0x30, 0x01, 0xac, 0x01, 0x00, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, 0x01, 0x13, 0x01, 0x00, + 0x01, 0xad, 0x01, 0xa1, 0x01, 0x73, 0x01, 0xae, 0x09, 0xaf, 0x01, 0xb0, 0x01, 0xb1, 0x01, 0xb2, 0x0c, 0xaf, 0x01, 0xb3, 0x01, 0x48, 0x01, 0x16, + 0x01, 0xb4, 0x01, 0x02, 0x01, 0x07, 0x01, 0x12, 0x04, 0x00, 0x01, 0x07, 0x01, 0x00, 0x01, 0xb5, 0x01, 0xb6, 0x01, 0xb7, 0x01, 0xb8, 0x09, 0xb9, + 0x01, 0xba, 0x0d, 0xb9, 0x01, 0xbb, 0x01, 0xbc, 0x01, 0xbd, 0x09, 0x00, 0x01, 0x06, 0x1e, 0x00, 0x01, 0xa0, 0x09, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x03, 0x17, 0x04, 0x01, 0x43, 0x01, 0x03, 0x01, 0x05, 0x07, 0x00, +}; +const lcd_status_icon_t lcd_status_battery_icons[10] = { + {battery_palette_0, battery_runs_0, sizeof(battery_runs_0)}, + {battery_palette_1, battery_runs_1, sizeof(battery_runs_1)}, + {battery_palette_2, battery_runs_2, sizeof(battery_runs_2)}, + {battery_palette_3, battery_runs_3, sizeof(battery_runs_3)}, + {battery_palette_4, battery_runs_4, sizeof(battery_runs_4)}, + {battery_palette_5, battery_runs_5, sizeof(battery_runs_5)}, + {battery_palette_6, battery_runs_6, sizeof(battery_runs_6)}, + {battery_palette_7, battery_runs_7, sizeof(battery_runs_7)}, + {battery_palette_8, battery_runs_8, sizeof(battery_runs_8)}, + {battery_palette_9, battery_runs_9, sizeof(battery_runs_9)}, +}; diff --git a/components/platform/src/lcd_direct.c b/components/platform/src/lcd_direct.c index 60f3169..9ba398c 100644 --- a/components/platform/src/lcd_direct.c +++ b/components/platform/src/lcd_direct.c @@ -8,6 +8,7 @@ #include "lcd_direct.h" #include "lcd_direct_assets.h" #include "platform_asset_bundle.h" +#include "lcd_status_assets.h" #include #include @@ -87,17 +88,16 @@ #define LCD_DIRECT_BACKLIGHT_PWM_TIMER LEDC_TIMER_0 #define LCD_DIRECT_BACKLIGHT_PWM_CHANNEL LEDC_CHANNEL_0 #define LCD_DIRECT_BACKLIGHT_LOCK_TIMEOUT_MS 100U -/* 5x7 点阵放大4倍,24像素步进为字形留出间隔;颜色为 RGB565 白字黑描边。 */ +/* Montserrat 14 子集直接合成,无 label 字形缓存或新增动态缓冲。 */ #define LCD_DIRECT_CLOCK_X 12U -#define LCD_DIRECT_CLOCK_Y 10U -#define LCD_DIRECT_CLOCK_GLYPH_WIDTH 5U -#define LCD_DIRECT_CLOCK_GLYPH_HEIGHT 7U -#define LCD_DIRECT_CLOCK_GLYPH_SCALE 4U -#define LCD_DIRECT_CLOCK_GLYPH_ADVANCE 24U +#define LCD_DIRECT_CLOCK_Y 14U #define LCD_DIRECT_CLOCK_TEXT_LENGTH 5U -#define LCD_DIRECT_CLOCK_OUTLINE_PX 1 -#define LCD_DIRECT_CLOCK_COLOR 0xFFFFU #define LCD_DIRECT_CLOCK_OUTLINE_COLOR 0x0000U +#define LCD_DIRECT_CLOCK_COLOR 0xFFFFU +#define LCD_DIRECT_BATTERY_WIDTH 40U +#define LCD_DIRECT_BATTERY_HEIGHT 20U +#define LCD_DIRECT_BATTERY_X (LCD_DIRECT_WIDTH - LCD_DIRECT_BATTERY_WIDTH - 8U) +#define LCD_DIRECT_BATTERY_Y 12U #if CONFIG_TQ_LCD_EMOTE_GFX_TEST #define LCD_DIRECT_HUD_ROWS 40U @@ -202,21 +202,6 @@ static const lcd_direct_init_cmd_t s_st7789_init_cmds[] = { {0, {0}, 0xFF}, }; -/* Five-bit rows, most-significant displayed column first. Kept in flash. */ -static const uint8_t s_clock_glyph_rows[][LCD_DIRECT_CLOCK_GLYPH_HEIGHT] = { - {0x0E, 0x11, 0x13, 0x15, 0x19, 0x11, 0x0E}, /* 0 */ - {0x04, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x0E}, /* 1 */ - {0x0E, 0x11, 0x01, 0x02, 0x04, 0x08, 0x1F}, /* 2 */ - {0x1E, 0x01, 0x01, 0x0E, 0x01, 0x01, 0x1E}, /* 3 */ - {0x02, 0x06, 0x0A, 0x12, 0x1F, 0x02, 0x02}, /* 4 */ - {0x1F, 0x10, 0x10, 0x1E, 0x01, 0x01, 0x1E}, /* 5 */ - {0x0E, 0x10, 0x10, 0x1E, 0x11, 0x11, 0x0E}, /* 6 */ - {0x1F, 0x01, 0x02, 0x04, 0x08, 0x08, 0x08}, /* 7 */ - {0x0E, 0x11, 0x11, 0x0E, 0x11, 0x11, 0x0E}, /* 8 */ - {0x0E, 0x11, 0x11, 0x0F, 0x01, 0x01, 0x0E}, /* 9 */ - {0x00, 0x04, 0x04, 0x00, 0x04, 0x04, 0x00}, /* : */ - {0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00}, /* - */ -}; static esp_lcd_panel_io_handle_t s_panel_io; static esp_lcd_panel_handle_t s_panel; @@ -646,7 +631,7 @@ static bool lcd_direct_should_stop_idle(void) return stop; } -/* 调用方持有 GFX 锁;字形复用 PNG 路径,无字体包和额外 PNG 解码。 */ +/* 调用方持有 GFX 锁;两种后端共用 Montserrat 子集和电池资产,无动态解码缓存。 */ static esp_err_t lcd_direct_emote_update_hud(bool force, bool *changed) { if (changed != NULL) { @@ -1745,7 +1730,7 @@ static size_t lcd_direct_append_status_icons(const lcd_direct_image_t *image, .y = LCD_DIRECT_LOW_BATTERY_ICON_Y, }; } - /* 充电状态改由右上角程序绘制的电池图标表示,避免和百分比重叠。 */ + /* 充电状态由右上角新电池素材表示;保留底部低电量提醒。 */ return icon_count; } @@ -1837,131 +1822,92 @@ static void lcd_direct_clock_text(char text[LCD_DIRECT_CLOCK_TEXT_LENGTH + 1U]) text[5] = '\0'; } -static void lcd_direct_draw_clock_pass(uint16_t *pixel_buffer, - uint16_t row_start, - uint16_t row_count, - const char text[LCD_DIRECT_CLOCK_TEXT_LENGTH + 1U], - int x_offset, - int y_offset, - uint16_t color) +/* 输入/输出沿用 PNG 行缓冲字节序;GFX HUD 在提交前统一转换。 */ +static void lcd_direct_hud_blend_pixel(uint16_t *pixels, uint16_t row_start, + uint16_t rows, int x, int y, + uint16_t color, uint8_t alpha) { - const int row_end = (int)row_start + (int)row_count; - for (size_t character_index = 0; character_index < LCD_DIRECT_CLOCK_TEXT_LENGTH; - ++character_index) { - const uint8_t *glyph = - s_clock_glyph_rows[lcd_direct_clock_glyph_index(text[character_index])]; - const int glyph_x = (int)LCD_DIRECT_CLOCK_X + - (int)(character_index * LCD_DIRECT_CLOCK_GLYPH_ADVANCE) + - x_offset; - const int glyph_y = (int)LCD_DIRECT_CLOCK_Y + y_offset; - - for (uint16_t source_y = 0; source_y < LCD_DIRECT_CLOCK_GLYPH_HEIGHT; ++source_y) { - for (uint16_t scale_y = 0; scale_y < LCD_DIRECT_CLOCK_GLYPH_SCALE; ++scale_y) { - const int destination_y = glyph_y + - (int)(source_y * LCD_DIRECT_CLOCK_GLYPH_SCALE + scale_y); - if (destination_y < (int)row_start || destination_y >= row_end) { - continue; - } - - for (uint16_t source_x = 0; source_x < LCD_DIRECT_CLOCK_GLYPH_WIDTH; - ++source_x) { - if ((glyph[source_y] & - (1U << (LCD_DIRECT_CLOCK_GLYPH_WIDTH - 1U - source_x))) == 0U) { - continue; - } - for (uint16_t scale_x = 0; scale_x < LCD_DIRECT_CLOCK_GLYPH_SCALE; - ++scale_x) { - const int destination_x = glyph_x + - (int)(source_x * LCD_DIRECT_CLOCK_GLYPH_SCALE + scale_x); - if (destination_x < 0 || destination_x >= (int)LCD_DIRECT_WIDTH) { - continue; - } - const uint32_t destination_index = - (uint32_t)(destination_y - (int)row_start) * LCD_DIRECT_WIDTH + - (uint32_t)destination_x; - pixel_buffer[destination_index] = lcd_direct_swap_color(color); - } - } - } - } - } -} - -static void lcd_direct_overlay_clock(uint16_t *pixel_buffer, - uint16_t row_start, - uint16_t row_count, - const char text[LCD_DIRECT_CLOCK_TEXT_LENGTH + 1U]) -{ - /* 时钟作为最终覆盖层绘制,保证 presentation 与状态图标不会遮住时间。 */ - if (pixel_buffer == NULL || text == NULL) { + if (pixels == NULL || alpha == 0 || x < 0 || x >= (int)LCD_DIRECT_WIDTH || + y < (int)row_start || y >= (int)row_start + (int)rows) { return; } - - lcd_direct_draw_clock_pass(pixel_buffer, - row_start, - row_count, - text, - LCD_DIRECT_CLOCK_OUTLINE_PX, - LCD_DIRECT_CLOCK_OUTLINE_PX, - LCD_DIRECT_CLOCK_OUTLINE_COLOR); - lcd_direct_draw_clock_pass(pixel_buffer, - row_start, - row_count, - text, - 0, - 0, - LCD_DIRECT_CLOCK_COLOR); + const size_t index = (size_t)(y - row_start) * LCD_DIRECT_WIDTH + (size_t)x; + const uint16_t background = lcd_direct_swap_color(pixels[index]); + pixels[index] = lcd_direct_swap_color(lcd_direct_blend_rgb565(background, color, alpha)); } -/* 小型电池 + 数字百分比,沿用 5x7 点阵;所有写入都裁剪到当前行块。 */ -static void lcd_direct_hud_pixel(uint16_t *pixels, uint16_t row_start, - uint16_t rows, int x, int y, uint16_t color) +static void lcd_direct_draw_clock_pass(uint16_t *pixels, uint16_t row_start, + uint16_t rows, + const char text[LCD_DIRECT_CLOCK_TEXT_LENGTH + 1U], + int x_offset, int y_offset, uint16_t color) { - if (x >= 0 && x < LCD_DIRECT_WIDTH && y >= row_start && y < row_start + rows) { - pixels[(y - row_start) * LCD_DIRECT_WIDTH + x] = lcd_direct_swap_color(color); + int cursor = LCD_DIRECT_CLOCK_X; + for (size_t i = 0; i < LCD_DIRECT_CLOCK_TEXT_LENGTH; ++i) { + const lcd_status_glyph_t *glyph = &lcd_status_font_glyphs[lcd_direct_clock_glyph_index(text[i])]; + /* 原字体 line_height=16、base_line=3;不缩放,保留 4-bit 抗锯齿。 */ + const int top = (int)LCD_DIRECT_CLOCK_Y + 16 - 3 - glyph->height - glyph->y; + for (unsigned y = 0; y < glyph->height; ++y) { + for (unsigned x = 0; x < glyph->width; ++x) { + const size_t pixel = y * glyph->width + x; + const uint8_t packed = lcd_status_font_bitmap[glyph->offset + pixel / 2]; + const uint8_t alpha = ((pixel & 1U) ? packed & 15U : packed >> 4) * 17U; + lcd_direct_hud_blend_pixel(pixels, row_start, rows, + cursor + glyph->x + x_offset + (int)x, + top + y_offset + (int)y, color, alpha); + } + } + cursor += glyph->advance; } } +static void lcd_direct_overlay_clock(uint16_t *pixels, uint16_t row_start, + uint16_t rows, + const char text[LCD_DIRECT_CLOCK_TEXT_LENGTH + 1U]) +{ + if (pixels == NULL || text == NULL || + (int)row_start >= (int)LCD_DIRECT_CLOCK_Y + 17 || + (int)row_start + rows <= (int)LCD_DIRECT_CLOCK_Y) { + return; + } + lcd_direct_draw_clock_pass(pixels, row_start, rows, text, 1, 1, LCD_DIRECT_CLOCK_OUTLINE_COLOR); + lcd_direct_draw_clock_pass(pixels, row_start, rows, text, 0, 0, LCD_DIRECT_CLOCK_COLOR); +} + +/* 档位向上分组:0..10→1,11..25→25,26..50→50,51..75→75,76..100→100。 */ +static unsigned lcd_direct_battery_icon_index(uint8_t percent, bool charging) +{ + unsigned level = percent <= 10 ? 0 : percent <= 25 ? 1 : + percent <= 50 ? 2 : percent <= 75 ? 3 : 4; + return level + (charging ? 5U : 0U); +} + static void lcd_direct_overlay_battery(uint16_t *pixels, uint16_t row_start, uint16_t rows) { platform_lcd_status_overlay_t status; portENTER_CRITICAL(&s_state_lock); status = s_status_overlay; portEXIT_CRITICAL(&s_state_lock); - const uint16_t color = status.charging_visible ? 0x07E0U : - status.low_battery_visible ? 0xF800U : 0xFFFFU; - const int left = LCD_DIRECT_WIDTH - 108; - char text[5]; - if (status.battery_valid) { - snprintf(text, sizeof(text), "%u%%", (unsigned)status.battery_percent); - } else { - memcpy(text, "--%", 4); + /* 素材没有未知电量图标;读取有效电量前不显示,避免暗示错误档位。 */ + if (pixels == NULL || !status.battery_valid || + (int)row_start >= (int)(LCD_DIRECT_BATTERY_Y + LCD_DIRECT_BATTERY_HEIGHT) || + (int)row_start + rows <= (int)LCD_DIRECT_BATTERY_Y) { + return; } - static const uint8_t percent[7] = {0x19, 0x1A, 0x02, 0x04, 0x08, 0x0B, 0x13}; - for (size_t i = 0; text[i] != '\0'; ++i) { - const uint8_t *glyph = text[i] == '%' ? percent : - s_clock_glyph_rows[lcd_direct_clock_glyph_index(text[i])]; - for (int y = 0; y < 21; ++y) { - for (int x = 0; x < 15; ++x) { - if (glyph[y / 3] & (1U << (4 - x / 3))) { - lcd_direct_hud_pixel(pixels, row_start, rows, left + i * 18 + x, 13 + y, color); - } + const lcd_status_icon_t *icon = &lcd_status_battery_icons[ + lcd_direct_battery_icon_index(status.battery_percent, status.charging_visible)]; + size_t pixel = 0; + /* 从 Flash 流式读 palette/RLE,保留源图 Alpha,不创建解码图缓存。 */ + for (size_t run = 0; run + 1 < icon->run_bytes; run += 2) { + const uint8_t *value = icon->palette + (size_t)icon->runs[run + 1] * 3; + const uint16_t color = ((uint16_t)value[0] << 8) | value[1]; + for (unsigned count = 0; count < icon->runs[run]; ++count, ++pixel) { + if (pixel >= LCD_DIRECT_BATTERY_WIDTH * LCD_DIRECT_BATTERY_HEIGHT) { + return; } - } - } - const int icon_x = LCD_DIRECT_WIDTH - 32; - const int fill = status.battery_valid ? status.battery_percent * 16 / 100 : 0; - for (int y = 0; y < 20; ++y) { - for (int x = 0; x < 24; ++x) { - bool on = x < 22 && (x < 2 || x >= 20 || y < 2 || y >= 18); - on |= x >= 22 && y >= 6 && y < 14; - on |= status.battery_valid && x >= 3 && x < 3 + fill && y >= 3 && y < 17; - /* 充电时在电池中挖出黑色闪电,绿色外框仍可辨识。 */ - if (status.charging_visible && y >= 3 && y < 17 && - x >= 11 - (y - 3) / 3 && x <= 14 - (y - 3) / 3) { - on = false; - } - lcd_direct_hud_pixel(pixels, row_start, rows, icon_x + x, 14 + y, on ? color : 0); + lcd_direct_hud_blend_pixel(pixels, row_start, rows, + LCD_DIRECT_BATTERY_X + pixel % LCD_DIRECT_BATTERY_WIDTH, + LCD_DIRECT_BATTERY_Y + pixel / LCD_DIRECT_BATTERY_WIDTH, + color, value[2]); } } } diff --git a/docs/GFX表情显示应用与开发指南.md b/docs/GFX表情显示应用与开发指南.md index b80f85b..d285b2c 100644 --- a/docs/GFX表情显示应用与开发指南.md +++ b/docs/GFX表情显示应用与开发指南.md @@ -124,9 +124,38 @@ DMA 等待超时后禁止继续复用可能仍被硬件读取的缓冲,GFX 传 左上显示系统本地时间,尚未同步时显示 `--:--`。当前配置为中国标准时间;时区应通过现有时间服务配置,不在显示模块硬编码。 -右上显示领域层提供的电量百分比、有效性及充电状态。未知时显示 `--%`,充电显示绿色电池及闪电缺口,低电量显示红色。显示层不得从 ADC 电压自行重算电量。 +右上只显示电池图标,不再显示百分比。电量有效性及充电状态仍来自领域层; +未知电量时暂不显示图标,避免把未知值画成某个电量档位。显示层不得从 ADC +电压自行重算电量。旧底部低电量提示保留。 -状态栏复用内置 5×7 点阵数字和程序绘制图标,无需额外字体包。GFX 状态栏为 320×40 RGB565 图层,只在内容变化时刷新。PNG 表情在每帧合成时更新状态;二维码和屏幕边界测试不叠加它。 +时间改用现有 LVGL 依赖中的 Montserrat 14 字形,仅提取 `0..9`、冒号及横线, +不缩放,保留原始 4-bit Alpha。白字及黑色偏移阴影直接合成到已有缓冲, +并非创建 GFX label,也不启动 LVGL GUI。字形数组常量位于 Flash,无动态字形缓存。 +电池使用用户提供的 `battery_icons.zip` 中 40×20 的十张透明 PNG(五档及充电版本), +位于 `(272,12)`(320 像素宽时);不采用 80×40 版本,不拉伸、不改图标画风。 +电量分档:0~10→1、11~25→25、26~50→50、51~75→75、76~100→100。 +图标名表示视觉档位,不是重新计算 SOC;充电状态选择对应带闪电版本。 +PNG 原图和优化图均保留,但实际编译为 RGB565+A8 调色板+游程数组, +每条游程为“数量、调色板索引”,与表情的四字节 RLE 不同。 +在 Flash 中流式读取并按 Alpha 混合,不解码成常驻纹理。 +GFX 状态栏仍为 320×40 RGB565 图层,只在内容变化时刷新。PNG 表情在每帧合成时 +更新状态;二维码和屏幕边界测试不叠加它。两种后端使用同一字体和图标。 + +资源生成:`tools/prepare_status_hud_assets.py`;原图及优化图: +`components/platform/assets/status_hud/battery_source/` 与 `battery_optimized/`; +实际编译:`components/platform/src/generated/lcd_status_assets.c`,私有描述见 +`components/platform/internal/lcd_status_assets.h`。运行生成脚本会重建优化 PNG/C, +原 PNG 不覆盖;首次导入可指定 `--import-zip <压缩包路径>`,日常验证用 `--check`。 +需要 Pillow;字形来自现有依赖,不需要下载新字体。 + +本次 HUD 构建镜像 3,105,872 B,相对前一版 3,094,176 B 增加 11,696 B。 +生成资产的 ESP32-S3 对象只读数据为 12,083 B:字形位图 425 B、字形描述 96 B、 +十图标压缩载荷 11,442 B、图标描述 120 B。原十 PNG 9,973 B,优化后 9,806 B; +压缩载荷仍比优化 PNG 大 1,636 B,选择它是为避免 PNG 解码及额外像素缓存, +不能称作最小 Flash。新增常驻/初始化像素 PSRAM、普通堆、静态可写 RAM、DMA +均为 0;复用原状态栏/行缓冲,仍有局部栈和绘制 CPU 成本,需实机测量。 +四个主机显示测试、ESP-IDF 5.5.4 构建及日志关闭/GFX 关闭的 LCD 编译均通过; +字体大小、图标显示、充电插拔及最低内存仍待实机验收。 当前不能据此声称已实现任意中文文字。后续中文提示需要选择字体、字符子集、布局及字形缓存策略;数字时间和电量不需要引入完整中文字库或大型界面框架。 @@ -393,7 +422,8 @@ python3 tools/test_lcd_listening_gfx.py | 不需要触摸/复杂 GUI,精致流畅为主 | 局部 GFX 图层,不迁移完整 LVGL GUI | | 拆分原表情,允许性能适配但整体保持 | 待机/listening 拆分与固定静态层;后续延续原画风,大幅变化需确认 | | 眼睛向中间闭合,避免重影和撕裂 | 单一轮廓、闭眼弧线、缓存和连续传输;没有 TE,不能承诺零撕裂 | -| 统一所有返回待机入口、补时间电量 | 已实现统一后端及 HUD;不能覆盖新 pending;数字点阵不代表任意中文文字 | +| 统一所有返回待机入口、补时间电量 | 已实现统一后端及 HUD;不能覆盖新 pending;Montserrat 数字子集不代表任意中文文字 | +| 时间使用 Montserrat 14、移除电量数值、使用提供的电池图标 | 直接合成字形子集和 40×20 图标;构建与主机检查通过,待实机验收 | | 增加可开关日志、计算具体帧数 | 已有 emote_fps/emote_cost;区分步骤/实际更新/面板扫描率 | | 全中文开发说明与 AI 注意事项 | 本指南、资产台账及 AGENTS.md 中文 GFX 约束;原有仓库架构规范保留 | | listening 也迁移为流畅表情并报告开销 | 已接入,开销见上表;保持业务监听生命周期与旧 PNG 后备 | diff --git a/docs/lcd-idle-status.zh-CN.md b/docs/lcd-idle-status.zh-CN.md index 0861f3d..e73c7cd 100644 --- a/docs/lcd-idle-status.zh-CN.md +++ b/docs/lcd-idle-status.zh-CN.md @@ -24,21 +24,26 @@ ## 状态栏 - 左上 HH:MM,沿用 SNTP 和系统时区;未同步显示 --:--。 -- 右上百分比和电池;未知值显示 --%,充电绿色并带闪电缺口,低电量红色。 +- 左上时间已改成 Montserrat 14 原始字号,提取数字、冒号、横线直接绘制; + 无 GFX label 分配、无 LVGL GUI 初始化。旧 5×7 字形已从 HUD 实现移除。 +- 右上删除百分比,使用用户提供的 40×20 五档电池图标及对应充电版本; + 未知电量不显示,保留原底部低电量提示。档位规则、成本和生成入口见新指南第五节。 - SOC、有效性和充电状态来自现有 domain battery 服务,不从 ADC 重算。 - GFX 顶部 320x40 RGB565 图层,常驻 25,600 B PSRAM;只在分钟或电池状态 改变时使图层失效并刷新。正常待机/listening 眨眼切换缓存,不重新解码 PNG; 实时网格与程序闭眼弧线属于待机缓存生成或缓存失败后备路径。 -- PNG 表情复用相同点阵 / 电池绘制器,在每帧合成时更新;二维码和 LCD +- PNG 表情复用相同 Montserrat 子集 / 电池素材绘制器,在每帧合成时更新;二维码和 LCD 边界测试页面不显示状态栏。PNG 无限等待期间不会独立重绘状态栏。 -- 不需要字体包或新图片。旧 PNG 低电量底部告警保留;旧充电 PNG 不再自动 - 叠加,避免与数字电量冲突。GFX 待机低电量以红色电池表示。 +- 新增字形子集和十个电池素材编译数组,不创建字形/图标解码缓存;普通堆、 + 像素 PSRAM 和 DMA 无新增。旧 PNG 低电量底部告警保留;旧充电 PNG 不再 + 自动叠加。低电量图标颜色来自用户素材,不再由代码统一染红。 ## 验证 `python3 tools/test_lcd_status_hud.py` 从实际源码提取绘制函数,用 Clang -AddressSanitizer / UndefinedBehaviorSanitizer 检查 808 组有效性、充电、 -低电量、0..100% 组合,验证行块和整帧等价、边界及颜色。 +AddressSanitizer / UndefinedBehaviorSanitizer 检查 2,048 组有效性、充电、 +低电量、完整 uint8 电量输入组合和全天 1,440 个时间,验证行块与整帧等价、 +边界、原图 Alpha、透明背景恢复、240/320 像素画布和字节交换开关。 使用 ESP-IDF v5.5.4 执行 idf.py build。实机需验证: diff --git a/docs/显示与音频资产台账.zh-CN.md b/docs/显示与音频资产台账.zh-CN.md index f7d0d66..31fe348 100644 --- a/docs/显示与音频资产台账.zh-CN.md +++ b/docs/显示与音频资产台账.zh-CN.md @@ -2,8 +2,9 @@ ## 范围、日期与计量口径 -这是 2026-10-09 lucky-cat 工作区的只读核对快照;采集时包含尚未提交的 listening -素材以及两个未跟踪的历史待机 C 资产。它不是构建输入或自动生成的实时报告。 +这是 2026-10-09 lucky-cat 工作区的核对快照;初始采集时 listening 素材尚未提交, +两个历史待机 C 资产未跟踪;本次已追加 HUD 字形/电池素材及构建结果。 +它不是构建输入或自动生成的实时报告。 新增、替换、移出固件或经授权清理资产时,应同步更新此表及指南。 范围包含平台图片/图层/音频、生成 GFX C 文件、旧音频副本、领域内嵌网页和项目 @@ -33,7 +34,7 @@ | 领域网页资源 | 1 | 5,373 | 8,192 | user_config.html 单独 EMBED_TXTFILES,不在素材包 | | 文档中的独立显示预览 | 2 | 98,302 | 102,400 | 仅电脑预览,不入固件 | -以下同名文件跨目录是不同用途,不应直接合并或重复计入 Flash。当前没有独立中文字体包;数字 HUD 使用代码内置点阵,不意味着已支持任意中文字形。 +以下同名文件跨目录是不同用途,不应直接合并或重复计入 Flash。当前没有独立中文字体包;时间 HUD 已改为 Montserrat 14 数字子集,电量仅显示素材图标,不意味着已支持任意中文字形。 ## 原始 LCD 图片 @@ -358,8 +359,8 @@ | 包头、条目头及名称 | 3,222 | 打包元数据 | | platform_assets.pack | 820,125 | 上述三项之和,包含于应用 | | 六份在用 RLE 载荷 | 69,512 | 独立 C 数组链接入应用,不在素材包内 | -| 应用镜像 | 3,094,176 | 已包含 PNG、Opus、RLE、网页、代码及其他链接数据 | -| 单个 OTA 槽 | 4,718,592 | 应用余量 1,624,416 字节;不能把两个槽余量合并供一次 OTA 使用 | +| 应用镜像 | 3,105,872 | HUD 更新后的本次构建,包含 PNG、Opus、RLE、网页、代码及其他链接数据 | +| 单个 OTA 槽 | 4,718,592 | 应用余量 1,612,720 字节;不能把两个槽余量合并供一次 OTA 使用 | | 独立语音模型镜像 | 2,681,351 | model 分区容量 3,145,728 字节,不属于应用内图片包 | 文件总大小不能当作“当前整个 Flash 用量”;NVS、分区表、引导程序、模型和 @@ -375,6 +376,49 @@ RGB565+A8 像素共 255,528 字节,新 RLE 载荷共 50,176 字节。相对原 常驻像素共 423,234 字节;初始化额外关键图 167,706 字节,随后释放。 当前没有新增 DMA 暂存区、合成缓冲或任务。它是用户已接受的空间换流畅度方案。 +## 新增时间字形与电池图标(2026-10-09 HUD 更新) + +素材来自用户提供的 `battery_icons.zip`,只导入 `out/40x20/` 中明确列出的十张 PNG, +80×40 版本不入工程。源图与优化 PNG 均不加入 `platform_assets.pack`,避免重复计费; +实际链接生成的 C 只读数组。以下新增项不包含在上面的旧目录汇总里。 + +| 源图名称 | 原 PNG 字节 | 优化 PNG 字节 | 调色板+游程载荷字节 | +| --- | ---: | ---: | ---: | +| `battery_1.png` | 704 | 687 | 805 | +| `battery_25.png` | 815 | 800 | 995 | +| `battery_50.png` | 594 | 571 | 927 | +| `battery_75.png` | 601 | 574 | 919 | +| `battery_100.png` | 543 | 524 | 806 | +| `battery_charging_1.png` | 1,206 | 1,197 | 1,300 | +| `battery_charging_25.png` | 1,367 | 1,344 | 1,500 | +| `battery_charging_50.png` | 1,333 | 1,319 | 1,363 | +| `battery_charging_75.png` | 1,451 | 1,437 | 1,477 | +| `battery_charging_100.png` | 1,359 | 1,353 | 1,350 | +| 合计 | 9,973 | 9,806 | 11,442 | + +源 PNG:`components/platform/assets/status_hud/battery_source/`,十文件分配空间共 +40,960 B;优化 PNG:同目录 `battery_optimized/`,十文件分配空间共 40,960 B。 +颜色先按现有 RGB565 精度转换,完整保留 A8;调色板编码对 RGB565+A8 无损, +不等于 RGB888 转 RGB565 无损。游程往返与 PNG 优化像素一致性由生成脚本验证。 +十图标原始 RGB565+A8 为 24,000 B,索引游程为 11,442 B,减少约 52.3%; +但比优化 PNG 大 1,636 B。这里选的是无需运行时解码缓存的折中,不是最小文件编码。 + +时间字形来自已安装 LVGL 的 `lv_font_montserrat_14.c`,只提取数字、冒号、横线, +4-bit Alpha 位图 425 B,十二个描述共 96 B(ESP32-S3 对象验证),原始字号不放大。 +许可说明保留在 `status_hud/LVGL-LICENSE.txt`(不入固件)。 +生成脚本 `tools/prepare_status_hud_assets.py`,验证用 `--check`;输入字体版本/格式 +变化会触发断言,不能静默生成错误字形。 + +实际编译 `components/platform/src/generated/lcd_status_assets.c`:文本文件 75,630 B, +目标对象只读载荷 12,083 B,包括 425 B 字形、96 B 字形描述、11,442 B 图标数据、 +120 B 图标描述;目标对象可写 data/BSS 为 0。它不属于上面的六份表情 RLE。 +PNG 包仍为 820,125 B、75 PNG/32 Opus;只读资产已包含于整个应用,不再重复相加。 + +完整应用从 3,094,176 B 增至 3,105,872 B,净增 11,696 B(包含旧字形/绘制代码 +移除和段对齐变化),OTA 槽剩余 1,612,720 B。新增常驻/初始化像素 PSRAM、普通堆、 +内部/DMA 专用缓冲及静态可写数据均为 0;复用既有 HUD 和行缓冲。 +局部栈、CPU 耗时和设备最低内存尚未新增实机测量,不应写成整体资源零成本。 + ## 维护与后续清理 1. PNG 新增/替换按 [图片优化流程](lcd-image-asset-optimization.zh-CN.md) 生成并验证, @@ -385,4 +429,4 @@ RGB565+A8 像素共 255,528 字节,新 RLE 载荷共 50,176 字节。相对原 GFX 关闭/故障后备以及收益,经过用户确认并完成迁移验收后再修改构建及资源表。 4. 清理优先区分“不再入固件”与“删除可编辑源文件”。前者有 Flash 收益,后者 可能仅省开发机空间,不能混为一谈。保留 Git 可恢复记录,并验证正常/故障路径。 -5. 这里没有安排立即清理、批量迁移所有表情或新增字体;这些需要单独确定范围。 +5. 这里没有安排立即清理、批量迁移所有表情或加入完整字库;当前仅按用户要求提取 Montserrat 数字子集。 diff --git a/tools/prepare_status_hud_assets.py b/tools/prepare_status_hud_assets.py new file mode 100644 index 0000000..7a64c06 --- /dev/null +++ b/tools/prepare_status_hud_assets.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +"""生成 HUD 字形子集和无损调色板游程数据;无需运行时分配/解压缓存。 + +--import-zip 只导入明确列出的 40x20 PNG,不执行压缩包中的任何内容。 +原 PNG 保留;优化 PNG 与生成 C 是可再生文件。--check 只校验不写入。 +""" +import argparse +import io +import re +from pathlib import Path +from zipfile import ZipFile +from PIL import Image + +ROOT = Path(__file__).resolve().parents[1] +ASSETS = ROOT / 'components/platform/assets/status_hud' +OUTPUT = ROOT / 'components/platform/src/generated/lcd_status_assets.c' +NAMES = [f'battery_{n}.png' for n in (1, 25, 50, 75, 100)] + [ + f'battery_charging_{n}.png' for n in (1, 25, 50, 75, 100)] + +def array(name, data): + rows = [' ' + ', '.join(f'0x{n:02x}' for n in data[i:i+24]) + ',' + for i in range(0, len(data), 24)] + return f'static const uint8_t {name}[] = {{\n' + '\n'.join(rows) + '\n};\n' + +def generate(check=False): + font = (ROOT / 'managed_components/lvgl__lvgl/src/font/lv_font_montserrat_14.c').read_text() + assert '.bpp = 4,' in font and '.bitmap_format = 0,' in font + assert re.search(r'\.line_height\s*=\s*16\b', font) + assert re.search(r'\.base_line\s*=\s*3\b', font) + assert '.range_start = 32, .range_length = 95, .glyph_id_start = 1,' in font + block = re.search(r'glyph_bitmap\[\]\s*=\s*\{(.*?)\n};', font, re.S)[1] + block = re.sub(r'/\*.*?\*/', '', block, flags=re.S) + bitmap = bytes(int(n, 16) for n in re.findall(r'0x[0-9a-fA-F]+', block)) + block = re.search(r'glyph_dsc\[\]\s*=\s*\{(.*?)\n};', font, re.S)[1] + glyphs = [dict((key, int(value)) for key, value in re.findall(r'\.(\w+)\s*=\s*(-?\d+)', row)) + for row in re.findall(r'\{([^{}]+)\}', block)] + subset = bytearray(); descriptions = [] + for c in '0123456789:-': + g = glyphs[ord(c)-32+1] + count = (g['box_w'] * g['box_h'] + 1) // 2 + raw = bitmap[g['bitmap_index']:g['bitmap_index']+count] + assert len(raw) == count + descriptions.append(f" {{{len(subset)}, {(g['adv_w']+8)//16}, {g['box_w']}, {g['box_h']}, {g['ofs_x']}, {g['ofs_y']}}}, /* {c} */") + subset.extend(raw) + text = ('/* Generated by tools/prepare_status_hud_assets.py; do not edit.\n' + ' * Font subset derived from LVGL Montserrat 14, Copyright (c) 2025 LVGL Kft.\n' + ' * See components/platform/assets/status_hud/LVGL-LICENSE.txt. */\n' + '#include "lcd_status_assets.h"\n\n') + text += array('lcd_status_font_bitmap', subset).replace('static const', 'const') + text += 'const lcd_status_glyph_t lcd_status_font_glyphs[12] = {\n' + '\n'.join(descriptions) + '\n};\n' + payload = 0 + for i, name in enumerate(NAMES): + source = (ASSETS / 'battery_source' / name).read_bytes() + image = Image.open(io.BytesIO(source)).convert('RGBA') + assert image.size == (40, 20), name + out = io.BytesIO(); image.save(out, format='PNG', optimize=True, compress_level=9) + optimized = min((source, out.getvalue()), key=len) + assert Image.open(io.BytesIO(optimized)).convert('RGBA').tobytes() == image.tobytes() + destination = ASSETS / 'battery_optimized' / name + if check: + assert destination.read_bytes() == optimized, name + else: + destination.parent.mkdir(parents=True, exist_ok=True); destination.write_bytes(optimized) + rgba = image.tobytes() + pixels = [(((rgba[j] >> 3) << 11) | ((rgba[j+1] >> 2) << 5) | (rgba[j+2] >> 3), rgba[j+3]) + for j in range(0, len(rgba), 4)] + palette = list(dict.fromkeys(pixels)); assert len(palette) <= 256 + indices = {p: n for n, p in enumerate(palette)}; runs = bytearray() + for p in pixels: + index = indices[p] + if runs and runs[-1] == index and runs[-2] < 255: runs[-2] += 1 + else: runs.extend((1, index)) + decoded = [palette[runs[j+1]] for j in range(0, len(runs), 2) for _ in range(runs[j])] + assert decoded == pixels, name + pal = bytes(v for color, alpha in palette for v in (color >> 8, color & 255, alpha)) + text += array(f'battery_palette_{i}', pal) + array(f'battery_runs_{i}', runs) + payload += len(pal)+len(runs) + print(f'{name}: PNG {len(source)} -> {len(optimized)} B; indexed RLE {len(pal)+len(runs)} B') + text += 'const lcd_status_icon_t lcd_status_battery_icons[10] = {\n' + text += ''.join(f' {{battery_palette_{i}, battery_runs_{i}, sizeof(battery_runs_{i})}},\n' for i in range(10)) + '};\n' + if check: assert OUTPUT.read_text() == text + else: OUTPUT.parent.mkdir(parents=True, exist_ok=True); OUTPUT.write_text(text) + print(f'Font bitmap {len(subset)} B; battery payload {payload} B; no runtime pixel allocations') + +if __name__ == '__main__': + parser = argparse.ArgumentParser(); parser.add_argument('--import-zip', type=Path); parser.add_argument('--check', action='store_true') + args = parser.parse_args() + if args.import_zip: + assert not args.check + with ZipFile(args.import_zip) as archive: + for name in NAMES: + data = archive.read('out/40x20/' + name) + image = Image.open(io.BytesIO(data)); assert image.size == (40, 20) + path = ASSETS / 'battery_source' / name + path.parent.mkdir(parents=True, exist_ok=True); path.write_bytes(data) + generate(args.check) diff --git a/tools/test_lcd_status_hud.py b/tools/test_lcd_status_hud.py index 7752077..0e9d79a 100644 --- a/tools/test_lcd_status_hud.py +++ b/tools/test_lcd_status_hud.py @@ -1,68 +1,120 @@ +"""实际 HUD 函数与生成资产的 ASan/UBSan 回归;不启动 LVGL/GFX 引擎。""" from pathlib import Path -import subprocess, tempfile, re -src=(Path(__file__).resolve().parents[1]/'components/platform/src/lcd_direct.c').read_text() +import subprocess +import tempfile +import re + +ROOT = Path(__file__).resolve().parents[1] +src = (ROOT/'components/platform/src/lcd_direct.c').read_text() def function(name): - # Locate definition rather than the forward declaration. - matches=list(re.finditer(r'static [^;{}]+\b'+name+r'\([^;{}]*\)\s*\{',src)) - assert len(matches)==1,name - start=matches[0].start(); p=src.index('{',start); depth=1; end=p+1 + matches = list(re.finditer(r'static [^;{}]+\b'+name+r'\([^;{}]*\)\s*\{', src)) + assert len(matches) == 1, name + start = matches[0].start(); p = src.index('{', start); depth = 1; end = p+1 while depth: - if src[end]=='{':depth+=1 - if src[end]=='}':depth-=1 - end+=1 + if src[end] == '{': depth += 1 + if src[end] == '}': depth -= 1 + end += 1 return src[start:end] -table=re.search(r'static const uint8_t s_clock_glyph_rows.*?\n};',src,re.S).group(0) -prefix='''#include +prefix = '''#include #include #include #include #include -#define LCD_DIRECT_WIDTH 320 -#define LCD_DIRECT_CLOCK_GLYPH_HEIGHT 7 -#define CONFIG_TQ_SCREEN_SWAP_COLOR_BYTES 1 +#include "lcd_status_assets.h" +#define LCD_DIRECT_CLOCK_X 12U +#define LCD_DIRECT_CLOCK_Y 14U +#define LCD_DIRECT_CLOCK_TEXT_LENGTH 5U +#define LCD_DIRECT_CLOCK_COLOR 0xffffU +#define LCD_DIRECT_CLOCK_OUTLINE_COLOR 0U +#define LCD_DIRECT_BATTERY_WIDTH 40U +#define LCD_DIRECT_BATTERY_HEIGHT 20U +#define LCD_DIRECT_BATTERY_X (LCD_DIRECT_WIDTH - 48U) +#define LCD_DIRECT_BATTERY_Y 12U #define portENTER_CRITICAL(x) ((void)0) #define portEXIT_CRITICAL(x) ((void)0) typedef struct {bool low_battery_visible, charging_visible, battery_valid; uint8_t battery_percent;} platform_lcd_status_overlay_t; static platform_lcd_status_overlay_t s_status_overlay; #define PLATFORM_LCD_PRESENTATION_IDLE 0 -typedef struct { int kind; } lcd_direct_request_t; +typedef struct {int kind;} lcd_direct_request_t; static lcd_direct_request_t s_pending; static bool s_pending_valid, s_stop_requested; ''' -test='''int main(void) { - uint16_t full[320*240+2], blocks[320*240+2]; +test = '''int main(int argc, char **argv) { + uint16_t full[LCD_DIRECT_WIDTH*240+2], blocks[LCD_DIRECT_WIDTH*240+2]; for (unsigned valid=0;valid<2;++valid) for (unsigned charge=0;charge<2;++charge) for (unsigned low=0;low<2;++low) - for (unsigned percent=0;percent<=100;++percent) { + for (unsigned percent=0;percent<=255;++percent) { s_status_overlay=(platform_lcd_status_overlay_t){low,charge,valid,percent}; - for (unsigned i=0;i<320*240+2;++i) full[i]=blocks[i]=0x1234; + for (unsigned i=0;i=34) assert(full[1+y*320+x]==0x1234); + assert(full[0]==0x1234 && full[LCD_DIRECT_WIDTH*240+1]==0x1234); + unsigned level=percent<=10?0:percent<=25?1:percent<=50?2:percent<=75?3:4; + assert(lcd_direct_battery_icon_index(percent,charge)==level+(charge?5:0)); + for(unsigned y=0;y<240;++y) for(unsigned x=0;x=LCD_DIRECT_BATTERY_X+40 || y<12 || y>=32) + assert(full[1+y*LCD_DIRECT_WIDTH+x]==0x1234); + } + if(valid) { + const lcd_status_icon_t *icon=&lcd_status_battery_icons[level+(charge?5:0)]; + unsigned p=0; + for(unsigned r=0;rrun_bytes;r+=2) { + const uint8_t *value=icon->palette+icon->runs[r+1]*3; + for(unsigned n=0;nruns[r];++n,++p) { + unsigned index=1+(12+p/40)*LCD_DIRECT_WIDTH+LCD_DIRECT_BATTERY_X+p%40; + uint16_t color=((uint16_t)value[0]<<8)|value[1]; + assert(full[index]==lcd_direct_swap_color(lcd_direct_blend_rgb565(lcd_direct_swap_color(0x1234),color,value[2]))); + } + } + assert(p==800); } - uint16_t expected=lcd_direct_swap_color(charge?0x07e0:low?0xf800:0xffff); - assert(full[1+14*320+288]==expected); - unsigned fill=percent*16/100; - if(valid && !charge && fill) assert(full[1+17*320+291]==expected); - if(!valid) assert(full[1+17*320+291]==0); } - for (unsigned pending=0;pending<2;++pending) - for (unsigned stopping=0;stopping<2;++stopping) { - s_pending=(lcd_direct_request_t){99}; - s_pending_valid=pending; s_stop_requested=stopping; + for(unsigned hour=0;hour<24;++hour) for(unsigned minute=0;minute<60;++minute) { + char text[6]; snprintf(text,sizeof(text),"%02u:%02u",hour,minute); + for(unsigned i=0;i=64 || y<14 || y>=31) assert(full[1+y*LCD_DIRECT_WIDTH+x]==0x1234); + } + lcd_direct_overlay_clock(full+1,0,240,"--:--"); + lcd_direct_overlay_clock(NULL,0,240,"--:--"); + lcd_direct_overlay_clock(full+1,0,240,NULL); + lcd_direct_overlay_battery(NULL,0,240); + for(unsigned pending=0;pending<2;++pending) + for(unsigned stopping=0;stopping<2;++stopping) { + s_pending=(lcd_direct_request_t){99}; s_pending_valid=pending; s_stop_requested=stopping; lcd_direct_queue_idle_if_available(); assert(s_pending.kind==((pending || stopping)?99:PLATFORM_LCD_PRESENTATION_IDLE)); assert(s_pending_valid==(pending || !stopping)); } - puts("PASS: idle queue preserves pending requests and stop; 808 battery combinations; full-frame/8-row equivalence, bounds, colors and fill"); + if(argc==2) { + memset(full,0,sizeof(full)); + lcd_direct_overlay_clock(full,0,240,"12:34"); + s_status_overlay=(platform_lcd_status_overlay_t){false,true,true,50}; + lcd_direct_overlay_battery(full,0,240); + FILE *f=fopen(argv[1],"wb"); assert(f); fwrite(full,2,LCD_DIRECT_WIDTH*240,f); fclose(f); + } + puts("PASS: 2048 battery states, all 1440 times, alpha/background, byte order, 8-row equivalence, bounds and idle guards"); }''' +names = ['lcd_direct_swap_color', 'lcd_direct_rgb888_to_rgb565', 'lcd_direct_blend_rgb565', 'lcd_direct_clock_glyph_index', + 'lcd_direct_hud_blend_pixel', 'lcd_direct_draw_clock_pass', 'lcd_direct_overlay_clock', + 'lcd_direct_battery_icon_index', 'lcd_direct_overlay_battery', 'lcd_direct_queue_idle_if_available'] with tempfile.TemporaryDirectory(prefix='lucky-hud-') as tmp: - c=Path(tmp)/'hud.c'; exe=Path(tmp)/'hud' - c.write_text(prefix+table+'\n'+'\n'.join(function(n) for n in ['lcd_direct_swap_color','lcd_direct_clock_glyph_index','lcd_direct_hud_pixel','lcd_direct_overlay_battery','lcd_direct_queue_idle_if_available'])+'\n'+test) - subprocess.run(['clang','-std=c11','-fsanitize=address,undefined','-g',str(c),'-o',str(exe)],check=True) - subprocess.run([str(exe)],check=True) + c = Path(tmp)/'hud.c'; exe = Path(tmp)/'hud' + c.write_text(prefix+'\n'+'\n'.join(function(n) for n in names)+'\n'+test) + for width in (320, 240): + for swap in (0, 1): + subprocess.run(['clang','-std=c11','-fsanitize=address,undefined','-g', + f'-DLCD_DIRECT_WIDTH={width}', f'-DCONFIG_TQ_SCREEN_SWAP_COLOR_BYTES={swap}', + '-I'+str(ROOT/'components/platform/internal'),str(c), + str(ROOT/'components/platform/src/generated/lcd_status_assets.c'), + '-o',str(exe)],check=True) + preview = ['/tmp/lucky-status-hud.rgb565'] if width == 320 and swap == 0 else [] + subprocess.run([str(exe), *preview],check=True)