#include "touch.h" #include "pins.h" #include #if defined(CYD_BOARD_3248S035) #include #endif /** * 2.8": dedicated SoftSPI + BL/TR diagonal fix. * 3.5C (3248S035C): capacitive GT911 on I2C SDA33/SCL32/INT21/RST25. */ 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 int16_t clampi(int32_t v, int32_t lo, int32_t hi) { if (v < lo) { return (int16_t)lo; } if (v > hi) { return (int16_t)hi; } return (int16_t)v; } #if defined(CYD_BOARD_3248S035) /* Minimal GT911 — no config rewrite (TAMC setResolution can hang Wire). */ static uint8_t s_gt_addr = 0x5D; static constexpr uint16_t GT_POINT_INFO = 0x814E; static constexpr uint16_t GT_POINT_1 = 0x814F; static bool gt_write8(uint16_t reg, uint8_t val) { Wire.beginTransmission(s_gt_addr); Wire.write((uint8_t)(reg >> 8)); Wire.write((uint8_t)(reg & 0xFF)); Wire.write(val); return Wire.endTransmission() == 0; } static bool gt_read(uint16_t reg, uint8_t *buf, uint8_t len) { Wire.beginTransmission(s_gt_addr); Wire.write((uint8_t)(reg >> 8)); Wire.write((uint8_t)(reg & 0xFF)); if (Wire.endTransmission(false) != 0) { return false; } const uint8_t n = Wire.requestFrom(s_gt_addr, len); if (n != len) { return false; } for (uint8_t i = 0; i < len; i++) { buf[i] = Wire.read(); } return true; } static bool gt_probe(uint8_t addr) { Wire.beginTransmission(addr); return Wire.endTransmission() == 0; } /* TAMC-compatible address select: INT low => 0x5D, INT high => 0x14 */ static void gt_hw_reset(bool addr_0x14) { pinMode(CYD_GT911_INT, OUTPUT); pinMode(CYD_GT911_RST, OUTPUT); digitalWrite(CYD_GT911_INT, LOW); digitalWrite(CYD_GT911_RST, LOW); delay(10); digitalWrite(CYD_GT911_INT, addr_0x14 ? HIGH : LOW); delay(1); digitalWrite(CYD_GT911_RST, HIGH); delay(5); digitalWrite(CYD_GT911_INT, LOW); delay(50); /* Backlight is GPIO27 — leave INT as input for polling / optional IRQ. */ pinMode(CYD_GT911_INT, INPUT); delay(50); } static bool gt_find_addr() { for (uint8_t a : {uint8_t(0x5D), uint8_t(0x14)}) { if (gt_probe(a)) { s_gt_addr = a; return true; } } return false; } void touch_init() { Serial.println("Touch: GT911 I2C capacitive (3.5C) minimal"); Wire.begin(CYD_GT911_SDA, CYD_GT911_SCL); Wire.setClock(100000); #if defined(WIRE_HAS_TIMEOUT) || defined(ESP32) Wire.setTimeOut(50); #endif if (!gt_find_addr()) { Serial.println("GT911 not found — hw reset 0x5D"); gt_hw_reset(false); if (!gt_find_addr()) { Serial.println("GT911 not found — hw reset 0x14"); gt_hw_reset(true); gt_find_addr(); } } Serial.printf("GT911 probe 0x5D=%s 0x14=%s using=0x%02X\n", gt_probe(0x5D) ? "OK" : "no", gt_probe(0x14) ? "OK" : "no", s_gt_addr); Serial.printf("GT911 SDA=%d SCL=%d INT=%d RST=%d\n", CYD_GT911_SDA, CYD_GT911_SCL, CYD_GT911_INT, CYD_GT911_RST); } void touch_read_cb(lv_indev_t * /*indev*/, lv_indev_data_t *data) { uint8_t info = 0; static uint32_t last_log = 0; const bool do_log = (millis() - last_log > 200); if (!gt_read(GT_POINT_INFO, &info, 1)) { data->state = LV_INDEV_STATE_RELEASED; g_dbg_touch_down = false; if (do_log) { last_log = millis(); Serial.println("TouchProbe GT911 I2C err"); } return; } const uint8_t touches = info & 0x0F; const bool buffered = (info & 0x80) != 0; if (!buffered || touches == 0) { if (buffered) { gt_write8(GT_POINT_INFO, 0); } data->state = LV_INDEV_STATE_RELEASED; g_dbg_touch_down = false; return; } uint8_t pt[7]; if (!gt_read(GT_POINT_1, pt, 7)) { gt_write8(GT_POINT_INFO, 0); data->state = LV_INDEV_STATE_RELEASED; g_dbg_touch_down = false; return; } gt_write8(GT_POINT_INFO, 0); const int16_t raw_x = (int16_t)(pt[1] | (pt[2] << 8)); const int16_t raw_y = (int16_t)(pt[3] | (pt[4] << 8)); /* Native 320x480 → LVGL 270. Mirror long axis so L/R matches UI * (else preset 3 hits 10). Resulting UI ≈ (H-1-raw_y, raw_x). */ const int16_t nx = clampi(raw_x, 0, SCREEN_WIDTH - 1); const int16_t ny = clampi(raw_y, 0, SCREEN_HEIGHT - 1); const int16_t feed_x = (int16_t)((SCREEN_WIDTH - 1) - nx); const int16_t feed_y = (int16_t)((SCREEN_HEIGHT - 1) - ny); const int16_t ui_x = (int16_t)((SCREEN_HEIGHT - 1) - ny); const int16_t ui_y = nx; g_dbg_phys_x = raw_x; g_dbg_phys_y = raw_y; g_dbg_logic_x = ui_x; g_dbg_logic_y = ui_y; g_dbg_touch_down = true; if (do_log) { last_log = millis(); Serial.printf("Touch HIT GT911 raw(%d,%d) ~ui(%d,%d)\n", raw_x, raw_y, ui_x, ui_y); } data->point.x = feed_x; data->point.y = feed_y; data->state = LV_INDEV_STATE_PRESSED; } #else 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 + diagonal fix (BL/TR)"); } void touch_read_cb(lv_indev_t * /*indev*/, lv_indev_data_t *data) { uint16_t adc_x = xpt_read(0x90); uint16_t adc_y = xpt_read(0xD0); adc_x = (uint16_t)((adc_x + xpt_read(0x90)) / 2); adc_y = (uint16_t)((adc_y + xpt_read(0xD0)) / 2); const bool irq = (digitalRead(CYD_TOUCH_IRQ) == LOW); const bool in_range = (adc_x > 80 && adc_x < 4000 && adc_y > 80 && adc_y < 4000); if (!in_range || (!irq && (adc_x < 200 || adc_y < 200))) { data->state = LV_INDEV_STATE_RELEASED; g_dbg_touch_down = false; return; } const int16_t p_x = (int16_t)adc_x; const int16_t p_y = (int16_t)(4095 - adc_y); int16_t x = map(p_x, 200, 3700, 1, SCREEN_WIDTH); int16_t y = map(p_y, 240, 3800, 1, SCREEN_HEIGHT); x = clampi(x, 0, SCREEN_WIDTH - 1); y = clampi(y, 0, SCREEN_HEIGHT - 1); const int32_t old_ux = y; const int32_t old_uy = (SCREEN_WIDTH - 1) - x; int16_t ui_x = clampi((old_uy * (UI_HOR_RES - 1)) / (UI_VER_RES - 1), 0, UI_HOR_RES - 1); int16_t ui_y = clampi((old_ux * (UI_VER_RES - 1)) / (UI_HOR_RES - 1), 0, UI_VER_RES - 1); const int16_t feed_x = (int16_t)((SCREEN_WIDTH - 1) - ui_y); const int16_t feed_y = ui_x; g_dbg_phys_x = x; g_dbg_phys_y = y; g_dbg_logic_x = ui_x; g_dbg_logic_y = ui_y; g_dbg_touch_down = true; static uint32_t last_log = 0; if (millis() - last_log > 80) { last_log = millis(); Serial.printf("Touch UI(%d,%d)\n", ui_x, ui_y); } data->point.x = feed_x; data->point.y = feed_y; data->state = LV_INDEV_STATE_PRESSED; } #endif