Drop LVGL ROTATION_270 double-transform; SoftSPI rot3 maps directly to screen pixels. Co-authored-by: Cursor <cursoragent@cursor.com>
120 lines
3.1 KiB
C++
120 lines
3.1 KiB
C++
#include "touch.h"
|
||
#include "pins.h"
|
||
|
||
#include <Arduino.h>
|
||
|
||
/**
|
||
* SoftSPI XPT2046 — 与 SD 分脚
|
||
*
|
||
* 对齐官方 CYD LVGL9 例程(witnessmenow):
|
||
* - 显示直接建为 320x240,LVGL rotation=0(触控不再被二次变换)
|
||
* - touch setRotation(3) + map 到 SCREEN_WIDTH/HEIGHT
|
||
* 参考:https://github.com/witnessmenow/ESP32-Cheap-Yellow-Display/blob/main/Examples/LVGL9/
|
||
*/
|
||
|
||
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 rot3 map 320x240 (no LVGL rot)");
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
// XPT2046_Touchscreen setRotation(3):
|
||
// xraw = 4095 - Y_sample, yraw = 4095 - X_sample
|
||
const int16_t p_x = (int16_t)(4095 - adc_y);
|
||
const int16_t p_y = (int16_t)(4095 - adc_x);
|
||
|
||
int16_t x = map(p_x, 200, 3700, 1, SCREEN_WIDTH);
|
||
int16_t y = map(p_y, 240, 3800, 1, SCREEN_HEIGHT);
|
||
|
||
if (x < 0) {
|
||
x = 0;
|
||
}
|
||
if (y < 0) {
|
||
y = 0;
|
||
}
|
||
if (x >= SCREEN_WIDTH) {
|
||
x = SCREEN_WIDTH - 1;
|
||
}
|
||
if (y >= SCREEN_HEIGHT) {
|
||
y = SCREEN_HEIGHT - 1;
|
||
}
|
||
|
||
g_dbg_phys_x = p_x;
|
||
g_dbg_phys_y = p_y;
|
||
g_dbg_logic_x = x;
|
||
g_dbg_logic_y = y;
|
||
g_dbg_touch_down = true;
|
||
|
||
static uint32_t last_log = 0;
|
||
if (millis() - last_log > 120) {
|
||
last_log = millis();
|
||
Serial.printf("Touch adc(%u,%u) p(%d,%d) -> (%d,%d)\n", adc_x, adc_y, p_x,
|
||
p_y, x, y);
|
||
}
|
||
|
||
data->point.x = x;
|
||
data->point.y = y;
|
||
data->state = LV_INDEV_STATE_PRESSED;
|
||
}
|