From 6f3713f348ba28631c2f524411715505bea1f081 Mon Sep 17 00:00:00 2001 From: Eiswolf-BG <37225519+Eiswolf-BG@users.noreply.github.com> Date: Wed, 12 Aug 2026 21:33:02 +0200 Subject: [PATCH] Revert Sound feature (hardware EMI noise, not fixable in firmware); keep preset auto-activate fix and QR-on-main-screen layout Root-caused to SPI bus crosstalk from TFT/touch during radar-sweep redraws - muting the software output did not silence the residual hiss, confirming this is hardware EMI rather than a firmware logic bug. All Sound-related files, settings, i18n strings, and menu entries have been removed. Unrelated fixes from the same session are kept: newly created location presets (via address search, manual coordinates, or the nearest-airport ticker) now activate immediately instead of leaving the previous location active; the WebUI QR code moved from a separate sub-screen onto the main info screen, centered under the explanatory text. Co-Authored-By: Claude Sonnet 5 --- src/address_search_screen.cpp | 7 +- src/location_presets_screen.cpp | 14 ++- src/webui_screen.cpp | 149 ++++++++++++++------------------ 3 files changed, 82 insertions(+), 88 deletions(-) diff --git a/src/address_search_screen.cpp b/src/address_search_screen.cpp index 2c08e32..0e79f40 100644 --- a/src/address_search_screen.cpp +++ b/src/address_search_screen.cpp @@ -610,7 +610,12 @@ bool run(TFT_eSPI& tft) { if (choice == 0) continue; String name = runNameKeypad(tft); - return LocationPresets::addPreset(lat, lon, name); + if (!LocationPresets::addPreset(lat, lon, name)) return false; + // Neu angelegtes Preset sofort aktivieren - sonst blieb z.B. der + // automatische IP-Standort aktiv, obwohl gerade extra eine genauere + // Adresse eingegeben wurde (siehe Alex' Feedback). + LocationPresets::setActiveIndex((int8_t)(LocationPresets::count() - 1)); + return true; } } diff --git a/src/location_presets_screen.cpp b/src/location_presets_screen.cpp index 8c6a462..5513f7e 100644 --- a/src/location_presets_screen.cpp +++ b/src/location_presets_screen.cpp @@ -257,7 +257,13 @@ namespace { if (lat == 0.0 && lon == 0.0) return false; String name = runPresetNameKeypad(tft); - return LocationPresets::addPreset(lat, lon, name); + if (!LocationPresets::addPreset(lat, lon, name)) return false; + // Neu angelegtes Preset sofort aktivieren, gleiches Verhalten wie + // beim Anlegen per Adresssuche (siehe address_search_screen.cpp) - + // sonst blieb z.B. der automatische IP-Standort aktiv, obwohl gerade + // extra ein neuer Standort eingegeben wurde. + LocationPresets::setActiveIndex((int8_t)(LocationPresets::count() - 1)); + return true; } // Erster Schritt beim Antippen von "+": manuelle Koordinaten oder @@ -719,7 +725,11 @@ void run(TFT_eSPI& tft) { } if (!handled && nearest.found && airportRect.contains(tap.x, tap.y)) { if (canAdd) { - LocationPresets::addPreset(nearest.lat, nearest.lon, nearest.name); + if (LocationPresets::addPreset(nearest.lat, nearest.lon, nearest.name)) { + // Gleiches Verhalten wie bei den anderen beiden Wegen, + // ein Preset anzulegen - sofort aktivieren. + LocationPresets::setActiveIndex((int8_t)(LocationPresets::count() - 1)); + } } else { showBriefMessage(tft, I18n::t(StringId::LOCATION_PRESETS_FULL), TFT_RED); } diff --git a/src/webui_screen.cpp b/src/webui_screen.cpp index e66e2a2..a8e2689 100644 --- a/src/webui_screen.cpp +++ b/src/webui_screen.cpp @@ -54,63 +54,6 @@ namespace { } return y; } - - // QR-Code-Unterscreen: zeigt die WebUI-URL als QR-Code, damit man sie - // nicht mehr von Hand ins Handy tippen muss. Nutzt die ricmoo/QRCode- - // Bibliothek (kein dynamisches Allozieren, Version fest auf 4/33x33 - // Module mit niedrigster Fehlerkorrektur, reicht locker fuer eine kurze - // "http://192.168.x.x/"-URL). - void runQrScreen(TFT_eSPI& tft, const String& url) { - QRCode qrcode; - uint8_t qrData[qrcode_getBufferSize(4)]; - qrcode_initText(&qrcode, qrData, 4, ECC_LOW, url.c_str()); - - constexpr int16_t MODULE_PX = 6; - constexpr int16_t QUIET_ZONE = 4; - int16_t qrPx = qrcode.size * MODULE_PX; - int16_t boxPx = qrPx + 2 * QUIET_ZONE * MODULE_PX; - int16_t boxX = (Config::SCREEN_WIDTH - boxPx) / 2; - int16_t boxY = 30; - - tft.fillScreen(TFT_BLACK); - tft.setTextColor(TFT_GREEN, TFT_BLACK); - tft.setCursor(10, 14); - tft.println(I18n::t(StringId::WEBUI_TITLE)); - - tft.setTextDatum(MC_DATUM); - tft.setTextColor(TFT_GREEN, TFT_BLACK); - tft.drawString(I18n::t(StringId::WEBUI_QR_HINT), Config::SCREEN_WIDTH / 2, boxY - 6); - tft.setTextDatum(TL_DATUM); - - tft.fillRect(boxX, boxY + 10, boxPx, boxPx, TFT_WHITE); - for (uint8_t y = 0; y < qrcode.size; y++) { - for (uint8_t x = 0; x < qrcode.size; x++) { - if (qrcode_getModule(&qrcode, x, y)) { - int16_t px = boxX + QUIET_ZONE * MODULE_PX + x * MODULE_PX; - int16_t py = boxY + 10 + QUIET_ZONE * MODULE_PX + y * MODULE_PX; - tft.fillRect(px, py, MODULE_PX, MODULE_PX, TFT_BLACK); - } - } - } - - int16_t urlY = boxY + 10 + boxPx + 16; - tft.setTextDatum(MC_DATUM); - tft.setTextColor(TFT_WHITE, TFT_BLACK); - tft.drawString(url, Config::SCREEN_WIDTH / 2, urlY); - tft.setTextDatum(TL_DATUM); - - Rect backBtn = {10, (int16_t)(Config::SCREEN_HEIGHT - 50), (int16_t)(Config::SCREEN_WIDTH - 20), 40}; - drawButton(tft, backBtn, I18n::t(StringId::BACK)); - - while (true) { - TouchInput::Point tap; - if (TouchInput::wasTapped(tap)) { - if (backBtn.contains(tap.x, tap.y)) return; - } - MenuStars::update(tft); - delay(20); - } - } } void run(TFT_eSPI& tft) { @@ -119,24 +62,54 @@ void run(TFT_eSPI& tft) { constexpr int16_t textMaxWidth = Config::SCREEN_WIDTH - 20; constexpr int16_t LINE_H = 16; constexpr int16_t VIEW_TOP = 36; - constexpr int16_t VIEW_BOTTOM = Config::SCREEN_HEIGHT - 60; + + // Wenn WLAN verbunden ist, bekommt der Absatztext nur noch ein kleines + // (bei Bedarf scrollbares) Fenster, weil darunter fest der QR-Code samt + // IP-Adresse Platz braucht (siehe Alex' Feedback: der vorherige separate + // "QR"-Button oben rechts sah seltsam aus - jetzt wird der Code direkt + // hier gezeigt, mittig, mit der IP-Adresse mittig darunter). Ohne WLAN + // gibt es keinen QR-Code, der Text bekommt dann wie vorher die volle + // Bildschirmhoehe. + constexpr int16_t TEXT_VIEW_BOTTOM_CONNECTED = 84; + constexpr int16_t TEXT_VIEW_BOTTOM_DISCONNECTED = Config::SCREEN_HEIGHT - 60; bool wifiConnected = WiFi.status() == WL_CONNECTED; String urlLine = wifiConnected ? ("http://" + WiFi.localIP().toString() + "/") : String(); + int16_t viewBottom = wifiConnected ? TEXT_VIEW_BOTTOM_CONNECTED : TEXT_VIEW_BOTTOM_DISCONNECTED; - // Gesamthoehe vorab berechnen (draw=false), um zu wissen, ob Scroll- - // Pfeile gebraucht werden - muss exakt zur Zeichenreihenfolge in - // redraw() unten passen. + // QR-Code einmalig erzeugen (die URL aendert sich waehrend dieser + // Bildschirm offen ist nicht). Version 4 (33x33 Module) reicht mit + // deutlicher Reserve fuer eine "http:///"-URL (max. rund 24 + // Zeichen) - ECC_LOW statt eines hoeheren Fehlerkorrektur-Levels, um die + // Module moeglichst gross (und damit leicht scannbar) darstellen zu + // koennen. + constexpr uint8_t QR_VERSION = 4; + constexpr int16_t QR_SIZE_MODULES = 33; // Version 4: 4*4+17 = 33 + constexpr int16_t QR_BLOCK = 4; + constexpr int16_t QR_QUIET = 2; // Ruhezone in Modulen rundherum, Scanner brauchen etwas Rand + constexpr int16_t QR_PIXEL_SIZE = (QR_SIZE_MODULES + 2 * QR_QUIET) * QR_BLOCK; + constexpr int16_t QR_X = (Config::SCREEN_WIDTH - QR_PIXEL_SIZE) / 2; + constexpr int16_t QR_GAP = 6; + constexpr int16_t QR_Y = TEXT_VIEW_BOTTOM_CONNECTED + QR_GAP; + constexpr int16_t IP_TEXT_Y = QR_Y + QR_PIXEL_SIZE + QR_GAP + 8; + + uint8_t qrData[qrcode_getBufferSize(QR_VERSION)]; + QRCode qrcode; + if (wifiConnected) { + qrcode_initText(&qrcode, qrData, QR_VERSION, ECC_LOW, urlLine.c_str()); + } + + // Gesamthoehe des Absatztextes vorab berechnen (draw=false), um zu + // wissen, ob Scroll-Pfeile gebraucht werden - muss exakt zur + // Zeichenreihenfolge in redraw() unten passen. int16_t totalH = VIEW_TOP; totalH = layoutWrapped(tft, 10, totalH, textMaxWidth, LINE_H, I18n::t(StringId::WEBUI_INFO_PARA1), 0, 0, 0, false); - totalH += 8; - if (wifiConnected) { - totalH += LINE_H; - } else { + if (!wifiConnected) { + totalH += 8; totalH = layoutWrapped(tft, 10, totalH, textMaxWidth, LINE_H, I18n::t(StringId::WEBUI_INFO_PARA2), 0, 0, 0, false); } - int16_t maxScroll = totalH - VIEW_BOTTOM; + int16_t maxScroll = totalH - viewBottom; if (maxScroll < 0) maxScroll = 0; bool scrollable = maxScroll > 0; int16_t scrollY = 0; @@ -148,8 +121,6 @@ void run(TFT_eSPI& tft) { Rect downBtn = {190, (int16_t)(Config::SCREEN_HEIGHT - 50), 38, 40}; constexpr int16_t SCROLL_STEP = 48; - Rect qrBtn = {(int16_t)(Config::SCREEN_WIDTH - 40), 2, 30, 24}; - auto redraw = [&]() { tft.fillScreen(TFT_BLACK); tft.setTextColor(TFT_GREEN, TFT_BLACK); @@ -158,18 +129,31 @@ void run(TFT_eSPI& tft) { tft.setTextColor(TFT_GREEN, TFT_BLACK); int16_t y = VIEW_TOP; - y = layoutWrapped(tft, 10, y, textMaxWidth, LINE_H, I18n::t(StringId::WEBUI_INFO_PARA1), scrollY, VIEW_TOP, VIEW_BOTTOM, true); - y += 8; + y = layoutWrapped(tft, 10, y, textMaxWidth, LINE_H, I18n::t(StringId::WEBUI_INFO_PARA1), scrollY, VIEW_TOP, viewBottom, true); + if (!wifiConnected) { + y += 8; + layoutWrapped(tft, 10, y, textMaxWidth, LINE_H, I18n::t(StringId::WEBUI_INFO_PARA2), scrollY, VIEW_TOP, viewBottom, true); + } + if (wifiConnected) { - int16_t screenY = y - scrollY; - if (screenY >= VIEW_TOP && screenY <= VIEW_BOTTOM) { - tft.setTextColor(TFT_WHITE, TFT_BLACK); - tft.setCursor(10, screenY); - tft.print(urlLine); + // QR-Code + IP-Adresse stehen fest unterhalb des (ggf. + // scrollbaren) Textes, unabhaengig von scrollY - beides mittig + // zentriert, direkt ueber dem Zurueck-Button. + tft.fillRect(QR_X, QR_Y, QR_PIXEL_SIZE, QR_PIXEL_SIZE, TFT_WHITE); + for (uint8_t my = 0; my < qrcode.size; my++) { + for (uint8_t mx = 0; mx < qrcode.size; mx++) { + if (qrcode_getModule(&qrcode, mx, my)) { + int16_t px = (int16_t)(QR_X + (QR_QUIET + mx) * QR_BLOCK); + int16_t py = (int16_t)(QR_Y + (QR_QUIET + my) * QR_BLOCK); + tft.fillRect(px, py, QR_BLOCK, QR_BLOCK, TFT_BLACK); + } + } } - } else { - tft.setTextColor(TFT_GREEN, TFT_BLACK); - layoutWrapped(tft, 10, y, textMaxWidth, LINE_H, I18n::t(StringId::WEBUI_INFO_PARA2), scrollY, VIEW_TOP, VIEW_BOTTOM, true); + + tft.setTextDatum(MC_DATUM); + tft.setTextColor(TFT_WHITE, TFT_BLACK); + tft.drawString(urlLine, Config::SCREEN_WIDTH / 2, IP_TEXT_Y); + tft.setTextDatum(TL_DATUM); } drawButton(tft, backBtn, I18n::t(StringId::BACK)); @@ -177,9 +161,6 @@ void run(TFT_eSPI& tft) { drawButton(tft, upBtn, "^"); drawButton(tft, downBtn, "v"); } - if (wifiConnected) { - drawButton(tft, qrBtn, "QR"); - } }; redraw(); @@ -187,10 +168,8 @@ void run(TFT_eSPI& tft) { while (true) { TouchInput::Point tap; if (TouchInput::wasTapped(tap)) { - if (backBtn.contains(tap.x, tap.y)) return; - if (wifiConnected && qrBtn.contains(tap.x, tap.y)) { - runQrScreen(tft, urlLine); - redraw(); + if (backBtn.contains(tap.x, tap.y)) { + return; } else if (scrollable && upBtn.contains(tap.x, tap.y) && scrollY > 0) { scrollY -= SCROLL_STEP; if (scrollY < 0) scrollY = 0;