K1Guitar/APP/app_log.c

633 lines
22 KiB
C
Raw Permalink Normal View History

#include "includes.h"
#include "SEGGER_RTT.h"
#include <stdarg.h>
#if APP_LOG_ENABLE
static char s_slots[APP_LOG_SLOT_COUNT][APP_LOG_SLOT_SIZE];
static uint16_t s_head;
static uint16_t s_count;
static uint32_t s_overflow;
static uint32_t s_boot_count;
static char s_ui_page[16] = "boot";
static char s_debug_level = 'D';
static char s_cmd_buf[64];
static uint8_t s_cmd_len;
/* RTT 二进制烧录:写到 W25Q128ui0902 或本地曲目) */
static uint8_t s_flash_mode;
static uint32_t s_flash_base;
static uint32_t s_flash_addr;
static uint32_t s_flash_remain;
static uint32_t s_flash_last_sector;
static uint16_t s_flash_page_len;
static uint8_t s_flash_page[256];
static char s_flash_ok_tag[24];
uint8_t app_log_flash_busy(void)
{
return s_flash_mode;
}
static uint32_t app_log_ms(void)
{
return (uint32_t)(rt_tick_get() * 1000U / RT_TICK_PER_SECOND);
}
static void app_log_flash_flush_page(void)
{
uint32_t sector;
char ack[40];
if (s_flash_page_len == 0U) {
return;
}
sector = s_flash_addr & ~0xFFFU;
if (sector != s_flash_last_sector) {
W25Q128_Erase_Sector(sector);
s_flash_last_sector = sector;
}
W25Q128_Write(s_flash_page, s_flash_addr, s_flash_page_len);
s_flash_addr += s_flash_page_len;
s_flash_remain -= s_flash_page_len;
s_flash_page_len = 0U;
/* 每页 ACK避免主机打爆 RTT 下行缓冲 */
snprintf(ack, sizeof(ack), "FLASH_ACK %lu\n", (unsigned long)s_flash_addr);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, ack);
}
static void app_log_flash_feed(const uint8_t *data, unsigned len)
{
unsigned i;
for (i = 0; i < len && s_flash_remain > 0U; i++) {
if (s_flash_page_len == 0U && s_flash_addr == s_flash_base && i == 0U) {
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "FLASH_RX\n");
}
s_flash_page[s_flash_page_len++] = data[i];
if (s_flash_page_len >= sizeof(s_flash_page) ||
s_flash_page_len >= s_flash_remain) {
app_log_flash_flush_page();
}
}
if (s_flash_remain == 0U && s_flash_mode) {
s_flash_mode = 0U;
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, s_flash_ok_tag);
UI_DrawModeSelectScreen();
}
}
static void app_log_flash_start_at(uint32_t base, uint32_t size, const char *go_tag, const char *ok_tag)
{
char msg[80];
if (size == 0U || size > (2U * 1024U * 1024U)) {
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "FLASH_ERR size\n");
return;
}
s_flash_mode = 1U;
s_flash_base = base;
s_flash_addr = base;
s_flash_remain = size;
s_flash_last_sector = 0xFFFFFFFFUL;
s_flash_page_len = 0U;
s_cmd_len = 0U;
s_cmd_buf[0] = '\0';
strncpy(s_flash_ok_tag, ok_tag, sizeof(s_flash_ok_tag) - 1U);
s_flash_ok_tag[sizeof(s_flash_ok_tag) - 1U] = '\0';
snprintf(msg, sizeof(msg),
"%s base=0x%08lX size=%lu\n",
go_tag, (unsigned long)base, (unsigned long)size);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, msg);
}
static void app_log_flash_start(uint32_t size)
{
app_log_flash_start_at(UI0902_RES_BASE, size, "FLASH_UI0902_GO", "FLASH_UI0902_OK\n");
}
static void app_log_slot_store(const char *line)
{
uint16_t idx = s_head;
strncpy(s_slots[idx], line, APP_LOG_SLOT_SIZE - 1U);
s_slots[idx][APP_LOG_SLOT_SIZE - 1U] = '\0';
s_head = (uint16_t)((s_head + 1U) % APP_LOG_SLOT_COUNT);
if (s_count < APP_LOG_SLOT_COUNT) {
s_count++;
} else {
s_overflow++;
}
}
void app_log_set_ui_page(const char *name)
{
if (name == NULL) {
return;
}
strncpy(s_ui_page, name, sizeof(s_ui_page) - 1U);
s_ui_page[sizeof(s_ui_page) - 1U] = '\0';
}
void app_log_write(char level, const char *cat, const char *fmt, ...)
{
/* 静态行缓冲TaskBTRecv 等小栈线程禁止再开 128B 局部数组 */
static char line[APP_LOG_SLOT_SIZE];
static rt_mutex_t s_log_mtx = RT_NULL;
va_list ap;
int n;
if (level == 'D' && s_debug_level != 'D') {
return;
}
if (s_log_mtx == RT_NULL) {
s_log_mtx = rt_mutex_create("applog", RT_IPC_FLAG_PRIO);
}
if (s_log_mtx != RT_NULL) {
if (rt_mutex_take(s_log_mtx, rt_tick_from_millisecond(20)) != RT_EOK) {
return;
}
}
n = snprintf(line, sizeof(line), "[%05u][%c][%-4s] ",
(unsigned)app_log_ms(), level, cat);
if (n < 0) {
if (s_log_mtx != RT_NULL) {
rt_mutex_release(s_log_mtx);
}
return;
}
if ((size_t)n >= sizeof(line)) {
n = (int)sizeof(line) - 1;
}
va_start(ap, fmt);
vsnprintf(line + n, sizeof(line) - (size_t)n, fmt, ap);
va_end(ap);
app_log_slot_store(line);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "\n");
if (s_log_mtx != RT_NULL) {
rt_mutex_release(s_log_mtx);
}
}
static void app_log_dump_ram(void)
{
uint16_t start;
uint16_t i;
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "LOG_DUMP_BEGIN\n");
{
char meta[APP_LOG_SLOT_SIZE];
snprintf(meta, sizeof(meta),
"meta boot=%u lines=%u overflow=%u ui=%s",
(unsigned)s_boot_count,
(unsigned)s_count,
(unsigned)s_overflow,
s_ui_page);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, meta);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "\n");
}
if (s_count == 0U) {
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "LOG_DUMP_END\n");
return;
}
start = (s_count < APP_LOG_SLOT_COUNT)
? 0U
: s_head;
for (i = 0; i < s_count; i++) {
uint16_t idx = (uint16_t)((start + i) % APP_LOG_SLOT_COUNT);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, s_slots[idx]);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "\n");
}
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "LOG_DUMP_END\n");
}
static void app_log_clear_ram(void)
{
s_head = 0U;
s_count = 0U;
s_overflow = 0U;
memset(s_slots, 0, sizeof(s_slots));
LOG_I("LOG", "ram cleared");
}
static void app_log_print_status(void)
{
char line[APP_LOG_SLOT_SIZE];
snprintf(line, sizeof(line),
"LOG_STATUS boot=%u lines=%u overflow=%u level=%c ui=%s tick=%u",
(unsigned)s_boot_count,
(unsigned)s_count,
(unsigned)s_overflow,
s_debug_level,
s_ui_page,
(unsigned)app_log_ms());
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "\n");
}
static void app_log_sys_reset(void)
{
LOG_I("SYS", "reset via RTT");
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "SYS_RESET_OK\n");
rt_thread_mdelay(20);
__disable_irq();
nvic_system_reset();
}
uint8_t app_log_try_command(const char *cmd)
{
if (cmd == NULL || cmd[0] == '\0') {
return 0U;
}
if (strncmp(cmd, "log dump", 8) == 0) {
app_log_dump_ram();
return 1U;
}
if (strncmp(cmd, "log clear", 9) == 0) {
app_log_clear_ram();
return 1U;
}
if (strncmp(cmd, "log status", 10) == 0) {
app_log_print_status();
return 1U;
}
if (strncmp(cmd, "log level ", 10) == 0 && cmd[10] != '\0') {
s_debug_level = cmd[10];
LOG_I("LOG", "level set %c", s_debug_level);
return 1U;
}
if (strncmp(cmd, "tp status", 9) == 0) {
TP_LogStatus();
return 1U;
}
if (strncmp(cmd, "tp live off", 11) == 0) {
TP_SetLiveMode(0);
return 1U;
}
if (strncmp(cmd, "tp live", 7) == 0) {
TP_SetLiveMode(1);
return 1U;
}
if (strncmp(cmd, "sys reset", 9) == 0) {
app_log_sys_reset();
return 1U;
}
if (strncmp(cmd, "flash ui0902 ", 13) == 0) {
uint32_t size = (uint32_t)strtoul(cmd + 13, NULL, 10);
app_log_flash_start(size);
return 1U;
}
if (strncmp(cmd, "flash haitian ", 14) == 0) {
uint32_t size = (uint32_t)strtoul(cmd + 14, NULL, 10);
app_log_flash_start_at(FLASH_ADDR_SONG_HAITIAN, size,
"FLASH_HAITIAN_GO", "FLASH_HAITIAN_OK\n");
return 1U;
}
if (strncmp(cmd, "flash bin3 ", 11) == 0) {
uint32_t size = (uint32_t)strtoul(cmd + 11, NULL, 10);
app_log_flash_start_at(EXTFLASH_BIN3_UNIVERSAL_ADDR, size,
"FLASH_BIN3_GO", "FLASH_BIN3_OK\n");
return 1U;
}
if (strncmp(cmd, "tone status", 11) == 0) {
uint8_t hdr[16];
uint8_t name[40];
uint8_t cur_hdr[16];
char *pname;
char line[192];
const char *map;
W25Q128_Read(hdr, FLASH_ADDR_SONG_HAITIAN, 16);
W25Q128_Read(name, FLASH_ADDR_SONG_HAITIAN + 1280 + 4, 32);
name[32] = 0;
W25Q128_Read(cur_hdr, (uint32_t)ADDRESS, 16);
pname = AutoBandTop1_GetPresetName();
if (ADDRESS == EXTFLASH_BIN1_RHYTHM_ADDR)
map = "BIN1_RHYTHM";
else if (ADDRESS == EXTFLASH_BIN2_SONG_HAITIAN_ADDR)
map = "BIN2_SONG_HAITIAN";
else if (ADDRESS == EXTFLASH_BIN3_UNIVERSAL_ADDR)
map = "BIN3_UNIVERSAL";
else
map = "UNKNOWN";
snprintf(line, sizeof(line),
"TONE tab=%u sw=%u addr=0x%08lX map=%s songidx=%u rhyt=%u\n",
(unsigned)mGuiData[GUI_TAB_INDEX].Current,
(unsigned)mGuiData[GUI_AUTOBAND_SW].Current,
(unsigned long)ADDRESS, map,
(unsigned)ParamGuiData[EXPRESS_MODE_PARAM].Current,
(unsigned)ParamGuiData[SONG_MODE_PARAM].Current);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
snprintf(line, sizeof(line),
"TONE map BIN1=0x%08lX BIN2=0x%08lX BIN3=0x%08lX\n",
(unsigned long)EXTFLASH_BIN1_RHYTHM_ADDR,
(unsigned long)EXTFLASH_BIN2_SONG_HAITIAN_ADDR,
(unsigned long)EXTFLASH_BIN3_UNIVERSAL_ADDR);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
snprintf(line, sizeof(line),
"TONE @ADDRESS magic=%02X%02X%02X%02X cnt=%lu\n",
cur_hdr[0], cur_hdr[1], cur_hdr[2], cur_hdr[3],
(unsigned long)(cur_hdr[12] | (cur_hdr[13] << 8) |
(cur_hdr[14] << 16) | (cur_hdr[15] << 24)));
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
{
uint8_t b3[16];
W25Q128_Read(b3, EXTFLASH_BIN3_UNIVERSAL_ADDR, 16);
snprintf(line, sizeof(line),
"TONE @BIN3 magic=%02X%02X%02X%02X cnt=%lu\n",
b3[0], b3[1], b3[2], b3[3],
(unsigned long)(b3[12] | (b3[13] << 8) |
(b3[14] << 16) | (b3[15] << 24)));
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
}
snprintf(line, sizeof(line),
"TONE @BIN2 magic=%02X%02X%02X%02X max=%lu cnt=%lu name=%.16s\n",
hdr[0], hdr[1], hdr[2], hdr[3],
(unsigned long)(hdr[8] | (hdr[9] << 8) | (hdr[10] << 16) | (hdr[11] << 24)),
(unsigned long)(hdr[12] | (hdr[13] << 8) | (hdr[14] << 16) | (hdr[15] << 24)),
(char *)name);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
snprintf(line, sizeof(line),
"TONE loaded name=%s count=%d\n",
pname ? pname : "(null)",
AutoBandTop1_GetPresetItemCount());
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
return 1U;
}
if (strncmp(cmd, "tone reload", 11) == 0) {
char line[96];
UI_ReloadTonePreset();
snprintf(line, sizeof(line),
"TONE_RELOAD addr=0x%08lX name=%s\n",
(unsigned long)ADDRESS,
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "(null)");
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
return 1U;
}
if (strncmp(cmd, "tone local", 10) == 0) {
char line[128];
int ret;
mGuiData[GUI_TAB_INDEX].Current = 1; /* 专业 */
mGuiData[GUI_AUTOBAND_SW].Current = 1; /* 本地曲目 */
ParamGuiData[EXPRESS_MODE_PARAM].Current = 0;
UI_ApplyToneAddress();
AutoBandTop1_Stop();
StartFlag = 0;
ret = AutoBandTop1_LoadPresetItemFromFlash(0);
snprintf(line, sizeof(line),
"TONE_LOCAL ret=%d addr=0x%08lX map=BIN2@0x%08lX name=%s count=%d %s\n",
ret, (unsigned long)ADDRESS,
(unsigned long)EXTFLASH_BIN2_SONG_HAITIAN_ADDR,
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "(null)",
AutoBandTop1_GetPresetItemCount(),
(ADDRESS == EXTFLASH_BIN2_SONG_HAITIAN_ADDR) ? "OK" : "MISMATCH");
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
return 1U;
}
/* tone bin1 [idx] → 1.bin 节奏(专业+节奏类型) */
if (strncmp(cmd, "tone bin1", 9) == 0) {
char line[160];
int ret;
unsigned idx = 0;
int count;
if (cmd[9] == ' ' && cmd[10] != '\0')
idx = (unsigned)strtoul(cmd + 10, NULL, 10);
mGuiData[GUI_TAB_INDEX].Current = 1; /* 专业 */
mGuiData[GUI_AUTOBAND_SW].Current = 0; /* 节奏类型→1.bin */
ParamGuiData[SONG_MODE_PARAM].Current = (uint8_t)idx;
UI_ApplyToneAddress();
AutoBandTop1_Stop();
StartFlag = 0;
count = AutoBandTop1_GetPresetItemCount();
if (count > 0 && (int)idx >= count)
idx = (unsigned)(count - 1);
ParamGuiData[SONG_MODE_PARAM].Current = (uint8_t)idx;
ret = AutoBandTop1_LoadPresetItemFromFlash((int)idx);
snprintf(line, sizeof(line),
"TONE_BIN1 ret=%d idx=%u addr=0x%08lX map=BIN1@0x%08lX name=%s count=%d %s\n",
ret, idx, (unsigned long)ADDRESS,
(unsigned long)EXTFLASH_BIN1_RHYTHM_ADDR,
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "(null)",
AutoBandTop1_GetPresetItemCount(),
(ADDRESS == EXTFLASH_BIN1_RHYTHM_ADDR) ? "OK" : "MISMATCH");
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
return 1U;
}
/* tone bin3 [idx] → 3.bin 万能和弦走向 */
if (strncmp(cmd, "tone bin3", 9) == 0) {
char line[160];
int ret;
unsigned idx = 0;
int count;
if (cmd[9] == ' ' && cmd[10] != '\0')
idx = (unsigned)strtoul(cmd + 10, NULL, 10);
mGuiData[GUI_TAB_INDEX].Current = 0; /* 万能 */
mGuiData[GUI_AUTOBAND_SW].Current = 0;
ParamGuiData[ALL_MODE_PARAM].Current = (uint8_t)idx;
UI_ApplyToneAddress();
AutoBandTop1_Stop();
StartFlag = 0;
count = AutoBandTop1_GetPresetItemCount();
if (count > 0 && (int)idx >= count)
idx = (unsigned)(count - 1);
ParamGuiData[ALL_MODE_PARAM].Current = (uint8_t)idx;
ret = AutoBandTop1_LoadPresetItemFromFlash((int)idx);
snprintf(line, sizeof(line),
"TONE_BIN3 ret=%d idx=%u addr=0x%08lX map=BIN3@0x%08lX name=%s count=%d %s\n",
ret, idx, (unsigned long)ADDRESS,
(unsigned long)EXTFLASH_BIN3_UNIVERSAL_ADDR,
AutoBandTop1_GetPresetName() ? AutoBandTop1_GetPresetName() : "(null)",
AutoBandTop1_GetPresetItemCount(),
(ADDRESS == EXTFLASH_BIN3_UNIVERSAL_ADDR) ? "OK" : "MISMATCH");
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
return 1U;
}
/* tone start在当前已加载音色上拨片起奏不改 TAB/库) */
if (strncmp(cmd, "tone start", 10) == 0) {
StartFlag = 0;
if (!(cmd[10] == ' ' && (cmd[11] == 'k' || cmd[11] == 'K')))
KEY_ID_1629 = 0;
Pick_Handle();
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "TONE_START_DONE\n");
return 1U;
}
if (strncmp(cmd, "tone pick", 9) == 0) {
/* tone pick uni → 万能;默认仍测专业+本地曲目 */
if (cmd[9] == ' ' && (cmd[10] == 'u' || cmd[10] == 'U')) {
mGuiData[GUI_TAB_INDEX].Current = 0;
mGuiData[GUI_AUTOBAND_SW].Current = 0;
UI_ApplyToneAddress();
AutoBandTop1_Stop();
StartFlag = 0;
(void)AutoBandTop1_LoadPresetItemFromFlash(ParamGuiData[ALL_MODE_PARAM].Current);
KEY_ID_1629 = 0;
PressFlag = 0;
Pick_Handle();
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "TONE_PICK_UNI_DONE\n");
return 1U;
}
/* 模拟专业+本地曲目拨片chord pick keep → 保留已注入的 KEY_ID */
mGuiData[GUI_TAB_INDEX].Current = 1;
mGuiData[GUI_AUTOBAND_SW].Current = 1;
if (!(cmd[9] == ' ' && (cmd[10] == 'k' || cmd[10] == 'K'))) {
KEY_ID_1629 = 0; /* 默认走一级和弦兜底 */
}
StartFlag = 0;
Pick_Handle();
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "TONE_PICK_DONE\n");
return 1U;
}
/* 测试注入chord key N0释放 / 1~21和弦 / 22拍速 / 23停止 */
if (strncmp(cmd, "chord key ", 10) == 0 && cmd[10] != '\0') {
unsigned key = (unsigned)strtoul(cmd + 10, NULL, 10);
char line[48];
if (key > 23U) {
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "CHORD_KEY_BAD\n");
return 1U;
}
app_tm1629_inject_key((uint8_t)key);
snprintf(line, sizeof(line), "CHORD_KEY_OK key=%u\n", key);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
return 1U;
}
/* 测试注入chord xpose N0~11C=0 */
if (strncmp(cmd, "chord xpose ", 12) == 0 && cmd[12] != '\0') {
unsigned xp = (unsigned)strtoul(cmd + 12, NULL, 10);
char line[48];
if (xp > 11U) {
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "CHORD_XPOSE_BAD\n");
return 1U;
}
mGuiData[GUI_TRANSPOSE].Current = (uint8_t)xp;
snprintf(line, sizeof(line), "CHORD_XPOSE_OK xp=%u\n", xp);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, line);
LOG_I("REG", "xpose set %u", xp);
return 1U;
}
if (strncmp(cmd, "flash erase chip", 16) == 0) {
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "FLASH_ERASE_BEGIN\n");
LOG_I("FLASH", "W25Q128 chip erase start");
W25Q128_Erase_Chip();
LOG_I("FLASH", "W25Q128 chip erase done");
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "FLASH_ERASE_OK\n");
return 1U;
}
if (strncmp(cmd, "ui boot", 7) == 0) {
LCD_BLK_Set();
LCD_WR_PIC_FROM_FLASH(0, 0, UI0902_BOOT_LOGO_W, UI0902_BOOT_LOGO_H,
UI0902_BOOT_LOGO_ADDR);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "UI_BOOT_OK\n");
return 1U;
}
if (strncmp(cmd, "ui charge", 9) == 0) {
uint8_t peek[4];
LCD_BLK_Set();
LCD_FillByColor(0, 0, 240, 320, UI0902_BG_COLOR);
W25Q128_Read(peek, UI0902_CHARGE_SCREEN_ADDR, 4);
if (peek[0] != 0xFF || peek[1] != 0xFF) {
LCD_WR_PIC_FROM_FLASH(0, 0, UI0902_CHARGE_SCREEN_W, UI0902_CHARGE_SCREEN_H,
UI0902_CHARGE_SCREEN_ADDR);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "UI_CHARGE_OK\n");
} else {
Draw_Charging_Icon(120, 150, 2, 0x3D7F);
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "UI_CHARGE_EMPTY\n");
}
{
const char *s = "50";
uint16_t tw = g_ChargePctPercent.w;
uint16_t x, y = 266;
uint8_t i;
for (i = 0; s[i]; i++)
tw = (uint16_t)(tw + g_ChargePctDigits[s[i] - '0'].w);
LCD_FillByColor(40, 262, 200, 290, UI0902_BG_COLOR);
x = (uint16_t)((240 - tw) / 2);
for (i = 0; s[i]; i++) {
const ChargePctGlyph *g = &g_ChargePctDigits[s[i] - '0'];
LCD_WR_PIC_Trans(x, y, g->w, g->h, g->data, BLACK);
x = (uint16_t)(x + g->w);
}
LCD_WR_PIC_Trans(x, y, g_ChargePctPercent.w, g_ChargePctPercent.h,
g_ChargePctPercent.data, BLACK);
}
return 1U;
}
return 0U;
}
static void app_log_feed_char(char c)
{
if (c == '\r' || c == '\n' || c == '\0') {
if (s_cmd_len > 0U) {
s_cmd_buf[s_cmd_len] = '\0';
(void)app_log_try_command(s_cmd_buf);
}
s_cmd_len = 0U;
s_cmd_buf[0] = '\0';
return;
}
if (s_cmd_len + 1U >= sizeof(s_cmd_buf)) {
s_cmd_len = 0U;
}
s_cmd_buf[s_cmd_len++] = c;
s_cmd_buf[s_cmd_len] = '\0';
if (strstr(s_cmd_buf, "sys reset") != NULL) {
s_cmd_len = 0U;
s_cmd_buf[0] = '\0';
(void)app_log_try_command("sys reset");
}
}
void app_log_poll(void)
{
uint8_t rx[64];
unsigned read_len;
unsigned i;
read_len = SEGGER_RTT_Read(APP_LOG_RTT_CHANNEL, rx, sizeof(rx));
if (read_len == 0U) {
return;
}
if (s_flash_mode) {
app_log_flash_feed(rx, read_len);
return;
}
for (i = 0; i < read_len; i++) {
app_log_feed_char((char)rx[i]);
}
}
void app_log_init(void)
{
s_boot_count++;
LOG_I("BOOT", "app_log init boot=%u", (unsigned)s_boot_count);
}
#else
void app_log_init(void) {}
void app_log_write(char level, const char *cat, const char *fmt, ...) { (void)level; (void)cat; (void)fmt; }
void app_log_poll(void) {}
uint8_t app_log_try_command(const char *cmd) { (void)cmd; return 0U; }
void app_log_set_ui_page(const char *name) { (void)name; }
uint8_t app_log_flash_busy(void) { return 0U; }
#endif /* APP_LOG_ENABLE */