CLK on GPIO22, DIO on GPIO27; value/brightness/colon controls and flashable firmware/cyd package. Co-authored-by: Cursor <cursoragent@cursor.com>
126 lines
3.4 KiB
C++
126 lines
3.4 KiB
C++
#include "touch.h"
|
||
#include "pins.h"
|
||
|
||
#include <Arduino.h>
|
||
|
||
/**
|
||
* SoftSPI XPT2046
|
||
* BL↔TR 是矩形主对角线镜像(XY 对调),不是 180°(180° 会搞成 TL↔BR)。
|
||
* 先按 rot2 得到旧 UI,再做对角修正,反变换喂给 LVGL 270。
|
||
*/
|
||
|
||
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;
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
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);
|
||
|
||
// 旧 UI(LVGL270):(y, 239-x) — 该空间里 BL↔TR,做主对角线镜像
|
||
// (ux,uy) -> (uy*(319/239), ux*(239/319))
|
||
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);
|
||
|
||
// 反变换喂 LVGL,使最终落在 (ui_x, ui_y)
|
||
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;
|
||
}
|