Files
ld2420test/src/touch.cpp
DESKTOP-PUHFO60\dsx2016 786f48ebd6 Fix 3.5C pins per CYD_PROJECT_GUIDE: BL=27, LD2420 TX=GPIO4, GT911 INT as INPUT.
Black-screen cause was TFT_BL=21; archive flashable firmware/cyd_35r.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-25 11:04:59 +08:00

194 lines
5.2 KiB
C++

#include "touch.h"
#include <Arduino.h>
/**
* 2.8": XPT2046 resistive SoftSPI bus (CS33).
* 3.5C (3248S035C): GT911 capacitive on I2C Wire SDA33/SCL32/INT21/RST25.
* Backlight is GPIO27 — INT(21) is NOT the backlight. After address select,
* leave INT as INPUT (poll-only; some boards have broken INT wiring).
* Feed coords are always native panel 320x480 for LVGL ROTATION_270.
*/
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)
#include <Wire.h>
/* Native panel size — not UI landscape SCREEN_* (480x320). */
static constexpr int16_t PANEL_W = 320;
static constexpr int16_t PANEL_H = 480;
#define CYD_GT911_SDA 33
#define CYD_GT911_SCL 32
#define CYD_GT911_INT 21
#define CYD_GT911_RST 25
/* 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);
}
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;
if (!gt_read(GT_POINT_INFO, &info, 1)) {
data->state = LV_INDEV_STATE_RELEASED;
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;
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;
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. UI ≈ (H-1-raw_y, raw_x). */
const int16_t nx = clampi(raw_x, 0, PANEL_W - 1);
const int16_t ny = clampi(raw_y, 0, PANEL_H - 1);
data->point.x = (int16_t)((PANEL_W - 1) - nx);
data->point.y = (int16_t)((PANEL_H - 1) - ny);
data->state = LV_INDEV_STATE_PRESSED;
}
#else
#include <SPI.h>
#include <XPT2046_Touchscreen.h>
#define XPT2046_IRQ 36
#define XPT2046_MOSI 32
#define XPT2046_MISO 39
#define XPT2046_CLK 25
#define XPT2046_CS 33
/* 2.8 UI landscape feed (unchanged from prior main.cpp). */
static constexpr int16_t UI_W = 320;
static constexpr int16_t UI_H = 240;
static SPIClass touchscreenSPI = SPIClass(VSPI);
static XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);
void touch_init() {
touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
touchscreen.begin(touchscreenSPI);
touchscreen.setRotation(2);
Serial.println("Touch: XPT2046 resistive (2.8)");
}
void touch_read_cb(lv_indev_t * /*indev*/, lv_indev_data_t *data) {
if (touchscreen.tirqTouched() && touchscreen.touched()) {
TS_Point p = touchscreen.getPoint();
data->point.x = map(p.y, 240, 3800, 1, UI_W);
data->point.y = map(p.x, 200, 3700, UI_H, 1);
data->state = LV_INDEV_STATE_PRESSED;
} else {
data->state = LV_INDEV_STATE_RELEASED;
}
}
#endif