Black-screen cause was TFT_BL=21; archive flashable firmware/cyd_35r. Co-authored-by: Cursor <cursoragent@cursor.com>
194 lines
5.2 KiB
C++
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
|