Fix double touch rotation so bottom LVGL buttons receive hits.

Report physical 240x320 coordinates and let LVGL apply ROTATION_270.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-17 17:57:57 +08:00
parent 36bf614d11
commit 86064bca9c
4 changed files with 32 additions and 19 deletions

View File

@@ -1,9 +1,14 @@
# Changelog
## 2026-10-17 — Fix touch Y (buttons dead zone)
- Root cause: feeding already-landscape 320x240 points while LVGL also applies
ROTATION_270 (double transform) → only upper ~1/3 hit-tested correctly.
- Fix: report physical 240x320 coords; let LVGL rotate (matches `lv_indev.c`).
## 2026-10-17 — Restore LVGL touch
- SoftSPI + LVGL `lv_indev` (with `lv_indev_set_display`).
- Same landscape map as `temperature`; IRQ optional (sample-range fallback).
- Larger clickable speaker/play buttons.
## 2026-10-17 — Fix touch offset

View File

@@ -1,5 +1,5 @@
name: CYD TF card + touch speaker (cyd)
git: fe4b085
git: 36bf614
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 6EA45305C88045B6ECBA897D200294C05570C19619F498BE25B57C2419B94DC4
firmware.bin 5AFF818CB116CF68761168F931E9B9B5EB1B39AA0CFE40D79815BF85F0E2B007
partitions.bin 148B959CBFF1C38AA8E1D5C0BA9D612C54997B945E56A63F41223EEF650653A1

Binary file not shown.

View File

@@ -4,8 +4,11 @@
#include <Arduino.h>
/**
* SoftSPI XPT2046 → LVGL pointer indev
* 读数用简单稳定协议(此前能点到);坐标变换对齐 temperature(rot2 + map 320x240)。
* SoftSPI XPT2046 → LVGL indev
*
* 关键:必须上报与 lv_tft_espi_create(240,320) 一致的【物理竖屏】坐标。
* LVGL 在 ROTATION_270 时会自己做镜像+交换(见 lv_indev.c indev_pointer_proc)。
* 若再 map 成 320x240,等于旋转两次,就会出现「只有上 1/3 有反应、底部按钮点不到」。
*/
static void soft_write(uint8_t data) {
@@ -50,11 +53,10 @@ void touch_init() {
pinMode(CYD_TOUCH_IRQ, INPUT);
digitalWrite(CYD_TOUCH_CS, HIGH);
digitalWrite(CYD_TOUCH_CLK, LOW);
Serial.println("Touch: LVGL indev SoftSPI");
Serial.println("Touch: physical 240x320 for LVGL rotation");
}
void touch_read_cb(lv_indev_t * /*indev*/, lv_indev_data_t *data) {
// 不依赖 IRQ(部分板子 IRQ 不可靠):用采样有效性判断
uint16_t raw_x = xpt_read(0x90);
uint16_t raw_y = xpt_read(0xD0);
raw_x = (uint16_t)((raw_x + xpt_read(0x90)) / 2);
@@ -64,18 +66,24 @@ 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 || (!irq && (raw_x < 200 || raw_y < 200))) {
if (!in_range) {
data->state = LV_INDEV_STATE_RELEASED;
return;
}
// 无 IRQ 时仍允许(部分板 IRQ 不可靠),但过滤空闲噪声
if (!irq && (raw_x < 150 || raw_y < 150)) {
data->state = LV_INDEV_STATE_RELEASED;
return;
}
// XPT2046_Touchscreen setRotation(2)
// XPT2046_Touchscreen setRotation(2) 等价变换
const int16_t p_x = (int16_t)raw_x;
const int16_t p_y = (int16_t)(4095 - raw_y);
// temperature 横屏逻辑坐标(UI 320x240)
int16_t x = map(p_y, 240, 3800, 1, UI_HOR_RES);
int16_t y = map(p_x, 200, 3700, UI_VER_RES, 1);
// 物理竖屏:宽 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);
int16_t y = map(p_y, 240, 3800, 0, SCREEN_HEIGHT - 1);
if (x < 0) {
x = 0;
@@ -83,18 +91,18 @@ void touch_read_cb(lv_indev_t * /*indev*/, lv_indev_data_t *data) {
if (y < 0) {
y = 0;
}
if (x >= UI_HOR_RES) {
x = UI_HOR_RES - 1;
if (x >= SCREEN_WIDTH) {
x = SCREEN_WIDTH - 1;
}
if (y >= UI_VER_RES) {
y = UI_VER_RES - 1;
if (y >= SCREEN_HEIGHT) {
y = SCREEN_HEIGHT - 1;
}
static uint32_t last_log = 0;
if (millis() - last_log > 250) {
if (millis() - last_log > 200) {
last_log = millis();
Serial.printf("LVGL touch irq=%d raw(%u,%u) -> (%d,%d)\n", irq ? 1 : 0, raw_x,
raw_y, x, y);
Serial.printf("Touch phys(%d,%d) raw(%u,%u) irq=%d\n", x, y, raw_x, raw_y,
irq ? 1 : 0);
}
data->point.x = x;