#include "touch_input.h" #include "config.h" #include #include #include 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; } }