Calibrate touch from serial logs: invert physical X axis.
Bottom LVGL buttons were mapped to the top; add on-screen logic coordinate debug. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
name: CYD TF card + touch speaker (cyd)
|
||||
git: 36bf614
|
||||
git: 86064bc
|
||||
date: 2026-10-17
|
||||
board: ESP32-2432S028R (ILI9341)
|
||||
features: TF/SD info, SoftSPI touch, GPIO26 speaker
|
||||
@@ -12,5 +12,5 @@ offsets:
|
||||
sha256:
|
||||
bootloader.bin 3D234A7471F67B013686DABD4DEE7C1FA915C9928463616A94BC9297ACF1ABF8
|
||||
boot_app0.bin F94C5D786A7A8FAB06AC5D10E33BF37711A6697636DC037559EA19CC410A17F0
|
||||
firmware.bin 5AFF818CB116CF68761168F931E9B9B5EB1B39AA0CFE40D79815BF85F0E2B007
|
||||
firmware.bin 142CB38A32343602F699F1CE8CE3BB699D6F3AFD03EA38A9B961EB2897B38797
|
||||
partitions.bin 148B959CBFF1C38AA8E1D5C0BA9D612C54997B945E56A63F41223EEF650653A1
|
||||
|
||||
Binary file not shown.
@@ -1,6 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <lvgl.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void touch_init();
|
||||
void touch_read_cb(lv_indev_t *indev, lv_indev_data_t *data);
|
||||
|
||||
// 调试:最近一次触点(物理 / LVGL 旋转后逻辑)
|
||||
extern int16_t g_dbg_phys_x, g_dbg_phys_y;
|
||||
extern int16_t g_dbg_logic_x, g_dbg_logic_y;
|
||||
extern bool g_dbg_touch_down;
|
||||
|
||||
@@ -5,3 +5,4 @@
|
||||
void ui_create();
|
||||
void ui_update(const SdCardInfo &info);
|
||||
void ui_refresh_audio_buttons();
|
||||
void ui_set_touch_debug(int16_t lx, int16_t ly, bool down);
|
||||
|
||||
@@ -77,10 +77,11 @@ void loop() {
|
||||
refresh_sd_ui();
|
||||
}
|
||||
|
||||
// 播放过程中刷新按钮文字(Playing / Stop)
|
||||
if (now - last_btn_ui_ms >= 300) {
|
||||
// 播放过程中刷新按钮文字;同步触点调试
|
||||
if (now - last_btn_ui_ms >= 200) {
|
||||
last_btn_ui_ms = now;
|
||||
ui_refresh_audio_buttons();
|
||||
ui_set_touch_debug(g_dbg_logic_x, g_dbg_logic_y, g_dbg_touch_down);
|
||||
}
|
||||
|
||||
delay(5);
|
||||
|
||||
@@ -4,13 +4,18 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
/**
|
||||
* SoftSPI XPT2046 → LVGL indev
|
||||
* SoftSPI XPT2046 → LVGL indev(物理 240x320,LVGL 再做 ROTATION_270)
|
||||
*
|
||||
* 关键:必须上报与 lv_tft_espi_create(240,320) 一致的【物理竖屏】坐标。
|
||||
* LVGL 在 ROTATION_270 时会自己做镜像+交换(见 lv_indev.c indev_pointer_proc)。
|
||||
* 若再 map 成 320x240,等于旋转两次,就会出现「只有上 1/3 有反应、底部按钮点不到」。
|
||||
* 串口实测:未反转时,点屏幕下方按钮对应到上方区域;
|
||||
* 故对物理 X 取反,使视觉上下与逻辑 ly 一致。
|
||||
*/
|
||||
|
||||
int16_t g_dbg_phys_x = -1;
|
||||
int16_t g_dbg_phys_y = -1;
|
||||
int16_t g_dbg_logic_x = -1;
|
||||
int16_t g_dbg_logic_y = -1;
|
||||
bool g_dbg_touch_down = false;
|
||||
|
||||
static void soft_write(uint8_t data) {
|
||||
for (int i = 7; i >= 0; --i) {
|
||||
digitalWrite(CYD_TOUCH_MOSI, (data >> i) & 1);
|
||||
@@ -53,7 +58,7 @@ void touch_init() {
|
||||
pinMode(CYD_TOUCH_IRQ, INPUT);
|
||||
digitalWrite(CYD_TOUCH_CS, HIGH);
|
||||
digitalWrite(CYD_TOUCH_CLK, LOW);
|
||||
Serial.println("Touch: physical 240x320 for LVGL rotation");
|
||||
Serial.println("Touch: phys 240x320, invert X (from serial calib)");
|
||||
}
|
||||
|
||||
void touch_read_cb(lv_indev_t * /*indev*/, lv_indev_data_t *data) {
|
||||
@@ -66,23 +71,18 @@ void touch_read_cb(lv_indev_t * /*indev*/, lv_indev_data_t *data) {
|
||||
const bool in_range =
|
||||
(raw_x > 80 && raw_x < 4000 && raw_y > 80 && raw_y < 4000);
|
||||
|
||||
if (!in_range) {
|
||||
data->state = LV_INDEV_STATE_RELEASED;
|
||||
return;
|
||||
}
|
||||
// 无 IRQ 时仍允许(部分板 IRQ 不可靠),但过滤空闲噪声
|
||||
if (!irq && (raw_x < 150 || raw_y < 150)) {
|
||||
if (!in_range || (!irq && (raw_x < 150 || raw_y < 150))) {
|
||||
data->state = LV_INDEV_STATE_RELEASED;
|
||||
g_dbg_touch_down = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// XPT2046_Touchscreen setRotation(2) 等价变换
|
||||
// setRotation(2) 等价
|
||||
const int16_t p_x = (int16_t)raw_x;
|
||||
const int16_t p_y = (int16_t)(4095 - raw_y);
|
||||
|
||||
// 物理竖屏:宽 SCREEN_WIDTH=240,高 SCREEN_HEIGHT=320
|
||||
// (与 create(240,320) 的 disp->hor_res / ver_res 一致,供 LVGL 再旋转)
|
||||
int16_t x = map(p_x, 200, 3700, 0, SCREEN_WIDTH - 1);
|
||||
// 物理竖屏;X 反向(串口日志标定)
|
||||
int16_t x = map(p_x, 200, 3700, SCREEN_WIDTH - 1, 0);
|
||||
int16_t y = map(p_y, 240, 3800, 0, SCREEN_HEIGHT - 1);
|
||||
|
||||
if (x < 0) {
|
||||
@@ -98,11 +98,22 @@ void touch_read_cb(lv_indev_t * /*indev*/, lv_indev_data_t *data) {
|
||||
y = SCREEN_HEIGHT - 1;
|
||||
}
|
||||
|
||||
// LVGL ROTATION_270 之后的逻辑坐标(与 indev_pointer_proc 一致)
|
||||
// lx = y, ly = hor_res - x - 1 (hor_res=240)
|
||||
const int16_t logic_x = y;
|
||||
const int16_t logic_y = (int16_t)(SCREEN_WIDTH - 1 - x);
|
||||
|
||||
g_dbg_phys_x = x;
|
||||
g_dbg_phys_y = y;
|
||||
g_dbg_logic_x = logic_x;
|
||||
g_dbg_logic_y = logic_y;
|
||||
g_dbg_touch_down = true;
|
||||
|
||||
static uint32_t last_log = 0;
|
||||
if (millis() - last_log > 200) {
|
||||
if (millis() - last_log > 150) {
|
||||
last_log = millis();
|
||||
Serial.printf("Touch phys(%d,%d) raw(%u,%u) irq=%d\n", x, y, raw_x, raw_y,
|
||||
irq ? 1 : 0);
|
||||
Serial.printf("Touch raw(%u,%u) phys(%d,%d) logic(%d,%d)\n", raw_x, raw_y, x,
|
||||
y, logic_x, logic_y);
|
||||
}
|
||||
|
||||
data->point.x = x;
|
||||
|
||||
19
src/ui.cpp
19
src/ui.cpp
@@ -13,6 +13,7 @@ static lv_obj_t *btn_speaker;
|
||||
static lv_obj_t *btn_play;
|
||||
static lv_obj_t *lbl_speaker;
|
||||
static lv_obj_t *lbl_play;
|
||||
static lv_obj_t *lbl_touch_dbg;
|
||||
|
||||
static lv_obj_t *make_row(lv_obj_t *parent, const char *title, lv_obj_t **value_out) {
|
||||
lv_obj_t *row = lv_obj_create(parent);
|
||||
@@ -149,9 +150,27 @@ void ui_create() {
|
||||
lv_obj_set_style_text_font(lbl_play, &lv_font_montserrat_14, 0);
|
||||
lv_obj_center(lbl_play);
|
||||
|
||||
lbl_touch_dbg = lv_label_create(col);
|
||||
lv_label_set_text(lbl_touch_dbg, "Touch: --");
|
||||
lv_obj_set_style_text_font(lbl_touch_dbg, &lv_font_montserrat_14, 0);
|
||||
lv_obj_set_style_text_color(lbl_touch_dbg, lv_color_hex(0xFFB74D), 0);
|
||||
|
||||
ui_refresh_audio_buttons();
|
||||
}
|
||||
|
||||
void ui_set_touch_debug(int16_t lx, int16_t ly, bool down) {
|
||||
if (!lbl_touch_dbg) {
|
||||
return;
|
||||
}
|
||||
if (!down) {
|
||||
lv_label_set_text(lbl_touch_dbg, "Touch: up");
|
||||
return;
|
||||
}
|
||||
char buf[40];
|
||||
snprintf(buf, sizeof(buf), "Touch L:%d,%d", (int)lx, (int)ly);
|
||||
lv_label_set_text(lbl_touch_dbg, buf);
|
||||
}
|
||||
|
||||
void ui_update(const SdCardInfo &info) {
|
||||
if (!info.mounted || !info.present) {
|
||||
lv_label_set_text(lbl_status, info.error.length() ? info.error.c_str() : "Fail");
|
||||
|
||||
Reference in New Issue
Block a user