Compare commits

..

No commits in common. "956eeee1a50a8abec7f0dc164a4924edd2fc62c7" and "27cf30cbe42916db11fd946104ce311740cbb1f2" have entirely different histories.

31 changed files with 322 additions and 5014 deletions

View File

@ -1,226 +0,0 @@
#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[48];
static uint8_t s_cmd_len;
static uint32_t app_log_ms(void)
{
return (uint32_t)(rt_tick_get() * 1000U / RT_TICK_PER_SECOND);
}
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, ...)
{
char line[APP_LOG_SLOT_SIZE];
va_list ap;
int n;
if (level == 'D' && s_debug_level != 'D') {
return;
}
n = snprintf(line, sizeof(line), "[%05u][%c][%-4s] ",
(unsigned)app_log_ms(), level, cat);
if (n < 0) {
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");
}
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, "sys reset", 9) == 0) {
app_log_sys_reset();
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)
{
char rx[16];
unsigned read_len;
unsigned i;
read_len = SEGGER_RTT_Read(APP_LOG_RTT_CHANNEL, rx, sizeof(rx));
if (read_len == 0U) {
return;
}
for (i = 0; i < read_len; i++) {
app_log_feed_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; }
#endif /* APP_LOG_ENABLE */

View File

@ -1,66 +0,0 @@
#ifndef __APP_LOG_H__
#define __APP_LOG_H__
#include <stdint.h>
#ifndef APP_LOG_ENABLE
#define APP_LOG_ENABLE 1
#endif
#ifndef APP_LOG_DEBUG
#define APP_LOG_DEBUG 1
#endif
#ifndef APP_LOG_RAM_SIZE
#define APP_LOG_RAM_SIZE (4U * 1024U)
#endif
#ifndef APP_LOG_SLOT_SIZE
#define APP_LOG_SLOT_SIZE 128U
#endif
#ifndef APP_LOG_RTT_CHANNEL
#define APP_LOG_RTT_CHANNEL 0
#endif
#ifndef APP_LOG_TP_VERBOSE
#define APP_LOG_TP_VERBOSE 1
#endif
#define APP_LOG_SLOT_COUNT (APP_LOG_RAM_SIZE / APP_LOG_SLOT_SIZE)
void app_log_init(void);
void app_log_write(char level, const char *cat, const char *fmt, ...);
void app_log_poll(void);
uint8_t app_log_try_command(const char *cmd);
void app_log_set_ui_page(const char *name);
#if APP_LOG_ENABLE
#define LOG_I(cat, fmt, ...) app_log_write('I', (cat), (fmt), ##__VA_ARGS__)
#define LOG_W(cat, fmt, ...) app_log_write('W', (cat), (fmt), ##__VA_ARGS__)
#define LOG_E(cat, fmt, ...) app_log_write('E', (cat), (fmt), ##__VA_ARGS__)
#if APP_LOG_DEBUG
#define LOG_D(cat, fmt, ...) app_log_write('D', (cat), (fmt), ##__VA_ARGS__)
#else
#define LOG_D(cat, fmt, ...) ((void)0)
#endif
#if APP_LOG_TP_VERBOSE
#define LOG_TP(fmt, ...) LOG_D("TP", fmt, ##__VA_ARGS__)
#else
#define LOG_TP(fmt, ...) ((void)0)
#endif
#else
#define LOG_I(cat, fmt, ...) ((void)0)
#define LOG_W(cat, fmt, ...) ((void)0)
#define LOG_E(cat, fmt, ...) ((void)0)
#define LOG_D(cat, fmt, ...) ((void)0)
#define LOG_TP(fmt, ...) ((void)0)
#endif
#endif /* __APP_LOG_H__ */

View File

@ -78,7 +78,6 @@ uint8_t app_tm1617_scan_key(void)
if (key != key_last) if (key != key_last)
{ {
key_last = key; key_last = key;
LOG_I("KEY", "tm1617 key=%u", (unsigned)key);
TM1617_Handle(key); TM1617_Handle(key);
return key; return key;
} }

View File

@ -31,7 +31,6 @@ uint8_t app_tm1629_Scan_Key(void)
if(key != key_last) if(key != key_last)
{ {
key_last = key; key_last = key;
LOG_I("KEY", "tm1629 key=%u", (unsigned)key);
TM1629_Handle(key); TM1629_Handle(key);
return key; return key;
} }

View File

@ -1,46 +1,64 @@
#include "includes.h" #include "includes.h"
/* ?????????????????????????????? */ /* ============================================================================
* app_touch
*
* Touch_Process
* IDLE PRESS_WAIT_STABLE PRESS_STABLE SLIDING
*
*
* 20ms (TOUCH_STABLE_TIME)
* 10px (TOUCH_SLIDE_THRESH)
* 5px (TOUCH_SLIDE_STEP)
* 1000ms (TOUCH_LONG_PRESS_TIME)
* 120ms (TOUCH_REPEAT_INTERVAL)
* ==========================================================================*/
/* ==================== 状态机枚举 ==================== */
typedef enum { typedef enum {
TOUCH_IDLE, TOUCH_IDLE, /* 空闲 */
TOUCH_PRESS_WAIT_STABLE, TOUCH_PRESS_WAIT_STABLE, /* 按下,等待稳定判定 */
TOUCH_PRESS_STABLE, TOUCH_PRESS_STABLE, /* 稳定按下(可长按) */
TOUCH_SLIDING TOUCH_SLIDING /* 滑动中 */
} touch_state_t; } touch_state_t;
#define TOUCH_STABLE_TIME 8 /* ==================== 时序参数 ==================== */
#define TOUCH_SLIDE_THRESH 12 #define TOUCH_STABLE_TIME 20 /* 按下稳定判定时间 ms */
#define TOUCH_SLIDE_STEP 5 #define TOUCH_SLIDE_THRESH 10 /* 进入滑动的最小位移 px */
#define TOUCH_LONG_PRESS_TIME 800 #define TOUCH_SLIDE_STEP 5 /* 滑动事件最小步进 px */
#define TOUCH_REPEAT_INTERVAL 120 #define TOUCH_LONG_PRESS_TIME 1000 /* 长按触发 ms */
#define TOUCH_REPEAT_INTERVAL 120 /* 长按重复间隔 ms */
/* ==================== 状态变量 ==================== */
static touch_state_t touch_state = TOUCH_IDLE; static touch_state_t touch_state = TOUCH_IDLE;
static uint16_t down_x = 0; static uint16_t down_x = 0;
static uint16_t down_y = 0; static uint16_t down_y = 0;
static uint32_t touch_tick = 0; static uint32_t touch_tick = 0;
static uint32_t repeat_tick = 0; static uint32_t repeat_tick = 0;
static uint8_t long_press_fired = 0; static uint8_t long_press_fired = 0;
static uint8_t click_sent = 0;
static uint16_t last_slide_x = 0; static uint16_t last_slide_x = 0;
static uint16_t last_slide_y = 0; static uint16_t last_slide_y = 0;
/* 取绝对值(避免引入 math.h */
static inline uint16_t abs_diff(int16_t a, int16_t b) static inline uint16_t abs_diff(int16_t a, int16_t b)
{ {
int16_t d = a - b; int16_t d = a - b;
return (d < 0) ? (uint16_t)(-d) : (uint16_t)d; return (d < 0) ? (uint16_t)(-d) : (uint16_t)d;
} }
/* ==================== 重置 ==================== */
void app_touch_reset(void) void app_touch_reset(void)
{ {
touch_state = TOUCH_IDLE; touch_state = TOUCH_IDLE;
down_x = down_y = 0; down_x = down_y = 0;
touch_tick = repeat_tick = 0; touch_tick = repeat_tick = 0;
long_press_fired = 0; long_press_fired = 0;
click_sent = 0;
last_slide_x = last_slide_y = 0; last_slide_x = last_slide_y = 0;
} }
/* ==================== 手势识别 ==================== */
app_touch_result_t app_touch_process(uint16_t x, uint16_t y, uint8_t pressed) app_touch_result_t app_touch_process(uint16_t x, uint16_t y, uint8_t pressed)
{ {
app_touch_result_t r; app_touch_result_t r;
@ -50,26 +68,22 @@ app_touch_result_t app_touch_process(uint16_t x, uint16_t y, uint8_t pressed)
uint32_t now = rt_tick_get(); uint32_t now = rt_tick_get();
/* ---------- 抬起处理 ---------- */
if (!pressed) { if (!pressed) {
if (!long_press_fired && !click_sent && /* 若曾稳定按下且未触发长按 → 释放(可当作 TAP */
(touch_state == TOUCH_PRESS_WAIT_STABLE || if (touch_state == TOUCH_PRESS_STABLE && !long_press_fired) {
touch_state == TOUCH_PRESS_STABLE))
{
r.gesture = GESTURE_RELEASE; r.gesture = GESTURE_RELEASE;
r.x = down_x; r.x = down_x; r.y = down_y; /* 用按下点作为释放坐标 */
r.y = down_y;
LOG_D("TP", "release x=%u y=%u", (unsigned)down_x, (unsigned)down_y);
MainTask_Sendmsg(MSG_ID_TOUCH, 1, down_x, down_y);
} }
touch_state = TOUCH_IDLE; touch_state = TOUCH_IDLE;
down_x = down_y = 0; down_x = down_y = 0;
last_slide_x = last_slide_y = 0; last_slide_x = last_slide_y = 0;
touch_tick = repeat_tick = 0; touch_tick = repeat_tick = 0;
long_press_fired = 0; long_press_fired = 0;
click_sent = 0;
return r; return r;
} }
/* ---------- 按下处理 ---------- */
switch (touch_state) switch (touch_state)
{ {
case TOUCH_IDLE: case TOUCH_IDLE:
@ -77,42 +91,44 @@ app_touch_result_t app_touch_process(uint16_t x, uint16_t y, uint8_t pressed)
down_y = y; down_y = y;
touch_tick = now; touch_tick = now;
long_press_fired = 0; long_press_fired = 0;
click_sent = 0;
repeat_tick = 0; repeat_tick = 0;
touch_state = TOUCH_PRESS_WAIT_STABLE; touch_state = TOUCH_PRESS_WAIT_STABLE;
/* ??????????????????????? */
click_sent = 1;
LOG_D("TP", "press down x=%u y=%u", (unsigned)down_x, (unsigned)down_y);
MainTask_Sendmsg(MSG_ID_TOUCH, 1, down_x, down_y);
break; break;
case TOUCH_PRESS_WAIT_STABLE: case TOUCH_PRESS_WAIT_STABLE:
if ((now - touch_tick) >= TOUCH_STABLE_TIME) { if ((now - touch_tick) >= TOUCH_STABLE_TIME) {
if (abs_diff(x, down_x) < 24 && abs_diff(y, down_y) < 24) /* 位移小 → 进入稳定 */
if (abs_diff(x, down_x) < 8 && abs_diff(y, down_y) < 8) {
touch_state = TOUCH_PRESS_STABLE; touch_state = TOUCH_PRESS_STABLE;
else { last_slide_x = down_x;
down_x = x; last_slide_y = down_y;
down_y = y;
touch_tick = now; touch_tick = now;
MainTask_Sendmsg(MSG_ID_TOUCH, 1, down_x, down_y);
} else {
/* 位移大 → 视为误触,回到空闲 */
touch_state = TOUCH_IDLE;
} }
} }
break; break;
case TOUCH_PRESS_STABLE: case TOUCH_PRESS_STABLE:
{
/* ----- 长按检测 ----- */
if (!long_press_fired && (now - touch_tick) >= TOUCH_LONG_PRESS_TIME) { if (!long_press_fired && (now - touch_tick) >= TOUCH_LONG_PRESS_TIME) {
long_press_fired = 1; long_press_fired = 1;
repeat_tick = now; repeat_tick = now;
r.gesture = GESTURE_LONG_PRESS; r.gesture = GESTURE_LONG_PRESS;
LOG_D("TP", "long_press x=%u y=%u", (unsigned)down_x, (unsigned)down_y);
MainTask_Sendmsg(MSG_ID_TOUCH_LONG_REPEAT, 1, down_x, down_y); MainTask_Sendmsg(MSG_ID_TOUCH_LONG_REPEAT, 1, down_x, down_y);
return r; return r;
} }
/* ----- 长按重复 ----- */
if (long_press_fired && (now - repeat_tick) >= TOUCH_REPEAT_INTERVAL) { if (long_press_fired && (now - repeat_tick) >= TOUCH_REPEAT_INTERVAL) {
repeat_tick = now; repeat_tick = now;
r.gesture = GESTURE_REPEAT; r.gesture = GESTURE_REPEAT;
MainTask_Sendmsg(MSG_ID_TOUCH_LONG_REPEAT, 1, down_x, down_y); MainTask_Sendmsg(MSG_ID_TOUCH_LONG_REPEAT, 1, down_x, down_y);
return r; return r;
} }
/* ----- 位移进入滑动 ----- */
if (abs_diff(x, down_x) >= TOUCH_SLIDE_THRESH || if (abs_diff(x, down_x) >= TOUCH_SLIDE_THRESH ||
abs_diff(y, down_y) >= TOUCH_SLIDE_THRESH) { abs_diff(y, down_y) >= TOUCH_SLIDE_THRESH) {
touch_state = TOUCH_SLIDING; touch_state = TOUCH_SLIDING;
@ -120,12 +136,15 @@ app_touch_result_t app_touch_process(uint16_t x, uint16_t y, uint8_t pressed)
last_slide_y = y; last_slide_y = y;
} }
break; break;
}
case TOUCH_SLIDING: case TOUCH_SLIDING:
{
/* 位移超过步进 → 产生拖动事件 */
if (abs_diff(x, last_slide_x) >= TOUCH_SLIDE_STEP || if (abs_diff(x, last_slide_x) >= TOUCH_SLIDE_STEP ||
abs_diff(y, last_slide_y) >= TOUCH_SLIDE_STEP) { abs_diff(y, last_slide_y) >= TOUCH_SLIDE_STEP) {
r.gesture = GESTURE_DRAG; r.gesture = GESTURE_DRAG;
r.down_x = last_slide_x; r.down_x = last_slide_x; /* 记录上次位置,便于消费端算增量 */
r.down_y = last_slide_y; r.down_y = last_slide_y;
MainTask_Sendmsg(MSG_ID_TOUCH, 1, x, y); MainTask_Sendmsg(MSG_ID_TOUCH, 1, x, y);
last_slide_x = x; last_slide_x = x;
@ -133,11 +152,12 @@ app_touch_result_t app_touch_process(uint16_t x, uint16_t y, uint8_t pressed)
return r; return r;
} }
break; break;
}
default: default:
touch_state = TOUCH_IDLE; touch_state = TOUCH_IDLE;
break; break;
} }
return r; return r; /* 无手势 */
} }

View File

@ -130,17 +130,13 @@ int main(void)
TM1617_GPIO_Init(); TM1617_GPIO_Init();
/* 短暂等待总线稳定;默认跳转 App。 wk_delay_ms(1000);
* KEY_MAIN_A USB
* KEY_NULL App Boot */
wk_delay_ms(50);
TM1617KeyValue = TM1617_ScanFkey(); TM1617KeyValue = TM1617_ScanFkey();
if (TM1617KeyValue != KEY_MAIN_A) if(TM1617KeyValue == 4)
{ {
JumpToApplication(); JumpToApplication();
/* 若 App 向量无效则继续走升级模式 */
} }
/* init spi1 function. */ /* init spi1 function. */
BSP_MainPowerEnable(1); BSP_MainPowerEnable(1);
wk_spi1_init(); wk_spi1_init();

View File

@ -52,33 +52,37 @@ Fader_t faders[4] = {
const Touch_AreaTypeDef Touch_Areas[] = const Touch_AreaTypeDef Touch_Areas[] =
{ {
/* Xmin,Xmax,Ymin,Ymax, Flag, Value, ID, action — 坐标相对 240x320 */ // Xmin, Xmax, Ymin, Ymax, flag,value ID, action
{ 0, 60, 25, 95, -1, 0, GUI_TRANSPOSE, NULL }, { 0, 60, 25, 90, -1, 0, GUI_TRANSPOSE, NULL },
{ 60, 120, 25, 95, 1, 0, GUI_TRANSPOSE, NULL }, { 60, 120, 25, 90, 1, 0, GUI_TRANSPOSE, NULL },
{ 125, 180, 25, 95, -1, 0, GUI_SPEED, NULL }, { 125, 180, 25, 90, -1, 0, GUI_SPEED, NULL },
{ 180, 239, 25, 95, 1, 0, GUI_SPEED, NULL }, { 180, 240, 25, 90, 1, 0, GUI_SPEED, NULL },
{ 0, 85, 95, 130, 0, 0, GUI_AUTOBAND_SW, NULL }, { 0, 80, 90, 120, 0, 0, GUI_AUTOBAND_SW, NULL },
{ 90, 175, 95, 130, 0, 1, GUI_AUTOBAND_SW, NULL }, { 90, 170, 90, 120, 0, 1, GUI_AUTOBAND_SW, NULL },
{ 80, 140, 0, 30, 0, 0, GUI_BL_SW, NULL },
{ 0, 120, 130, 165, -1, 0, GUI_MODE_PARAM, NULL }, { 0, 120, 120, 150, -1, 0, GUI_MODE_PARAM, NULL },
{ 120, 239, 130, 165, 1, 0, GUI_MODE_PARAM, NULL }, {120, 240, 120, 150, 1, 0, GUI_MODE_PARAM, NULL },
{ 0, 120, 165, 215, -1, 0, GUI_TIMBRE_SELECT, NULL }, { 10, 120, 125, 150, -1, 0, GUI_MODE_PARAM, NULL },
{ 120, 239, 165, 215, 1, 0, GUI_TIMBRE_SELECT, NULL }, { 80, 140, 0, 30, 0, 0, GUI_MODE_PARAM, NULL },
{ 0, 117, 155, 200, -1, 0, GUI_TIMBRE_SELECT, NULL },
{ 120, 240, 155, 200, 1, 0, GUI_TIMBRE_SELECT, NULL },
{ 10, 50, 275, 340, 0,2, GUI_TAB_INDEX, NULL },
{ 70, 130, 275, 340, 0,0, GUI_TAB_INDEX, NULL },
{ 130, 170, 275, 340, 0,1, GUI_TAB_INDEX, NULL },
{ 190, 230, 275, 340, 0,3, GUI_TAB_INDEX, NULL },
{ 10, 60, 240, 320, 0,0, GUI_PLAY_SECTION, NULL },
{ 60, 110, 240, 320, 0,1, GUI_PLAY_SECTION, NULL },
{ 110, 170, 240, 320, 0,2, GUI_PLAY_SECTION, NULL },
{ 170, 220, 240, 320, 0,3, GUI_PLAY_SECTION, NULL },
/* 演奏段落 1~4 */
{ 10, 60, 220, 270, 0, 0, GUI_PLAY_SECTION, NULL },
{ 60, 110, 220, 270, 0, 1, GUI_PLAY_SECTION, NULL },
{ 110, 165, 220, 270, 0, 2, GUI_PLAY_SECTION, NULL },
{ 165, 220, 220, 270, 0, 3, GUI_PLAY_SECTION, NULL },
/* 底栏 TAB万能/普通/专业/设置Value=目标 TAB */
{ 0, 60, 275, 319, 0, 0, GUI_TAB_INDEX, NULL },
{ 60, 120, 275, 319, 0, 2, GUI_TAB_INDEX, NULL },
{ 120, 180, 275, 319, 0, 1, GUI_TAB_INDEX, NULL },
{ 180, 239, 275, 319, 0, 3, GUI_TAB_INDEX, NULL },
}; };
int16_t MIC_VOL_MAP[10]= {-9000,-7000,-5000,-3000,-1000,1000,3000,5000,7000,9000}; int16_t MIC_VOL_MAP[10]= {-9000,-7000,-5000,-3000,-1000,1000,3000,5000,7000,9000};
@ -96,22 +100,12 @@ bool AutoCloseFlag = true;
void MainTask_Sendmsg(uint16_t ID, uint16_t ID2, uint16_t HiByte, uint16_t LoByte) void MainTask_Sendmsg(uint16_t ID, uint16_t ID2, uint16_t HiByte, uint16_t LoByte)
{ {
DisplayTaskMessage_Type msg; DisplayTaskMessage_Type msg;
rt_err_t ret;
msg.MessageType = ID; /* 业务消息 IDMSG_ID_xxx */ msg.MessageType = ID; /* 业务消息 IDMSG_ID_xxx */
msg.ID = ID2; msg.ID = ID2;
msg.HiByte = HiByte; msg.HiByte = HiByte;
msg.LoByte = LoByte; msg.LoByte = LoByte;
ret = rt_mq_send(MainTask_msg, &msg, sizeof(DisplayTaskMessage_Type)); rt_mq_send(MainTask_msg, &msg, sizeof(DisplayTaskMessage_Type));
if (ret != RT_EOK) {
LOG_E("MSG", "send fail id=%u ret=%d", (unsigned)ID, (int)ret);
} else if (ID == MSG_ID_TOUCH || ID == MSG_ID_TOUCH_LONG_REPEAT ||
ID == MSG_ID_POWER_ON || ID == MSG_ID_POWER_OFF ||
ID == MSG_ID_BP_KEY || ID == MSG_ID_TAP_SPEED ||
ID == MSG_ID_BP_TRANSPOSE) {
LOG_I("MSG", "id=%u hi=%u lo=%u", (unsigned)ID, (unsigned)HiByte, (unsigned)LoByte);
}
} }
@ -161,9 +155,8 @@ static uint32_t pwr_press_tick = 0;
bool powon = false; bool powon = false;
/* ==================== 开机/关机动作 ==================== */ /* ==================== 开机/关机动作 ==================== */
void System_PowerOn(void) static void PowerOn(void)
{ {
LOG_I("PWR", "power_on begin");
/* 控制电源硬件 */ /* 控制电源硬件 */
BSP_MainPowerEnable(1); BSP_MainPowerEnable(1);
BSP_DreamCorePowerEnable(1); BSP_DreamCorePowerEnable(1);
@ -176,26 +169,16 @@ void System_PowerOn(void)
app_tm1617_init(); app_tm1617_init();
XPT2046_Init(); XPT2046_Init();
App_Auto_Init(); App_Auto_Init();
LOG_I("PWR", "periph ready send POWER_ON");
/* 通知 UI 层画开机界面 */ /* 通知 UI 层画开机界面 */
MainTask_Sendmsg(MSG_ID_POWER_ON,0,0,0); MainTask_Sendmsg(MSG_ID_POWER_ON,0,0,0);
} }
static void PowerOn(void)
{
System_PowerOn();
}
static void PowerOff(void) static void PowerOff(void)
{ {
uint8_t nvm_ret;
LOG_I("PWR", "power_off begin");
powon = false; /* 更新关机标志 */ powon = false; /* 更新关机标志 */
StopFullTask(); StopFullTask();
nvm_ret = drv_nvm_save_to_flash(); drv_nvm_save_to_flash();
LOG_I("PWR", "nvm_save=%u", (unsigned)nvm_ret);
LCD_FillByColor(0, 0, 240, 320, BLACK); LCD_FillByColor(0, 0, 240, 320, BLACK);
LCD_BLK_Clr(); LCD_BLK_Clr();
@ -208,7 +191,6 @@ static void PowerOff(void)
BSP_DreamCorePowerEnable(0); BSP_DreamCorePowerEnable(0);
BSP_HT7178PowerEnable(0); BSP_HT7178PowerEnable(0);
BSP_BlueToothPowerEnable(0); BSP_BlueToothPowerEnable(0);
LOG_I("PWR", "reset");
__disable_irq(); __disable_irq();
nvic_system_reset(); nvic_system_reset();
//MainTask_Sendmsg(MSG_ID_POWER_OFF,0,0,0); //MainTask_Sendmsg(MSG_ID_POWER_OFF,0,0,0);
@ -220,20 +202,6 @@ void Power_Key_Scan()
uint32_t now = rt_tick_get(); uint32_t now = rt_tick_get();
uint32_t holdtick = 0; uint32_t holdtick = 0;
/* 复位/烧录后自动开机一次,避免黑屏干等长按;正常关机后下电再上电仍走此路径 */
if (powon == false && pwr_key_state == KEY_STATE_IDLE && pwr_press_tick == 0)
{
static uint8_t s_auto_poweron_pending = 1;
if (s_auto_poweron_pending)
{
s_auto_poweron_pending = 0;
LOG_I("PWR", "auto power_on");
PowerOn();
pwr_key_state = KEY_STATE_NONE; /* 忽略开机瞬间可能残留的按键电平 */
return;
}
}
switch(pwr_key_state) switch(pwr_key_state)
{ {
case KEY_STATE_IDLE: case KEY_STATE_IDLE:
@ -256,13 +224,11 @@ void Power_Key_Scan()
/* 用 powon 区分:关机长按 3s 开机,开机长按 2s 关机 */ /* 用 powon 区分:关机长按 3s 开机,开机长按 2s 关机 */
if(powon == false && holdtick >= PWR_ON_HOLD_MS) if(powon == false && holdtick >= PWR_ON_HOLD_MS)
{ {
LOG_I("PWR", "key power_on hold=%u", (unsigned)holdtick);
PowerOn(); PowerOn();
pwr_key_state = KEY_STATE_NONE; pwr_key_state = KEY_STATE_NONE;
} }
else if(powon == true && holdtick >= PWR_OFF_HOLD_MS) else if(powon == true && holdtick >= PWR_OFF_HOLD_MS)
{ {
LOG_I("PWR", "key power_off hold=%u", (unsigned)holdtick);
PowerOff(); PowerOff();
pwr_key_state = KEY_STATE_NONE; pwr_key_state = KEY_STATE_NONE;
} }

View File

@ -164,8 +164,6 @@ extern rt_timer_t OutTime_Stop_timer;
extern uint8_t KEY_ID_1629; extern uint8_t KEY_ID_1629;
extern bool powon; extern bool powon;
void Power_Key_Scan(void);
void System_PowerOn(void);
extern uint8_t Led; extern uint8_t Led;
extern bool PressFlag; extern bool PressFlag;
@ -196,6 +194,8 @@ extern void (*CurrUIProcress)(DisplayTaskMessage_Type xEvent);
void Stop_AutoBand(); void Stop_AutoBand();
void Power_Key_Scan();
static void ShowPowerOn(); static void ShowPowerOn();
void GET_ParamNum_Str(int16_t NUM, uint8_t ValidLen, char* Str, uint8_t hasSign); void GET_ParamNum_Str(int16_t NUM, uint8_t ValidLen, char* Str, uint8_t hasSign);

View File

@ -19,40 +19,23 @@ void RGB_Y_TO_G()
#define UI_MODE_SCREEN_WIDTH 240 #define UI_MODE_SCREEN_WIDTH 240
#define UI_MODE_SCREEN_HEIGHT 320 #define UI_MODE_SCREEN_HEIGHT 320
#define UI_MODE_BG_COLOR 0x1925
#define UI_MODE_LINE_COLOR DARKBLUE
#define UI_MODE_TEXT_COLOR 0xFFFF
#define UI_MODE_FONT_SIZE 16
/* 模式选择页焦点0=万能 1=普通 2=专业,默认选中万能(与规范一致) */ /* 模式选择页焦点0=万能 1=普通 2=专业,默认选中万能(与规范一致) */
static uint8_t s_mode_select_focus = 0; static uint8_t s_mode_select_focus = 0;
extern bool InModeFlag; static void UI_DrawModeSelectButton(uint16_t y, const uint8_t *text,
const uint8_t *icon, uint8_t focused)
static void UI_ModeSelect_DrawButtons(void);
static void UI_ModeSelect_SetFocus(uint8_t idx)
{
if (idx > 2 || idx == s_mode_select_focus)
return;
s_mode_select_focus = idx;
UI_ModeSelect_DrawButtons();
}
void UI_ReturnToModeSelect(void)
{
StartFlag = 0;
InModeFlag = false;
AutoBandTop1_Stop();
s_mode_select_focus = 0;
CallUI_Idle();
UI_DrawModeSelectScreen();
}
/* 0831 美工试用图:图标+MiSans 文字整行位图 */
static void UI_DrawModeSelectButton(uint16_t y, const uint8_t *row, uint8_t focused)
{ {
const uint16_t btn_w = 220; const uint16_t btn_w = 220;
const uint16_t btn_h = 87; const uint16_t btn_h = 87;
const uint16_t btn_r = 10; const uint16_t btn_r = 10;
const uint16_t btn_x = (240 - btn_w) / 2; const uint16_t btn_x = (240 - btn_w) / 2;
const uint16_t row_x = (uint16_t)(btn_x + (btn_w - UI_MODE0831_ROW_W) / 2); uint16_t text_y = y + (btn_h - UI_MODE_FONT_SIZE) / 2;
const uint16_t row_y = (uint16_t)(y + (btn_h - UI_MODE0831_ROW_H) / 2); uint16_t text_x;
if (focused) if (focused)
{ {
@ -64,37 +47,47 @@ static void UI_DrawModeSelectButton(uint16_t y, const uint8_t *row, uint8_t focu
LCD_FillRoundRect(btn_x, y, btn_w, btn_h, btn_r, COLOR_NORMAL_BG); LCD_FillRoundRect(btn_x, y, btn_w, btn_h, btn_r, COLOR_NORMAL_BG);
} }
LCD_WR_PIC_Trans(row_x, row_y, UI_MODE0831_ROW_W, UI_MODE0831_ROW_H, row, BLACK); /* 叠加绘制文字,避免在渐变底上打出实心色块 */
} text_x = LCD_ShowChinese_AutoAlign(
btn_x, btn_x + btn_w,
static void UI_ModeSelect_DrawButtons(void) text_y,
{ text,
UI_DrawModeSelectButton(40, LCD_ALIGN_CENTER,
gImage_Mode0831_Universal_Row_180_52, UI_MODE_TEXT_COLOR,
s_mode_select_focus == 0); BLACK,
UI_DrawModeSelectButton(132, 1,
gImage_Mode0831_Normal_Row_180_52, UI_MODE_FONT_SIZE
s_mode_select_focus == 1); );
UI_DrawModeSelectButton(224, LCD_WR_PIC_Trans(text_x - 45, text_y - 5, 40, 30, icon, BLACK);
gImage_Mode0831_Expert_Row_180_52,
s_mode_select_focus == 2);
} }
void UI_DrawModeSelectScreen(void) void UI_DrawModeSelectScreen(void)
{ {
UI_ClearFocus(); UI_ClearFocus();
pCurrentTouch_Area = Touch_ModeSelect_Areas; s_mode_select_focus = 0;
LCD_FillByColor(0, 0, 240, 320, BLACK); LCD_FillByColor(0, 0, 240, 320, BLACK);
label_top(); label_top();
UI_ModeSelect_DrawButtons();
UI_DrawModeSelectButton(40,
(const uint8_t *)"\xCD\xF2\xC4\xDC\xC4\xA3\xCA\xBD",
gImage_FreeMode_Icon_40_30,
s_mode_select_focus == 0);
UI_DrawModeSelectButton(132,
(const uint8_t *)"\xC6\xD5\xCD\xA8\xC4\xA3\xCA\xBD",
gImage_NormalMode_Icon_40_30,
s_mode_select_focus == 1);
UI_DrawModeSelectButton(224,
(const uint8_t *)"\xD7\xA8\xD2\xB5\xC4\xA3\xCA\xBD",
gImage_ExpressMode_Icon_40_30,
s_mode_select_focus == 2);
} }
const Touch_AreaTypeDef Touch_ModeSelect_Areas[] = { const Touch_AreaTypeDef Touch_ModeSelect_Areas[] = {
/* Flag=按钮序号(0万能/1普通/2专业)ID=进入 TAB */ // Xmin, Xmax, Ymin, Ymax, flag, ID, action
{ 0, 239, 38, 127, 0, 0, 0, NULL }, { 10, 229, 40, 126, 0, 0, GUI_MODE_SELECT3, NULL }, //<2F><><EFBFBD><EFBFBD>
{ 0, 239, 128, 219, 1, 0, 2, NULL }, { 10, 229, 132, 218, 1, 0, GUI_MODE_SELECT1, NULL }, //????/<2F><><EFBFBD><EFBFBD>
{ 0, 239, 220, 311, 2, 0, 1, NULL }, { 10, 229, 224, 310, 2, 0, GUI_MODE_SELECT2, NULL }, //רҵ/ר???
}; };
#define TOUCH_AREA_MODE_SELECT_NUM (sizeof(Touch_ModeSelect_Areas)/sizeof(Touch_AreaTypeDef)) #define TOUCH_AREA_MODE_SELECT_NUM (sizeof(Touch_ModeSelect_Areas)/sizeof(Touch_AreaTypeDef))
@ -137,36 +130,44 @@ void LoadConfig()
void Touch_Mode_Select_Action(int8_t FLAG, uint8_t ID, uint8_t areaIndex) void Touch_Mode_Select_Action(int8_t FLAG, uint8_t ID, uint8_t areaIndex)
{ {
(void)areaIndex;
StartTask(); StartTask();
s_mode_select_focus = (uint8_t)FLAG; s_mode_select_focus = (uint8_t)FLAG;
/* ID 为 TAB 索引0=万能(Song) 1=专业(Expert) 2=普通(Free) */
mGuiData[GUI_TAB_INDEX].Current = ID; mGuiData[GUI_TAB_INDEX].Current = ID;
InModeFlag = true; InModeFlag = true;
// <20>ٽ<EFBFBD><D9BD><EFBFBD><EFBFBD>ٽ<EFBFBD><D9BD><EFBFBD>
switch (ID) switch(ID)
{
case 0:
if(mGuiData[GUI_AUTOBAND_SW].Current)
{ {
case 0: /* 万能 */
if (mGuiData[GUI_AUTOBAND_SW].Current)
ADDRESS = 0x0009EB5F; ADDRESS = 0x0009EB5F;
}
else else
{
ADDRESS = 0x0001B8F0; ADDRESS = 0x0001B8F0;
}
MenuPage_SongMode_Proc(); MenuPage_SongMode_Proc();
break; break;
case 1: /* 专业 */ case 1:
if (mGuiData[GUI_AUTOBAND_SW].Current) if(mGuiData[GUI_AUTOBAND_SW].Current)
{
ADDRESS = 0x0009EB5F; ADDRESS = 0x0009EB5F;
}
else else
{
// ADDRESS = 0x0001B8F0;
ADDRESS = 0x00000000; ADDRESS = 0x00000000;
}
MenuPage_ExpertMode_Proc(); MenuPage_ExpertMode_Proc();
break; break;
case 2: /* 普通 */ case 2:
ADDRESS = 0x0009598F; ADDRESS = 0x0009598F;
MenuPage_FreeMode_Proc(); MenuPage_FreeMode_Proc();
break; break;
default:
break;
} }
} }
extern uint8_t bat_init_done; extern uint8_t bat_init_done;
@ -180,8 +181,7 @@ void IdleProcess(DisplayTaskMessage_Type msg)
LCD_FillByColor(0, 0, 240, 320, WHITE); LCD_FillByColor(0, 0, 240, 320, WHITE);
LCD_WR_PIC_FROM_FLASH(40, 80, 168, 155, 0x00000000); LCD_WR_PIC_FROM_FLASH(40, 80, 168, 155, 0x00000000);
BSP_SelectAdcChannel(6); BSP_SelectAdcChannel(6);
/* 让出 CPU避免忙等卡住触摸/主循环线程 */ wk_delay_ms(1000);
rt_thread_mdelay(1000);
LoadConfig(); LoadConfig();
vol = ADC_ReadChannel(ADC_CHANNEL_1)>>5; vol = ADC_ReadChannel(ADC_CHANNEL_1)>>5;
if (vol <= 5) level = 0; if (vol <= 5) level = 0;
@ -192,7 +192,6 @@ void IdleProcess(DisplayTaskMessage_Type msg)
else level = 5; else level = 5;
Send_volume(vol); Send_volume(vol);
s_mode_select_focus = 0;
UI_DrawModeSelectScreen(); UI_DrawModeSelectScreen();
TM1629D_AllLedOn(LED_COLOR_G); TM1629D_AllLedOn(LED_COLOR_G);
TM1629D_UpdateDisplay(0); TM1629D_UpdateDisplay(0);
@ -211,34 +210,15 @@ void IdleProcess(DisplayTaskMessage_Type msg)
break; break;
case MSG_ID_TOUCH: case MSG_ID_TOUCH:
{
uint8_t hit = 0U;
for(uint8_t k=0; k<TOUCH_AREA_MODE_SELECT_NUM; k++) for(uint8_t k=0; k<TOUCH_AREA_MODE_SELECT_NUM; k++)
{ {
if( msg.HiByte >= Touch_ModeSelect_Areas[k].x_min && msg.HiByte <= Touch_ModeSelect_Areas[k].x_max && if( msg.HiByte >= pCurrentTouch_Area[k].x_min && msg.HiByte <= pCurrentTouch_Area[k].x_max &&
msg.LoByte >= Touch_ModeSelect_Areas[k].y_min && msg.LoByte <= Touch_ModeSelect_Areas[k].y_max ) msg.LoByte >= pCurrentTouch_Area[k].y_min && msg.LoByte <= pCurrentTouch_Area[k].y_max )
{ {
hit = 1U; Touch_Mode_Select_Action(pCurrentTouch_Area[k].Flag,pCurrentTouch_Area[k].ID,k);
uint8_t row = (uint8_t)Touch_ModeSelect_Areas[k].Flag;
LOG_I("UI", "mode_select hit area=%u row=%u x=%u y=%u",
(unsigned)k, (unsigned)row,
(unsigned)msg.HiByte, (unsigned)msg.LoByte);
if (row == s_mode_select_focus)
Touch_Mode_Select_Action(Touch_ModeSelect_Areas[k].Flag, Touch_ModeSelect_Areas[k].ID, k);
else
UI_ModeSelect_SetFocus(row);
break; break;
} }
} }
if (!hit) {
LOG_I("UI", "mode_select miss x=%u y=%u",
(unsigned)msg.HiByte, (unsigned)msg.LoByte);
}
}
break;
case MSG_ID_TOUCH_LONG_REPEAT:
/* 模式页暂无长按动作 */
break; break;
case MSG_ID_BATTERY_VALUE: case MSG_ID_BATTERY_VALUE:

View File

@ -377,27 +377,16 @@ void UI_SongMode_Process(DisplayTaskMessage_Type msg)
switch(msg.MessageType) switch(msg.MessageType)
{ {
case MSG_ID_TOUCH: case MSG_ID_TOUCH:
{
uint8_t hit = 0U;
for(uint8_t k=0; k<TOUCH_AREA_NUM; k++) for(uint8_t k=0; k<TOUCH_AREA_NUM; k++)
{ {
if( msg.HiByte >= pCurrentTouch_Area[k].x_min && msg.HiByte <= pCurrentTouch_Area[k].x_max && if( msg.HiByte >= pCurrentTouch_Area[k].x_min && msg.HiByte <= pCurrentTouch_Area[k].x_max &&
msg.LoByte >= pCurrentTouch_Area[k].y_min && msg.LoByte <= pCurrentTouch_Area[k].y_max ) msg.LoByte >= pCurrentTouch_Area[k].y_min && msg.LoByte <= pCurrentTouch_Area[k].y_max )
{ {
hit = 1U;
LOG_I("UI", "song hit area=%u id=%u x=%u y=%u",
(unsigned)k, (unsigned)pCurrentTouch_Area[k].ID,
(unsigned)msg.HiByte, (unsigned)msg.LoByte);
Touch_Action(pCurrentTouch_Area[k].Flag,pCurrentTouch_Area[k].ID,k,pCurrentTouch_Area[k].Value); Touch_Action(pCurrentTouch_Area[k].Flag,pCurrentTouch_Area[k].ID,k,pCurrentTouch_Area[k].Value);
ResetAutoPowerCount(); ResetAutoPowerCount();
break; break;
} }
} }
if (!hit) {
LOG_I("UI", "song miss x=%u y=%u",
(unsigned)msg.HiByte, (unsigned)msg.LoByte);
}
}
break; break;
case MSG_ID_BATTERY_VALUE: case MSG_ID_BATTERY_VALUE:
@ -428,12 +417,6 @@ void UI_SongMode_Process(DisplayTaskMessage_Type msg)
break; break;
case MSG_ID_TOUCH_LONG_REPEAT: case MSG_ID_TOUCH_LONG_REPEAT:
{ {
/* 长按顶栏y<28返回三键模式选择页 */
if (msg.LoByte < 28)
{
UI_ReturnToModeSelect();
break;
}
for(uint8_t k=0; k<TOUCH_AREA_NUM; k++) for(uint8_t k=0; k<TOUCH_AREA_NUM; k++)
{ {
if( msg.HiByte >= pCurrentTouch_Area[k].x_min && msg.HiByte <= pCurrentTouch_Area[k].x_max && if( msg.HiByte >= pCurrentTouch_Area[k].x_min && msg.HiByte <= pCurrentTouch_Area[k].x_max &&

View File

@ -33,59 +33,43 @@ void InitMenuUI(void) {
// ============================================== // ==============================================
void CallUI_Idle(void) { void CallUI_Idle(void) {
CurrUIProcress = IdleProcess; CurrUIProcress = IdleProcess;
app_log_set_ui_page("Idle");
LOG_I("UI", "page Idle");
} }
void CallUI_SongMode(void) { void CallUI_SongMode(void) {
UI_SongMode_Init(); UI_SongMode_Init();
CurrUIProcress = UI_SongMode_Process; CurrUIProcress = UI_SongMode_Process;
app_log_set_ui_page("Song");
LOG_I("UI", "page SongMode tab=%u", (unsigned)mGuiData[GUI_TAB_INDEX].Current);
} }
void CallUI_ExpertMode(void) { void CallUI_ExpertMode(void) {
UI_ExpertMode_Init(); UI_ExpertMode_Init();
// CurrUIProcress = UI_ExpertMode_Process; // CurrUIProcress = UI_ExpertMode_Process;
CurrUIProcress = UI_SongMode_Process; CurrUIProcress = UI_SongMode_Process;
app_log_set_ui_page("Expert");
LOG_I("UI", "page ExpertMode");
} }
void CallUI_FreeMode(void) { void CallUI_FreeMode(void) {
UI_FreeMode_Init(); UI_FreeMode_Init();
// CurrUIProcress = UI_FreeMode_Process; // CurrUIProcress = UI_FreeMode_Process;
CurrUIProcress = UI_SongMode_Process; CurrUIProcress = UI_SongMode_Process;
app_log_set_ui_page("Free");
LOG_I("UI", "page FreeMode");
} }
void CallUI_Setting(void) { void CallUI_Setting(void) {
CurrUIProcress = UI_Setting_Process; CurrUIProcress = UI_Setting_Process;
UI_Setting_Init(); UI_Setting_Init();
app_log_set_ui_page("Setting");
LOG_I("UI", "page Setting");
} }
void CallUI_Mixer(void) { void CallUI_Mixer(void) {
CurrUIProcress = UI_Mixer_Process; CurrUIProcress = UI_Mixer_Process;
UI_Mixer_Init(); UI_Mixer_Init();
app_log_set_ui_page("Mixer");
LOG_I("UI", "page Mixer");
} }
void CallUI_SystemSetting(void) { void CallUI_SystemSetting(void) {
CurrUIProcress = UI_SystemSet_Process; CurrUIProcress = UI_SystemSet_Process;
UI_SystemSet_Init(); UI_SystemSet_Init();
app_log_set_ui_page("SysSet");
LOG_I("UI", "page SystemSetting");
} }
void CallUI_RestoreSelect(void) { void CallUI_RestoreSelect(void) {
CurrUIProcress = UI_Restore_Select_Process; CurrUIProcress = UI_Restore_Select_Process;
UI_Restore_Select_Init(); UI_Restore_Select_Init();
app_log_set_ui_page("Restore");
LOG_I("UI", "page Restore");
} }
static uint8_t s_ui_focus_id = UI_FOCUS_NONE; static uint8_t s_ui_focus_id = UI_FOCUS_NONE;
@ -172,7 +156,7 @@ void label_top()
const uint16_t btn_color = /*DARKLGRAY*/0x2988; // 深灰<E6B7B1>????? const uint16_t btn_color = /*DARKLGRAY*/0x2988; // 深灰<E6B7B1>?????
//LCD_FillByColor(0,0,240,25,BLACK); //LCD_FillByColor(0,0,240,25,BLACK);
//LCD_WR_PIC(5,0,12,20,gImage_bar); //LCD_WR_PIC(5,0,12,20,gImage_bar);
Draw_Volume_Bar(8, 5, level, 1, WHITE, GRAY); Draw_Volume_Bar(5, 5, level, 1, WHITE, GRAY);
LCD_DrawLine(0, 26, 240, 26, btn_color); LCD_DrawLine(0, 26, 240, 26, btn_color);
Show_BL_Icon(mGuiData[GUI_BL_SW].Current); Show_BL_Icon(mGuiData[GUI_BL_SW].Current);
Show_Battery_Icon(usb_charging_state); Show_Battery_Icon(usb_charging_state);

View File

@ -28,11 +28,9 @@ void CallUI_RestoreSelect(void);
#define UI_STATUS_BAR_H 26 #define UI_STATUS_BAR_H 26
/* 电量组在 Draw_Battery_Icon 内按右对齐重算;此值为允许的最左起点 */ #define UI_STATUS_BATTERY_X 180
#define UI_STATUS_BATTERY_X 150
#define UI_STATUS_BATTERY_H 11 #define UI_STATUS_BATTERY_H 11
#define UI_STATUS_BATTERY_Y ((UI_STATUS_BAR_H - UI_STATUS_BATTERY_H) / 2) #define UI_STATUS_BATTERY_Y ((UI_STATUS_BAR_H - UI_STATUS_BATTERY_H) / 2)
#define UI_STATUS_BATTERY_RIGHT_MARGIN 8
#define UI_FOCUS_NONE 0xFF #define UI_FOCUS_NONE 0xFF
void UI_ClearFocus(void); void UI_ClearFocus(void);

View File

@ -9,7 +9,7 @@ typedef enum {
extern const Touch_AreaTypeDef Touch_ModeSelect_Areas[]; extern const Touch_AreaTypeDef Touch_ModeSelect_Areas[];
extern void UI_DrawModeSelectScreen(void); extern void UI_DrawModeSelectScreen(void);
extern void UI_ReturnToModeSelect(void);
extern void IdleProcess(DisplayTaskMessage_Type xEvent); extern void IdleProcess(DisplayTaskMessage_Type xEvent);

View File

@ -150,13 +150,14 @@ void LCD_WR_PIC(uint16_t x, uint16_t y, uint16_t length, uint16_t width, const u
} }
} }
/* 跳过近黑色像素(图标导出底色常为 0x0000/0x0001/0x0022非纯 BLACK */ /* 跳过 key_color 像素,用于图标透明底(常见 key=BLACK */
void LCD_WR_PIC_Trans(uint16_t x, uint16_t y, uint16_t length, uint16_t width, void LCD_WR_PIC_Trans(uint16_t x, uint16_t y, uint16_t length, uint16_t width,
const uint8_t data[], uint16_t key_color) const uint8_t data[], uint16_t key_color)
{ {
uint32_t total_pixels = (uint32_t)length * width; uint32_t total_pixels = (uint32_t)length * width;
uint8_t key_h = (uint8_t)(key_color >> 8);
uint8_t key_l = (uint8_t)(key_color & 0xFF);
uint32_t i; uint32_t i;
(void)key_color;
if (total_pixels == 0) if (total_pixels == 0)
return; return;
@ -165,18 +166,11 @@ void LCD_WR_PIC_Trans(uint16_t x, uint16_t y, uint16_t length, uint16_t width,
{ {
uint8_t hi = data[i * 2]; uint8_t hi = data[i * 2];
uint8_t lo = data[i * 2 + 1]; uint8_t lo = data[i * 2 + 1];
uint16_t c = (uint16_t)((hi << 8) | lo); if (hi == key_h && lo == key_l)
uint8_t r5 = (uint8_t)((c >> 11) & 0x1F);
uint8_t g6 = (uint8_t)((c >> 5) & 0x3F);
uint8_t b5 = (uint8_t)(c & 0x1F);
/* 近黑视为透明,避免图标黑底方块 */
if (r5 <= 1 && g6 <= 2 && b5 <= 2)
continue; continue;
LCD_DrawPoint((uint16_t)(x + (i % length)), LCD_DrawPoint((uint16_t)(x + (i % length)),
(uint16_t)(y + (i / length)), (uint16_t)(y + (i / length)),
c); (uint16_t)((hi << 8) | lo));
} }
} }
@ -1800,14 +1794,11 @@ void Draw_Battery_Icon(uint16_t x, uint16_t y, uint8_t battery_percent,uint8_t s
uint8_t round_r = 2 * scale; uint8_t round_r = 2 * scale;
uint8_t stroke = 1 * scale; uint8_t stroke = 1 * scale;
uint16_t fill_gap = 2 * scale; uint16_t fill_gap = 2 * scale;
/* PDF 标注 7.5,但 8px ASCII 位图乱码;用 16px 并整组右对齐,避免左右被裁 */ uint8_t text_size = 16 * scale; /* 16px ASCII 字体渲染可靠13px 位图与驱动不匹配会乱码 */
uint8_t text_size = 16 * scale;
uint8_t status_bar_h = 26 * scale; uint8_t status_bar_h = 26 * scale;
uint8_t Info[40]; uint8_t Info[40];
uint16_t pole_w = 2 * scale; uint16_t pole_w = 2 * scale;
uint16_t pole_h = 5 * scale; uint16_t pole_h = 5 * scale;
uint16_t gap = 6 * scale;
uint16_t right_margin = 14 * scale;
uint16_t pole_x; uint16_t pole_x;
uint16_t pole_y; uint16_t pole_y;
uint16_t inner_w; uint16_t inner_w;
@ -1815,9 +1806,6 @@ void Draw_Battery_Icon(uint16_t x, uint16_t y, uint8_t battery_percent,uint8_t s
uint16_t fill_w; uint16_t fill_w;
uint16_t text_x; uint16_t text_x;
uint16_t text_y; uint16_t text_y;
uint16_t text_w;
uint16_t group_w;
uint16_t bat_x = x;
uint16_t clear_h; uint16_t clear_h;
if(battery_percent > 100) if(battery_percent > 100)
@ -1825,26 +1813,18 @@ void Draw_Battery_Icon(uint16_t x, uint16_t y, uint8_t battery_percent,uint8_t s
battery_percent = 100; battery_percent = 100;
} }
sprintf((char*)Info, "%d%%", battery_percent);
text_w = (uint16_t)(strlen((char*)Info) * (text_size / 2));
group_w = (uint16_t)(bat_w + pole_w + gap + text_w);
if (group_w + right_margin < 240)
bat_x = (uint16_t)(240 - right_margin - group_w);
if (bat_x < x)
bat_x = x;
clear_h = (bat_h > text_size) ? bat_h : text_size; clear_h = (bat_h > text_size) ? bat_h : text_size;
if(status_bar_h > clear_h) if(status_bar_h > clear_h)
{ {
clear_h = status_bar_h; clear_h = status_bar_h;
} }
LCD_FillByColor(bat_x > 4 ? (uint16_t)(bat_x - 4) : 0, 0, 240, clear_h, BLACK); LCD_FillByColor(x, 0, 240, clear_h, BLACK);
/* 圆角外壳:外框 + 内挖空 */ /* 圆角外壳:外框 + 内挖空 */
LCD_FillRoundRect(bat_x, y, bat_w, bat_h, round_r, border_color); LCD_FillRoundRect(x, y, bat_w, bat_h, round_r, border_color);
if(bat_w > 2 * stroke && bat_h > 2 * stroke) if(bat_w > 2 * stroke && bat_h > 2 * stroke)
{ {
LCD_FillRoundRect(bat_x + stroke, y + stroke, LCD_FillRoundRect(x + stroke, y + stroke,
bat_w - 2 * stroke, bat_h - 2 * stroke, bat_w - 2 * stroke, bat_h - 2 * stroke,
(round_r > stroke) ? (round_r - stroke) : 0, (round_r > stroke) ? (round_r - stroke) : 0,
bg_color); bg_color);
@ -1854,25 +1834,26 @@ void Draw_Battery_Icon(uint16_t x, uint16_t y, uint8_t battery_percent,uint8_t s
inner_h = bat_h - 2 * fill_gap; inner_h = bat_h - 2 * fill_gap;
fill_w = inner_w * battery_percent / 100; fill_w = inner_w * battery_percent / 100;
/* 从左向右实心填充,宽度与百分比一致 */
if(battery_percent > 0 && fill_w > 0) if(battery_percent > 0 && fill_w > 0)
{ {
if(fill_w > inner_w) if(fill_w > inner_w)
{ {
fill_w = inner_w; fill_w = inner_w;
} }
LCD_FillRoundRect(bat_x + fill_gap, y + fill_gap, LCD_FillRoundRect(x + fill_gap, y + fill_gap,
fill_w, inner_h, fill_w, inner_h,
1 * scale, fill_color); 1 * scale, fill_color);
} }
pole_x = bat_x + bat_w; /* 右侧正极小凸起 */
pole_x = x + bat_w;
pole_y = y + (bat_h - pole_h) / 2; pole_y = y + (bat_h - pole_h) / 2;
LCD_FillRoundRect(pole_x, pole_y, pole_w, pole_h, 1 * scale, border_color); LCD_FillRoundRect(pole_x, pole_y, pole_w, pole_h, 1 * scale, border_color);
text_x = (uint16_t)(pole_x + pole_w + gap); sprintf((char*)Info, "%d%%", battery_percent);
text_x = pole_x + pole_w + 2 * scale;
text_y = (status_bar_h - text_size) / 2; text_y = (status_bar_h - text_size) / 2;
if ((int16_t)text_y < 0)
text_y = 0;
LCD_ShowString(text_x, text_y, Info, WHITE, BLACK, text_size, 0); LCD_ShowString(text_x, text_y, Info, WHITE, BLACK, text_size, 0);
} }

View File

@ -7,11 +7,9 @@
#define LCD_DUMP_RTT_UP_CH 1 #define LCD_DUMP_RTT_UP_CH 1
#define LCD_DUMP_RTT_DOWN_CH 0 #define LCD_DUMP_RTT_DOWN_CH 0
#define LCD_DUMP_CMD "DUMP" #define LCD_DUMP_CMD "DUMP"
#define LCD_DUMP_TAP_CMD "TAP"
#define LCD_DUMP_RESET_CMD "sys reset"
#define LCD_DUMP_MAGIC "SCRN" #define LCD_DUMP_MAGIC "SCRN"
#define LCD_DUMP_FMT_RGB565 1 #define LCD_DUMP_FMT_RGB565 1
#define LCD_DUMP_CMD_BUF_SIZE 32 #define LCD_DUMP_CMD_BUF_SIZE 16
#pragma pack(1) #pragma pack(1)
typedef struct { typedef struct {
@ -199,14 +197,6 @@ static uint8_t LCD_Dump_CommandPending(void)
char c = rx[i]; char c = rx[i];
if (c == '\r' || c == '\n' || c == '\0') { if (c == '\r' || c == '\n' || c == '\0') {
if (s_cmd_len > 0U) {
s_cmd_buf[s_cmd_len] = '\0';
if (app_log_try_command(s_cmd_buf)) {
s_cmd_len = 0U;
s_cmd_buf[0] = '\0';
continue;
}
}
s_cmd_len = 0U; s_cmd_len = 0U;
s_cmd_buf[0] = '\0'; s_cmd_buf[0] = '\0';
continue; continue;
@ -218,22 +208,6 @@ static uint8_t LCD_Dump_CommandPending(void)
s_cmd_buf[s_cmd_len++] = c; s_cmd_buf[s_cmd_len++] = c;
s_cmd_buf[s_cmd_len] = '\0'; s_cmd_buf[s_cmd_len] = '\0';
/* 合成点击:验证 UI 命中路径(点万能按钮中心) */
if (strstr(s_cmd_buf, LCD_DUMP_TAP_CMD) != NULL) {
s_cmd_len = 0U;
s_cmd_buf[0] = '\0';
MainTask_Sendmsg(MSG_ID_TOUCH, 1, 120, 80);
SEGGER_RTT_WriteString(0, "TAP inject 120,80\n");
continue;
}
if (strstr(s_cmd_buf, LCD_DUMP_RESET_CMD) != NULL) {
s_cmd_len = 0U;
s_cmd_buf[0] = '\0';
(void)app_log_try_command(LCD_DUMP_RESET_CMD);
continue;
}
if (c == 0x01 || strstr(s_cmd_buf, LCD_DUMP_CMD) != NULL) { if (c == 0x01 || strstr(s_cmd_buf, LCD_DUMP_CMD) != NULL) {
s_cmd_len = 0U; s_cmd_len = 0U;
s_cmd_buf[0] = '\0'; s_cmd_buf[0] = '\0';

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +0,0 @@
#ifndef __DRV_ILI9341_LCD_IMAGE_MODESELECT0831_H
#define __DRV_ILI9341_LCD_IMAGE_MODESELECT0831_H
#include "stdint.h"
#define UI_MODE0831_ROW_W 180
#define UI_MODE0831_ROW_H 52
extern const unsigned char gImage_Mode0831_Universal_Row_180_52[];
extern const unsigned char gImage_Mode0831_Normal_Row_180_52[];
extern const unsigned char gImage_Mode0831_Expert_Row_180_52[];
#endif

View File

@ -97,156 +97,110 @@ uint16_t TP_Read_AD(uint8_t cmd)
uint8_t i; uint8_t i;
uint16_t adc_val = 0; uint16_t adc_val = 0;
TP_CS_Clr(); TP_CS_Clr(); // 片选拉低选中XPT2046
Delay_us(2); Delay_us(2); // 片选稳定时间
TP_Write_Byte(cmd);
TP_Write_Byte(cmd); // MCU通过DIN发送命令XPT2046的DIN输入接收
// 等待XPT2046完成AD转换约6us转换期间OUT无有效数据
Delay_us(6); Delay_us(6);
// 读取16位数据XPT2046通过自身OUT输出数据MCU通过OUT输入读取
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
{ {
adc_val <<= 1; adc_val <<= 1; // 左移,准备接收下一位
// 时钟上升沿XPT2046更新OUT引脚输出下降沿MCU读取OUT输入
TP_CLK_Set(); TP_CLK_Set();
Delay_us(1); Delay_us(1);
TP_CLK_Clr(); TP_CLK_Clr();
Delay_us(1); Delay_us(1);
// MCU读取OUT引脚的输入数据高12位有效低4位丢弃
if (TP_OUT_Read()) if (TP_OUT_Read())
{
adc_val |= 0x01; adc_val |= 0x01;
} }
}
TP_CS_Set(); TP_CS_Set(); // 释放片选
return adc_val >> 4; return adc_val >> 4; // 取高12位有效数据
} }
// 简单去抖动读取连续n次相同状态视为有效
uint8_t TP_CheckPressed(uint8_t n) uint8_t TP_CheckPressed(uint8_t n)
{ {
uint8_t count = 0; uint8_t count = 0;
uint8_t i;
for (i = 0; i < n; i++) for (uint8_t i = 0; i < n; i++)
{ {
if (TP_IRQ_Read() == 0) if (TP_IRQ_Read() == 0)
{ // IRQ低电平表示按下
count++; count++;
}
Delay_us(100); Delay_us(100);
} }
return (count >= (n / 2)) ? 1 : 0;
} return (count >= n/2) ? 1 : 0;
static uint16_t TP_SampleAxis(uint8_t cmd)
{
(void)TP_Read_AD(cmd);
Delay_us(15);
return TP_Read_AD(cmd);
} }
// 读取原始坐标(未校准)
TP_Point TP_ReadRaw(void) TP_Point TP_ReadRaw(void)
{ {
TP_Point p = {0, 0, 0}; TP_Point p = {0, 0, 0};
if (!TP_CheckPressed(3))
{ // 检查触摸状态
return p;
}
// 多次读取取平均值,减少噪声
uint32_t x_sum = 0, y_sum = 0; uint32_t x_sum = 0, y_sum = 0;
uint8_t i;
static uint8_t s_raw_logged;
if (!TP_CheckPressed(3)) { for (uint8_t i = 0; i < 5; i++)
s_raw_logged = 0U;
return p;
}
for (i = 0; i < 5; i++)
{ {
x_sum += TP_SampleAxis(XPT2046_READ_X); x_sum += TP_Read_AD(XPT2046_READ_X);
Delay_us(15); y_sum += TP_Read_AD(XPT2046_READ_Y);
y_sum += TP_SampleAxis(XPT2046_READ_Y);
Delay_us(15);
}
p.x = (uint16_t)(x_sum / 5);
p.y = (uint16_t)(y_sum / 5);
/* Y 通道常为 0 时,交换 X/Y 命令再采一次 */
if (p.y < 80u && p.x > 80u)
{
uint32_t sx = 0, sy = 0;
for (i = 0; i < 3; i++)
{
sx += TP_SampleAxis(XPT2046_READ_Y);
Delay_us(15);
sy += TP_SampleAxis(XPT2046_READ_X);
Delay_us(15);
}
if (sy / 3u > p.y)
{
p.x = (uint16_t)(sx / 3);
p.y = (uint16_t)(sy / 3);
}
} }
p.x = x_sum / 5;
p.y = y_sum / 5;
p.pressed = 1; p.pressed = 1;
if (!s_raw_logged) {
LOG_TP("raw x=%u y=%u irq=%u", (unsigned)p.x, (unsigned)p.y,
(unsigned)(TP_IRQ_Read() == 0U));
s_raw_logged = 1U;
}
return p; return p;
} }
#define CALIB_X_MIN 200 // 校准参数需实际触摸四个角后修改示例为240x320屏
#define CALIB_X_MAX 3800 #define CALIB_X_MIN 200 // 最小X原始值
#define CALIB_Y_MIN 200 #define CALIB_X_MAX 3800 // 最大X原始值
#define CALIB_Y_MAX 3800 #define CALIB_Y_MIN 200 // 最小Y原始值
#define CALIB_Y_MAX 3800 // 最大Y原始值
/* 竖屏:多数 ILI9341+XPT2046 板级需 XY 对调X 镜像与历史 240-tp.x 一致 */ #define LCD_WIDTH 240 // LCD宽度
#define TP_SWAP_XY 1 #define LCD_HEIGHT 320 // LCD高度
#define TP_MIRROR_X 1
#define TP_MIRROR_Y 0
static uint16_t TP_MapAxis(uint16_t adc, uint16_t adc_min, uint16_t adc_max, uint16_t px_max)
{
int32_t v = (int32_t)adc;
int32_t a0 = (int32_t)adc_min;
int32_t a1 = (int32_t)adc_max;
int32_t span = a1 - a0;
int32_t px;
if (span <= 0)
return 0;
if (v < a0)
v = a0;
if (v > a1)
v = a1;
px = (v - a0) * (int32_t)px_max / span;
if (px < 0)
px = 0;
if (px > (int32_t)px_max)
px = (int32_t)px_max;
return (uint16_t)px;
}
// 校准后获取LCD坐标
TP_Point TP_Read(void) TP_Point TP_Read(void)
{ {
// char Info[40];
TP_Point raw = TP_ReadRaw(); TP_Point raw = TP_ReadRaw();
// sprintf (Info, "(x=%03d y=%03d) ", raw.x, raw.y);
// LCD_ShowString(2, 176+16, (const uint8_t*)Info, RED, WHITE, 16, 0);
TP_Point calib = {0, 0, raw.pressed}; TP_Point calib = {0, 0, raw.pressed};
uint16_t ax, ay;
if (!raw.pressed) if (!raw.pressed) {
return calib; return calib;
}
#if TP_SWAP_XY // 线性映射将原始ADC值转换为LCD像素坐标
ax = TP_MapAxis(raw.y, CALIB_Y_MIN, CALIB_Y_MAX, (uint16_t)(LCD_W - 1)); calib.x = (raw.x - CALIB_X_MIN) * LCD_WIDTH / (CALIB_X_MAX - CALIB_X_MIN);
ay = TP_MapAxis(raw.x, CALIB_X_MIN, CALIB_X_MAX, (uint16_t)(LCD_H - 1)); calib.y = (raw.y - CALIB_Y_MIN) * LCD_HEIGHT / (CALIB_Y_MAX - CALIB_Y_MIN);
#else
ax = TP_MapAxis(raw.x, CALIB_X_MIN, CALIB_X_MAX, (uint16_t)(LCD_W - 1));
ay = TP_MapAxis(raw.y, CALIB_Y_MIN, CALIB_Y_MAX, (uint16_t)(LCD_H - 1));
#endif
#if TP_MIRROR_X // 边界限制
ax = (uint16_t)(LCD_W - 1 - ax); if (calib.x > LCD_WIDTH - 1) calib.x = LCD_WIDTH - 1;
#endif if (calib.x == 0) calib.x = 0;
#if TP_MIRROR_Y if (calib.y > LCD_HEIGHT - 1) calib.y = LCD_HEIGHT - 1;
ay = (uint16_t)(LCD_H - 1 - ay); if (calib.y == 0) calib.y = 0;
#endif
calib.x = ax;
calib.y = ay;
return calib; return calib;
} }

View File

@ -33,11 +33,11 @@
#define TP_DIN_Clr() gpio_bits_reset(TP_DIN_PORT, TP_DIN_PIN) // DIN输出低MCU→XPT2046 #define TP_DIN_Clr() gpio_bits_reset(TP_DIN_PORT, TP_DIN_PIN) // DIN输出低MCU→XPT2046
#define TP_DIN_Set() gpio_bits_set(TP_DIN_PORT, TP_DIN_PIN) // DIN输出高MCU→XPT2046 #define TP_DIN_Set() gpio_bits_set(TP_DIN_PORT, TP_DIN_PIN) // DIN输出高MCU→XPT2046
// XPT2046命令(与 BOOT 工程一致) // XPT2046命令定义
#define XPT2046_READ_X 0xD0 #define XPT2046_READ_X 0xD0 // 读X坐标命令MCU通过DIN发送给XPT2046
#define XPT2046_READ_Y 0x90 #define XPT2046_READ_Y 0x90 // 读Y坐标命令
#define XPT2046_READ_Z1 0xB0 #define XPT2046_READ_Z1 0xB0 // 读压力Z1
#define XPT2046_READ_Z2 0xC0 #define XPT2046_READ_Z2 0xC0 // 读压力Z2
// 触摸状态结构体 // 触摸状态结构体
typedef struct typedef struct

View File

@ -79,7 +79,7 @@ void drv_nvm_init(void)
dataSum1 = ~dataSum0; dataSum1 = ~dataSum0;
if ((dataSum0 != mNvmData.sum[0]) || (dataSum1 != mNvmData.sum[1]) || (mNvmData.data.nvm_version != NVM_VERSION)) { if ((dataSum0 != mNvmData.sum[0]) || (dataSum1 != mNvmData.sum[1]) || (mNvmData.data.nvm_version != NVM_VERSION)) {
LOG_W("NVM", "checksum fail load default ver=%u", (unsigned)mNvmData.data.nvm_version); // load default value;
drv_nvm_load_default_value(&mNvmData.data); drv_nvm_load_default_value(&mNvmData.data);
drv_nvm_save_to_flash(); drv_nvm_save_to_flash();
}else }else
@ -88,7 +88,6 @@ void drv_nvm_init(void)
drv_nvm_save_to_flash(); drv_nvm_save_to_flash();
} }
memcpy(&mNvmDataShadow, &mNvmData, sizeof(NvmData_Type)); memcpy(&mNvmDataShadow, &mNvmData, sizeof(NvmData_Type));
LOG_I("NVM", "init ok ver=%u", (unsigned)mNvmData.data.nvm_version);
} }
NvmParam_Type * drv_nvm_param_ptr(void) NvmParam_Type * drv_nvm_param_ptr(void)
@ -147,9 +146,8 @@ uint8_t drv_nvm_save_to_flash(void)
uint32_t addr = INNER_FLASH_SAVE_ADDRESS; uint32_t addr = INNER_FLASH_SAVE_ADDRESS;
NvmData_Type * NvmDataToSave; NvmData_Type * NvmDataToSave;
// 无变化不保存 // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (memcmp(&mNvmDataShadow, &mNvmData, sizeof(NvmData_Type)) == 0) { if (memcmp(&mNvmDataShadow, &mNvmData, sizeof(NvmData_Type)) == 0) {
LOG_D("NVM", "save skip unchanged");
return 0; return 0;
} }
@ -174,7 +172,6 @@ uint8_t drv_nvm_save_to_flash(void)
flash_write_nocheck(addr,pData16,len); flash_write_nocheck(addr,pData16,len);
flash_lock(); flash_lock();
LOG_I("NVM", "saved to flash");
return 1; return 1;
} }

View File

@ -2001,12 +2001,6 @@
<file> <file>
<name>$PROJ_DIR$\..\..\APP\app_touch.h</name> <name>$PROJ_DIR$\..\..\APP\app_touch.h</name>
</file> </file>
<file>
<name>$PROJ_DIR$\..\..\APP\app_log.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\APP\app_log.h</name>
</file>
</group> </group>
<group> <group>
<name>AutoBand</name> <name>AutoBand</name>
@ -2084,12 +2078,6 @@
<file> <file>
<name>$PROJ_DIR$\..\..\device\LCD_ILI9341\Drv_ILI9341_Lcd_Image.c</name> <name>$PROJ_DIR$\..\..\device\LCD_ILI9341\Drv_ILI9341_Lcd_Image.c</name>
</file> </file>
<file>
<name>$PROJ_DIR$\..\..\device\LCD_ILI9341\Drv_ILI9341_Lcd_Image_ModeSelect0831.c</name>
</file>
<file>
<name>$PROJ_DIR$\..\..\device\LCD_ILI9341\Drv_ILI9341_Lcd_Image_ModeSelect0831.h</name>
</file>
<file> <file>
<name>$PROJ_DIR$\..\..\device\LCD_ILI9341\Drv_ILI9341_Lcd_Image.h</name> <name>$PROJ_DIR$\..\..\device\LCD_ILI9341\Drv_ILI9341_Lcd_Image.h</name>
</file> </file>

View File

@ -35,7 +35,6 @@
#include "Drv_ILI9341_Lcd_Init.h" #include "Drv_ILI9341_Lcd_Init.h"
#include "Drv_ILI9341_Lcd_App.h" #include "Drv_ILI9341_Lcd_App.h"
#include "Drv_ILI9341_Lcd_Image.h" #include "Drv_ILI9341_Lcd_Image.h"
#include "Drv_ILI9341_Lcd_Image_ModeSelect0831.h"
#include "Drv_ILI9341_Lcd_Dump.h" #include "Drv_ILI9341_Lcd_Dump.h"
#include "Drv_XPT2046_Touch.h" #include "Drv_XPT2046_Touch.h"
@ -76,6 +75,5 @@
#include "app_tm1617.h" #include "app_tm1617.h"
#include "app_touch.h" #include "app_touch.h"
#include "app_adc.h" #include "app_adc.h"
#include "app_log.h"
#endif #endif

View File

@ -83,7 +83,6 @@ int main(void)
bsp_init(); bsp_init();
LCD_Init(); LCD_Init();
LCD_Dump_Init(); LCD_Dump_Init();
app_log_init();
drv_nvm_init(); drv_nvm_init();
TaskInit(); TaskInit();
timer_init(); timer_init();
@ -91,7 +90,6 @@ int main(void)
BSP_HT7178PowerEnable (1); BSP_HT7178PowerEnable (1);
BSP_ChargerEnable(1); BSP_ChargerEnable(1);
CurrUIProcress = IdleProcess; CurrUIProcress = IdleProcess;
LOG_I("BOOT", "main init done ui=Idle");
/* add user code end 2 */ /* add user code end 2 */
while(1) while(1)
@ -104,9 +102,6 @@ int main(void)
/* add user code begin 3 */ /* add user code begin 3 */
Power_Key_Scan(); Power_Key_Scan();
LCD_Dump_Poll(); LCD_Dump_Poll();
#if !DEBUG_LCD_DUMP
app_log_poll();
#endif
rt_thread_delay(1); rt_thread_delay(1);
/* add user code end 3 */ /* add user code end 3 */

View File

@ -44,18 +44,13 @@ void TaskUIThread_entry(void* parameter)
void TaskTouchThread_entry(void* parameter) void TaskTouchThread_entry(void* parameter)
{ {
static uint8_t s_last_pressed = 0;
while(1) while(1)
{ {
TP_Point tp = TP_Read(); /* 已含轴交换/镜像,直接进手势 */ TP_Point tp = TP_Read(); /* 读 XPT2046 触摸坐标 */
if (tp.pressed && !s_last_pressed) app_touch_process(240-tp.x, tp.y, tp.pressed);
{ LCD_Dump_Poll();
LOG_TP("down cal x=%u y=%u", (unsigned)tp.x, (unsigned)tp.y);
}
s_last_pressed = tp.pressed;
app_touch_process(tp.x, tp.y, tp.pressed);
Read_Cur_Measure(); Read_Cur_Measure();
rt_thread_mdelay(8); rt_thread_mdelay(10);
} }
} }
@ -151,7 +146,7 @@ rt_err_t TaskInit(void)
BLTask_msg = rt_mq_create("BLTask msgQ",sizeof(DisplayTaskMessage_Type),128,RT_IPC_FLAG_FIFO); BLTask_msg = rt_mq_create("BLTask msgQ",sizeof(DisplayTaskMessage_Type),128,RT_IPC_FLAG_FIFO);
if(MainTask_msg == RT_NULL || UITask_msg == RT_NULL) if(MainTask_msg == RT_NULL || UITask_msg == RT_NULL)
{ {
LOG_E("BOOT", "mq create fail main=%p ui=%p", MainTask_msg, UITask_msg); __NOP();
} }
ret = rt_thread_init(&TaskScanThread, ret = rt_thread_init(&TaskScanThread,
@ -225,120 +220,36 @@ rt_err_t TaskInit(void)
void StartTask(void) void StartTask(void)
{ {
/* 扫描任务可能已由 StartScanTask 拉起;重复 startup 会被 RT-Thread 忽略 */ rt_thread_startup(&TaskScanThread);
StartScanTask();
if ((TaskBTHandleThread.stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
{
rt_thread_init(&TaskBTHandleThread,
"TaskBTHandleThread",
TaskBTHandleThread_entry,
RT_NULL,
&TaskBTTHandlehread_Stack,
sizeof(TaskBTTHandlehread_Stack),
5,
20);
}
if ((TaskBTHandleThread.stat & RT_THREAD_STAT_MASK) == RT_THREAD_INIT)
rt_thread_startup(&TaskBTHandleThread); rt_thread_startup(&TaskBTHandleThread);
if ((TaskBTRecvThread.stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
{
rt_thread_init(&TaskBTRecvThread,
"TaskBTRecvThread",
TaskBTRecvThread_entry,
RT_NULL,
&TaskBTRecvThread_Stack,
sizeof(TaskBTRecvThread_Stack),
5,
20);
}
if ((TaskBTRecvThread.stat & RT_THREAD_STAT_MASK) == RT_THREAD_INIT)
rt_thread_startup(&TaskBTRecvThread); rt_thread_startup(&TaskBTRecvThread);
if ((TaskAutobandThread.stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
{
rt_thread_init(&TaskAutobandThread,
"TaskAutobandThread",
TaskAutobandThread_entry,
RT_NULL,
&TaskAutobandThread_Stack,
sizeof(TaskAutobandThread_Stack),
4,
20);
}
if ((TaskAutobandThread.stat & RT_THREAD_STAT_MASK) == RT_THREAD_INIT)
rt_thread_startup(&TaskAutobandThread); rt_thread_startup(&TaskAutobandThread);
} }
void StartTouchTask(void) void StartTouchTask(void)
{ {
rt_uint8_t st = (rt_uint8_t)(TaskTouchThread.stat & RT_THREAD_STAT_MASK);
if (st == RT_THREAD_CLOSE)
{
rt_thread_init(&TaskTouchThread,
"TaskTouchThread",
TaskTouchThread_entry,
RT_NULL,
&TaskTouchThread_Stack,
sizeof(TaskTouchThread_Stack),
5,
20);
st = RT_THREAD_INIT;
}
if (st == RT_THREAD_INIT)
rt_thread_startup(&TaskTouchThread); rt_thread_startup(&TaskTouchThread);
} }
void StartScanTask(void) void StartScanTask(void)
{ {
rt_uint8_t st = (rt_uint8_t)(TaskScanThread.stat & RT_THREAD_STAT_MASK);
if (st == RT_THREAD_CLOSE)
{
rt_thread_init(&TaskScanThread,
"TaskScanThread",
TaskScanThread_entry,
RT_NULL,
&TaskScanThread_Stack,
sizeof(TaskScanThread_Stack),
5,
20);
st = RT_THREAD_INIT;
}
if (st == RT_THREAD_INIT)
rt_thread_startup(&TaskScanThread); rt_thread_startup(&TaskScanThread);
} }
void StopFullTask(void) void StopFullTask(void)
{ {
LOG_I("TASK", "StopFullTask begin"); if((TaskScanThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE)
if((TaskScanThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) {
LOG_I("TASK", "stop ScanThread");
rt_thread_detach(&TaskScanThread); rt_thread_detach(&TaskScanThread);
} if((TaskUIThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE)
if((TaskUIThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) {
LOG_I("TASK", "stop UIThread");
rt_thread_detach(&TaskUIThread); rt_thread_detach(&TaskUIThread);
} if((TaskTouchThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE)
if((TaskTouchThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) {
LOG_I("TASK", "stop TouchThread");
rt_thread_detach(&TaskTouchThread); rt_thread_detach(&TaskTouchThread);
} if((TaskMainThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE)
if((TaskMainThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) {
LOG_I("TASK", "stop MainThread");
rt_thread_detach(&TaskMainThread); rt_thread_detach(&TaskMainThread);
} if((TaskBTHandleThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE)
if((TaskBTHandleThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) {
LOG_I("TASK", "stop BTHandleThread");
rt_thread_detach(&TaskBTHandleThread); rt_thread_detach(&TaskBTHandleThread);
} if((TaskBTRecvThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE)
if((TaskBTRecvThread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE) {
LOG_I("TASK", "stop BTRecvThread");
rt_thread_detach(&TaskBTRecvThread); rt_thread_detach(&TaskBTRecvThread);
}
LOG_I("TASK", "StopFullTask done");
} }

View File

@ -3,20 +3,30 @@
* The Embedded Experts * * The Embedded Experts *
* www.segger.com * * www.segger.com *
********************************************************************** **********************************************************************
* *
* SEGGER RTT * Real Time Transfer for embedded targets *
* https://github.com/SEGGERMicro/RTT *
* *
**********************************************************************
---------------------------END-OF-HEADER------------------------------
Purpose : User configuration file for RTT. Purpose : User configuration file for RTT.
For available configuration, For available configuration,
refer to SEGGER_RTT_ConfDefaults.h. refer to SEGGER_RTT_ConfDefaults.h.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
#ifndef SEGGER_RTT_CONF_H #ifndef SEGGER_RTT_CONF_H
#define SEGGER_RTT_CONF_H #define SEGGER_RTT_CONF_H
#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3)
#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) /*********************************************************************
#define BUFFER_SIZE_UP (2048) *
#define BUFFER_SIZE_DOWN (256) * Defines, configurable
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (256u) *
**********************************************************************
*/
#endif #endif
/*************************** End of file ****************************/ /*************************** End of file ****************************/

View File

@ -1,79 +0,0 @@
# K1 设备日志导出J-Link RTT
## 用途
固件运行时将启动/关机、触摸、按键、UI 切换、异常等事件写入 RAM 环形缓冲(约 4KB / 32 条),并通过 SEGGER RTT 实时输出。现场复现问题后,用 J-Link 一键导出日志文件发回分析。
## 前置条件
- J-Link 调试器 + SWD 连接设备
- Python 3.8+
- 依赖:`pip install pylink-square`
- 已烧录包含 `app_log` 模块的固件
## 操作步骤
1. 设备上电,复现问题(例如模式选择页触摸无响应)。
2. PC 连接 J-Link**不要**随意 Reset会丢失 RAM 日志;若必须复位,请先导出或复现后再导出)。
3. 在项目 `tools` 目录执行:
```bash
python rtt_log_dump.py --out problem.log
```
4. 将生成的 `problem.log` 发送给研发分析。
## 其他 RTT 命令RTT Viewer 终端输入)
| 命令 | 说明 |
|------|------|
| `log dump` | 导出 RAM 中全部历史日志 |
| `log clear` | 清空 RAM 日志 |
| `log status` | 查看 boot 次数、条数、溢出、当前 UI 页 |
| `log level D` | 开启 Debug 级(含触摸细节);`I` 仅 Info 以上 |
| `sys reset` | MCU 软件复位(自动重新开机,**RAM 日志会丢失** |
或通过脚本(**复位后脚本会自动 `go()` 释放 CPU避免 J-Link 停核黑屏**
```bash
python rtt_reset.py
```
若固件较旧无 `sys reset`,脚本会自动用 J-Link 硬件复位兜底。
## 日志格式
```
[tick_ms][LVL][CAT] message key=val ...
```
类别 CAT`BOOT` `PWR` `UI` `TP` `KEY` `MSG` `NVM` `TASK` `ERR` `ADC`
## 配套工具
- 屏幕截图:`python rtt_lcd_capture.py --out screen.png`
- 日志导出:`python rtt_log_dump.py --out problem.log`
- 远程复位:`python rtt_reset.py`
## 触摸问题排查要点
导出后重点 grep
- `[TP]` — raw/cal 坐标、irq 状态
- `[MSG] id=12` — 触摸消息是否发出
- `[UI] mode_select miss` — UI 命中测试是否失败
## 已验证2026-08-31
烧录:`cspybat` + `C:\Temp\k1flash\YNGJ-GT1-M.out` 下载J-Link reset/run 后约 4s 开机。
日志导出示例(`python rtt_log_dump.py --out test.log`
```
[00185][I][BOOT] app_log init boot=1
[00224][I][NVM ] init ok ver=2
[00224][I][BOOT] main init done ui=Idle
[00224][I][PWR ] auto power_on
[00401][I][PWR ] periph ready send POWER_ON
[00500][I][MSG ] id=0 hi=0 lo=0
```

View File

@ -1,5 +1,7 @@
@echo off @echo off
REM Flash YNGJ-GT1-M app via IAR cspybat, then reset+run and wait for UI boot. REM Flash YNGJ-GT1-M app via IAR cspybat (AT32 flash loader).
REM Do NOT pass Commander-style .jlink files to --jlink_script_file.
setlocal setlocal
set ROOT=%~dp0.. set ROOT=%~dp0..
set OUT=%ROOT%\project\IAR_V7.4\YNGJ-GT1-M\Exe\YNGJ-GT1-M.out set OUT=%ROOT%\project\IAR_V7.4\YNGJ-GT1-M\Exe\YNGJ-GT1-M.out
@ -7,29 +9,17 @@ set GEN=%ROOT%\project\IAR_V7.4\settings\YNGJ-GT1-M.YNGJ-GT1-M.general.xcl
set DRV=%ROOT%\project\IAR_V7.4\settings\YNGJ-GT1-M.YNGJ-GT1-M.driver.xcl set DRV=%ROOT%\project\IAR_V7.4\settings\YNGJ-GT1-M.YNGJ-GT1-M.driver.xcl
set CSPY="C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.3\common\bin\cspybat" set CSPY="C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.3\common\bin\cspybat"
set STAGE=C:\Temp\k1flash set STAGE=C:\Temp\k1flash
set JLINK="C:\Program Files\SEGGER\JLink_V818\JLink.exe"
if not exist "%OUT%" ( if not exist "%OUT%" (
echo ERROR: missing %OUT% - build first echo ERROR: missing %OUT% - build first
exit /b 1 exit /b 1
) )
REM Avoid stale debugger locking SWD (cspybat can hang otherwise)
taskkill /F /IM cspybat.exe >nul 2>&1
mkdir "%STAGE%" 2>nul mkdir "%STAGE%" 2>nul
copy /Y "%OUT%" "%STAGE%\YNGJ-GT1-M.out" >nul copy /Y "%OUT%" "%STAGE%\YNGJ-GT1-M.out" >nul
echo [1/3] Downloading (may take ~60s)...
%CSPY% -f "%GEN%" "--debug_file=%STAGE%\YNGJ-GT1-M.out" --download_only --backend -f "%DRV%" %CSPY% -f "%GEN%" "--debug_file=%STAGE%\YNGJ-GT1-M.out" --download_only --backend -f "%DRV%"
if errorlevel 1 exit /b 1 if errorlevel 1 exit /b 1
echo [2/3] Reset and run... "C:\Program Files\SEGGER\JLink_V818\JLink.exe" -CommandFile "%~dp0reset_run.jlink"
%JLINK% -CommandFile "%~dp0reset_run.jlink" exit /b %ERRORLEVEL%
if errorlevel 1 exit /b 1
echo [3/3] Wait for auto PowerOn + logo (about 4s)...
timeout /t 4 /nobreak >nul
echo Done. UI should be on mode-select screen.
echo Log dump: python rtt_log_dump.py --out problem.log
exit /b 0

View File

@ -1,129 +0,0 @@
#!/usr/bin/env python3
"""Convert Doc/UI 0831 trial PNG slices to RGB565 C arrays for mode-select."""
from PIL import Image, ImageDraw
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SRC = ROOT / "tools" / "assets_0831"
OUT_C = ROOT / "device" / "LCD_ILI9341" / "Drv_ILI9341_Lcd_Image_ModeSelect0831.c"
OUT_H = ROOT / "device" / "LCD_ILI9341" / "Drv_ILI9341_Lcd_Image_ModeSelect0831.h"
PREV = SRC / "preview_mode_select.png"
# Only emit composite rows (icon+MiSans text) to save Flash.
ROW_W, ROW_H = 180, 52
NAMES = [
("Universal", "mode_row_0.png"), # 万能
("Normal", "mode_row_1.png"), # 普通
("Expert", "mode_row_2.png"), # 专业
]
def rgba_to_rgb565_bytes(im: Image.Image) -> bytes:
im = im.convert("RGBA")
px = im.load()
w, h = im.size
out = bytearray(w * h * 2)
i = 0
for y in range(h):
for x in range(w):
r, g, b, a = px[x, y]
if a < 40 or (r < 12 and g < 12 and b < 12):
out[i] = 0
out[i + 1] = 0
else:
r = (r * a) // 255
g = (g * a) // 255
b = (b * a) // 255
c = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)
out[i] = (c >> 8) & 0xFF
out[i + 1] = c & 0xFF
i += 2
return bytes(out)
def fit_on_canvas(src_im: Image.Image, cw: int, ch: int) -> Image.Image:
im = src_im.convert("RGBA")
bbox = im.getbbox()
if bbox:
im = im.crop(bbox)
sw, sh = im.size
scale = min(cw / sw, ch / sh)
nw = max(1, int(round(sw * scale)))
nh = max(1, int(round(sh * scale)))
im = im.resize((nw, nh), Image.Resampling.LANCZOS)
canvas = Image.new("RGBA", (cw, ch), (0, 0, 0, 255))
ox = (cw - nw) // 2
oy = (ch - nh) // 2
canvas.paste(im, (ox, oy), im)
return canvas
def emit_array(name: str, data: bytes, w: int, h: int, lines: list) -> None:
lines.append(f"const unsigned char {name}[{len(data)}] = {{ /* {w}x{h} RGB565 BE */")
for i in range(0, len(data), 16):
chunk = data[i : i + 16]
hexes = ",".join(f"0x{b:02X}" for b in chunk)
lines.append(hexes + ",")
lines.append("};")
lines.append("")
def main() -> None:
c_lines = [
'#include "Drv_ILI9341_Lcd_Image_ModeSelect0831.h"',
"",
"/* Auto-generated from Doc/UI 0831 trial PNG. Do not hand-edit. */",
"",
]
h_lines = [
"#ifndef __DRV_ILI9341_LCD_IMAGE_MODESELECT0831_H",
"#define __DRV_ILI9341_LCD_IMAGE_MODESELECT0831_H",
"",
'#include "stdint.h"',
"",
f"#define UI_MODE0831_ROW_W {ROW_W}",
f"#define UI_MODE0831_ROW_H {ROW_H}",
"",
]
screen = Image.new("RGBA", (240, 320), (0, 0, 0, 255))
d = ImageDraw.Draw(screen)
d.rectangle([0, 0, 239, 27], fill=(20, 28, 40, 255))
btn_ys = [40, 132, 224]
btn_w, btn_h, btn_r = 220, 87, 10
total = 0
for idx, (tag, row_n) in enumerate(NAMES):
row = fit_on_canvas(Image.open(SRC / row_n), ROW_W, ROW_H)
row.save(SRC / f"gen_{tag.lower()}_row.png")
rdata = rgba_to_rgb565_bytes(row)
total += len(rdata)
rname = f"gImage_Mode0831_{tag}_Row_{ROW_W}_{ROW_H}"
emit_array(rname, rdata, ROW_W, ROW_H, c_lines)
h_lines.append(f"extern const unsigned char {rname}[];")
h_lines.append("")
by = btn_ys[idx]
bx = (240 - btn_w) // 2
fill = (47, 54, 71, 255) if idx == 0 else (25, 32, 45, 255)
d.rounded_rectangle([bx, by, bx + btn_w - 1, by + btn_h - 1], radius=btn_r, fill=fill)
rx = bx + (btn_w - ROW_W) // 2
ry = by + (btn_h - ROW_H) // 2
screen.paste(row, (rx, ry), row)
h_lines += ["#endif", ""]
OUT_H.write_text("\n".join(h_lines), encoding="utf-8")
OUT_C.write_text("\n".join(c_lines), encoding="utf-8")
screen.convert("RGB").save(PREV)
print(f"wrote {OUT_C} ({OUT_C.stat().st_size} bytes)")
print(f"wrote {OUT_H}")
print(f"flash payload ~{total} bytes")
print(f"preview {PREV}")
if __name__ == "__main__":
main()

View File

@ -138,26 +138,17 @@ def capture_rtt_png(out_path: str, device: str, timeout_s: float, do_reset: bool
buffer = b"" buffer = b""
deadline = time.time() + timeout_s deadline = time.time() + timeout_s
header_off = -1
while time.time() < deadline: while time.time() < deadline:
term = jlink.rtt_read(0, 1024) term = jlink.rtt_read(0, 1024)
if term: if term:
print("RTT0:", bytes(term).decode("utf-8", errors="replace").strip()) print("RTT0:", bytes(term).decode("utf-8", errors="replace").strip())
chunk = jlink.rtt_read(1, 16384) chunk = jlink.rtt_read(1, 8192)
if chunk: if chunk:
buffer += bytes(chunk) buffer += bytes(chunk)
# Drain stale bytes before SCRN (previous incomplete dumps). if len(buffer) >= HEADER_SIZE and buffer[:4] == MAGIC:
header_off = buffer.find(MAGIC)
if header_off >= 0 and len(buffer) >= header_off + HEADER_SIZE:
if header_off > 0:
print(f"Discarded {header_off} stale RTT1 bytes before SCRN")
buffer = buffer[header_off:]
break break
# Cap memory if SCRN never appears time.sleep(0.01)
if len(buffer) > 256 * 1024:
buffer = buffer[-65536:]
time.sleep(0.001)
if len(buffer) < HEADER_SIZE or buffer[:4] != MAGIC: if len(buffer) < HEADER_SIZE or buffer[:4] != MAGIC:
raise SystemExit("Timeout waiting for SCRN header on RTT channel 1") raise SystemExit("Timeout waiting for SCRN header on RTT channel 1")

View File

@ -1,184 +0,0 @@
#!/usr/bin/env python3
"""Pull K1 device log ring buffer via J-Link RTT (log dump command)."""
from __future__ import annotations
import argparse
import os
import sys
import time
from datetime import datetime
DEFAULT_DEVICES = ("Cortex-M4", "AT32F403AC", "AT32F403A")
DUMP_CMD = b"log dump\n"
END_MARKERS = (b"LOG_DUMP_END",)
def import_deps():
try:
import pylink # noqa: F401
except ImportError as exc:
raise SystemExit("Missing dependency: pip install pylink-square") from exc
def connect_jlink(device: str):
import pylink
jlink = pylink.JLink()
jlink.open()
try:
jlink.exec_command("HideDeviceSelection = 1")
except Exception:
pass
jlink.set_tif(pylink.enums.JLinkInterfaces.SWD)
last_error = None
for candidate in (device, *DEFAULT_DEVICES):
try:
try:
jlink.exec_command(f"Device = {candidate}")
except Exception:
pass
jlink.connect(candidate)
print(f"Connected as {candidate}")
return jlink
except pylink.errors.JLinkException as exc:
last_error = exc
jlink.close()
raise SystemExit(f"Failed to connect J-Link: {last_error}")
def find_rtt_control_block(jlink, ram_base: int = 0x20000000, ram_size: int = 0x18000) -> int | None:
needle = b"SEGGER RTT"
chunk = 0x1000
was_halted = jlink.halted()
if not was_halted:
jlink.halt()
try:
for off in range(0, ram_size, chunk):
data = bytes(jlink.memory_read8(ram_base + off, min(chunk, ram_size - off)))
idx = data.find(needle)
if idx >= 0:
return ram_base + off + idx
finally:
if not was_halted:
if hasattr(jlink, "restart"):
jlink.restart()
else:
jlink.go()
time.sleep(0.1)
return None
def wait_rtt_ready(jlink, timeout_s: float = 15.0) -> None:
deadline = time.time() + timeout_s
while time.time() < deadline:
try:
if jlink.rtt_get_num_up_buffers() > 0:
return
except Exception:
pass
time.sleep(0.2)
raise SystemExit("RTT control block found but buffers not ready")
def send_command(jlink, payload: bytes, retries: int = 30) -> None:
for _ in range(retries):
wrote = jlink.rtt_write(0, list(payload))
if wrote > 0:
print(f"Sent command ({wrote} bytes): {payload.decode('ascii', errors='replace').strip()}")
return
time.sleep(0.2)
raise SystemExit("Failed to send RTT down command on channel 0")
def dump_log(out_path: str, device: str, timeout_s: float) -> None:
jlink = connect_jlink(device)
lines: list[str] = []
try:
cb = find_rtt_control_block(jlink)
if cb is None:
raise SystemExit("SEGGER RTT control block not found in SRAM")
print(f"RTT CB @ 0x{cb:08X}")
jlink.rtt_start(cb)
wait_rtt_ready(jlink)
# Drain stale RTT output.
for _ in range(5):
stale = jlink.rtt_read(0, 4096)
if stale:
text = bytes(stale).decode("utf-8", errors="replace")
if text.strip():
print("RTT0 stale:", text.strip()[:200])
time.sleep(0.05)
send_command(jlink, DUMP_CMD)
buffer = b""
deadline = time.time() + timeout_s
started = False
while time.time() < deadline:
chunk = jlink.rtt_read(0, 4096)
if chunk:
buffer += bytes(chunk)
if not started and b"LOG_DUMP_BEGIN" in buffer:
started = True
if b"LOG_DUMP_END" in buffer:
break
else:
time.sleep(0.01)
if b"LOG_DUMP_END" not in buffer:
raise SystemExit("Timeout waiting for LOG_DUMP_END (is firmware with app_log flashed?)")
text = buffer.decode("utf-8", errors="replace")
capture = False
for line in text.splitlines():
if line.strip() == "LOG_DUMP_BEGIN":
capture = True
continue
if line.strip() == "LOG_DUMP_END":
break
if capture:
lines.append(line)
header = (
f"# K1 log dump {datetime.now().isoformat(timespec='seconds')}\n"
f"# device={device}\n"
)
body = "\n".join(lines) + ("\n" if lines else "")
with open(out_path, "w", encoding="utf-8", newline="\n") as f:
f.write(header)
f.write(body)
print(f"Saved {len(lines)} log lines to {out_path}")
finally:
try:
jlink.rtt_stop()
except Exception:
pass
jlink.close()
def main() -> None:
parser = argparse.ArgumentParser(description="Dump K1 RAM log ring via J-Link RTT")
parser.add_argument(
"--out",
default=f"k1_log_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log",
help="Output log file path",
)
parser.add_argument("--device", default="AT32F403AC", help="J-Link device name")
parser.add_argument("--timeout", type=float, default=20.0, help="Seconds to wait for dump")
args = parser.parse_args()
import_deps()
dump_log(args.out, args.device, args.timeout)
if os.name == "nt" and os.path.isfile(args.out):
print(f"Full path: {os.path.abspath(args.out)}")
if __name__ == "__main__":
main()

View File

@ -1,185 +0,0 @@
#!/usr/bin/env python3
"""Send sys reset via J-Link RTT to reboot K1 MCU (software NVIC reset)."""
from __future__ import annotations
import argparse
import time
DEFAULT_DEVICES = ("Cortex-M4", "AT32F403AC", "AT32F403A")
RESET_CMD = b"sys reset\n"
ACK = b"SYS_RESET_OK"
def import_deps():
try:
import pylink # noqa: F401
except ImportError as exc:
raise SystemExit("Missing dependency: pip install pylink-square") from exc
def connect_jlink(device: str):
import pylink
jlink = pylink.JLink()
jlink.open()
try:
jlink.exec_command("HideDeviceSelection = 1")
except Exception:
pass
jlink.set_tif(pylink.enums.JLinkInterfaces.SWD)
last_error = None
for candidate in (device, *DEFAULT_DEVICES):
try:
try:
jlink.exec_command(f"Device = {candidate}")
except Exception:
pass
jlink.connect(candidate)
print(f"Connected as {candidate}")
return jlink
except pylink.errors.JLinkException as exc:
last_error = exc
jlink.close()
raise SystemExit(f"Failed to connect J-Link: {last_error}")
def find_rtt_control_block(jlink, ram_base: int = 0x20000000, ram_size: int = 0x18000) -> int | None:
needle = b"SEGGER RTT"
chunk = 0x1000
was_halted = jlink.halted()
if not was_halted:
jlink.halt()
try:
for off in range(0, ram_size, chunk):
data = bytes(jlink.memory_read8(ram_base + off, min(chunk, ram_size - off)))
idx = data.find(needle)
if idx >= 0:
return ram_base + off + idx
finally:
if not was_halted:
resume_cpu(jlink)
return None
def resume_cpu(jlink) -> None:
"""J-Link often halts the core on reset; must run() or UI stays black."""
try:
jlink.rtt_stop()
except Exception:
pass
try:
jlink.reset(halt=False)
except Exception:
pass
try:
if hasattr(jlink, "restart"):
jlink.restart()
else:
jlink.go()
except Exception:
jlink.go()
time.sleep(0.05)
def wait_rtt_ready(jlink, timeout_s: float = 15.0) -> None:
deadline = time.time() + timeout_s
while time.time() < deadline:
try:
if jlink.rtt_get_num_up_buffers() > 0:
return
except Exception:
pass
time.sleep(0.2)
raise SystemExit("RTT control block found but buffers not ready")
def send_reset(device: str, timeout_s: float, wait_boot_s: float, hw_fallback: bool) -> None:
jlink = connect_jlink(device)
ack_seen = False
try:
if jlink.halted():
print("Target was halted, resuming before RTT...")
resume_cpu(jlink)
time.sleep(0.2)
cb = find_rtt_control_block(jlink)
if cb is None:
raise SystemExit("SEGGER RTT control block not found in SRAM")
print(f"RTT CB @ 0x{cb:08X}")
resume_cpu(jlink)
time.sleep(0.15)
jlink.rtt_start(cb)
wait_rtt_ready(jlink)
wrote = 0
for _ in range(30):
wrote = jlink.rtt_write(0, list(RESET_CMD))
if wrote > 0:
break
time.sleep(0.2)
if wrote <= 0:
raise SystemExit("Failed to send sys reset on RTT down channel 0")
print(f"Sent sys reset ({wrote} bytes)")
deadline = time.time() + timeout_s
while time.time() < deadline:
chunk = jlink.rtt_read(0, 1024)
if chunk:
text = bytes(chunk)
if ACK in text:
ack_seen = True
print("SYS_RESET_OK (firmware handled reset)")
break
time.sleep(0.05)
if not ack_seen:
print("No SYS_RESET_OK from firmware.")
if hw_fallback:
print("Using J-Link hardware reset fallback...")
resume_cpu(jlink)
else:
print("Hint: re-run with --hw-fallback or flash latest firmware.")
# Critical: release CPU after reset — otherwise screen stays black.
print("Resuming CPU after reset...")
resume_cpu(jlink)
if wait_boot_s > 0:
print(f"Waiting {wait_boot_s:.0f}s for auto boot...")
time.sleep(wait_boot_s)
resume_cpu(jlink)
print("Done. Device should be back on mode-select screen.")
finally:
try:
resume_cpu(jlink)
except Exception:
pass
jlink.close()
def main() -> None:
parser = argparse.ArgumentParser(description="Reboot K1 via RTT sys reset command")
parser.add_argument("--device", default="AT32F403AC", help="J-Link device name")
parser.add_argument("--timeout", type=float, default=3.0, help="Seconds to wait for ACK")
parser.add_argument(
"--wait-boot",
type=float,
default=4.0,
help="Seconds to wait after reset for auto power-on (0 to skip)",
)
parser.add_argument(
"--no-hw-fallback",
action="store_true",
help="Do not use J-Link hardware reset when firmware ACK is missing",
)
args = parser.parse_args()
import_deps()
send_reset(args.device, args.timeout, args.wait_boot, not args.no_hw_fallback)
if __name__ == "__main__":
main()