diff --git a/firmware/cyd/VERSION.txt b/firmware/cyd/VERSION.txt index de24106..7730ba3 100644 --- a/firmware/cyd/VERSION.txt +++ b/firmware/cyd/VERSION.txt @@ -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 diff --git a/firmware/cyd/firmware.bin b/firmware/cyd/firmware.bin index c6fefba..53402eb 100644 Binary files a/firmware/cyd/firmware.bin and b/firmware/cyd/firmware.bin differ diff --git a/include/touch.h b/include/touch.h index 788ec0f..86e00fe 100644 --- a/include/touch.h +++ b/include/touch.h @@ -1,6 +1,12 @@ #pragma once #include +#include 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; diff --git a/include/ui.h b/include/ui.h index 2dcdfdf..db66073 100644 --- a/include/ui.h +++ b/include/ui.h @@ -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); diff --git a/src/main.cpp b/src/main.cpp index 59fff8d..24aa43c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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); diff --git a/src/touch.cpp b/src/touch.cpp index c14a063..256cf1b 100644 --- a/src/touch.cpp +++ b/src/touch.cpp @@ -4,13 +4,18 @@ #include /** - * 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; diff --git a/src/ui.cpp b/src/ui.cpp index 40ab4c1..3a1740b 100644 --- a/src/ui.cpp +++ b/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");