130 lines
3.4 KiB
C++
130 lines
3.4 KiB
C++
#include "touch_input.h"
|
|
#include "config.h"
|
|
#include <SPI.h>
|
|
#include <XPT2046_Touchscreen.h>
|
|
#include <SD.h>
|
|
|
|
namespace TouchInput {
|
|
|
|
namespace {
|
|
SPIClass touchSpi(VSPI);
|
|
XPT2046_Touchscreen touch(Config::TOUCH_CS_PIN, Config::TOUCH_IRQ_PIN);
|
|
|
|
constexpr int16_t MARGIN_PX = 24; // Abstand der Kalibrierungspunkte vom Rand
|
|
|
|
// Rohe Min/Max-Werte aus der Kalibrierung. Bis zur ersten Kalibrierung
|
|
// grosszuegige Standardwerte, damit die Kalibrierungs-Routine selbst schon
|
|
// grob nutzbare (wenn auch ungenaue) Koordinaten bekommt.
|
|
int16_t calXmin = 200;
|
|
int16_t calXmax = 3900;
|
|
int16_t calYmin = 200;
|
|
int16_t calYmax = 3900;
|
|
bool calibrationLoaded = false;
|
|
|
|
bool lastTouched = false;
|
|
Point lastRaw;
|
|
|
|
int16_t clampi(int16_t v, int16_t lo, int16_t hi) {
|
|
if (v < lo) return lo;
|
|
if (v > hi) return hi;
|
|
return v;
|
|
}
|
|
}
|
|
|
|
void begin() {
|
|
touchSpi.begin(Config::TOUCH_CLK_PIN, Config::TOUCH_MISO_PIN,
|
|
Config::TOUCH_MOSI_PIN, Config::TOUCH_CS_PIN);
|
|
touch.begin(touchSpi);
|
|
touch.setRotation(0);
|
|
}
|
|
|
|
bool hasCalibration() { return calibrationLoaded; }
|
|
|
|
void setCalibration(int16_t rawXmin, int16_t rawXmax, int16_t rawYmin, int16_t rawYmax) {
|
|
calXmin = rawXmin;
|
|
calXmax = rawXmax;
|
|
calYmin = rawYmin;
|
|
calYmax = rawYmax;
|
|
calibrationLoaded = true;
|
|
}
|
|
|
|
bool loadCalibration() {
|
|
if (!SD.exists(Config::SD_CALIBRATION_FILE)) return false;
|
|
|
|
File f = SD.open(Config::SD_CALIBRATION_FILE, FILE_READ);
|
|
if (!f) return false;
|
|
|
|
String line = f.readStringUntil('\n');
|
|
f.close();
|
|
line.trim();
|
|
|
|
int p1 = line.indexOf(',');
|
|
int p2 = line.indexOf(',', p1 + 1);
|
|
int p3 = line.indexOf(',', p2 + 1);
|
|
if (p1 < 0 || p2 < 0 || p3 < 0) return false;
|
|
|
|
int16_t xmin = line.substring(0, p1).toInt();
|
|
int16_t xmax = line.substring(p1 + 1, p2).toInt();
|
|
int16_t ymin = line.substring(p2 + 1, p3).toInt();
|
|
int16_t ymax = line.substring(p3 + 1).toInt();
|
|
|
|
if (xmax <= xmin || ymax <= ymin) return false;
|
|
|
|
setCalibration(xmin, xmax, ymin, ymax);
|
|
return true;
|
|
}
|
|
|
|
void saveCalibration() {
|
|
File f = SD.open(Config::SD_CALIBRATION_FILE, FILE_WRITE);
|
|
if (!f) return;
|
|
f.printf("%d,%d,%d,%d\n", calXmin, calXmax, calYmin, calYmax);
|
|
f.close();
|
|
}
|
|
|
|
Point rawPoint() {
|
|
Point p;
|
|
p.touched = touch.touched();
|
|
if (p.touched) {
|
|
TS_Point raw = touch.getPoint();
|
|
p.x = raw.x;
|
|
p.y = raw.y;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
Point mappedPoint() {
|
|
Point raw = rawPoint();
|
|
Point out;
|
|
out.touched = raw.touched;
|
|
if (!raw.touched) return out;
|
|
|
|
long mx = map((long)raw.x, calXmin, calXmax, MARGIN_PX, Config::SCREEN_WIDTH - MARGIN_PX);
|
|
long my = map((long)raw.y, calYmin, calYmax, MARGIN_PX, Config::SCREEN_HEIGHT - MARGIN_PX);
|
|
|
|
out.x = clampi((int16_t)mx, 0, Config::SCREEN_WIDTH - 1);
|
|
out.y = clampi((int16_t)my, 0, Config::SCREEN_HEIGHT - 1);
|
|
|
|
if (Config::DISPLAY_ROTATION == 2) {
|
|
out.x = Config::SCREEN_WIDTH - 1 - out.x;
|
|
out.y = Config::SCREEN_HEIGHT - 1 - out.y;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
bool wasTapped(Point& outPoint) {
|
|
Point cur = mappedPoint();
|
|
|
|
bool fired = false;
|
|
if (!cur.touched && lastTouched) {
|
|
// Loslassen erkannt -> Tap an der zuletzt bekannten Position melden.
|
|
outPoint = lastRaw;
|
|
fired = true;
|
|
}
|
|
|
|
lastTouched = cur.touched;
|
|
if (cur.touched) lastRaw = cur;
|
|
|
|
return fired;
|
|
}
|
|
|
|
} |