Skip to content

Commit 005ea00

Browse files
angeloINTJclaude
andcommitted
fix: AP mode touch detection and mandatory first-boot calibration
Bug fix — AP mode via touch: Add DisplayManager::beginTouch() which initializes the XPT2046 touch controller on Core 0 during boot, without needing Core 1 running. isScreenTouched() now polls hardware directly when _ts is available. This keeps the safe boot order: storage init (Core 1 off) → touch init → AP detection with working touch. Feature — mandatory calibration on first boot: When magic != 0xCA (factory reset or first boot), the full calibration flow runs before entering the dashboard: sensitivity threshold → 4-point position calibration × 2 cycles. Core 0 blocks until complete. The Cancel button during boot applies safe defaults and proceeds to dashboard instead of going to Settings. Calibration defaults tightened: xMin=300, xMax=3800, yMin=200, yMax=3700. Tests: 49/49 pass. All 3 sensor configs build. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 8d677dc commit 005ea00

4 files changed

Lines changed: 49 additions & 33 deletions

File tree

src/AppManager_Boot.cpp

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -157,13 +157,8 @@ void AppManager::setup( ) {
157157

158158
delay(BOOT_STEP_DELAY_MS);
159159

160-
_displayMgr->startCore1( );
161-
{
162-
unsigned long _wait_start = millis( );
163-
while (!_displayMgr->isCore1Ready( ) && millis( ) - _wait_start < 1500) {
164-
tight_loop_contents( );
165-
}
166-
}
160+
_displayMgr->beginTouch( );
161+
167162
bool forceAP = false;
168163
_displayMgr->setBootStatusKey(TR_BOOT_HOLD_AP);
169164

@@ -453,31 +448,28 @@ void AppManager::setup( ) {
453448
_displayMgr->loadTouchCalibration(cal);
454449

455450
if (!_displayMgr->isTouchCalibrated( )) {
456-
457-
/* Factory boot without saved calibration: apply safe default to
458-
* unblock boot. Without this, the calibration screen loop would
459-
* wait for 4 valid taps — and on XPT2046 with stuck-true touch
460-
* (this hardware) the loop is infinite or produces degenerate
461-
* calibration with identical coordinates. The user can recalibrate
462-
* later via Settings -> Touch Cal or via CLI.
463-
* Default range 200..3900 covers most XPT2046 panels. */
464-
Serial.printf("[BOOT] no touch cal saved (touch_settled=%d) — applying default\n",
465-
touch_settled ? 1 : 0);
466-
TouchCalData* calOut = reinterpret_cast<TouchCalData*>(cfg.reserved);
467-
calOut->magic = 0xCA;
468-
calOut->flags = 0;
469-
calOut->xMin = 300;
470-
calOut->xMax = 3800;
471-
calOut->yMin = 200;
472-
calOut->yMax = 3700;
473-
calOut->zThreshold = 400;
474-
_displayMgr->loadTouchCalibration(calOut);
475-
476-
_storageMgr->saveConfiguration( );
477-
478451
LOG_CODE(LOG_WARN, "APP", APP_TOUCH_CAL_REQUIRED, 0,
479-
TRL("Touch cal missing; default applied (recalibrate via Settings)"));
480-
452+
TRL("First boot — touch calibration required"));
453+
454+
_displayMgr->setBootStatusKey(TR_BOOT_TOUCH_CAL_REQ);
455+
_displayMgr->showTouchCalibration( );
456+
457+
/* Block Core 0 until user completes calibration on Core 1.
458+
* The calibration flow (sensitivity → 4-point position × 2 cycles)
459+
* runs entirely on Core 1. isTouchCalibrated() becomes true when
460+
* the position calibration is accepted (or the user cancels). */
461+
while (!_displayMgr->isTouchCalibrated( )) {
462+
delay(20);
463+
}
464+
465+
/* Persist the calibration result to flash. */
466+
TouchCalData calOut;
467+
_displayMgr->fillCalData(&calOut);
468+
memcpy(cfg.reserved, &calOut, sizeof(TouchCalData));
469+
_storageMgr->saveConfiguration( );
470+
471+
LOG_CODE(LOG_INFO, "APP", APP_TOUCH_CAL_REQUIRED, 0,
472+
TRL("Touch calibration completed"));
481473
}
482474
}
483475

src/DisplayManager.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,16 @@ bool DisplayManager::isSkipPressed( ) {
449449
return false;
450450
}
451451

452-
bool DisplayManager::isScreenTouched( ) { return _rawTouchState; }
452+
bool DisplayManager::isScreenTouched( ) {
453+
if (_ts) return _ts->touched( );
454+
return _rawTouchState;
455+
}
456+
457+
void DisplayManager::beginTouch( ) {
458+
if (!_ts) _ts = new XPT2046_Touchscreen(TOUCH_CS, TOUCH_IRQ);
459+
_ts->begin( );
460+
_ts->setRotation(3);
461+
}
453462

454463
/* Inject simulated touch for automation (screenshot capture).
455464
* Set flag + coords; Core 1 sees it on the next handleTouch iteration.

src/DisplayManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ class DisplayManager {
172172
bool isHeavyRendering( );
173173
bool isSkipPressed( );
174174
bool isScreenTouched( );
175+
void beginTouch( ); /**< Init touch controller on Core 0 for AP detection during boot. */
175176

176177

177178
void setWebBusy(bool busy, const char* username = nullptr);

src/DisplayManager_Touch.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,21 @@ void DisplayManager::handleTouch( ) {
148148
int16_t sx, sy;
149149
mapTouchPoint(p, sx, sy);
150150
if (sy > 195 && sx < 125) {
151-
if (acceptTouch(0)) { showSettingsMain( ); return; }
151+
if (acceptTouch(0)) {
152+
if (_sharedState.isBooting) {
153+
_calXMin = 300; _calXMax = 3800;
154+
_calYMin = 200; _calYMax = 3700;
155+
_sensZThreshold = 400;
156+
_calValid = true;
157+
_calSwapXY = false;
158+
_uiMode = MODE_DASHBOARD;
159+
_forceSettingsRedraw = true;
160+
_repaintSettings = true;
161+
} else {
162+
showSettingsMain( );
163+
}
164+
return;
165+
}
152166
}
153167
}
154168

0 commit comments

Comments
 (0)