#include "touch.h" #include "pins.h" #include /** * SoftSPI XPT2046(与 SD 的 VSPI 分脚,互不抢总线) * 标定对齐 temperature(rot2 + map 到 UI 320x240),再反变换喂给 LVGL * ROTATION_270(见 lv_indev.c):out=(y_in, 239-x_in) */ 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); digitalWrite(CYD_TOUCH_CLK, HIGH); delayMicroseconds(2); digitalWrite(CYD_TOUCH_CLK, LOW); delayMicroseconds(2); } } static uint16_t soft_read12() { uint16_t v = 0; digitalWrite(CYD_TOUCH_CLK, HIGH); delayMicroseconds(2); digitalWrite(CYD_TOUCH_CLK, LOW); delayMicroseconds(2); for (int i = 0; i < 12; ++i) { digitalWrite(CYD_TOUCH_CLK, HIGH); delayMicroseconds(2); v = (uint16_t)((v << 1) | (digitalRead(CYD_TOUCH_MISO) ? 1u : 0u)); digitalWrite(CYD_TOUCH_CLK, LOW); delayMicroseconds(2); } return v; } static uint16_t xpt_read(uint8_t cmd) { digitalWrite(CYD_TOUCH_CS, LOW); soft_write(cmd); uint16_t v = soft_read12(); digitalWrite(CYD_TOUCH_CS, HIGH); return v; } void touch_init() { pinMode(CYD_TOUCH_CS, OUTPUT); pinMode(CYD_TOUCH_CLK, OUTPUT); pinMode(CYD_TOUCH_MOSI, OUTPUT); pinMode(CYD_TOUCH_MISO, INPUT); pinMode(CYD_TOUCH_IRQ, INPUT); digitalWrite(CYD_TOUCH_CS, HIGH); digitalWrite(CYD_TOUCH_CLK, LOW); Serial.println("Touch: SoftSPI + temp map + LVGL inverse"); } void touch_read_cb(lv_indev_t * /*indev*/, lv_indev_data_t *data) { uint16_t raw_x = xpt_read(0x90); uint16_t raw_y = xpt_read(0xD0); raw_x = (uint16_t)((raw_x + xpt_read(0x90)) / 2); raw_y = (uint16_t)((raw_y + xpt_read(0xD0)) / 2); const bool irq = (digitalRead(CYD_TOUCH_IRQ) == LOW); 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))) { data->state = LV_INDEV_STATE_RELEASED; g_dbg_touch_down = false; return; } // 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 坐标 int16_t lx = map(p_y, 240, 3800, 1, UI_HOR_RES); int16_t ly = map(p_x, 200, 3700, UI_VER_RES, 1); if (lx < 0) { lx = 0; } if (ly < 0) { ly = 0; } if (lx >= UI_HOR_RES) { lx = UI_HOR_RES - 1; } if (ly >= UI_VER_RES) { ly = UI_VER_RES - 1; } // 反变换:让 LVGL ROTATION_270 之后落到 (lx, ly) const int16_t x_in = (int16_t)((SCREEN_WIDTH - 1) - ly); const int16_t y_in = lx; g_dbg_phys_x = p_x; g_dbg_phys_y = p_y; g_dbg_logic_x = lx; g_dbg_logic_y = ly; g_dbg_touch_down = true; static uint32_t last_log = 0; if (millis() - last_log > 120) { last_log = millis(); Serial.printf("Touch raw(%u,%u) UI(%d,%d) feed(%d,%d)\n", raw_x, raw_y, lx, ly, x_in, y_in); } data->point.x = x_in; data->point.y = y_in; data->state = LV_INDEV_STATE_PRESSED; }