diff --git a/CHANGELOG.md b/CHANGELOG.md index ba9c32e..e008969 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 2026-10-17 — Fix touch offset + +- SoftSPI touch now uses the same rotation=2 transform + map as `temperature`. +- Pressure (Z) sampling instead of IRQ-only; oversampled like XPT2046_Touchscreen. + ## 2026-10-17 — Prebuilt firmware folder - Add `firmware/cyd/` with bin + `flash.ps1` / `flash.bat` (same pattern as temperature). diff --git a/README.md b/README.md index a866bbb..f1c55a9 100644 --- a/README.md +++ b/README.md @@ -60,8 +60,7 @@ pio device monitor ## 注意事项 - TF 需 **FAT/FAT32**。 -- 若触屏坐标偏移,改 `src/touch.cpp` 里 `map(...)` 校准范围。 -- 若点按无反应,检查排线/旋转;可尝试交换 raw_x/raw_y 映射。 +- 触屏校准与 `temperature` 工程一致(`setRotation(2)` + map);仍偏可改 `src/touch.cpp` 的 `map(...)` 边界。 - 变更请更新 `CHANGELOG.md`、必要时重新 `export_from_build.ps1`,并提交本地 git。 ## 版本 diff --git a/firmware/cyd/VERSION.txt b/firmware/cyd/VERSION.txt index 6a8c5a1..a75a528 100644 --- a/firmware/cyd/VERSION.txt +++ b/firmware/cyd/VERSION.txt @@ -1,5 +1,5 @@ name: CYD TF card + touch speaker (cyd) -git: f05c5d6 +git: b54e36b date: 2026-10-17 board: ESP32-2432S028R (ILI9341) features: TF/SD info, SoftSPI touch, GPIO26 speaker @@ -12,5 +12,5 @@ offsets: sha256: bootloader.bin 3D234A7471F67B013686DABD4DEE7C1FA915C9928463616A94BC9297ACF1ABF8 boot_app0.bin F94C5D786A7A8FAB06AC5D10E33BF37711A6697636DC037559EA19CC410A17F0 - firmware.bin 1FB845985551DBB1C92D5510278EFAF773311F4CE370B06F78585D397144FE87 + firmware.bin 48A37AE15A12242AE5B965D0A326E0D272CF62DB8137654A1528DD1ABE033192 partitions.bin 148B959CBFF1C38AA8E1D5C0BA9D612C54997B945E56A63F41223EEF650653A1 diff --git a/firmware/cyd/firmware.bin b/firmware/cyd/firmware.bin index 898706c..e4f0c74 100644 Binary files a/firmware/cyd/firmware.bin and b/firmware/cyd/firmware.bin differ diff --git a/src/touch.cpp b/src/touch.cpp index efcbc94..13bbe74 100644 --- a/src/touch.cpp +++ b/src/touch.cpp @@ -3,39 +3,88 @@ #include -static void soft_spi_write(uint8_t data) { - for (int i = 7; i >= 0; --i) { - digitalWrite(CYD_TOUCH_MOSI, (data >> i) & 1); - digitalWrite(CYD_TOUCH_CLK, HIGH); - delayMicroseconds(1); - digitalWrite(CYD_TOUCH_CLK, LOW); - delayMicroseconds(1); - } -} +// SoftSPI bitbang XPT2046 — 坐标变换对齐 temperature 工程(setRotation(2) + map) -static uint16_t soft_spi_read12() { - uint16_t v = 0; - for (int i = 0; i < 12; ++i) { - digitalWrite(CYD_TOUCH_CLK, HIGH); - delayMicroseconds(1); - v = (v << 1) | (digitalRead(CYD_TOUCH_MISO) ? 1 : 0); - digitalWrite(CYD_TOUCH_CLK, LOW); - delayMicroseconds(1); - } - // 丢掉多余时钟位 +static void clk_pulse() { digitalWrite(CYD_TOUCH_CLK, HIGH); delayMicroseconds(1); digitalWrite(CYD_TOUCH_CLK, LOW); - return v; + delayMicroseconds(1); } -static uint16_t xpt_read(uint8_t cmd) { +static void soft_spi_write8(uint8_t data) { + for (int i = 7; i >= 0; --i) { + digitalWrite(CYD_TOUCH_MOSI, (data >> i) & 1); + clk_pulse(); + } +} + +// 模拟 library 的 transfer16 >> 3(12-bit ADC) +static uint16_t soft_spi_transfer16_shr3() { + uint16_t v = 0; + for (int i = 0; i < 16; ++i) { + digitalWrite(CYD_TOUCH_CLK, HIGH); + delayMicroseconds(1); + v = (v << 1) | (digitalRead(CYD_TOUCH_MISO) ? 1u : 0u); + digitalWrite(CYD_TOUCH_CLK, LOW); + delayMicroseconds(1); + } + return v >> 3; +} + +static uint16_t xpt_cmd_read(uint8_t cmd) { + soft_spi_write8(cmd); + return soft_spi_transfer16_shr3(); +} + +static int16_t best_two_avg(int16_t a, int16_t b, int16_t c) { + const int16_t ab = abs(a - b); + const int16_t ac = abs(a - c); + const int16_t bc = abs(b - c); + if (ab <= ac && ab <= bc) { + return (a + b) >> 1; + } + if (ac <= ab && ac <= bc) { + return (a + c) >> 1; + } + return (b + c) >> 1; +} + +// 返回 true 并写出 raw(已做 rotation=2,与 XPT2046_Touchscreen 一致) +static bool touch_sample(int16_t *out_x, int16_t *out_y) { digitalWrite(CYD_TOUCH_CS, LOW); - soft_spi_write(cmd); - delayMicroseconds(5); - uint16_t v = soft_spi_read12(); + + // Z 压力(参考 Stoffregen 库) + int16_t z1 = (int16_t)xpt_cmd_read(0xB1); + int16_t z2 = (int16_t)xpt_cmd_read(0xC1); + int z = z1 + 4095; + z -= (int16_t)xpt_cmd_read(0x91); + + int16_t data[6] = {0, 0, 0, 0, 0, 0}; + if (z >= 300) { + (void)xpt_cmd_read(0x91); // dummy X + data[0] = (int16_t)xpt_cmd_read(0xD1); // Y + data[1] = (int16_t)xpt_cmd_read(0x91); // X + data[2] = (int16_t)xpt_cmd_read(0xD1); + data[3] = (int16_t)xpt_cmd_read(0x91); + } + data[4] = (int16_t)xpt_cmd_read(0xD0); // Y power down + data[5] = (int16_t)xpt_cmd_read(0x00); + digitalWrite(CYD_TOUCH_CS, HIGH); - return v; + + if (z < 300) { + return false; + } + + // 库内:x=avg(Y采样), y=avg(X采样) + const int16_t avg_y_cmd = best_two_avg(data[0], data[2], data[4]); + const int16_t avg_x_cmd = best_two_avg(data[1], data[3], data[5]); + + // setRotation(2) + *out_x = avg_x_cmd; + *out_y = 4095 - avg_y_cmd; + return true; } void touch_init() { @@ -46,23 +95,20 @@ void touch_init() { pinMode(CYD_TOUCH_IRQ, INPUT); digitalWrite(CYD_TOUCH_CS, HIGH); digitalWrite(CYD_TOUCH_CLK, LOW); - Serial.println("Touch: XPT2046 SoftSPI ready"); + Serial.println("Touch: SoftSPI calib = temperature map (rot2)"); } void touch_read_cb(lv_indev_t * /*indev*/, lv_indev_data_t *data) { - const bool irq = (digitalRead(CYD_TOUCH_IRQ) == LOW); - - uint16_t raw_x = xpt_read(0x90); - uint16_t raw_y = xpt_read(0xD0); - - if (!irq || raw_x < 80 || raw_y < 80 || raw_x > 4000 || raw_y > 4000) { + int16_t p_x = 0; + int16_t p_y = 0; + if (!touch_sample(&p_x, &p_y)) { data->state = LV_INDEV_STATE_RELEASED; return; } - // LV_DISPLAY_ROTATION_270 → 逻辑 320x240 - int16_t x = map((int)raw_y, 200, 3800, 0, UI_HOR_RES - 1); - int16_t y = map((int)raw_x, 240, 3700, 0, UI_VER_RES - 1); + // 与 temperature/src/main.cpp 完全一致(逻辑横屏 320x240) + int16_t x = map(p_y, 240, 3800, 1, UI_HOR_RES); + int16_t y = map(p_x, 200, 3700, UI_VER_RES, 1); if (x < 0) { x = 0;