Restore SoftSPI touch and exclusive VSPI for SD.
HW SPI remux froze touch at (0,4095) and broke SD; keep temperature UI map plus LVGL inverse feed. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
101
src/touch.cpp
101
src/touch.cpp
@@ -1,12 +1,13 @@
|
||||
#include "touch.h"
|
||||
#include "bus_vspi.h"
|
||||
#include "pins.h"
|
||||
|
||||
#include <XPT2046_Touchscreen.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
// 与 temperature 完全相同的硬件触摸驱动
|
||||
static XPT2046_Touchscreen touchscreen(CYD_TOUCH_CS, CYD_TOUCH_IRQ);
|
||||
/**
|
||||
* 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;
|
||||
@@ -14,35 +15,74 @@ int16_t g_dbg_logic_x = -1;
|
||||
int16_t g_dbg_logic_y = -1;
|
||||
bool g_dbg_touch_down = false;
|
||||
|
||||
void touch_init() {
|
||||
pinMode(CYD_TOUCH_IRQ, INPUT);
|
||||
pinMode(CYD_TOUCH_CS, OUTPUT);
|
||||
digitalWrite(CYD_TOUCH_CS, HIGH);
|
||||
pinMode(SD_CS, OUTPUT);
|
||||
digitalWrite(SD_CS, HIGH);
|
||||
|
||||
cyd_vspi_select_touch();
|
||||
if (!touchscreen.begin(cyd_vspi())) {
|
||||
Serial.println("Touch: begin FAILED");
|
||||
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);
|
||||
}
|
||||
touchscreen.setRotation(2); // temperature 相同
|
||||
Serial.println("Touch: XPT2046 + temp map + LVGL inverse");
|
||||
}
|
||||
|
||||
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) {
|
||||
cyd_vspi_select_touch();
|
||||
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);
|
||||
|
||||
if (!(touchscreen.tirqTouched() && touchscreen.touched())) {
|
||||
g_dbg_touch_down = false;
|
||||
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;
|
||||
}
|
||||
|
||||
TS_Point p = touchscreen.getPoint();
|
||||
// XPT2046_Touchscreen setRotation(2)
|
||||
const int16_t p_x = (int16_t)raw_x;
|
||||
const int16_t p_y = (int16_t)(4095 - raw_y);
|
||||
|
||||
// 1) 与 temperature 相同:得到「屏幕上看到的」横屏坐标 320x240
|
||||
int16_t lx = map(p.y, 240, 3800, 1, UI_HOR_RES);
|
||||
int16_t ly = map(p.x, 200, 3700, UI_VER_RES, 1);
|
||||
// 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;
|
||||
@@ -57,17 +97,12 @@ void touch_read_cb(lv_indev_t * /*indev*/, lv_indev_data_t *data) {
|
||||
ly = UI_VER_RES - 1;
|
||||
}
|
||||
|
||||
// 2) LVGL 在 ROTATION_270 时还会变换一次(create 240x320):
|
||||
// lx_out = y_in
|
||||
// ly_out = hor_res - 1 - x_in (hor_res = 240)
|
||||
// 故要让最终 = (lx, ly),应上报:
|
||||
// x_in = 239 - ly
|
||||
// y_in = lx
|
||||
// 反变换:让 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_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;
|
||||
@@ -75,8 +110,8 @@ void touch_read_cb(lv_indev_t * /*indev*/, lv_indev_data_t *data) {
|
||||
static uint32_t last_log = 0;
|
||||
if (millis() - last_log > 120) {
|
||||
last_log = millis();
|
||||
Serial.printf("Touch raw(%d,%d) UI(%d,%d) feed(%d,%d)\n", p.x, p.y, lx, ly,
|
||||
x_in, y_in);
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user