feat: Add touch coordinate mapping and RTOS task yielding (#2481)

Co-authored-by: Julia Nguyen <julia@uxj.io>
This commit is contained in:
Justin Mitchell
2026-07-20 16:31:07 -04:00
committed by GitHub
co-authored by Julia Nguyen
parent c9188a7347
commit f42fab1c66
123 changed files with 3564 additions and 1380 deletions
+23 -19
View File
@@ -8,7 +8,6 @@
#include <WiFi.h>
#include <esp_efuse.h>
#include <esp_efuse_table.h>
#include <esp_task_wdt.h>
#include <algorithm>
#include <cctype>
@@ -26,6 +25,7 @@
#include "html/SettingsPageHtml.generated.h"
#include "html/js/jszip_minJs.generated.h"
#include "util/BookCacheUtils.h"
#include "util/TaskWatchdog.h"
namespace {
// Folders/files to hide from the web interface file browser
@@ -394,6 +394,8 @@ void CrossPointWebServer::handleStatus() const {
char snBuf[33] = {0};
bool valid = false;
#if !CONFIG_IDF_TARGET_ESP32
// Classic ESP32's efuse table has no USER_DATA block (C3/S3 only)
if (esp_efuse_read_field_blob(ESP_EFUSE_USER_DATA, snBuf, 256) == ESP_OK) {
valid = snBuf[0] != '\0' && snBuf[0] != (char)0xFF;
for (int i = 0; i < 32 && snBuf[i] != '\0'; i++) {
@@ -403,6 +405,7 @@ void CrossPointWebServer::handleStatus() const {
}
}
}
#endif
if (valid) {
doc["serial"] = snBuf;
@@ -466,8 +469,8 @@ void CrossPointWebServer::scanFiles(const char* path, const std::function<void(F
}
file.close();
yield(); // Yield to allow WiFi and other tasks to process during long scans
esp_task_wdt_reset(); // Reset watchdog to prevent timeout on large directories
yield(); // Yield to allow WiFi and other tasks to process during long scans
resetTaskWatchdogIfSubscribed(); // Reset watchdog to prevent timeout on large directories
file = root.openNextFile();
}
root.close();
@@ -598,7 +601,7 @@ void CrossPointWebServer::handleDownload() const {
size_t bytesRead = static_cast<size_t>(result);
size_t totalWritten = 0;
while (totalWritten < bytesRead) {
esp_task_wdt_reset();
resetTaskWatchdogIfSubscribed();
size_t wrote = client.write(buffer + totalWritten, bytesRead - totalWritten);
if (wrote == 0) {
downloadOk = false;
@@ -618,12 +621,12 @@ static size_t writeCount = 0;
static bool flushUploadBuffer(CrossPointWebServer::UploadState& state) {
if (state.bufferPos > 0 && state.file) {
esp_task_wdt_reset(); // Reset watchdog before potentially slow SD write
resetTaskWatchdogIfSubscribed(); // Reset watchdog before potentially slow SD write
const unsigned long writeStart = millis();
const size_t written = state.file.write(state.buffer.data(), state.bufferPos);
totalWriteTime += millis() - writeStart;
writeCount++;
esp_task_wdt_reset(); // Reset watchdog after SD write
resetTaskWatchdogIfSubscribed(); // Reset watchdog after SD write
if (written != state.bufferPos) {
LOG_DBG("WEB", "[UPLOAD] Buffer flush failed: expected %d, wrote %d", state.bufferPos, written);
@@ -639,7 +642,7 @@ void CrossPointWebServer::handleUpload(UploadState& state) const {
static size_t lastLoggedSize = 0;
// Reset watchdog at start of every upload callback - HTTP parsing can be slow
esp_task_wdt_reset();
resetTaskWatchdogIfSubscribed();
// Safety check: ensure server is still valid
if (!running || !server) {
@@ -651,7 +654,7 @@ void CrossPointWebServer::handleUpload(UploadState& state) const {
if (upload.status == UPLOAD_FILE_START) {
// Reset watchdog - this is the critical 1% crash point
esp_task_wdt_reset();
resetTaskWatchdogIfSubscribed();
state.fileName = upload.filename;
state.size = 0;
@@ -687,7 +690,8 @@ void CrossPointWebServer::handleUpload(UploadState& state) const {
if (!filePath.endsWith("/")) filePath += "/";
filePath += state.fileName;
esp_task_wdt_reset();
// Check if file already exists - SD operations can be slow
resetTaskWatchdogIfSubscribed();
if (Storage.exists(filePath.c_str())) {
state.error = "File already exists: " + state.fileName;
LOG_DBG("WEB", "[UPLOAD] Collision: %s", filePath.c_str());
@@ -695,13 +699,13 @@ void CrossPointWebServer::handleUpload(UploadState& state) const {
}
// Open file for writing - this can be slow due to FAT cluster allocation
esp_task_wdt_reset();
resetTaskWatchdogIfSubscribed();
if (!Storage.openFileForWrite("WEB", filePath, state.file)) {
state.error = "Failed to create file on SD card";
LOG_DBG("WEB", "[UPLOAD] FAILED to create file: %s", filePath.c_str());
return;
}
esp_task_wdt_reset();
resetTaskWatchdogIfSubscribed();
LOG_DBG("WEB", "[UPLOAD] File created successfully: %s", filePath.c_str());
} else if (upload.status == UPLOAD_FILE_WRITE) {
@@ -1638,7 +1642,7 @@ void CrossPointWebServer::onWebSocketEvent(uint8_t num, WStype_t type, uint8_t*
if (!filePath.endsWith("/")) filePath += "/";
filePath += wsUploadFileName;
esp_task_wdt_reset();
resetTaskWatchdogIfSubscribed();
if (Storage.exists(filePath.c_str())) {
LOG_DBG("WS", "Upload collision: %s", filePath.c_str());
wsServer->sendTXT(num, "ERROR:File already exists: " + wsUploadFileName);
@@ -1649,14 +1653,14 @@ void CrossPointWebServer::onWebSocketEvent(uint8_t num, WStype_t type, uint8_t*
filePath.c_str());
// Open file for writing
esp_task_wdt_reset();
resetTaskWatchdogIfSubscribed();
if (!Storage.openFileForWrite("WS", filePath, wsUploadFile)) {
wsServer->sendTXT(num, "ERROR:Failed to create file");
wsUploadInProgress = false;
wsUploadClientNum = 255;
return;
}
esp_task_wdt_reset();
resetTaskWatchdogIfSubscribed();
// Zero-byte upload: complete immediately without waiting for BIN frames
if (wsUploadSize == 0) {
@@ -1695,9 +1699,9 @@ void CrossPointWebServer::onWebSocketEvent(uint8_t num, WStype_t type, uint8_t*
wsServer->sendTXT(num, "ERROR:Upload overflow");
return;
}
esp_task_wdt_reset();
resetTaskWatchdogIfSubscribed();
size_t written = wsUploadFile.write(payload, length);
esp_task_wdt_reset();
resetTaskWatchdogIfSubscribed();
if (written != length) {
abortWsUpload("WS");
@@ -1801,7 +1805,7 @@ void CrossPointWebServer::handleFontUploadData() {
switch (upload.status) {
case UPLOAD_FILE_START: {
esp_task_wdt_reset();
resetTaskWatchdogIfSubscribed();
String family = server->arg("family");
fontUpload.file = HalFile();
fontUpload.familyName.clear();
@@ -1852,7 +1856,7 @@ void CrossPointWebServer::handleFontUploadData() {
case UPLOAD_FILE_WRITE: {
if (!fontUpload.valid) break;
esp_task_wdt_reset();
resetTaskWatchdogIfSubscribed();
// Validate magic bytes on first chunk only
if (!fontUpload.magicChecked && upload.currentSize >= 8) {
@@ -1879,7 +1883,7 @@ void CrossPointWebServer::handleFontUploadData() {
fontUpload.file.write(fontUpload.buffer.data(), fontUpload.bufferPos);
fontUpload.bytesWritten += fontUpload.bufferPos;
fontUpload.bufferPos = 0;
esp_task_wdt_reset();
resetTaskWatchdogIfSubscribed();
}
}
break;