From caddd445bd5505d20003e8d4d870ad119981bae8 Mon Sep 17 00:00:00 2001 From: DeFiDude <59237470+DeFiDude@users.noreply.github.com> Date: Sun, 24 May 2026 00:11:23 -0600 Subject: [PATCH] radio: apply persisted LoRa config on boot --- src/main.cpp | 95 ++++++++++++++++++++++------- src/reticulum/ReticulumManager.cpp | 2 +- src/ui/screens/LvSettingsScreen.cpp | 23 ++++--- 3 files changed, 88 insertions(+), 32 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 908eee9..d1c80f2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -140,6 +140,34 @@ bool wifiSTAStarted = false; WiFiMulti wifiMulti; bool wifiSTAConnected = false; unsigned long lastAutoAnnounce = 0; +bool bootAnnouncePending = false; +uint8_t bootAnnounceAttempts = 0; +unsigned long bootAnnounceAt = 0; +constexpr unsigned long BOOT_ANNOUNCE_DELAY_MS = 5000; +constexpr uint8_t BOOT_ANNOUNCE_MAX_ATTEMPTS = 3; + +static void applyRadioSettingsToHardware(const UserSettings& s, const char* context) { + if (!radioOnline) return; + + if (!s.loraEnabled) { + radio.sleep(); + Serial.printf("[%s] LoRa disabled by config\n", context); + return; + } + + radio.setFrequency(s.loraFrequency); + radio.setSpreadingFactor(s.loraSF); + radio.setSignalBandwidth(s.loraBW); + radio.setCodingRate4(s.loraCR); + radio.setTxPower(s.loraTxPower); + radio.setPreambleLength(s.loraPreamble); + radio.receive(); + Serial.printf("[%s] Radio: %lu Hz, SF%d, BW%lu, CR4/%d, %d dBm, pre=%ld\n", + context, + (unsigned long)s.loraFrequency, s.loraSF, + (unsigned long)s.loraBW, s.loraCR, s.loraTxPower, + s.loraPreamble); +} // STA reconnects are scheduled from WiFi events and fired from loop(). std::atomic wifiNeedsReconnect{false}; @@ -230,7 +258,8 @@ RNS::Bytes encodeAnnounceName(const String& name) { static bool hasUsableAnnounceTransport() { if (!rns.isTransportActive()) return false; - if (radioOnline) return true; + auto* loraIf = rns.loraInterface(); + if (radioOnline && loraIf && loraIf->isOnline()) return true; if (wifiImpl && wifiImpl->isAPActive() && wifiImpl->getClientCount() > 0) return true; for (auto* tcp : tcpClients) { if (tcp && tcp->isConnected()) return true; @@ -805,6 +834,8 @@ static void bootRender() { // ============================================================================= void setup() { + bool flashMounted = false; + // Step 1: Power pin — CRITICAL: enables all T-Deck Plus peripherals Power::enablePeripherals(); @@ -850,20 +881,26 @@ void setup() { pinMode(LORA_CS, OUTPUT); digitalWrite(LORA_CS, HIGH); pinMode(SD_CS, OUTPUT); digitalWrite(SD_CS, HIGH); + // Mount flash before radio bring-up so persisted RF settings are used from + // the first SX1262 init, instead of always booting at the US default first. + Serial.println("[BOOT] Mounting flash for early config..."); + if (flash.begin()) { + flashMounted = true; + userConfig.load(flash); + } else { + Serial.println("[BOOT] Early flash mount failed; using default radio config"); + } + // Step 4: Radio + SD init BEFORE display // Radio and SD must init while SPIClass exclusively owns SPI2_HOST. // LovyanGFX's init() later joins the bus via spi_bus_add_device(). // This avoids any bus re-init dance that would invalidate device handles. Serial.println("[BOOT] Initializing radio..."); - if (radio.begin(LORA_DEFAULT_FREQ)) { - radio.setSpreadingFactor(LORA_DEFAULT_SF); - radio.setSignalBandwidth(LORA_DEFAULT_BW); - radio.setCodingRate4(LORA_DEFAULT_CR); - radio.setTxPower(LORA_DEFAULT_TX_POWER); - radio.setPreambleLength(LORA_DEFAULT_PREAMBLE); - radio.receive(); + if (radio.begin(userConfig.settings().loraFrequency)) { radioOnline = true; - Serial.println("[RADIO] SX1262 online at 915 MHz"); + applyRadioSettingsToHardware(userConfig.settings(), "RADIO"); + Serial.printf("[RADIO] SX1262 online at %lu Hz\n", + (unsigned long)userConfig.settings().loraFrequency); } else { Serial.println("[RADIO] SX1262 not detected!"); } @@ -971,10 +1008,13 @@ void setup() { // Step 12: Mount LittleFS lvBootScreen.setProgress(0.60f, "Mounting flash..."); // (LVGL boot renders via lv_timer_handler in setProgress) - if (!flash.begin()) { + if (flashMounted) { + Serial.println("[BOOT] LittleFS already mounted OK"); + } else if (!flash.begin()) { Serial.println("[BOOT] Flash init failed; automatic formatting disabled"); lvBootScreen.setProgress(0.62f, "Flash mount failed"); } else { + flashMounted = true; Serial.println("[BOOT] LittleFS mounted OK"); } @@ -995,6 +1035,7 @@ void setup() { lvBootScreen.setProgress(0.64f, "Loading config..."); userConfig.load(sdStore, flash); inputManager.setTrackballSpeed(userConfig.settings().trackballSpeed); + applyRadioSettingsToHardware(userConfig.settings(), "BOOT PRE-RNS"); lvBootScreen.setProgress(0.65f, "Starting Reticulum..."); // (LVGL boot renders via lv_timer_handler in setProgress) @@ -1077,17 +1118,7 @@ void setup() { // Step 21: Apply radio config if (radioOnline && userConfig.settings().loraEnabled) { - auto& s = userConfig.settings(); - radio.setFrequency(s.loraFrequency); - radio.setSpreadingFactor(s.loraSF); - radio.setSignalBandwidth(s.loraBW); - radio.setCodingRate4(s.loraCR); - radio.setTxPower(s.loraTxPower); - radio.setPreambleLength(s.loraPreamble); - radio.receive(); - Serial.printf("[BOOT] Radio: %lu Hz, SF%d, BW%lu, CR4/%d, %d dBm, pre=%ld\n", - (unsigned long)s.loraFrequency, s.loraSF, - (unsigned long)s.loraBW, s.loraCR, s.loraTxPower, s.loraPreamble); + applyRadioSettingsToHardware(userConfig.settings(), "BOOT"); ui.lvStatusBar().setLoRaOnline(true); } else if (radioOnline) { radio.sleep(); @@ -1482,7 +1513,10 @@ void setup() { ui.setBootMode(false); ui.setScreen(&lvHomeScreen); ui.lvTabBar().setActiveTab(LvTabBar::TAB_HOME); - Serial.println("[BOOT] Home ready; first auto announce after configured interval"); + bootAnnouncePending = true; + bootAnnounceAttempts = 0; + bootAnnounceAt = millis() + BOOT_ANNOUNCE_DELAY_MS; + Serial.println("[BOOT] Home ready; startup announce scheduled"); }; // Show timezone screen, then go home @@ -1689,6 +1723,23 @@ void loop() { lv_timer_handler(); } + if (bootComplete && bootAnnouncePending && (long)(millis() - bootAnnounceAt) >= 0) { + bootAnnounceAttempts++; + if (announceWithName(true)) { + bootAnnouncePending = false; + lastAutoAnnounce = millis(); + Serial.println("[BOOT] Startup announce sent"); + } else if (bootAnnounceAttempts < BOOT_ANNOUNCE_MAX_ATTEMPTS) { + bootAnnounceAt = millis() + BOOT_ANNOUNCE_DELAY_MS; + Serial.printf("[BOOT] Startup announce retry scheduled (%u/%u)\n", + (unsigned)bootAnnounceAttempts, + (unsigned)BOOT_ANNOUNCE_MAX_ATTEMPTS); + } else { + bootAnnouncePending = false; + Serial.println("[BOOT] Startup announce skipped after retries"); + } + } + // 5. Auto-announce every 30-360 minutes from boot. Manual announces do // not reset this schedule. const unsigned long announceInterval = (unsigned long)userConfig.settings().announceInterval * 60000; // m -> ms diff --git a/src/reticulum/ReticulumManager.cpp b/src/reticulum/ReticulumManager.cpp index 5e973aa..51bb0ed 100644 --- a/src/reticulum/ReticulumManager.cpp +++ b/src/reticulum/ReticulumManager.cpp @@ -208,7 +208,7 @@ bool ReticulumManager::begin(SX1262* radio, FlashStore* flash, bool loraEnabled) } if (loraEnabled) { - _loraImpl = new LoRaInterface(radio, "LoRa.915"); + _loraImpl = new LoRaInterface(radio, "LoRa"); _loraIface = _loraImpl; _loraIface.mode(RNS::Type::Interface::MODE_GATEWAY); RNS::Transport::register_interface(_loraIface); diff --git a/src/ui/screens/LvSettingsScreen.cpp b/src/ui/screens/LvSettingsScreen.cpp index 4f8d3ea..0bb2672 100644 --- a/src/ui/screens/LvSettingsScreen.cpp +++ b/src/ui/screens/LvSettingsScreen.cpp @@ -528,8 +528,9 @@ void LvSettingsScreen::buildItems() { regionItem.type = SettingType::ENUM_CHOICE; regionItem.getter = [&s]() { return (int)s.radioRegion; }; regionItem.setter = [this, &s](int v) { - s.radioRegion = constrain(v, 0, REGION_COUNT - 1); - if (_ui) _ui->lvStatusBar().showToast("Select a preset to apply frequency", 2500); + int region = constrain(v, 0, REGION_COUNT - 1); + s.radioRegion = region; + s.loraFrequency = REGION_FREQ[region]; }; regionItem.minVal = 0; regionItem.maxVal = REGION_COUNT - 1; regionItem.step = 1; regionItem.enumLabels = {REGION_LABELS[0], REGION_LABELS[1], REGION_LABELS[2], REGION_LABELS[3]}; @@ -2035,13 +2036,17 @@ void LvSettingsScreen::applyAndSave() { _power->setKbAutoOff(s.keyboardAutoOff); } if (_radio && _radio->isRadioOnline()) { - _radio->setFrequency(s.loraFrequency); - _radio->setTxPower(s.loraTxPower); - _radio->setSpreadingFactor(s.loraSF); - _radio->setSignalBandwidth(s.loraBW); - _radio->setCodingRate4(s.loraCR); - _radio->setPreambleLength(s.loraPreamble); - _radio->receive(); + if (s.loraEnabled) { + _radio->setFrequency(s.loraFrequency); + _radio->setTxPower(s.loraTxPower); + _radio->setSpreadingFactor(s.loraSF); + _radio->setSignalBandwidth(s.loraBW); + _radio->setCodingRate4(s.loraCR); + _radio->setPreambleLength(s.loraPreamble); + _radio->receive(); + } else { + _radio->sleep(); + } } if (_audio) { _audio->setEnabled(s.audioEnabled);