2026-08-31 11:24:10 +08:00
|
|
|
|
#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';
|
2026-09-13 21:21:11 +08:00
|
|
|
|
static char s_cmd_buf[64];
|
2026-08-31 11:24:10 +08:00
|
|
|
|
static uint8_t s_cmd_len;
|
|
|
|
|
|
|
2026-09-07 21:48:54 +08:00
|
|
|
|
/* RTT 二进制烧录:写到 W25Q128(ui0902 或本地曲目) */
|
2026-09-02 15:24:49 +08:00
|
|
|
|
static uint8_t s_flash_mode;
|
2026-09-07 21:48:54 +08:00
|
|
|
|
static uint32_t s_flash_base;
|
2026-09-02 15:24:49 +08:00
|
|
|
|
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];
|
2026-09-07 21:48:54 +08:00
|
|
|
|
static char s_flash_ok_tag[24];
|
2026-09-02 15:24:49 +08:00
|
|
|
|
|
|
|
|
|
|
uint8_t app_log_flash_busy(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
return s_flash_mode;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-31 11:24:10 +08:00
|
|
|
|
static uint32_t app_log_ms(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
return (uint32_t)(rt_tick_get() * 1000U / RT_TICK_PER_SECOND);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-02 15:24:49 +08:00
|
|
|
|
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;
|
|
|
|
|
|
|
2026-09-02 16:57:36 +08:00
|
|
|
|
/* 每页 ACK,避免主机打爆 RTT 下行缓冲 */
|
|
|
|
|
|
snprintf(ack, sizeof(ack), "FLASH_ACK %lu\n", (unsigned long)s_flash_addr);
|
|
|
|
|
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, ack);
|
2026-09-02 15:24:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void app_log_flash_feed(const uint8_t *data, unsigned len)
|
|
|
|
|
|
{
|
|
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < len && s_flash_remain > 0U; i++) {
|
2026-09-07 21:48:54 +08:00
|
|
|
|
if (s_flash_page_len == 0U && s_flash_addr == s_flash_base && i == 0U) {
|
2026-09-02 15:24:49 +08:00
|
|
|
|
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;
|
2026-09-07 21:48:54 +08:00
|
|
|
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, s_flash_ok_tag);
|
2026-09-02 15:24:49 +08:00
|
|
|
|
UI_DrawModeSelectScreen();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-07 21:48:54 +08:00
|
|
|
|
static void app_log_flash_start_at(uint32_t base, uint32_t size, const char *go_tag, const char *ok_tag)
|
2026-09-02 15:24:49 +08:00
|
|
|
|
{
|
2026-09-07 21:48:54 +08:00
|
|
|
|
char msg[80];
|
2026-09-02 15:24:49 +08:00
|
|
|
|
|
|
|
|
|
|
if (size == 0U || size > (2U * 1024U * 1024U)) {
|
2026-09-07 21:48:54 +08:00
|
|
|
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "FLASH_ERR size\n");
|
2026-09-02 15:24:49 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
s_flash_mode = 1U;
|
2026-09-07 21:48:54 +08:00
|
|
|
|
s_flash_base = base;
|
|
|
|
|
|
s_flash_addr = base;
|
2026-09-02 15:24:49 +08:00
|
|
|
|
s_flash_remain = size;
|
|
|
|
|
|
s_flash_last_sector = 0xFFFFFFFFUL;
|
|
|
|
|
|
s_flash_page_len = 0U;
|
|
|
|
|
|
s_cmd_len = 0U;
|
|
|
|
|
|
s_cmd_buf[0] = '\0';
|
2026-09-07 21:48:54 +08:00
|
|
|
|
strncpy(s_flash_ok_tag, ok_tag, sizeof(s_flash_ok_tag) - 1U);
|
|
|
|
|
|
s_flash_ok_tag[sizeof(s_flash_ok_tag) - 1U] = '\0';
|
2026-09-02 15:24:49 +08:00
|
|
|
|
|
|
|
|
|
|
snprintf(msg, sizeof(msg),
|
2026-09-07 21:48:54 +08:00
|
|
|
|
"%s base=0x%08lX size=%lu\n",
|
|
|
|
|
|
go_tag, (unsigned long)base, (unsigned long)size);
|
2026-09-02 15:24:49 +08:00
|
|
|
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, msg);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-07 21:48:54 +08:00
|
|
|
|
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");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-31 11:24:10 +08:00
|
|
|
|
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, ...)
|
|
|
|
|
|
{
|
2026-09-10 06:51:32 +08:00
|
|
|
|
/* 静态行缓冲:TaskBTRecv 等小栈线程禁止再开 128B 局部数组 */
|
|
|
|
|
|
static char line[APP_LOG_SLOT_SIZE];
|
|
|
|
|
|
static rt_mutex_t s_log_mtx = RT_NULL;
|
2026-08-31 11:24:10 +08:00
|
|
|
|
va_list ap;
|
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
|
|
if (level == 'D' && s_debug_level != 'D') {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-10 06:51:32 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-31 11:24:10 +08:00
|
|
|
|
n = snprintf(line, sizeof(line), "[%05u][%c][%-4s] ",
|
|
|
|
|
|
(unsigned)app_log_ms(), level, cat);
|
|
|
|
|
|
if (n < 0) {
|
2026-09-10 06:51:32 +08:00
|
|
|
|
if (s_log_mtx != RT_NULL) {
|
|
|
|
|
|
rt_mutex_release(s_log_mtx);
|
|
|
|
|
|
}
|
2026-08-31 11:24:10 +08:00
|
|
|
|
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");
|
2026-09-10 06:51:32 +08:00
|
|
|
|
|
|
|
|
|
|
if (s_log_mtx != RT_NULL) {
|
|
|
|
|
|
rt_mutex_release(s_log_mtx);
|
|
|
|
|
|
}
|
2026-08-31 11:24:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-31 12:31:53 +08:00
|
|
|
|
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();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-31 11:24:10 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-08-31 21:59:13 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-08-31 12:31:53 +08:00
|
|
|
|
if (strncmp(cmd, "sys reset", 9) == 0) {
|
|
|
|
|
|
app_log_sys_reset();
|
|
|
|
|
|
return 1U;
|
|
|
|
|
|
}
|
2026-09-02 15:24:49 +08:00
|
|
|
|
if (strncmp(cmd, "flash ui0902 ", 13) == 0) {
|
|
|
|
|
|
uint32_t size = (uint32_t)strtoul(cmd + 13, NULL, 10);
|
|
|
|
|
|
app_log_flash_start(size);
|
|
|
|
|
|
return 1U;
|
|
|
|
|
|
}
|
2026-09-07 21:48:54 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-09-09 11:32:40 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-09-07 21:48:54 +08:00
|
|
|
|
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);
|
2026-09-09 11:32:40 +08:00
|
|
|
|
{
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
2026-09-07 21:48:54 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-09-13 21:21:11 +08:00
|
|
|
|
/* 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;
|
|
|
|
|
|
}
|
2026-09-07 21:48:54 +08:00
|
|
|
|
if (strncmp(cmd, "tone pick", 9) == 0) {
|
2026-09-09 11:35:14 +08:00
|
|
|
|
/* 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;
|
|
|
|
|
|
}
|
2026-09-13 21:21:11 +08:00
|
|
|
|
/* 模拟专业+本地曲目拨片;chord pick keep → 保留已注入的 KEY_ID */
|
2026-09-07 21:48:54 +08:00
|
|
|
|
mGuiData[GUI_TAB_INDEX].Current = 1;
|
|
|
|
|
|
mGuiData[GUI_AUTOBAND_SW].Current = 1;
|
2026-09-13 21:21:11 +08:00
|
|
|
|
if (!(cmd[9] == ' ' && (cmd[10] == 'k' || cmd[10] == 'K'))) {
|
|
|
|
|
|
KEY_ID_1629 = 0; /* 默认走一级和弦兜底 */
|
|
|
|
|
|
}
|
2026-09-07 21:48:54 +08:00
|
|
|
|
StartFlag = 0;
|
|
|
|
|
|
Pick_Handle();
|
|
|
|
|
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "TONE_PICK_DONE\n");
|
|
|
|
|
|
return 1U;
|
|
|
|
|
|
}
|
2026-09-13 21:21:11 +08:00
|
|
|
|
/* 测试注入:chord key N(0释放 / 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 N(0~11,C=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;
|
|
|
|
|
|
}
|
2026-09-04 17:06:02 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-09-02 16:57:36 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-09-05 20:39:11 +08:00
|
|
|
|
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");
|
|
|
|
|
|
}
|
2026-09-05 21:11:28 +08:00
|
|
|
|
{
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
2026-09-05 20:39:11 +08:00
|
|
|
|
return 1U;
|
|
|
|
|
|
}
|
2026-08-31 11:24:10 +08:00
|
|
|
|
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';
|
2026-08-31 12:31:53 +08:00
|
|
|
|
|
|
|
|
|
|
if (strstr(s_cmd_buf, "sys reset") != NULL) {
|
|
|
|
|
|
s_cmd_len = 0U;
|
|
|
|
|
|
s_cmd_buf[0] = '\0';
|
|
|
|
|
|
(void)app_log_try_command("sys reset");
|
|
|
|
|
|
}
|
2026-08-31 11:24:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void app_log_poll(void)
|
|
|
|
|
|
{
|
2026-09-02 15:24:49 +08:00
|
|
|
|
uint8_t rx[64];
|
2026-08-31 11:24:10 +08:00
|
|
|
|
unsigned read_len;
|
|
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
|
|
|
|
read_len = SEGGER_RTT_Read(APP_LOG_RTT_CHANNEL, rx, sizeof(rx));
|
|
|
|
|
|
if (read_len == 0U) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-02 15:24:49 +08:00
|
|
|
|
if (s_flash_mode) {
|
|
|
|
|
|
app_log_flash_feed(rx, read_len);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-31 11:24:10 +08:00
|
|
|
|
for (i = 0; i < read_len; i++) {
|
2026-09-02 15:24:49 +08:00
|
|
|
|
app_log_feed_char((char)rx[i]);
|
2026-08-31 11:24:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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; }
|
2026-09-02 15:24:49 +08:00
|
|
|
|
uint8_t app_log_flash_busy(void) { return 0U; }
|
2026-08-31 11:24:10 +08:00
|
|
|
|
|
|
|
|
|
|
#endif /* APP_LOG_ENABLE */
|