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

@@ -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;