Add touch buttons for speaker toggle and music playback.
Enable SoftSPI touch, replace auto beeps with Speaker ON/OFF and Play Music controls, and document usage. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
83
src/touch.cpp
Normal file
83
src/touch.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#include "touch.h"
|
||||
#include "pins.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
static void soft_spi_write(uint8_t data) {
|
||||
for (int i = 7; i >= 0; --i) {
|
||||
digitalWrite(TOUCH_MOSI, (data >> i) & 1);
|
||||
digitalWrite(TOUCH_CLK, HIGH);
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(TOUCH_CLK, LOW);
|
||||
delayMicroseconds(1);
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t soft_spi_read12() {
|
||||
uint16_t v = 0;
|
||||
for (int i = 0; i < 12; ++i) {
|
||||
digitalWrite(TOUCH_CLK, HIGH);
|
||||
delayMicroseconds(1);
|
||||
v = (v << 1) | (digitalRead(TOUCH_MISO) ? 1 : 0);
|
||||
digitalWrite(TOUCH_CLK, LOW);
|
||||
delayMicroseconds(1);
|
||||
}
|
||||
// 丢掉多余时钟位
|
||||
digitalWrite(TOUCH_CLK, HIGH);
|
||||
delayMicroseconds(1);
|
||||
digitalWrite(TOUCH_CLK, LOW);
|
||||
return v;
|
||||
}
|
||||
|
||||
static uint16_t xpt_read(uint8_t cmd) {
|
||||
digitalWrite(TOUCH_CS, LOW);
|
||||
soft_spi_write(cmd);
|
||||
delayMicroseconds(5);
|
||||
uint16_t v = soft_spi_read12();
|
||||
digitalWrite(TOUCH_CS, HIGH);
|
||||
return v;
|
||||
}
|
||||
|
||||
void touch_init() {
|
||||
pinMode(TOUCH_CS, OUTPUT);
|
||||
pinMode(TOUCH_CLK, OUTPUT);
|
||||
pinMode(TOUCH_MOSI, OUTPUT);
|
||||
pinMode(TOUCH_MISO, INPUT);
|
||||
pinMode(TOUCH_IRQ, INPUT);
|
||||
digitalWrite(TOUCH_CS, HIGH);
|
||||
digitalWrite(TOUCH_CLK, LOW);
|
||||
Serial.println("Touch: XPT2046 SoftSPI ready");
|
||||
}
|
||||
|
||||
void touch_read_cb(lv_indev_t * /*indev*/, lv_indev_data_t *data) {
|
||||
const bool irq = (digitalRead(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) {
|
||||
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);
|
||||
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
}
|
||||
if (x >= UI_HOR_RES) {
|
||||
x = UI_HOR_RES - 1;
|
||||
}
|
||||
if (y >= UI_VER_RES) {
|
||||
y = UI_VER_RES - 1;
|
||||
}
|
||||
|
||||
data->point.x = x;
|
||||
data->point.y = y;
|
||||
data->state = LV_INDEV_STATE_PRESSED;
|
||||
}
|
||||
Reference in New Issue
Block a user