From daa4d387c605295d1c161d7eab01e204095c9519 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Thu, 28 Mar 2024 18:14:15 -0500 Subject: [PATCH 001/108] Don't reboot for non-radio lora config changes (#3505) --- src/PowerFSM.cpp | 1 - src/modules/AdminModule.cpp | 17 ++++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 5d86987df..b6e267e28 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -246,7 +246,6 @@ Fsm powerFSM(&stateBOOT); void PowerFSM_setup() { bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0); - bool isInfrastructureRole = isRouter || config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER; bool isTrackerOrSensor = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER || config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER || config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR; diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 2c04916dd..b40633af0 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -336,6 +336,7 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) auto changes = SEGMENT_CONFIG; auto existingRole = config.device.role; bool isRegionUnset = (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET); + bool requiresReboot = true; switch (c.which_payload_variant) { case meshtastic_Config_device_tag: @@ -375,7 +376,21 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) case meshtastic_Config_lora_tag: LOG_INFO("Setting config: LoRa\n"); config.has_lora = true; + // If no lora radio parameters change, don't need to reboot + if (config.lora.use_preset == c.payload_variant.lora.use_preset && config.lora.region == c.payload_variant.lora.region && + config.lora.modem_preset == c.payload_variant.lora.modem_preset && + config.lora.bandwidth == c.payload_variant.lora.bandwidth && + config.lora.spread_factor == c.payload_variant.lora.spread_factor && + config.lora.coding_rate == c.payload_variant.lora.coding_rate && + config.lora.tx_power == c.payload_variant.lora.tx_power && + config.lora.frequency_offset == c.payload_variant.lora.frequency_offset && + config.lora.override_frequency == c.payload_variant.lora.override_frequency && + config.lora.channel_num == c.payload_variant.lora.channel_num && + config.lora.sx126x_rx_boosted_gain == c.payload_variant.lora.sx126x_rx_boosted_gain) { + requiresReboot = false; + } config.lora = c.payload_variant.lora; + // If we're setting region for the first time, init the region if (isRegionUnset && config.lora.region > meshtastic_Config_LoRaConfig_RegionCode_UNSET) { config.lora.tx_enabled = true; initRegion(); @@ -395,7 +410,7 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) break; } - saveChanges(changes); + saveChanges(changes, requiresReboot); } void AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c) From 8187fa7115c928e32417a056bf10efd86f512395 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Fri, 29 Mar 2024 12:31:11 +1300 Subject: [PATCH 002/108] E-Ink Screensaver (#3477) * fix Wireless Paper double-clear screen at boot * log when flooded with "responsive" frames * show the "resuming" screen when waking from deep-sleep * rename drawDeepSleepScreen avoid future confusion with "Screen Paused" screen * show a screensaver frame when screen off The frame shown during deep sleep is now also passed through showScreensaverFrames() * Add macros for E-Ink color values. OLEDDISPLAY_COLOR is inverted. Result of light-mode on E-Ink vs dark-mode on OLED? * adapt drawDeepSleepScreen to new screensaver convention * Mark Wireless Paper V1.1 as having problems with ghosting Any other issues can be marked in a similar way, then handled in code where relevant * Change screensaver from fullscreen logo to overlay * identify "quirks" rather than "problems" * move async refresh polling from display() to a NotifiedWorkerThread * Prevent skipping of deep-sleep screen (Hopefully) * Redesign screensaver overlay Now displays short name * Optimize refresh for different displays * Support older EInkDisplay class * Don't assume text alignment * fix spelling of a quirk macro (No impact to code, but avoids future issues) * Handle impossibly unlikely millis() overflow error Should have just let it go, but here we are.. --------- Co-authored-by: Ben Meadors --- src/graphics/EInkDisplay2.cpp | 1 - src/graphics/EInkDynamicDisplay.cpp | 62 ++++++--- src/graphics/EInkDynamicDisplay.h | 35 +++-- src/graphics/Screen.cpp | 125 ++++++++++++++++-- src/graphics/Screen.h | 19 ++- variants/heltec_wireless_paper/platformio.ini | 2 + .../heltec_wireless_paper_v1/platformio.ini | 3 +- 7 files changed, 204 insertions(+), 43 deletions(-) diff --git a/src/graphics/EInkDisplay2.cpp b/src/graphics/EInkDisplay2.cpp index 6f7885b45..0c5fab4fb 100644 --- a/src/graphics/EInkDisplay2.cpp +++ b/src/graphics/EInkDisplay2.cpp @@ -184,7 +184,6 @@ bool EInkDisplay::connect() // Init GxEPD2 adafruitDisplay->init(); adafruitDisplay->setRotation(3); - adafruitDisplay->clearScreen(); // Clearing now, so the boot logo will draw nice and smoothe (fast refresh) } #elif defined(PCA10059) { diff --git a/src/graphics/EInkDynamicDisplay.cpp b/src/graphics/EInkDynamicDisplay.cpp index 732f6d3fb..f61cf891e 100644 --- a/src/graphics/EInkDynamicDisplay.cpp +++ b/src/graphics/EInkDynamicDisplay.cpp @@ -5,7 +5,7 @@ // Constructor EInkDynamicDisplay::EInkDynamicDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus) - : EInkDisplay(address, sda, scl, geometry, i2cBus) + : EInkDisplay(address, sda, scl, geometry, i2cBus), NotifiedWorkerThread("EInkDynamicDisplay") { // If tracking ghost pixels, grab memory #ifdef EINK_LIMIT_GHOSTING_PX @@ -112,12 +112,15 @@ void EInkDynamicDisplay::endOrDetach() // If the GxEPD2 version reports that it has the async modifications #ifdef HAS_EINK_ASYNCFULL if (previousRefresh == FULL) { - asyncRefreshRunning = true; // Set the flag - picked up at start of determineMode(), next loop. + asyncRefreshRunning = true; // Set the flag - checked in determineMode(); cleared by onNotify() if (previousFrameFlags & BLOCKING) awaitRefresh(); - else - LOG_DEBUG("Async full-refresh begins\n"); + else { + // Async begins + LOG_DEBUG("Async full-refresh begins (dropping frames)\n"); + notifyLater(intervalPollAsyncRefresh, DUE_POLL_ASYNCREFRESH, true); // Hand-off to NotifiedWorkerThread + } } // Fast Refresh @@ -141,7 +144,7 @@ bool EInkDynamicDisplay::determineMode() checkInitialized(); checkForPromotion(); #if defined(HAS_EINK_ASYNCFULL) - checkAsyncFullRefresh(); + checkBusyAsyncRefresh(); #endif checkRateLimiting(); @@ -252,6 +255,7 @@ void EInkDynamicDisplay::checkRateLimiting() if (now - previousRunMs < EINK_LIMIT_RATE_RESPONSIVE_SEC * 1000) { refresh = SKIPPED; reason = EXCEEDED_RATELIMIT_FAST; + LOG_DEBUG("refresh=SKIPPED, reason=EXCEEDED_RATELIMIT_FAST, frameFlags=0x%x\n", frameFlags); return; } } @@ -447,9 +451,44 @@ void EInkDynamicDisplay::resetGhostPixelTracking() } #endif // EINK_LIMIT_GHOSTING_PX +// Handle any asyc tasks +void EInkDynamicDisplay::onNotify(uint32_t notification) +{ + // Which task + switch (notification) { + case DUE_POLL_ASYNCREFRESH: + pollAsyncRefresh(); + break; + } +} + #ifdef HAS_EINK_ASYNCFULL -// Check the status of an "async full-refresh", and run the finish-up code if the hardware is ready -void EInkDynamicDisplay::checkAsyncFullRefresh() +// Run the post-update code if the hardware is ready +void EInkDynamicDisplay::pollAsyncRefresh() +{ + // We shouldn't be here.. + if (!asyncRefreshRunning) + return; + + // Still running, check back later + if (adafruitDisplay->epd2.isBusy()) { + // Schedule next call of pollAsyncRefresh() + NotifiedWorkerThread::notifyLater(intervalPollAsyncRefresh, DUE_POLL_ASYNCREFRESH, true); + return; + } + + // If asyncRefreshRunning flag is still set, but display's BUSY pin reports the refresh is done + adafruitDisplay->endAsyncFull(); // Run the end of nextPage() code + EInkDisplay::endUpdate(); // Run base-class code to finish off update (NOT our derived class override) + asyncRefreshRunning = false; // Unset the flag + LOG_DEBUG("Async full-refresh complete\n"); + + // Note: this code only works because of a modification to meshtastic/GxEPD2. + // It is only equipped to intercept calls to nextPage() +} + +// Check the status of "async full-refresh"; skip if running +void EInkDynamicDisplay::checkBusyAsyncRefresh() { // No refresh taking place, continue with determineMode() if (!asyncRefreshRunning) @@ -472,15 +511,6 @@ void EInkDynamicDisplay::checkAsyncFullRefresh() return; } - - // If we asyncRefreshRunning flag is still set, but display's BUSY pin reports the refresh is done - adafruitDisplay->endAsyncFull(); // Run the end of nextPage() code - EInkDisplay::endUpdate(); // Run base-class code to finish off update (NOT our derived class override) - asyncRefreshRunning = false; // Unset the flag - LOG_DEBUG("Async full-refresh complete\n"); - - // Note: this code only works because of a modification to meshtastic/GxEPD2. - // It is only equipped to intercept calls to nextPage() } // Hold control while an async refresh runs diff --git a/src/graphics/EInkDynamicDisplay.h b/src/graphics/EInkDynamicDisplay.h index 81963df58..39953b62a 100644 --- a/src/graphics/EInkDynamicDisplay.h +++ b/src/graphics/EInkDynamicDisplay.h @@ -6,6 +6,7 @@ #include "EInkDisplay2.h" #include "GxEPD2_BW.h" +#include "concurrency/NotifiedWorkerThread.h" /* Derives from the EInkDisplay adapter class. @@ -14,7 +15,7 @@ (Full, Fast, Skip) */ -class EInkDynamicDisplay : public EInkDisplay +class EInkDynamicDisplay : public EInkDisplay, protected concurrency::NotifiedWorkerThread { public: // Constructor @@ -61,13 +62,20 @@ class EInkDynamicDisplay : public EInkDisplay REDRAW_WITH_FULL, }; - void configForFastRefresh(); // GxEPD2 code to set fast-refresh - void configForFullRefresh(); // GxEPD2 code to set full-refresh - bool determineMode(); // Assess situation, pick a refresh type - void applyRefreshMode(); // Run any relevant GxEPD2 code, so next update will use correct refresh type - void adjustRefreshCounters(); // Update fastRefreshCount - bool update(); // Trigger the display update - determine mode, then call base class - void endOrDetach(); // Run the post-update code, or delegate it off to checkAsyncFullRefresh() + enum notificationTypes : uint8_t { // What was onNotify() called for + NONE = 0, // This behavior (NONE=0) is fixed by NotifiedWorkerThread class + DUE_POLL_ASYNCREFRESH = 1, + }; + const uint32_t intervalPollAsyncRefresh = 100; + + void onNotify(uint32_t notification) override; // Handle any async tasks - overrides NotifiedWorkerThread + void configForFastRefresh(); // GxEPD2 code to set fast-refresh + void configForFullRefresh(); // GxEPD2 code to set full-refresh + bool determineMode(); // Assess situation, pick a refresh type + void applyRefreshMode(); // Run any relevant GxEPD2 code, so next update will use correct refresh type + void adjustRefreshCounters(); // Update fastRefreshCount + bool update(); // Trigger the display update - determine mode, then call base class + void endOrDetach(); // Run the post-update code, or delegate it off to checkBusyAsyncRefresh() // Checks as part of determineMode() void checkInitialized(); // Is this the very first frame? @@ -111,10 +119,13 @@ class EInkDynamicDisplay : public EInkDisplay // Conditional - async full refresh - only with modified meshtastic/GxEPD2 #if defined(HAS_EINK_ASYNCFULL) - void checkAsyncFullRefresh(); // Check the status of "async full-refresh"; run the post-update code if the hardware is ready - void awaitRefresh(); // Hold control while an async refresh runs - void endUpdate() override {} // Disable base-class behavior of running post-update immediately after forceDisplay() - bool asyncRefreshRunning = false; // Flag, checked by checkAsyncFullRefresh() + void pollAsyncRefresh(); // Run the post-update code if the hardware is ready + void checkBusyAsyncRefresh(); // Check if display is busy running an async full-refresh (rejecting new frames) + void awaitRefresh(); // Hold control while an async refresh runs + void endUpdate() override {} // Disable base-class behavior of running post-update immediately after forceDisplay() + bool asyncRefreshRunning = false; // Flag, checked by checkBusyAsyncRefresh() +#else + void pollAsyncRefresh() {} // Dummy method. In theory, not reachable #endif }; diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 2453faec9..52829d1f7 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -262,14 +262,65 @@ static void drawWelcomeScreen(OLEDDisplay *display, OLEDDisplayUiState *state, i #ifdef USE_EINK /// Used on eink displays while in deep sleep -static void drawSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) +static void drawDeepSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { // Next frame should use full-refresh, and block while running, else device will sleep before async callback EINK_ADD_FRAMEFLAG(display, COSMETIC); EINK_ADD_FRAMEFLAG(display, BLOCKING); + LOG_DEBUG("Drawing deep sleep screen\n"); drawIconScreen("Sleeping...", display, state, x, y); } + +/// Used on eink displays when screen updates are paused +static void drawScreensaverOverlay(OLEDDisplay *display, OLEDDisplayUiState *state) +{ + LOG_DEBUG("Drawing screensaver overlay\n"); + + EINK_ADD_FRAMEFLAG(display, COSMETIC); // Take the opportunity for a full-refresh + + // Config + display->setFont(FONT_SMALL); + display->setTextAlignment(TEXT_ALIGN_LEFT); + const char *pauseText = "Screen Paused"; + const char *idText = owner.short_name; + constexpr uint16_t padding = 5; + constexpr uint8_t dividerGap = 1; + constexpr uint8_t imprecision = 5; // How far the box origins can drift from center. Combat burn-in. + + // Dimensions + const uint16_t idTextWidth = display->getStringWidth(idText, strlen(idText)); + const uint16_t pauseTextWidth = display->getStringWidth(pauseText, strlen(pauseText)); + const uint16_t boxWidth = padding + idTextWidth + padding + padding + pauseTextWidth + padding; + const uint16_t boxHeight = padding + FONT_HEIGHT_SMALL + padding; + + // Position + const int16_t boxLeft = (display->width() / 2) - (boxWidth / 2) + random(-imprecision, imprecision + 1); + // const int16_t boxRight = boxLeft + boxWidth - 1; + const int16_t boxTop = (display->height() / 2) - (boxHeight / 2 + random(-imprecision, imprecision + 1)); + const int16_t boxBottom = boxTop + boxHeight - 1; + const int16_t idTextLeft = boxLeft + padding; + const int16_t idTextTop = boxTop + padding; + const int16_t pauseTextLeft = boxLeft + padding + idTextWidth + padding + padding; + const int16_t pauseTextTop = boxTop + padding; + const int16_t dividerX = boxLeft + padding + idTextWidth + padding; + const int16_t dividerTop = boxTop + 1 + dividerGap; + const int16_t dividerBottom = boxBottom - 1 - dividerGap; + + // Draw: box + display->setColor(EINK_WHITE); + display->fillRect(boxLeft - 1, boxTop - 1, boxWidth + 2, boxHeight + 2); // Clear a slightly oversized area for the box + display->setColor(EINK_BLACK); + display->drawRect(boxLeft, boxTop, boxWidth, boxHeight); + + // Draw: Text + display->drawString(idTextLeft, idTextTop, idText); + display->drawString(pauseTextLeft, pauseTextTop, pauseText); + display->drawString(pauseTextLeft + 1, pauseTextTop, pauseText); // Faux bold + + // Draw: divider + display->drawLine(dividerX, dividerTop, dividerX, dividerBottom); +} #endif static void drawModuleFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) @@ -948,18 +999,17 @@ Screen::~Screen() void Screen::doDeepSleep() { #ifdef USE_EINK - static FrameCallback sleepFrames[] = {drawSleepScreen}; - static const int sleepFrameCount = sizeof(sleepFrames) / sizeof(sleepFrames[0]); - ui->setFrames(sleepFrames, sleepFrameCount); - ui->update(); + setOn(false, drawDeepSleepScreen); #ifdef PIN_EINK_EN digitalWrite(PIN_EINK_EN, LOW); // power off backlight #endif -#endif +#else + // Without E-Ink display: setOn(false); +#endif } -void Screen::handleSetOn(bool on) +void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) { if (!useDisplay) return; @@ -978,6 +1028,10 @@ void Screen::handleSetOn(bool on) setInterval(0); // Draw ASAP runASAP = true; } else { +#ifdef USE_EINK + // eInkScreensaver parameter is usually NULL (default argument), default frame used instead + setScreensaverFrames(einkScreensaver); +#endif LOG_INFO("Turning off screen\n"); dispdev->displayOff(); #ifdef T_WATCH_S3 @@ -1028,6 +1082,7 @@ void Screen::setup() logo_timeout *= 2; // Add frames. + EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); static FrameCallback bootFrames[] = {drawBootScreen}; static const int bootFrameCount = sizeof(bootFrames) / sizeof(bootFrames[0]); ui->setFrames(bootFrames, bootFrameCount); @@ -1283,6 +1338,58 @@ void Screen::setWelcomeFrames() } } +#ifdef USE_EINK +/// Determine which screensaver frame to use, then set the FrameCallback +void Screen::setScreensaverFrames(FrameCallback einkScreensaver) +{ + // Remember current frame, restore position at power-on + uint8_t frameNumber = ui->getUiState()->currentFrame; + + // Retain specified frame / overlay callback beyond scope of this method + static FrameCallback screensaverFrame; + static OverlayCallback screensaverOverlay; + + // If: one-off screensaver frame passed as argument. Handles doDeepSleep() + if (einkScreensaver != NULL) { + screensaverFrame = einkScreensaver; + ui->setFrames(&screensaverFrame, 1); + } + + // Else, display the usual "overlay" screensaver + else { + screensaverOverlay = drawScreensaverOverlay; + ui->setOverlays(&screensaverOverlay, 1); + } + + // Request new frame, ASAP + setFastFramerate(); + uint64_t startUpdate; + do { + startUpdate = millis(); // Handle impossibly unlikely corner case of a millis() overflow.. + delay(1); + ui->update(); + } while (ui->getUiState()->lastUpdate < startUpdate); + +#ifndef USE_EINK_DYNAMICDISPLAY + // Retrofit to EInkDisplay class + delay(10); + screen->forceDisplay(); +#endif + + // Prepare now for next frame, shown when display wakes + ui->setOverlays(NULL, 0); // Clear overlay + setFrames(); // Return to normal display updates + ui->switchToFrame(frameNumber); // Attempt to return to same frame after power-on + + // Pick a refresh method, for when display wakes +#ifdef EINK_HASQUIRK_GHOSTING + EINK_ADD_FRAMEFLAG(dispdev, COSMETIC); // Really ugly to see ghosting from "screen paused" +#else + EINK_ADD_FRAMEFLAG(dispdev, RESPONSIVE); // Really nice to wake screen with a fast-refresh +#endif +} +#endif + // restore our regular frame list void Screen::setFrames() { @@ -1383,7 +1490,8 @@ void Screen::handleShutdownScreen() { LOG_DEBUG("showing shutdown screen\n"); showingNormalScreen = false; - EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // E-Ink: Explicitly use fast-refresh for next frame + EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // E-Ink: Use fast-refresh for next frame, no skip please + EINK_ADD_FRAMEFLAG(dispdev, BLOCKING); // Edge case: if this frame is promoted to COSMETIC, wait for update auto frame = [](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void { drawFrameText(display, state, x, y, "Shutting down..."); @@ -1391,6 +1499,7 @@ void Screen::handleShutdownScreen() static FrameCallback frames[] = {frame}; setFrameImmediateDraw(frames); + forceDisplay(); } void Screen::handleRebootScreen() diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index a66cc44ec..971146012 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -73,6 +73,10 @@ class Screen #define MILES_TO_FEET 5280 #endif +// Intuitive colors. E-Ink display is inverted from OLED(?) +#define EINK_BLACK OLEDDISPLAY_COLOR::WHITE +#define EINK_WHITE OLEDDISPLAY_COLOR::BLACK + namespace graphics { @@ -139,12 +143,12 @@ class Screen : public concurrency::OSThread // Not thread safe - must be called before any other methods are called. void setup(); - /// Turns the screen on/off. - void setOn(bool on) + /// Turns the screen on/off. Optionally, pass a custom screensaver frame for E-Ink + void setOn(bool on, FrameCallback einkScreensaver = NULL) { if (!on) - handleSetOn( - false); // We handle off commands immediately, because they might be called because the CPU is shutting down + // We handle off commands immediately, because they might be called because the CPU is shutting down + handleSetOn(false, einkScreensaver); else enqueueCmd(ScreenCmd{.cmd = on ? Cmd::SET_ON : Cmd::SET_OFF}); } @@ -321,6 +325,11 @@ class Screen : public concurrency::OSThread void setWelcomeFrames(); +#ifdef USE_EINK + /// Draw an image to remain on E-Ink display after screen off + void setScreensaverFrames(FrameCallback einkScreensaver = NULL); +#endif + protected: /// Updates the UI. // @@ -351,7 +360,7 @@ class Screen : public concurrency::OSThread } // Implementations of various commands, called from doTask(). - void handleSetOn(bool on); + void handleSetOn(bool on, FrameCallback einkScreensaver = NULL); void handleOnPress(); void handleShowNextFrame(); void handleShowPrevFrame(); diff --git a/variants/heltec_wireless_paper/platformio.ini b/variants/heltec_wireless_paper/platformio.ini index 1e1bb9376..d7aac5e22 100644 --- a/variants/heltec_wireless_paper/platformio.ini +++ b/variants/heltec_wireless_paper/platformio.ini @@ -14,6 +14,8 @@ build_flags = -D EINK_LIMIT_RATE_RESPONSIVE_SEC=1 ; Minimum interval between RESPONSIVE updates -D EINK_LIMIT_GHOSTING_PX=2000 ; (Optional) How much image ghosting is tolerated -D EINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached. + -D EINK_HASQUIRK_GHOSTING ; Display model is identified as "prone to ghosting" + -D EINK_HASQUIRK_WEAKFASTREFRESH ; Pixels set with fast-refresh are easy to clear, disrupted by sunlight lib_deps = ${esp32s3_base.lib_deps} https://github.com/meshtastic/GxEPD2#55f618961db45a23eff0233546430f1e5a80f63a diff --git a/variants/heltec_wireless_paper_v1/platformio.ini b/variants/heltec_wireless_paper_v1/platformio.ini index cae1940b3..999f1586a 100644 --- a/variants/heltec_wireless_paper_v1/platformio.ini +++ b/variants/heltec_wireless_paper_v1/platformio.ini @@ -13,7 +13,8 @@ build_flags = -D EINK_LIMIT_RATE_BACKGROUND_SEC=30 ; Minimum interval between BACKGROUND updates -D EINK_LIMIT_RATE_RESPONSIVE_SEC=1 ; Minimum interval between RESPONSIVE updates -D EINK_LIMIT_GHOSTING_PX=2000 ; (Optional) How much image ghosting is tolerated - ;-D EINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached. + ;-D EINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached. + -D EINK_HASQUIRK_VICIOUSFASTREFRESH ; Identify that pixels drawn by fast-refresh are harder to clear lib_deps = ${esp32s3_base.lib_deps} https://github.com/meshtastic/GxEPD2#55f618961db45a23eff0233546430f1e5a80f63a From 7b391d1a9f36ee387cf6a81d748f47ab70f6cef3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 28 Mar 2024 19:27:34 -0500 Subject: [PATCH 003/108] [create-pull-request] automated change (#3507) Co-authored-by: thebentern --- version.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.properties b/version.properties index 58a6c19d7..5f162b8ae 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 3 -build = 3 +build = 4 From 64fd8664942ca272104059c3976896ff417b2cd4 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Fri, 29 Mar 2024 00:03:19 -0500 Subject: [PATCH 004/108] Make native honor HAS_SCREEN 0 (#3509) This allows easier building of the native target without the LovyanGFX libraries. --- src/graphics/TFTDisplay.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index 9475e0296..79f521fbb 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -333,7 +333,7 @@ static LGFX *tft = nullptr; #include // Graphics and font library for ILI9341 driver chip static TFT_eSPI *tft = nullptr; // Invoke library, pins defined in User_Setup.h -#elif ARCH_PORTDUINO +#elif ARCH_PORTDUINO && HAS_SCREEN != 0 #include // Graphics and font library for ST7735 driver chip class LGFX : public lgfx::LGFX_Device @@ -404,7 +404,8 @@ class LGFX : public lgfx::LGFX_Device static LGFX *tft = nullptr; #endif -#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || ARCH_PORTDUINO +#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || \ + (ARCH_PORTDUINO && HAS_SCREEN != 0) #include "SPILock.h" #include "TFTDisplay.h" #include From 3cf6c47bab231736292a57c0cb756f89a3ba960e Mon Sep 17 00:00:00 2001 From: Jorropo Date: Fri, 29 Mar 2024 07:01:40 +0100 Subject: [PATCH 005/108] replace arch with uname -m for arch linux (#3508) From the manpage: > arch - print machine hardware name (same as uname -m) Arch Linux does not have the `arch` alias, only `uname`, so use `uname` to fix this issue: > ``` > ./bin/build-native.sh: line 18: arch: command not found > ``` Co-authored-by: Jonathan Bennett --- bin/build-native.sh | 2 +- bin/native-install.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/build-native.sh b/bin/build-native.sh index 7e9fcb632..7065ea54f 100755 --- a/bin/build-native.sh +++ b/bin/build-native.sh @@ -15,6 +15,6 @@ rm -r $OUTDIR/* || true # Important to pull latest version of libs into all device flavors, otherwise some devices might be stale platformio pkg update pio run --environment native -cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(arch)" +cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)" cp bin/device-install.* $OUTDIR cp bin/device-update.* $OUTDIR diff --git a/bin/native-install.sh b/bin/native-install.sh index cc6d968f9..ba71c4f46 100755 --- a/bin/native-install.sh +++ b/bin/native-install.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -cp "release/meshtasticd_linux_$(arch)" /usr/sbin/meshtasticd +cp "release/meshtasticd_linux_$(uname -m)" /usr/sbin/meshtasticd mkdir /etc/meshtasticd if [[ -f "/etc/meshtasticd/config.yaml" ]]; then cp bin/config-dist.yaml /etc/meshtasticd/config-upgrade.yaml From 279464f96d5139920b017d437501233737daf407 Mon Sep 17 00:00:00 2001 From: Jorropo Date: Fri, 29 Mar 2024 13:42:20 +0100 Subject: [PATCH 006/108] linux-native: only install linux native deps (#3510) This is a couple times faster because platformio checks all environment sequentially. Co-authored-by: Ben Meadors --- bin/build-native.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/build-native.sh b/bin/build-native.sh index 7065ea54f..9d31d091a 100755 --- a/bin/build-native.sh +++ b/bin/build-native.sh @@ -13,7 +13,7 @@ mkdir -p $OUTDIR/ rm -r $OUTDIR/* || true # Important to pull latest version of libs into all device flavors, otherwise some devices might be stale -platformio pkg update +platformio pkg update --environment native pio run --environment native cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)" cp bin/device-install.* $OUTDIR From 46a63bf293b2f7d6e1a4306b6cdbdc08d3acb19c Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Mon, 1 Apr 2024 01:04:05 +1300 Subject: [PATCH 007/108] Handle edge cases for E-Ink screensaver (#3518) * remove redundant logic * Handle special screens for old EInkDisplayClass * Handle special screens for EInkDynamicDisplay class * Join an async refresh in progress to avoid skipping screensaver * attempt trunk fix --- src/graphics/EInkDynamicDisplay.cpp | 27 +++++++++++++++++++++++++-- src/graphics/EInkDynamicDisplay.h | 12 +++++++++++- src/graphics/Screen.cpp | 25 ++++++++++++++++++------- src/graphics/Screen.h | 2 +- src/platform/nrf52/NRF52Bluetooth.cpp | 2 ++ 5 files changed, 57 insertions(+), 11 deletions(-) diff --git a/src/graphics/EInkDynamicDisplay.cpp b/src/graphics/EInkDynamicDisplay.cpp index f61cf891e..b396446fa 100644 --- a/src/graphics/EInkDynamicDisplay.cpp +++ b/src/graphics/EInkDynamicDisplay.cpp @@ -463,10 +463,33 @@ void EInkDynamicDisplay::onNotify(uint32_t notification) } #ifdef HAS_EINK_ASYNCFULL -// Run the post-update code if the hardware is ready +// Public: wait for an refresh already in progress, then run the post-update code. See Screen::setScreensaverFrames() +void EInkDynamicDisplay::joinAsyncRefresh() +{ + // If no async refresh running, nothing to do + if (!asyncRefreshRunning) + return; + + LOG_DEBUG("Joining an async refresh in progress\n"); + + // Continually poll the BUSY pin + while (adafruitDisplay->epd2.isBusy()) + yield(); + + // If asyncRefreshRunning flag is still set, but display's BUSY pin reports the refresh is done + adafruitDisplay->endAsyncFull(); // Run the end of nextPage() code + EInkDisplay::endUpdate(); // Run base-class code to finish off update (NOT our derived class override) + asyncRefreshRunning = false; // Unset the flag + LOG_DEBUG("Refresh complete\n"); + + // Note: this code only works because of a modification to meshtastic/GxEPD2. + // It is only equipped to intercept calls to nextPage() +} + +// Called from NotifiedWorkerThread. Run the post-update code if the hardware is ready void EInkDynamicDisplay::pollAsyncRefresh() { - // We shouldn't be here.. + // In theory, this condition should never be met if (!asyncRefreshRunning) return; diff --git a/src/graphics/EInkDynamicDisplay.h b/src/graphics/EInkDynamicDisplay.h index 39953b62a..8f3ce205a 100644 --- a/src/graphics/EInkDynamicDisplay.h +++ b/src/graphics/EInkDynamicDisplay.h @@ -119,20 +119,30 @@ class EInkDynamicDisplay : public EInkDisplay, protected concurrency::NotifiedWo // Conditional - async full refresh - only with modified meshtastic/GxEPD2 #if defined(HAS_EINK_ASYNCFULL) + public: + void joinAsyncRefresh(); // Main thread joins an async refresh already in progress. Blocks, then runs post-update code + + protected: void pollAsyncRefresh(); // Run the post-update code if the hardware is ready void checkBusyAsyncRefresh(); // Check if display is busy running an async full-refresh (rejecting new frames) void awaitRefresh(); // Hold control while an async refresh runs void endUpdate() override {} // Disable base-class behavior of running post-update immediately after forceDisplay() bool asyncRefreshRunning = false; // Flag, checked by checkBusyAsyncRefresh() #else + public: + void joinAsyncRefresh() {} // Dummy method + + protected: void pollAsyncRefresh() {} // Dummy method. In theory, not reachable #endif }; -// Tidier calls to addFrameFlag() from outside class +// Hide the ugly casts used in Screen.cpp #define EINK_ADD_FRAMEFLAG(display, flag) static_cast(display)->addFrameFlag(EInkDynamicDisplay::flag) +#define EINK_JOIN_ASYNCREFRESH(display) static_cast(display)->joinAsyncRefresh() #else // !USE_EINK_DYNAMICDISPLAY // Dummy-macro, removes the need for include guards #define EINK_ADD_FRAMEFLAG(display, flag) +#define EINK_JOIN_ASYNCREFRESH(display) #endif \ No newline at end of file diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 52829d1f7..2087b8daf 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1349,6 +1349,12 @@ void Screen::setScreensaverFrames(FrameCallback einkScreensaver) static FrameCallback screensaverFrame; static OverlayCallback screensaverOverlay; +#if defined(HAS_EINK_ASYNCFULL) && defined(USE_EINK_DYNAMICDISPLAY) + // Join (await) a currently running async refresh, then run the post-update code. + // Avoid skipping of screensaver frame. Would otherwise be handled by NotifiedWorkerThread. + EINK_JOIN_ASYNCREFRESH(dispdev); +#endif + // If: one-off screensaver frame passed as argument. Handles doDeepSleep() if (einkScreensaver != NULL) { screensaverFrame = einkScreensaver; @@ -1370,10 +1376,9 @@ void Screen::setScreensaverFrames(FrameCallback einkScreensaver) ui->update(); } while (ui->getUiState()->lastUpdate < startUpdate); -#ifndef USE_EINK_DYNAMICDISPLAY - // Retrofit to EInkDisplay class - delay(10); - screen->forceDisplay(); + // Old EInkDisplay class +#if !defined(USE_EINK_DYNAMICDISPLAY) + static_cast(dispdev)->forceDisplay(0); // Screen::forceDisplay(), but override rate-limit #endif // Prepare now for next frame, shown when display wakes @@ -1490,8 +1495,11 @@ void Screen::handleShutdownScreen() { LOG_DEBUG("showing shutdown screen\n"); showingNormalScreen = false; - EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // E-Ink: Use fast-refresh for next frame, no skip please +#ifdef USE_EINK + EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Use fast-refresh for next frame, no skip please EINK_ADD_FRAMEFLAG(dispdev, BLOCKING); // Edge case: if this frame is promoted to COSMETIC, wait for update + handleSetOn(true); // Ensure power-on to receive deep-sleep screensaver (PowerFSM should handle?) +#endif auto frame = [](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void { drawFrameText(display, state, x, y, "Shutting down..."); @@ -1499,14 +1507,17 @@ void Screen::handleShutdownScreen() static FrameCallback frames[] = {frame}; setFrameImmediateDraw(frames); - forceDisplay(); } void Screen::handleRebootScreen() { LOG_DEBUG("showing reboot screen\n"); showingNormalScreen = false; - EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // E-Ink: Explicitly use fast-refresh for next frame +#ifdef USE_EINK + EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Use fast-refresh for next frame, no skip please + EINK_ADD_FRAMEFLAG(dispdev, BLOCKING); // Edge case: if this frame is promoted to COSMETIC, wait for update + handleSetOn(true); // Power-on to show rebooting screen (PowerFSM should handle?) +#endif auto frame = [](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void { drawFrameText(display, state, x, y, "Rebooting..."); diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index 971146012..d03ba4320 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -150,7 +150,7 @@ class Screen : public concurrency::OSThread // We handle off commands immediately, because they might be called because the CPU is shutting down handleSetOn(false, einkScreensaver); else - enqueueCmd(ScreenCmd{.cmd = on ? Cmd::SET_ON : Cmd::SET_OFF}); + enqueueCmd(ScreenCmd{.cmd = Cmd::SET_ON}); } /** diff --git a/src/platform/nrf52/NRF52Bluetooth.cpp b/src/platform/nrf52/NRF52Bluetooth.cpp index e1914a184..759cbb404 100644 --- a/src/platform/nrf52/NRF52Bluetooth.cpp +++ b/src/platform/nrf52/NRF52Bluetooth.cpp @@ -1,5 +1,6 @@ #include "NRF52Bluetooth.h" #include "BluetoothCommon.h" +#include "PowerFSM.h" #include "configuration.h" #include "main.h" #include "mesh/PhoneAPI.h" @@ -318,6 +319,7 @@ void NRF52Bluetooth::onConnectionSecured(uint16_t conn_handle) bool NRF52Bluetooth::onPairingPasskey(uint16_t conn_handle, uint8_t const passkey[6], bool match_request) { LOG_INFO("BLE pairing process started with passkey %.3s %.3s\n", passkey, passkey + 3); + powerFSM.trigger(EVENT_BLUETOOTH_PAIR); screen->startBluetoothPinScreen(configuredPasskey); if (match_request) { From a4c22321fca6fc8da7bab157c3812055603512ba Mon Sep 17 00:00:00 2001 From: GUVWAF <78759985+GUVWAF@users.noreply.github.com> Date: Sun, 31 Mar 2024 15:03:29 +0200 Subject: [PATCH 008/108] Don't save Neighbors to flash when receiving (#3519) * Don't save Neighbors to flash when receiving * Move `shouldSave` to `saveProtoForModule()` --------- Co-authored-by: Ben Meadors --- src/modules/NeighborInfoModule.cpp | 9 +++++---- src/modules/NeighborInfoModule.h | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/modules/NeighborInfoModule.cpp b/src/modules/NeighborInfoModule.cpp index 1e9652469..92395ffc5 100644 --- a/src/modules/NeighborInfoModule.cpp +++ b/src/modules/NeighborInfoModule.cpp @@ -114,8 +114,8 @@ size_t NeighborInfoModule::cleanUpNeighbors() (*numNeighbors)--; } - // Save the neighbor list if we removed any neighbors - if (indices_to_remove.size() > 0) { + // Save the neighbor list if we removed any neighbors or neighbors were already updated upon receiving a packet + if (indices_to_remove.size() > 0 || shouldSave) { saveProtoForModule(); } @@ -210,7 +210,6 @@ meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSen // Only if this is the original sender, the broadcast interval corresponds to it if (originalSender == n && node_broadcast_interval_secs != 0) nbr->node_broadcast_interval_secs = node_broadcast_interval_secs; - saveProtoForModule(); // Save the updated neighbor return nbr; } } @@ -228,7 +227,7 @@ meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSen new_nbr->node_broadcast_interval_secs = node_broadcast_interval_secs; else // Assume the same broadcast interval as us for the neighbor if we don't know it new_nbr->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval; - saveProtoForModule(); // Save the new neighbor + shouldSave = true; // Save the new neighbor upon next cleanup return new_nbr; } @@ -255,6 +254,8 @@ bool NeighborInfoModule::saveProtoForModule() #endif okay &= nodeDB->saveProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, &meshtastic_NeighborInfo_msg, &neighborState); + if (okay) + shouldSave = false; return okay; } \ No newline at end of file diff --git a/src/modules/NeighborInfoModule.h b/src/modules/NeighborInfoModule.h index b4acb0f66..d47004981 100644 --- a/src/modules/NeighborInfoModule.h +++ b/src/modules/NeighborInfoModule.h @@ -20,6 +20,9 @@ class NeighborInfoModule : public ProtobufModule, priva bool saveProtoForModule(); + private: + bool shouldSave = false; // Whether we should save the neighbor info to flash + protected: // Note: this holds our local info. meshtastic_NeighborInfo neighborState; From 15501e84ddd6d3fcc7a86d4419e7e1e260f7f728 Mon Sep 17 00:00:00 2001 From: rcarteraz Date: Mon, 1 Apr 2024 03:53:19 -0700 Subject: [PATCH 009/108] Add Station-G2 to install scripts (#3525) * add station g2 to device-install.bat * add station-g2 to device-install.sh * remove extra space --- bin/device-install.bat | 2 +- bin/device-install.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/device-install.bat b/bin/device-install.bat index cb652346f..1fe1df52a 100755 --- a/bin/device-install.bat +++ b/bin/device-install.bat @@ -32,7 +32,7 @@ IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% ( %PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME% @REM Account for S3 and C3 board's different OTA partition - IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% IF x%FILENAME:t-deck=%==x%FILENAME% IF x%FILENAME:wireless-paper=%==x%FILENAME% IF x%FILENAME:wireless-tracker=%==x%FILENAME% ( + IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% IF x%FILENAME:t-deck=%==x%FILENAME% IF x%FILENAME:wireless-paper=%==x%FILENAME% IF x%FILENAME:wireless-tracker=%==x%FILENAME% IF x%FILENAME:station-g2=%==x%FILENAME% ( IF x%FILENAME:esp32c3=%==x%FILENAME% ( %PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin ) else ( diff --git a/bin/device-install.sh b/bin/device-install.sh index 0e7bd8ada..6ef7b1204 100755 --- a/bin/device-install.sh +++ b/bin/device-install.sh @@ -52,7 +52,7 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then "$PYTHON" -m esptool erase_flash "$PYTHON" -m esptool write_flash 0x00 ${FILENAME} # Account for S3 board's different OTA partition - if [ -n "${FILENAME##*"s3"*}" ] && [ -n "${FILENAME##*"-v3"*}" ] && [ -n "${FILENAME##*"t-deck"*}" ] && [ -n "${FILENAME##*"wireless-paper"*}" ] && [ -n "${FILENAME##*"wireless-tracker"*}" ]; then + if [ -n "${FILENAME##*"s3"*}" ] && [ -n "${FILENAME##*"-v3"*}" ] && [ -n "${FILENAME##*"t-deck"*}" ] && [ -n "${FILENAME##*"wireless-paper"*}" ] && [ -n "${FILENAME##*"wireless-tracker"*}" ] && [ -n "${FILENAME##*"station-g2"*}" ]; then if [ -n "${FILENAME##*"esp32c3"*}" ]; then "$PYTHON" -m esptool write_flash 0x260000 bleota.bin else From 8bb562c5fa79c330b424ff49d61cc74a92828387 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Mon, 1 Apr 2024 18:31:36 -0500 Subject: [PATCH 010/108] Add spiTransfer function to Native to support Linux-managed CS (#3524) * Add spiTransfer function to Native to support Linux-managed CS * Trunk --------- Co-authored-by: Ben Meadors --- arch/portduino/portduino.ini | 2 +- src/mesh/RadioLibInterface.cpp | 6 ++++++ src/mesh/RadioLibInterface.h | 3 +++ variants/portduino/variant.h | 1 + 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index ef8711f8a..077a49b3f 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -1,6 +1,6 @@ ; The Portduino based sim environment on top of any host OS, all hardware will be simulated [portduino_base] -platform = https://github.com/meshtastic/platform-native.git#1b8a32c60ab7495026033858d53c737f7d1cb34a +platform = https://github.com/meshtastic/platform-native.git#117acc5e7fcc2047e9ba1dc11789daea26fc36d2 framework = arduino build_src_filter = diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index 9f42afa6d..3ad2abe23 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -22,6 +22,12 @@ void LockingArduinoHal::spiEndTransaction() ArduinoHal::spiEndTransaction(); } +#if ARCH_PORTDUINO +void LockingArduinoHal::spiTransfer(uint8_t *out, size_t len, uint8_t *in) +{ + spi->transfer(out, in, len); +} +#endif RadioLibInterface::RadioLibInterface(LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, PhysicalLayer *_iface) diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h index 4634ca7ee..62720cfc9 100644 --- a/src/mesh/RadioLibInterface.h +++ b/src/mesh/RadioLibInterface.h @@ -25,6 +25,9 @@ class LockingArduinoHal : public ArduinoHal void spiBeginTransaction() override; void spiEndTransaction() override; +#if ARCH_PORTDUINO + void spiTransfer(uint8_t *out, size_t len, uint8_t *in) override; +#endif }; #if defined(USE_STM32WLx) diff --git a/variants/portduino/variant.h b/variants/portduino/variant.h index 5aad8dbfc..414a3fa56 100644 --- a/variants/portduino/variant.h +++ b/variants/portduino/variant.h @@ -2,3 +2,4 @@ #define CANNED_MESSAGE_MODULE_ENABLE 1 #define HAS_GPS 1 #define MAX_NUM_NODES settingsMap[maxnodes] +#define RADIOLIB_GODMODE 1 From f2ed0f7c8c0333d6dff91718a11d5e10062d5942 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Wed, 3 Apr 2024 08:55:48 +1300 Subject: [PATCH 011/108] Fix Light-sleep for ESP32 (#3521) * Change wakeup source from EXT0 to GPIO * Avoid ISR issue on wake * Detect press from wake reason, instead of digitalRead * Missing #ifdef Risky phone-typed commit * Fix PowerFSM timed transition preventing light sleep Addresses https://github.com/meshtastic/firmware/issues/3517 --------- Co-authored-by: Ben Meadors --- src/PowerFSM.cpp | 39 ++++++++++++++++++++++----------------- src/sleep.cpp | 18 +++++++++++------- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index b6e267e28..0002a62b4 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -102,23 +102,18 @@ static void lsIdle() powerFSM.trigger(EVENT_SERIAL_CONNECTED); break; + case ESP_SLEEP_WAKEUP_GPIO: + // GPIO wakeup is now used for all ESP32 devices during light sleep + powerFSM.trigger(EVENT_PRESS); + break; + default: - // We woke for some other reason (button press, device interrupt) - // uint64_t status = esp_sleep_get_ext1_wakeup_status(); + // We woke for some other reason (device interrupt?) LOG_INFO("wakeCause2 %d\n", wakeCause2); -#ifdef BUTTON_PIN - bool pressed = !digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN); -#else - bool pressed = false; -#endif - if (pressed) { // If we woke because of press, instead generate a PRESS event. - powerFSM.trigger(EVENT_PRESS); - } else { - // Otherwise let the NB state handle the IRQ (and that state will handle stuff like IRQs etc) - // we lie and say "wake timer" because the interrupt will be handled by the regular IRQ code - powerFSM.trigger(EVENT_WAKE_TIMER); - } + // Let the NB state handle the IRQ (and that state will handle stuff like IRQs etc) + // we lie and say "wake timer" because the interrupt will be handled by the regular IRQ code + powerFSM.trigger(EVENT_WAKE_TIMER); break; } } else { @@ -348,9 +343,6 @@ void PowerFSM_setup() powerFSM.add_timed_transition(&statePOWER, &stateDARK, Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL, "Screen-on timeout"); - powerFSM.add_timed_transition(&stateDARK, &stateDARK, - Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL, - "Screen-on timeout"); // We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally) #ifdef ARCH_ESP32 @@ -361,11 +353,24 @@ void PowerFSM_setup() powerFSM.add_timed_transition(&stateNB, &stateLS, Default::getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL, "Min wake timeout"); + + // If ESP32 and using power-saving, timer mover from DARK to light-sleep + // Also serves purpose of the old DARK to DARK transition(?) See https://github.com/meshtastic/firmware/issues/3517 powerFSM.add_timed_transition( &stateDARK, &stateLS, Default::getConfiguredOrDefaultMs(config.power.wait_bluetooth_secs, default_wait_bluetooth_secs), NULL, "Bluetooth timeout"); + } else { + // If ESP32, but not using power-saving, check periodically if config has drifted out of stateDark + powerFSM.add_timed_transition(&stateDARK, &stateDARK, + Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), + NULL, "Screen-on timeout"); } +#else + // If not ESP32, light-sleep not used. Check periodically if config has drifted out of stateDark + powerFSM.add_timed_transition(&stateDARK, &stateDARK, + Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL, + "Screen-on timeout"); #endif powerFSM.run_machine(); // run one iteration of the state machine, so we run our on enter tasks for the initial DARK state diff --git a/src/sleep.cpp b/src/sleep.cpp index 2f4bd09e1..e91bda782 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -312,13 +312,11 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r // assert(esp_sleep_enable_uart_wakeup(0) == ESP_OK); #endif #ifdef BUTTON_PIN -#if SOC_PM_SUPPORT_EXT_WAKEUP - esp_sleep_enable_ext0_wakeup((gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN), - LOW); // when user presses, this button goes low -#else + // The enableLoraInterrupt() method is using ext0_wakeup, so we are forced to use GPIO wakeup + gpio_num_t pin = (gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN); + gpio_intr_disable(pin); + gpio_wakeup_enable(pin, GPIO_INTR_LOW_LEVEL); esp_sleep_enable_gpio_wakeup(); - gpio_wakeup_enable((gpio_num_t)BUTTON_PIN, GPIO_INTR_LOW_LEVEL); -#endif #endif enableLoraInterrupt(); #ifdef PMU_IRQ @@ -342,6 +340,12 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r } assert(res == ESP_OK); +#ifdef BUTTON_PIN + gpio_wakeup_disable(pin); + // Would have thought that need gpio_intr_enable() here, but nope.. + // Works fine without it; crashes with it. +#endif + esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); #ifdef BUTTON_PIN if (cause == ESP_SLEEP_WAKEUP_GPIO) { @@ -406,4 +410,4 @@ void enableLoraInterrupt() gpio_wakeup_enable((gpio_num_t)RF95_IRQ, GPIO_INTR_HIGH_LEVEL); // RF95 interrupt, active high #endif } -#endif \ No newline at end of file +#endif From 2caed6d29c68163673f934896122020bb78eabe3 Mon Sep 17 00:00:00 2001 From: AeroXuk Date: Tue, 2 Apr 2024 21:36:15 +0100 Subject: [PATCH 012/108] Feature parity between Pico and Pico W (#3538) --- variants/rpipicow/variant.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/variants/rpipicow/variant.h b/variants/rpipicow/variant.h index 27117680f..a17f05ee0 100644 --- a/variants/rpipicow/variant.h +++ b/variants/rpipicow/variant.h @@ -21,6 +21,8 @@ #define EXT_NOTIFY_OUT 22 #define BUTTON_PIN 17 +#define LED_PIN LED_BUILTIN + #define BATTERY_PIN 26 // ratio of voltage divider = 3.0 (R17=200k, R18=100k) #define ADC_MULTIPLIER 3.1 // 3.0 + a bit for being optimistic @@ -51,4 +53,4 @@ #define SX126X_RESET LORA_RESET #define SX126X_DIO2_AS_RF_SWITCH #define SX126X_DIO3_TCXO_VOLTAGE 1.8 -#endif \ No newline at end of file +#endif From a570e50acad384a2754b6735891aeead3931ab9d Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Thu, 4 Apr 2024 00:59:53 +1300 Subject: [PATCH 013/108] Disable holds / isolations on RTC IO pads after deep sleep (#3539) * disable holds on RTC IO pads after deep sleep * Don't assume SOC_RTCIO_HOLD_SUPPORTED --- src/graphics/EInkDisplay2.cpp | 23 ++--------------------- src/sleep.cpp | 12 ++++++++++++ 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/graphics/EInkDisplay2.cpp b/src/graphics/EInkDisplay2.cpp index 0c5fab4fb..04915fe07 100644 --- a/src/graphics/EInkDisplay2.cpp +++ b/src/graphics/EInkDisplay2.cpp @@ -151,31 +151,12 @@ bool EInkDisplay::connect() #elif defined(HELTEC_WIRELESS_PAPER_V1_0) || defined(HELTEC_WIRELESS_PAPER) { - // Is this a normal boot, or a wake from deep sleep? - esp_sleep_wakeup_cause_t wakeReason = esp_sleep_get_wakeup_cause(); - - // If waking from sleep, need to reverse rtc_gpio_isolate(), called in cpuDeepSleep() - // Otherwise, SPI won't work - if (wakeReason != ESP_SLEEP_WAKEUP_UNDEFINED) { - // HSPI + other display pins - rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_SCLK); - rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_DC); - rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_RES); - rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_BUSY); - rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_CS); - rtc_gpio_hold_dis((gpio_num_t)PIN_EINK_MOSI); - } - // Start HSPI hspi = new SPIClass(HSPI); hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS - // Enable VExt (ACTIVE LOW) - // Unsure if called elsewhere first? - delay(100); - pinMode(Vext, OUTPUT); - digitalWrite(Vext, LOW); - delay(100); + // VExt already enabled in setup() + // RTC GPIO hold disabled in setup() // Create GxEPD2 objects auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *hspi); diff --git a/src/sleep.cpp b/src/sleep.cpp index e91bda782..ddea9942c 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -147,6 +147,18 @@ void initDeepSleep() LOG_INFO("Booted, wake cause %d (boot count %d), reset_reason=%s\n", wakeCause, bootCount, reason); #endif + +#if SOC_RTCIO_HOLD_SUPPORTED + // If waking from sleep, release any and all RTC GPIOs + if (wakeCause != ESP_SLEEP_WAKEUP_UNDEFINED) { + LOG_DEBUG("Disabling any holds on RTC IO pads\n"); + for (uint8_t i = 0; i <= 45; i++) { + if (rtc_gpio_is_valid_gpio((gpio_num_t)i)) + rtc_gpio_hold_dis((gpio_num_t)i); + } + } +#endif + #endif } From 46ad4bf0e5bcfbb6c8b903b7436bec7b50ecdc9f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 3 Apr 2024 08:47:47 -0500 Subject: [PATCH 014/108] [create-pull-request] automated change (#3542) Co-authored-by: thebentern --- protobufs | 2 +- src/mesh/generated/meshtastic/config.pb.h | 6 +- .../generated/meshtastic/deviceonly.pb.cpp | 4 +- src/mesh/generated/meshtastic/deviceonly.pb.h | 119 +++++++++--------- src/mesh/generated/meshtastic/mesh.pb.h | 7 +- src/mesh/generated/meshtastic/mqtt.pb.h | 2 +- 6 files changed, 72 insertions(+), 68 deletions(-) diff --git a/protobufs b/protobufs index dea3a82ef..6157a5723 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit dea3a82ef2accd25112b4ef1c6f8991b579740f4 +Subproject commit 6157a5723745b3a750720b94676198a7f3839e2a diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index c56cf65a0..67c745214 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -30,12 +30,12 @@ typedef enum _meshtastic_Config_DeviceConfig_Role { meshtastic_Config_DeviceConfig_Role_REPEATER = 4, /* Description: Broadcasts GPS position packets as priority. Technical Details: Position Mesh packets will be prioritized higher and sent more frequently by default. - When used in conjunction with power.is_power_saving = true, nodes will wake up, + When used in conjunction with power.is_power_saving = true, nodes will wake up, send position, and then sleep for position.position_broadcast_secs seconds. */ meshtastic_Config_DeviceConfig_Role_TRACKER = 5, /* Description: Broadcasts telemetry packets as priority. Technical Details: Telemetry Mesh packets will be prioritized higher and sent more frequently by default. - When used in conjunction with power.is_power_saving = true, nodes will wake up, + When used in conjunction with power.is_power_saving = true, nodes will wake up, send environment telemetry, and then sleep for telemetry.environment_update_interval seconds. */ meshtastic_Config_DeviceConfig_Role_SENSOR = 6, /* Description: Optimized for ATAK system communication and reduces routine broadcasts. @@ -50,7 +50,7 @@ typedef enum _meshtastic_Config_DeviceConfig_Role { Can be used for clandestine operation or to dramatically reduce airtime / power consumption */ meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN = 8, /* Description: Broadcasts location as message to default channel regularly for to assist with device recovery. - Technical Details: Used to automatically send a text message to the mesh + Technical Details: Used to automatically send a text message to the mesh with the current position of the device on a frequent interval: "I'm lost! Position: lat / long" */ meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND = 9, diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.cpp b/src/mesh/generated/meshtastic/deviceonly.pb.cpp index a9925b517..127319b14 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.cpp +++ b/src/mesh/generated/meshtastic/deviceonly.pb.cpp @@ -6,13 +6,13 @@ #error Regenerate this file with the current version of nanopb generator. #endif -PB_BIND(meshtastic_DeviceState, meshtastic_DeviceState, 2) +PB_BIND(meshtastic_PositionLite, meshtastic_PositionLite, AUTO) PB_BIND(meshtastic_NodeInfoLite, meshtastic_NodeInfoLite, AUTO) -PB_BIND(meshtastic_PositionLite, meshtastic_PositionLite, AUTO) +PB_BIND(meshtastic_DeviceState, meshtastic_DeviceState, 2) PB_BIND(meshtastic_ChannelFile, meshtastic_ChannelFile, 2) diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index c75f35c04..cdd59d871 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -8,13 +8,25 @@ #include "meshtastic/channel.pb.h" #include "meshtastic/localonly.pb.h" #include "meshtastic/mesh.pb.h" -#include "meshtastic/telemetry.pb.h" #include "meshtastic/module_config.pb.h" +#include "meshtastic/telemetry.pb.h" #if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. #endif +/* Enum definitions */ +/* Font sizes for the device screen */ +typedef enum _meshtastic_ScreenFonts { + /* TODO: REPLACE */ + meshtastic_ScreenFonts_FONT_SMALL = 0, + /* TODO: REPLACE */ + meshtastic_ScreenFonts_FONT_MEDIUM = 1, + /* TODO: REPLACE */ + meshtastic_ScreenFonts_FONT_LARGE = 2 +} meshtastic_ScreenFonts; + +/* Struct definitions */ /* Position with static location information only for NodeDBLite */ typedef struct _meshtastic_PositionLite { /* The new preferred location encoding, multiply by 1e-7 to get degrees @@ -63,18 +75,6 @@ typedef struct _meshtastic_NodeInfoLite { bool is_favorite; } meshtastic_NodeInfoLite; -/* Enum definitions */ -/* TODO: REPLACE */ -typedef enum _meshtastic_ScreenFonts { - /* TODO: REPLACE */ - meshtastic_ScreenFonts_FONT_SMALL = 0, - /* TODO: REPLACE */ - meshtastic_ScreenFonts_FONT_MEDIUM = 1, - /* TODO: REPLACE */ - meshtastic_ScreenFonts_FONT_LARGE = 2 -} meshtastic_ScreenFonts; - -/* Struct definitions */ /* This message is never sent over the wire, but it is used for serializing DB state to flash in the device code FIXME, since we write this each time we enter deep sleep (and have infinite @@ -117,7 +117,6 @@ typedef struct _meshtastic_DeviceState { std::vector node_db_lite; } meshtastic_DeviceState; - /* The on-disk saved channels */ typedef struct _meshtastic_ChannelFile { /* The channels our node knows about */ @@ -164,37 +163,27 @@ extern "C" { #define _meshtastic_ScreenFonts_MAX meshtastic_ScreenFonts_FONT_LARGE #define _meshtastic_ScreenFonts_ARRAYSIZE ((meshtastic_ScreenFonts)(meshtastic_ScreenFonts_FONT_LARGE+1)) - - #define meshtastic_PositionLite_location_source_ENUMTYPE meshtastic_Position_LocSource + + #define meshtastic_OEMStore_oem_font_ENUMTYPE meshtastic_ScreenFonts /* Initializer values for message structs */ -#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default, 0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}, {{NULL}, NULL}} -#define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_User_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, 0, 0} #define meshtastic_PositionLite_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN} +#define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_User_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, 0, 0} +#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default, 0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}, {{NULL}, NULL}} #define meshtastic_ChannelFile_init_default {0, {meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default}, 0} #define meshtastic_OEMStore_init_default {0, 0, {0, {0}}, _meshtastic_ScreenFonts_MIN, "", {0, {0}}, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default} -#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero, 0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}, {{NULL}, NULL}} -#define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, 0, 0} #define meshtastic_PositionLite_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN} +#define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, 0, 0} +#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero, 0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}, {{NULL}, NULL}} #define meshtastic_ChannelFile_init_zero {0, {meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero}, 0} #define meshtastic_OEMStore_init_zero {0, 0, {0, {0}}, _meshtastic_ScreenFonts_MIN, "", {0, {0}}, false, meshtastic_LocalConfig_init_zero, false, meshtastic_LocalModuleConfig_init_zero} /* Field tags (for use in manual encoding/decoding) */ -#define meshtastic_DeviceState_my_node_tag 2 -#define meshtastic_DeviceState_owner_tag 3 -#define meshtastic_DeviceState_receive_queue_tag 5 -#define meshtastic_DeviceState_rx_text_message_tag 7 -#define meshtastic_DeviceState_version_tag 8 -#define meshtastic_DeviceState_no_save_tag 9 -#define meshtastic_DeviceState_did_gps_reset_tag 11 -#define meshtastic_DeviceState_rx_waypoint_tag 12 -#define meshtastic_DeviceState_node_remote_hardware_pins_tag 13 -#define meshtastic_DeviceState_node_db_lite_tag 14 #define meshtastic_PositionLite_latitude_i_tag 1 #define meshtastic_PositionLite_longitude_i_tag 2 #define meshtastic_PositionLite_altitude_tag 3 @@ -210,6 +199,16 @@ extern "C" { #define meshtastic_NodeInfoLite_via_mqtt_tag 8 #define meshtastic_NodeInfoLite_hops_away_tag 9 #define meshtastic_NodeInfoLite_is_favorite_tag 10 +#define meshtastic_DeviceState_my_node_tag 2 +#define meshtastic_DeviceState_owner_tag 3 +#define meshtastic_DeviceState_receive_queue_tag 5 +#define meshtastic_DeviceState_rx_text_message_tag 7 +#define meshtastic_DeviceState_version_tag 8 +#define meshtastic_DeviceState_no_save_tag 9 +#define meshtastic_DeviceState_did_gps_reset_tag 11 +#define meshtastic_DeviceState_rx_waypoint_tag 12 +#define meshtastic_DeviceState_node_remote_hardware_pins_tag 13 +#define meshtastic_DeviceState_node_db_lite_tag 14 #define meshtastic_ChannelFile_channels_tag 1 #define meshtastic_ChannelFile_version_tag 2 #define meshtastic_OEMStore_oem_icon_width_tag 1 @@ -222,6 +221,32 @@ extern "C" { #define meshtastic_OEMStore_oem_local_module_config_tag 8 /* Struct field encoding specification for nanopb */ +#define meshtastic_PositionLite_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, SFIXED32, latitude_i, 1) \ +X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 2) \ +X(a, STATIC, SINGULAR, INT32, altitude, 3) \ +X(a, STATIC, SINGULAR, FIXED32, time, 4) \ +X(a, STATIC, SINGULAR, UENUM, location_source, 5) +#define meshtastic_PositionLite_CALLBACK NULL +#define meshtastic_PositionLite_DEFAULT NULL + +#define meshtastic_NodeInfoLite_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, num, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, user, 2) \ +X(a, STATIC, OPTIONAL, MESSAGE, position, 3) \ +X(a, STATIC, SINGULAR, FLOAT, snr, 4) \ +X(a, STATIC, SINGULAR, FIXED32, last_heard, 5) \ +X(a, STATIC, OPTIONAL, MESSAGE, device_metrics, 6) \ +X(a, STATIC, SINGULAR, UINT32, channel, 7) \ +X(a, STATIC, SINGULAR, BOOL, via_mqtt, 8) \ +X(a, STATIC, SINGULAR, UINT32, hops_away, 9) \ +X(a, STATIC, SINGULAR, BOOL, is_favorite, 10) +#define meshtastic_NodeInfoLite_CALLBACK NULL +#define meshtastic_NodeInfoLite_DEFAULT NULL +#define meshtastic_NodeInfoLite_user_MSGTYPE meshtastic_User +#define meshtastic_NodeInfoLite_position_MSGTYPE meshtastic_PositionLite +#define meshtastic_NodeInfoLite_device_metrics_MSGTYPE meshtastic_DeviceMetrics + #define meshtastic_DeviceState_FIELDLIST(X, a) \ X(a, STATIC, OPTIONAL, MESSAGE, my_node, 2) \ X(a, STATIC, OPTIONAL, MESSAGE, owner, 3) \ @@ -244,32 +269,6 @@ extern bool meshtastic_DeviceState_callback(pb_istream_t *istream, pb_ostream_t #define meshtastic_DeviceState_node_remote_hardware_pins_MSGTYPE meshtastic_NodeRemoteHardwarePin #define meshtastic_DeviceState_node_db_lite_MSGTYPE meshtastic_NodeInfoLite -#define meshtastic_NodeInfoLite_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, num, 1) \ -X(a, STATIC, OPTIONAL, MESSAGE, user, 2) \ -X(a, STATIC, OPTIONAL, MESSAGE, position, 3) \ -X(a, STATIC, SINGULAR, FLOAT, snr, 4) \ -X(a, STATIC, SINGULAR, FIXED32, last_heard, 5) \ -X(a, STATIC, OPTIONAL, MESSAGE, device_metrics, 6) \ -X(a, STATIC, SINGULAR, UINT32, channel, 7) \ -X(a, STATIC, SINGULAR, BOOL, via_mqtt, 8) \ -X(a, STATIC, SINGULAR, UINT32, hops_away, 9) \ -X(a, STATIC, SINGULAR, BOOL, is_favorite, 10) -#define meshtastic_NodeInfoLite_CALLBACK NULL -#define meshtastic_NodeInfoLite_DEFAULT NULL -#define meshtastic_NodeInfoLite_user_MSGTYPE meshtastic_User -#define meshtastic_NodeInfoLite_position_MSGTYPE meshtastic_PositionLite -#define meshtastic_NodeInfoLite_device_metrics_MSGTYPE meshtastic_DeviceMetrics - -#define meshtastic_PositionLite_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, SFIXED32, latitude_i, 1) \ -X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 2) \ -X(a, STATIC, SINGULAR, INT32, altitude, 3) \ -X(a, STATIC, SINGULAR, FIXED32, time, 4) \ -X(a, STATIC, SINGULAR, UENUM, location_source, 5) -#define meshtastic_PositionLite_CALLBACK NULL -#define meshtastic_PositionLite_DEFAULT NULL - #define meshtastic_ChannelFile_FIELDLIST(X, a) \ X(a, STATIC, REPEATED, MESSAGE, channels, 1) \ X(a, STATIC, SINGULAR, UINT32, version, 2) @@ -291,16 +290,16 @@ X(a, STATIC, OPTIONAL, MESSAGE, oem_local_module_config, 8) #define meshtastic_OEMStore_oem_local_config_MSGTYPE meshtastic_LocalConfig #define meshtastic_OEMStore_oem_local_module_config_MSGTYPE meshtastic_LocalModuleConfig -extern const pb_msgdesc_t meshtastic_DeviceState_msg; -extern const pb_msgdesc_t meshtastic_NodeInfoLite_msg; extern const pb_msgdesc_t meshtastic_PositionLite_msg; +extern const pb_msgdesc_t meshtastic_NodeInfoLite_msg; +extern const pb_msgdesc_t meshtastic_DeviceState_msg; extern const pb_msgdesc_t meshtastic_ChannelFile_msg; extern const pb_msgdesc_t meshtastic_OEMStore_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define meshtastic_DeviceState_fields &meshtastic_DeviceState_msg -#define meshtastic_NodeInfoLite_fields &meshtastic_NodeInfoLite_msg #define meshtastic_PositionLite_fields &meshtastic_PositionLite_msg +#define meshtastic_NodeInfoLite_fields &meshtastic_NodeInfoLite_msg +#define meshtastic_DeviceState_fields &meshtastic_DeviceState_msg #define meshtastic_ChannelFile_fields &meshtastic_ChannelFile_msg #define meshtastic_OEMStore_fields &meshtastic_OEMStore_msg diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index fcefe508b..d15f968d4 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -141,6 +141,11 @@ typedef enum _meshtastic_HardwareModel { /* Heltec Wireless Tracker with ESP32-S3 CPU, built-in GPS, and TFT Older "V1.0" Variant */ meshtastic_HardwareModel_HELTEC_WIRELESS_TRACKER_V1_0 = 58, + /* unPhone with ESP32-S3, TFT touchscreen, LSM6DS3TR-C accelerometer and gyroscope */ + meshtastic_HardwareModel_UNPHONE = 59, + /* Teledatics TD-LORAC NRF52840 based M.2 LoRA module + Compatible with the TD-WRLS development board */ + meshtastic_HardwareModel_TD_LORAC = 60, /* ------------------------------------------------------------------------------------------------------------------------------------------ Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. ------------------------------------------------------------------------------------------------------------------------------------------ */ @@ -593,7 +598,7 @@ typedef struct _meshtastic_MeshPacket { meshtastic_MeshPacket_Delayed delayed; /* Describes whether this packet passed via MQTT somewhere along the path it currently took. */ bool via_mqtt; - /* Hop limit with which the original packet started. Sent via LoRa using three bits in the unencrypted header. + /* Hop limit with which the original packet started. Sent via LoRa using three bits in the unencrypted header. When receiving a packet, the difference between hop_start and hop_limit gives how many hops it traveled. */ uint8_t hop_start; } meshtastic_MeshPacket; diff --git a/src/mesh/generated/meshtastic/mqtt.pb.h b/src/mesh/generated/meshtastic/mqtt.pb.h index 8ca570d78..9ec29d5b1 100644 --- a/src/mesh/generated/meshtastic/mqtt.pb.h +++ b/src/mesh/generated/meshtastic/mqtt.pb.h @@ -4,8 +4,8 @@ #ifndef PB_MESHTASTIC_MESHTASTIC_MQTT_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_MQTT_PB_H_INCLUDED #include -#include "meshtastic/mesh.pb.h" #include "meshtastic/config.pb.h" +#include "meshtastic/mesh.pb.h" #if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. From eb0e705ba973a9596bf677c5ce185bbcfc279f7d Mon Sep 17 00:00:00 2001 From: Todd Herbert Date: Thu, 4 Apr 2024 17:04:10 +1300 Subject: [PATCH 015/108] de-init bluetooth --- src/nimble/NimbleBluetooth.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/nimble/NimbleBluetooth.cpp b/src/nimble/NimbleBluetooth.cpp index bc94abf6e..0b91bf44f 100644 --- a/src/nimble/NimbleBluetooth.cpp +++ b/src/nimble/NimbleBluetooth.cpp @@ -112,6 +112,12 @@ void NimbleBluetooth::shutdown() NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising(); pAdvertising->reset(); pAdvertising->stop(); + +#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0) + // Saving of ~1mA + // Probably applicable to other ESP32 boards - unverified + NimBLEDevice::deinit(); +#endif } bool NimbleBluetooth::isActive() From d1db51830b90241e0f5f0b6259ae0d027c5e5fd1 Mon Sep 17 00:00:00 2001 From: Todd Herbert Date: Thu, 4 Apr 2024 17:05:12 +1300 Subject: [PATCH 016/108] set GPIOs for sleep --- src/sleep.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/sleep.cpp b/src/sleep.cpp index ddea9942c..67b7f5c7c 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -277,6 +277,17 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false) if (shouldLoraWake(msecToWake)) { enableLoraInterrupt(); } + +#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0) // Applicable to most ESP32 boards? + // Avoid leakage through button pin + pinMode(0, INPUT); + rtc_gpio_hold_en((gpio_num_t)0); + + // LoRa CS (RADIO_NSS) needs to stay HIGH, even during deep sleep + pinMode(LORA_CS, OUTPUT); + digitalWrite(LORA_CS, HIGH); + rtc_gpio_hold_en((gpio_num_t)LORA_CS); +#endif #endif cpuDeepSleep(msecToWake); } From 30ebb6ae46560a81eb33e102f14bc873ddc000a5 Mon Sep 17 00:00:00 2001 From: Todd Herbert Date: Thu, 4 Apr 2024 17:18:40 +1300 Subject: [PATCH 017/108] use BUTTON_PIN macro --- src/sleep.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sleep.cpp b/src/sleep.cpp index 67b7f5c7c..0d36112c1 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -280,8 +280,8 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false) #if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0) // Applicable to most ESP32 boards? // Avoid leakage through button pin - pinMode(0, INPUT); - rtc_gpio_hold_en((gpio_num_t)0); + pinMode(BUTTON_PIN, INPUT); + rtc_gpio_hold_en((gpio_num_t)BUTTON_PIN); // LoRa CS (RADIO_NSS) needs to stay HIGH, even during deep sleep pinMode(LORA_CS, OUTPUT); From be889015f7792d8a15367d0ac471cb66b2f5d6cb Mon Sep 17 00:00:00 2001 From: Gareth Coleman Date: Wed, 3 Apr 2024 20:17:13 +0100 Subject: [PATCH 018/108] New device unPhone using HX8357D LCD and XPT2046 touchscreen --- src/graphics/Screen.cpp | 15 ++-- src/graphics/ScreenFonts.h | 2 +- src/graphics/TFTDisplay.cpp | 113 +++++++++++++++++++++++++++++- src/graphics/images.h | 5 +- src/main.cpp | 18 ++++- src/platform/esp32/architecture.h | 4 +- variants/unphone/platformio.ini | 16 +++++ variants/unphone/variant.h | 61 ++++++++++++++++ 8 files changed, 218 insertions(+), 16 deletions(-) create mode 100644 variants/unphone/platformio.ini create mode 100644 variants/unphone/variant.h diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 2087b8daf..8510562c4 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -528,7 +528,7 @@ static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const NodeStat { char usersString[20]; snprintf(usersString, sizeof(usersString), "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal()); -#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \ +#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) display->drawFastImage(x, y + 3, 8, 8, imgUser); #else @@ -955,7 +955,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O #elif defined(USE_SSD1306) dispdev = new SSD1306Wire(address.address, -1, -1, geometry, (address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE); -#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014) +#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS) dispdev = new TFTDisplay(address.address, -1, -1, geometry, (address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE); #elif defined(USE_EINK) && !defined(USE_EINK_DYNAMICDISPLAY) @@ -1101,7 +1101,7 @@ void Screen::setup() // Standard behaviour is to FLIP the screen (needed on T-Beam). If this config item is set, unflip it, and thereby logically // flip it. If you have a headache now, you're welcome. if (!config.display.flip_screen) { -#if defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014) +#if defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS) static_cast(dispdev)->flipScreenVertically(); #else dispdev->flipScreenVertically(); @@ -1686,7 +1686,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 #ifdef ARCH_ESP32 if (millis() - storeForwardModule->lastHeartbeat > (storeForwardModule->heartbeatInterval * 1200)) { // no heartbeat, overlap a bit -#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \ +#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, imgQuestionL1); @@ -1697,7 +1697,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 imgQuestion); #endif } else { -#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \ +#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8, imgSFL1); @@ -1711,7 +1711,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 #endif } else { // TODO: Raspberry Pi supports more than just the one screen size -#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || ARCH_PORTDUINO) && \ +#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS) || \ + ARCH_PORTDUINO) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, imgInfoL1); @@ -1974,4 +1975,4 @@ int Screen::handleInputEvent(const InputEvent *event) } // namespace graphics #else graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {} -#endif // HAS_SCREEN \ No newline at end of file +#endif // HAS_SCREEN diff --git a/src/graphics/ScreenFonts.h b/src/graphics/ScreenFonts.h index d858add2c..4b34563f7 100644 --- a/src/graphics/ScreenFonts.h +++ b/src/graphics/ScreenFonts.h @@ -8,7 +8,7 @@ #include "graphics/fonts/OLEDDisplayFontsUA.h" #endif -#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \ +#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) // The screen is bigger so use bigger fonts #define FONT_SMALL ArialMT_Plain_16 // Height: 19 diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index 79f521fbb..c1f482b84 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -402,9 +402,95 @@ class LGFX : public lgfx::LGFX_Device }; static LGFX *tft = nullptr; + +#elif defined(HX8357_CS) +#include // Graphics and font library for HX8357 driver chip + +class LGFX : public lgfx::LGFX_Device +{ + lgfx::Panel_HX8357D _panel_instance; + lgfx::Bus_SPI _bus_instance; + #if defined(USE_XPT2046) + lgfx::ITouch *_touch_instance; + // lgfx::Touch_XPT2046 _touch_instance; + #endif + + public: + LGFX(void) + { + // Panel_HX8357D + { + // configure SPI + auto cfg = _bus_instance.config(); + + cfg.spi_host = HX8357_SPI_HOST; + cfg.spi_mode = 0; + cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing + // 80MHz by an integer) + cfg.freq_read = SPI_READ_FREQUENCY; // SPI clock when receiving + cfg.spi_3wire = false; // Set to true if reception is done on the MOSI pin + cfg.use_lock = true; // Set to true to use transaction locking + cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch / + // SPI_DMA_CH_AUTO=auto setting) + cfg.pin_sclk = HX8357_SCK; // Set SPI SCLK pin number + cfg.pin_mosi = HX8357_MOSI; // Set SPI MOSI pin number + cfg.pin_miso = HX8357_MISO; // Set SPI MISO pin number (-1 = disable) + cfg.pin_dc = HX8357_RS; // Set SPI DC pin number (-1 = disable) + + _bus_instance.config(cfg); // applies the set value to the bus. + _panel_instance.setBus(&_bus_instance); // set the bus on the panel. + } + { + // Set the display panel control. + auto cfg = _panel_instance.config(); // Gets a structure for display panel settings. + + cfg.pin_cs = HX8357_CS; // Pin number where CS is connected (-1 = disable) + cfg.pin_rst = HX8357_RESET; // Pin number where RST is connected (-1 = disable) + cfg.pin_busy = HX8357_BUSY; // Pin number where BUSY is connected (-1 = disable) + + cfg.panel_width = TFT_WIDTH; // actual displayable width + cfg.panel_height = TFT_HEIGHT; // actual displayable height + cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction + cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction + cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is upside down) + cfg.dummy_read_pixel = 8; // Number of bits for dummy read before pixel readout + cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read + cfg.readable = true; // Set to true if data can be read + cfg.invert = TFT_INVERT; // Set to true if the light/darkness of the panel is reversed + cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped + cfg.dlen_16bit = false; + cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.) + + _panel_instance.config(cfg); + } + #if defined(USE_XPT2046) + { + // Configure settings for touch control. + _touch_instance = new lgfx::Touch_XPT2046; + auto touch_cfg = _touch_instance->config(); + + touch_cfg.pin_cs = TOUCH_CS; + touch_cfg.x_min = 0; + touch_cfg.x_max = TFT_HEIGHT - 1; + touch_cfg.y_min = 0; + touch_cfg.y_max = TFT_WIDTH - 1; + touch_cfg.pin_int = -1; + touch_cfg.bus_shared = true; + touch_cfg.offset_rotation = 1; + + _touch_instance->config(touch_cfg); + //_panel_instance->setTouch(_touch_instance); + } + #endif + setPanel(&_panel_instance); + } +}; + +static LGFX *tft = nullptr; + #endif -#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || \ +#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || defined(HX8357_CS) || \ (ARCH_PORTDUINO && HAS_SCREEN != 0) #include "SPILock.h" #include "TFTDisplay.h" @@ -487,7 +573,13 @@ void TFTDisplay::sendCommand(uint8_t com) #ifdef VTFT_CTRL digitalWrite(VTFT_CTRL, LOW); #endif - +#ifdef UNPHONE + Wire.beginTransmission(0x26); + Wire.write(0x02); + Wire.write(0x04); // Backlight on + Wire.write(0x22); // G&B LEDs off + Wire.endTransmission(); +#endif #ifdef RAK14014 #elif !defined(M5STACK) tft->setBrightness(172); @@ -514,6 +606,13 @@ void TFTDisplay::sendCommand(uint8_t com) #ifdef VTFT_CTRL digitalWrite(VTFT_CTRL, HIGH); #endif +#ifdef UNPHONE + Wire.beginTransmission(0x26); + Wire.write(0x02); + Wire.write(0x00); // Backlight off + Wire.write(0x22); // G&B LEDs off + Wire.endTransmission(); +#endif #ifdef RAK14014 #elif !defined(M5STACK) tft->setBrightness(0); @@ -585,6 +684,14 @@ bool TFTDisplay::connect() pinMode(ST7735_BL_V05, OUTPUT); digitalWrite(ST7735_BL_V05, TFT_BACKLIGHT_ON); #endif +#ifdef UNPHONE + Wire.beginTransmission(0x26); + Wire.write(0x02); + Wire.write(0x04); // Backlight on + Wire.write(0x22); // G&B LEDs off + Wire.endTransmission(); + LOG_INFO("Power to TFT Backlight\n"); +#endif tft->init(); @@ -606,4 +713,4 @@ bool TFTDisplay::connect() return true; } -#endif \ No newline at end of file +#endif diff --git a/src/graphics/images.h b/src/graphics/images.h index 207fc3a86..5c6fb4275 100644 --- a/src/graphics/images.h +++ b/src/graphics/images.h @@ -14,7 +14,8 @@ const uint8_t imgUser[] PROGMEM = {0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3 const uint8_t imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF}; const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF}; -#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || ARCH_PORTDUINO) && \ +#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS) || \ + ARCH_PORTDUINO) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff}; const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f}; @@ -30,4 +31,4 @@ const uint8_t imgQuestion[] PROGMEM = {0xbf, 0x41, 0xc0, 0x8b, 0xdb, 0x70, 0xa1, const uint8_t imgSF[] PROGMEM = {0xd2, 0xb7, 0xad, 0xbb, 0x92, 0x01, 0xfd, 0xfd, 0x15, 0x85, 0xf5}; #endif -#include "img/icon.xbm" \ No newline at end of file +#include "img/icon.xbm" diff --git a/src/main.cpp b/src/main.cpp index 0c45e903a..e93acf0ff 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -589,6 +589,20 @@ void setup() if (config.display.oled != meshtastic_Config_DisplayConfig_OledType_OLED_AUTO) screen_model = config.display.oled; +#ifdef UNPHONE + // initialise IO expander with pinmodes + Wire.beginTransmission(0x26); + Wire.write(0x06); + Wire.write(0x7A); + Wire.write(0xDD); + Wire.endTransmission(); + Wire.beginTransmission(0x26); + Wire.write(0x02); + Wire.write(0x04); // Backlight on + Wire.write(0x22); // G&B LEDs off + Wire.endTransmission(); +#endif + #if defined(USE_SH1107) screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // set dimension of 128x128 display_geometry = GEOMETRY_128_128; @@ -686,7 +700,7 @@ void setup() // Don't call screen setup until after nodedb is setup (because we need // the current region name) -#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS) +#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(HX8357_CS) screen->setup(); #elif defined(ARCH_PORTDUINO) if (screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) { @@ -986,4 +1000,4 @@ void loop() mainDelay.delay(delayMsec); } // if (didWake) LOG_DEBUG("wake!\n"); -} \ No newline at end of file +} diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h index 703bcefc9..6855265ac 100644 --- a/src/platform/esp32/architecture.h +++ b/src/platform/esp32/architecture.h @@ -135,6 +135,8 @@ #define HW_VENDOR meshtastic_HardwareModel_CHATTER_2 #elif defined(STATION_G2) #define HW_VENDOR meshtastic_HardwareModel_STATION_G2 +#elif defined(UNPHONE) +#define HW_VENDOR meshtastic_HardwareModel_UNPHONE #endif // ----------------------------------------------------------------------------- @@ -157,4 +159,4 @@ #define LORA_CS 18 #endif -#define SERIAL0_RX_GPIO 3 // Always GPIO3 on ESP32 // FIXME: may be different on ESP32-S3, etc. \ No newline at end of file +#define SERIAL0_RX_GPIO 3 // Always GPIO3 on ESP32 // FIXME: may be different on ESP32-S3, etc. diff --git a/variants/unphone/platformio.ini b/variants/unphone/platformio.ini new file mode 100644 index 000000000..9a4a63807 --- /dev/null +++ b/variants/unphone/platformio.ini @@ -0,0 +1,16 @@ +[env:unphone] +;build_type = debug ; to make it possible to step through our jtag debugger +extends = esp32s3_base +board_level = extra +board = unphone9 +upload_speed = 921600 +monitor_speed = 115200 +monitor_filters = esp32_exception_decoder + +build_flags = ${esp32_base.build_flags} + -D UNPHONE + -D BOARD_HAS_PSRAM + -I variants/unphone + +lib_deps = ${esp32s3_base.lib_deps} + lovyan03/LovyanGFX@^1.1.8 \ No newline at end of file diff --git a/variants/unphone/variant.h b/variants/unphone/variant.h new file mode 100644 index 000000000..3032156f4 --- /dev/null +++ b/variants/unphone/variant.h @@ -0,0 +1,61 @@ +#define SPI_SCK 39 +#define SPI_MOSI 40 +#define SPI_MISO 41 + +// We use the RFM95W LoRa module +#define USE_RF95 +#define LORA_SCK SPI_SCK +#define LORA_MOSI SPI_MOSI +#define LORA_MISO SPI_MISO +#define LORA_CS 44 +#define LORA_DIO0 10 // AKA LORA_IRQ +#define LORA_RESET 42 +#define LORA_DIO1 11 +#define LORA_DIO2 RADIOLIB_NC // Not really used + +// HX8357 TFT LCD +#define HX8357_CS 48 +#define HX8357_RS 47 // AKA DC +#define HX8357_RESET 46 +#define HX8357_SCK SPI_SCK +#define HX8357_MOSI SPI_MOSI +#define HX8357_MISO SPI_MISO +#define HX8357_BUSY -1 +#define HX8357_SPI_HOST SPI2_HOST +#define SPI_FREQUENCY 40000000 +#define SPI_READ_FREQUENCY 16000000 +#define TFT_HEIGHT 480 +#define TFT_WIDTH 320 +#define TFT_OFFSET_X 0 +#define TFT_OFFSET_Y 0 +#define TFT_OFFSET_ROTATION 6 // the unPhone's screen is wired unusually, 0 is typical value here +#define TFT_INVERT false +#define SCREEN_ROTATE true +#define SCREEN_TRANSITION_FRAMERATE 5 + +#define HAS_TOUCHSCREEN 1 +#define USE_XPT2046 1 +#define TOUCH_CS 38 + +#define HAS_GPS 0 // the unphone doesn't have a gps module +#undef GPS_RX_PIN +#undef GPS_TX_PIN + +#define HAS_SDCARD 1 +#define SDCARD_CS 43 + +#define LED_PIN 13 // the red part of the RGB LED +#define LED_INVERTED 1 + +#define BUTTON_PIN 21 // Button 3 - square - top button in landscape mode +#define BUTTON_NEED_PULLUP // we do need a helping hand up + +#define I2C_SDA 3 // I2C pins for this board +#define I2C_SCL 4 + +// ratio of voltage divider = 3.20 (R1=100k, R2=220k) +// #define ADC_MULTIPLIER 3.2 + +// #define BATTERY_PIN 13 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +// #define ADC_CHANNEL ADC2_GPIO13_CHANNEL +// #define BAT_MEASURE_ADC_UNIT 2 \ No newline at end of file From 4cdfae71cfe2a47b6265adb6bc2041384dcc6114 Mon Sep 17 00:00:00 2001 From: Gareth Coleman Date: Wed, 3 Apr 2024 20:34:31 +0100 Subject: [PATCH 019/108] first attempt at getting trunk to do linting --- src/graphics/TFTDisplay.cpp | 10 +++++----- variants/unphone/variant.h | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index c1f482b84..8de415185 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -410,10 +410,10 @@ class LGFX : public lgfx::LGFX_Device { lgfx::Panel_HX8357D _panel_instance; lgfx::Bus_SPI _bus_instance; - #if defined(USE_XPT2046) +#if defined(USE_XPT2046) lgfx::ITouch *_touch_instance; - // lgfx::Touch_XPT2046 _touch_instance; - #endif +// lgfx::Touch_XPT2046 _touch_instance; +#endif public: LGFX(void) @@ -463,7 +463,7 @@ class LGFX : public lgfx::LGFX_Device _panel_instance.config(cfg); } - #if defined(USE_XPT2046) +#if defined(USE_XPT2046) { // Configure settings for touch control. _touch_instance = new lgfx::Touch_XPT2046; @@ -481,7 +481,7 @@ class LGFX : public lgfx::LGFX_Device _touch_instance->config(touch_cfg); //_panel_instance->setTouch(_touch_instance); } - #endif +#endif setPanel(&_panel_instance); } }; diff --git a/variants/unphone/variant.h b/variants/unphone/variant.h index 3032156f4..dff03b8d5 100644 --- a/variants/unphone/variant.h +++ b/variants/unphone/variant.h @@ -28,7 +28,7 @@ #define TFT_WIDTH 320 #define TFT_OFFSET_X 0 #define TFT_OFFSET_Y 0 -#define TFT_OFFSET_ROTATION 6 // the unPhone's screen is wired unusually, 0 is typical value here +#define TFT_OFFSET_ROTATION 6 // the unPhone's screen is wired unusually, 0 is typical value here #define TFT_INVERT false #define SCREEN_ROTATE true #define SCREEN_TRANSITION_FRAMERATE 5 @@ -37,20 +37,20 @@ #define USE_XPT2046 1 #define TOUCH_CS 38 -#define HAS_GPS 0 // the unphone doesn't have a gps module +#define HAS_GPS 0 // the unphone doesn't have a gps module #undef GPS_RX_PIN #undef GPS_TX_PIN #define HAS_SDCARD 1 #define SDCARD_CS 43 -#define LED_PIN 13 // the red part of the RGB LED +#define LED_PIN 13 // the red part of the RGB LED #define LED_INVERTED 1 -#define BUTTON_PIN 21 // Button 3 - square - top button in landscape mode +#define BUTTON_PIN 21 // Button 3 - square - top button in landscape mode #define BUTTON_NEED_PULLUP // we do need a helping hand up -#define I2C_SDA 3 // I2C pins for this board +#define I2C_SDA 3 // I2C pins for this board #define I2C_SCL 4 // ratio of voltage divider = 3.20 (R1=100k, R2=220k) From 902f38238daefe5b6acb13ca86d73de9ea4dcd8d Mon Sep 17 00:00:00 2001 From: Gareth Coleman <30833824+garethhcoleman@users.noreply.github.com> Date: Fri, 5 Apr 2024 13:20:22 +0100 Subject: [PATCH 020/108] This change to the I2C Scan is to distinguish between two devices (#3554) sharing the same I2C address, the QMI8658 IMU and BQ24295 PMU. --- src/detect/ScanI2C.h | 1 + src/detect/ScanI2CTwoWire.cpp | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index 66e683982..ecb6db225 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -38,6 +38,7 @@ class ScanI2C MPU6050, LIS3DH, BMA423, + BQ24295, #ifdef HAS_NCP5623 NCP5623, #endif diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index 146daa3dc..ea6e692df 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -293,7 +293,18 @@ void ScanI2CTwoWire::scanPort(I2CPort port) SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB sensor found\n") SCAN_SIMPLE_CASE(QMC6310_ADDR, QMC6310, "QMC6310 Highrate 3-Axis magnetic sensor found\n") - SCAN_SIMPLE_CASE(QMI8658_ADDR, QMI8658, "QMI8658 Highrate 6-Axis inertial measurement sensor found\n") + + case QMI8658_ADDR: + registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0A), 1); // get ID + if (registerValue == 0xC0) { + type = BQ24295; + LOG_INFO("BQ24295 PMU found\n"); + } else { + type = QMI8658; + LOG_INFO("QMI8658 Highrate 6-Axis inertial measurement sensor found\n"); + } + break; + SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L Highrate 3-Axis magnetic sensor found\n") SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found\n") From f6e6f975c03920a46ae3be2ab23132c3fd3df7ae Mon Sep 17 00:00:00 2001 From: fuutott Date: Fri, 5 Apr 2024 14:58:00 +0100 Subject: [PATCH 021/108] Update platformio.ini should be dash instead of underscore --- variants/rpipico-slowclock/platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/variants/rpipico-slowclock/platformio.ini b/variants/rpipico-slowclock/platformio.ini index e583c4b0d..eec76ca0f 100644 --- a/variants/rpipico-slowclock/platformio.ini +++ b/variants/rpipico-slowclock/platformio.ini @@ -15,7 +15,7 @@ debug_init_cmds = # add our variants files to the include and src paths build_flags = ${rp2040_base.build_flags} -DRPI_PICO - -Ivariants/rpipico_slowclock + -Ivariants/rpipico-slowclock -DDEBUG_RP2040_PORT=Serial2 -DHW_SPI1_DEVICE -L "${platformio.libdeps_dir}/${this.__env__}/BSEC2 Software Library/src/cortex-m0plus" @@ -25,4 +25,4 @@ lib_deps = ${rp2040_base.lib_deps} debug_build_flags = ${rp2040_base.build_flags} -g - -DNO_USB \ No newline at end of file + -DNO_USB From 5b5f9c62b5d0afc691487da33eed4446fded04a2 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Sun, 7 Apr 2024 02:04:26 +1300 Subject: [PATCH 022/108] Remap backlight toggle and touch button (#3560) * Update E-Ink display after sending adhoc ping or disable/enable GPS * Resume display updates when touch button pressed * Use touch hold as modifier; change double-click behavior for user button * Fix preprocessor exclusions * Purge backlight behavior * Distinguish between 3x and 4x multi-presses * Touch button considers "Wake screen on tap or motion" user-setting * Don't assume device has BUTTON_PIN * Rename misleading method --- src/ButtonThread.cpp | 84 ++++++++++++++++++++++++++++++++--------- src/ButtonThread.h | 10 +++-- src/graphics/Screen.cpp | 25 +++++++++++- src/graphics/Screen.h | 4 +- 4 files changed, 99 insertions(+), 24 deletions(-) diff --git a/src/ButtonThread.cpp b/src/ButtonThread.cpp index a1f0170e8..069a92308 100644 --- a/src/ButtonThread.cpp +++ b/src/ButtonThread.cpp @@ -48,7 +48,7 @@ ButtonThread::ButtonThread() : OSThread("Button") userButton.setPressMs(c_longPressTime); userButton.setDebounceMs(1); userButton.attachDoubleClick(userButtonDoublePressed); - userButton.attachMultiClick(userButtonMultiPressed); + userButton.attachMultiClick(userButtonMultiPressed, this); // Reference to instance: get click count from non-static OneButton #ifndef T_DECK // T-Deck immediately wakes up after shutdown, so disable this function userButton.attachLongPressStart(userButtonPressedLongStart); userButton.attachLongPressStop(userButtonPressedLongStop); @@ -86,7 +86,8 @@ ButtonThread::ButtonThread() : OSThread("Button") #ifdef BUTTON_PIN_TOUCH userButtonTouch = OneButton(BUTTON_PIN_TOUCH, true, true); - userButtonTouch.attachClick(touchPressed); + userButtonTouch.setPressMs(400); + userButtonTouch.attachLongPressStart(touchPressedLongStart); // Better handling with longpress than click? wakeOnIrq(BUTTON_PIN_TOUCH, FALLING); #endif } @@ -138,26 +139,42 @@ int32_t ButtonThread::runOnce() case BUTTON_EVENT_DOUBLE_PRESSED: { LOG_BUTTON("Double press!\n"); -#if defined(USE_EINK) && defined(PIN_EINK_EN) - digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW); -#endif service.refreshLocalMeshNode(); service.sendNetworkPing(NODENUM_BROADCAST, true); - if (screen) + if (screen) { screen->print("Sent ad-hoc ping\n"); - break; - } -#if HAS_GPS - case BUTTON_EVENT_MULTI_PRESSED: { - LOG_BUTTON("Multi press!\n"); - if (!config.device.disable_triple_click && (gps != nullptr)) { - gps->toggleGpsMode(); - if (screen) - screen->forceDisplay(); + screen->forceDisplay(true); // Force a new UI frame, then force an EInk update } break; } + + case BUTTON_EVENT_MULTI_PRESSED: { + LOG_BUTTON("Mulitipress! %hux\n", multipressClickCount); + switch (multipressClickCount) { +#if HAS_GPS + // 3 clicks: toggle GPS + case 3: + if (!config.device.disable_triple_click && (gps != nullptr)) { + gps->toggleGpsMode(); + if (screen) + screen->forceDisplay(true); // Force a new UI frame, then force an EInk update + } + break; #endif +#if defined(USE_EINK) && defined(PIN_EINK_EN) // i.e. T-Echo + // 4 clicks: toggle backlight + case 4: + digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW); + break; +#endif + // No valid multipress action + default: + break; + } // end switch: click count + + break; + } // end multipress event + case BUTTON_EVENT_LONG_PRESSED: { LOG_BUTTON("Long press!\n"); powerFSM.trigger(EVENT_PRESS); @@ -176,12 +193,24 @@ int32_t ButtonThread::runOnce() power->shutdown(); break; } - case BUTTON_EVENT_TOUCH_PRESSED: { + +#ifdef BUTTON_PIN_TOUCH + case BUTTON_EVENT_TOUCH_LONG_PRESSED: { LOG_BUTTON("Touch press!\n"); - if (screen) - screen->forceDisplay(); + if (config.display.wake_on_tap_or_motion) { + if (screen) { + // Wake if asleep + if (powerFSM.getState() == &stateDARK) + powerFSM.trigger(EVENT_PRESS); + + // Update display (legacy behaviour) + screen->forceDisplay(); + } + } break; } +#endif // BUTTON_PIN_TOUCH + default: break; } @@ -206,6 +235,25 @@ void ButtonThread::wakeOnIrq(int irq, int mode) FALLING); } +// Static callback +void ButtonThread::userButtonMultiPressed(void *callerThread) +{ + // Grab click count from non-static button, while the info is still valid + ButtonThread *thread = (ButtonThread *)callerThread; + thread->storeClickCount(); + + // Then handle later, in the usual way + btnEvent = BUTTON_EVENT_MULTI_PRESSED; +} + +// Non-static method, runs during callback. Grabs info while still valid +void ButtonThread::storeClickCount() +{ +#ifdef BUTTON_PIN + multipressClickCount = userButton.getNumberClicks(); +#endif +} + void ButtonThread::userButtonPressedLongStart() { if (millis() > c_holdOffTime) { diff --git a/src/ButtonThread.h b/src/ButtonThread.h index 554c1f0c4..3f177302d 100644 --- a/src/ButtonThread.h +++ b/src/ButtonThread.h @@ -17,11 +17,12 @@ class ButtonThread : public concurrency::OSThread BUTTON_EVENT_MULTI_PRESSED, BUTTON_EVENT_LONG_PRESSED, BUTTON_EVENT_LONG_RELEASED, - BUTTON_EVENT_TOUCH_PRESSED + BUTTON_EVENT_TOUCH_LONG_PRESSED, }; ButtonThread(); int32_t runOnce() override; + void storeClickCount(); private: #ifdef BUTTON_PIN @@ -40,13 +41,16 @@ class ButtonThread : public concurrency::OSThread // set during IRQ static volatile ButtonEventType btnEvent; + // Store click count during callback, for later use + volatile int multipressClickCount = 0; + static void wakeOnIrq(int irq, int mode); // IRQ callbacks - static void touchPressed() { btnEvent = BUTTON_EVENT_TOUCH_PRESSED; } static void userButtonPressed() { btnEvent = BUTTON_EVENT_PRESSED; } static void userButtonDoublePressed() { btnEvent = BUTTON_EVENT_DOUBLE_PRESSED; } - static void userButtonMultiPressed() { btnEvent = BUTTON_EVENT_MULTI_PRESSED; } + static void userButtonMultiPressed(void *callerThread); // Retrieve click count from non-static Onebutton while still valid static void userButtonPressedLongStart(); static void userButtonPressedLongStop(); + static void touchPressedLongStart() { btnEvent = BUTTON_EVENT_TOUCH_LONG_PRESSED; } }; diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 8510562c4..11c0b7aa0 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1153,10 +1153,33 @@ void Screen::setup() MeshModule::observeUIEvents(&uiFrameEventObserver); } -void Screen::forceDisplay() +void Screen::forceDisplay(bool forceUiUpdate) { // Nasty hack to force epaper updates for 'key' frames. FIXME, cleanup. #ifdef USE_EINK + // If requested, make sure queued commands are run, and UI has rendered a new frame + if (forceUiUpdate) { + // No delay between UI frame rendering + setFastFramerate(); + + // Make sure all CMDs have run first + while (!cmdQueue.isEmpty()) + runOnce(); + + // Ensure at least one frame has drawn + uint64_t startUpdate; + do { + startUpdate = millis(); // Handle impossibly unlikely corner case of a millis() overflow.. + delay(10); + ui->update(); + } while (ui->getUiState()->lastUpdate < startUpdate); + + // Return to normal frame rate + targetFramerate = IDLE_FRAMERATE; + ui->setTargetFPS(targetFramerate); + } + + // Tell EInk class to update the display static_cast(dispdev)->forceDisplay(); #endif } diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index d03ba4320..2cb1cd5a9 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -20,7 +20,7 @@ class Screen void setOn(bool) {} void print(const char *) {} void doDeepSleep() {} - void forceDisplay() {} + void forceDisplay(bool forceUiUpdate = false) {} void startBluetoothPinScreen(uint32_t pin) {} void stopBluetoothPinScreen() {} void startRebootScreen() {} @@ -318,7 +318,7 @@ class Screen : public concurrency::OSThread int handleInputEvent(const InputEvent *arg); /// Used to force (super slow) eink displays to draw critical frames - void forceDisplay(); + void forceDisplay(bool forceUiUpdate = false); /// Draws our SSL cert screen during boot (called from WebServer) void setSSLFrames(); From 03f60dcb49184bab4474b9a0e8cf1302ac278da8 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sat, 6 Apr 2024 08:04:49 -0500 Subject: [PATCH 023/108] Make instructions clearer in config.yaml comments (#3559) --- bin/config-dist.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/config-dist.yaml b/bin/config-dist.yaml index 22ca3e7db..5a8e658cb 100644 --- a/bin/config-dist.yaml +++ b/bin/config-dist.yaml @@ -1,5 +1,6 @@ ### Define your devices here using Broadcom pin numbering ### Uncomment the block that corresponds to your hardware +### Including the "Module:" line! --- Lora: # Module: sx1262 # Waveshare SX126X XXXM From 0e9f1beb4055264d585c5cabf36c757b6f0929e6 Mon Sep 17 00:00:00 2001 From: Jared Quinn Date: Sun, 7 Apr 2024 02:32:15 +1100 Subject: [PATCH 024/108] Native Linux Build (ARM support and webserver deps) (#3506) * Added webserver libraries to build libs * Revert "Added webserver libraries to build libs" This reverts commit bcc72a06b9e1d26f57f46089ab96f502703bff3c. * Added piwebserver library dependencies to native build * Add webserver libraries to apt install for native build * Revert additional libraries added by mistake * Address trunk check issues on Dockerfile * Ignore linter checks for pinning build packages and apt-get --------- Co-authored-by: Jonathan Bennett Co-authored-by: Ben Meadors --- Dockerfile | 52 +++++++++++++++++++++++------------- arch/portduino/portduino.ini | 2 +- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/Dockerfile b/Dockerfile index 21e42ad87..76aa3e2a1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:bullseye-slim AS builder +FROM debian:bookworm-slim AS builder ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Etc/UTC @@ -11,31 +11,45 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"] # Install build deps USER root -RUN apt-get update && \ - apt-get -y install wget python3 g++ zip python3-venv git vim ca-certificates libgpiod-dev libyaml-cpp-dev libbluetooth-dev -# create a non-priveleged user & group +# trunk-ignore(terrascan/AC_DOCKER_0002): Known terrascan issue +# trunk-ignore(hadolint/DL3008): Use latest version of packages for buildchain +RUN apt-get update && apt-get install --no-install-recommends -y wget python3 python3-pip python3-wheel python3-venv g++ zip git \ + ca-certificates libgpiod-dev libyaml-cpp-dev libbluetooth-dev \ + libulfius-dev liborcania-dev libssl-dev pkg-config && \ + apt-get clean && rm -rf /var/lib/apt/lists/* + RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh - USER mesh -RUN wget https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py -qO /tmp/get-platformio.py && \ - chmod +x /tmp/get-platformio.py && \ - python3 /tmp/get-platformio.py && \ - git clone https://github.com/meshtastic/firmware --recurse-submodules /tmp/firmware && \ - cd /tmp/firmware && \ - chmod +x /tmp/firmware/bin/build-native.sh && \ - source ~/.platformio/penv/bin/activate && \ - ./bin/build-native.sh -FROM frolvlad/alpine-glibc:glibc-2.31 +WORKDIR /tmp/firmware +RUN python3 -m venv /tmp/firmware +RUN source ./bin/activate && pip3 install --no-cache-dir -U platformio==6.1.14 -RUN apk --update add --no-cache g++ shadow && \ - groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh +COPY . /tmp/firmware +RUN source ./bin/activate && chmod +x /tmp/firmware/bin/build-native.sh && ./bin/build-native.sh +RUN cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd" -COPY --from=builder /tmp/firmware/release/meshtasticd_linux_x86_64 /home/mesh/ +##### PRODUCTION BUILD ############# + +FROM debian:bookworm-slim +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=Etc/UTC + +# trunk-ignore(terrascan/AC_DOCKER_0002): Known terrascan issue +# trunk-ignore(hadolint/DL3008): Use latest version of packages for buildchain +RUN apt-get update && apt-get --no-install-recommends -y install libc-bin libc6 libgpiod2 libyaml-cpp0.7 libulfius2.7 liborcania2.3 libssl3 && \ + apt-get clean && rm -rf /var/lib/apt/lists/* + +RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh USER mesh + WORKDIR /home/mesh -CMD sh -cx "./meshtasticd_linux_x86_64 --hwid '${HWID:-$RANDOM}'" +COPY --from=builder /tmp/firmware/release/meshtasticd /home/mesh/ -HEALTHCHECK NONE \ No newline at end of file +VOLUME /home/mesh/data + +CMD [ "sh", "-cx", "./meshtasticd -d /home/mesh/data --hwid=${HWID:-$RANDOM}" ] + +HEALTHCHECK NONE diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index 077a49b3f..3c996741c 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -34,4 +34,4 @@ build_flags = -DPORTDUINO_LINUX_HARDWARE -lbluetooth -lgpiod - -lyaml-cpp \ No newline at end of file + -lyaml-cpp From 1baad2875a122fcd876024f5145587b38e711efd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Sun, 7 Apr 2024 02:12:57 +0200 Subject: [PATCH 025/108] Add keymappings for several utility functions (#3536) * - map fn+m to mute and unmute the external notification module - map fn+t to be an alternative for the TAB key * add whitelist to inputbroker * (maybe) sweet-talking t-deck into tabbing... * now for real - back in Kansas * More fancy mappings --------- Co-authored-by: Ben Meadors --- src/input/kbI2cBase.cpp | 4 +++ src/modules/CannedMessageModule.cpp | 42 ++++++++++++++++++++-- src/modules/ExternalNotificationModule.cpp | 4 +-- src/modules/ExternalNotificationModule.h | 5 +++ 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/input/kbI2cBase.cpp b/src/input/kbI2cBase.cpp index 048f8bbdc..74a6c718d 100644 --- a/src/input/kbI2cBase.cpp +++ b/src/input/kbI2cBase.cpp @@ -217,7 +217,11 @@ int32_t KbI2cBase::runOnce() e.kbchar = 0xb7; break; case 0x90: // fn+r + case 0x91: // fn+t case 0x9b: // fn+s + case 0xac: // fn+m + case 0x9e: // fn+g + case 0xaf: // fn+space // just pass those unmodified e.inputEvent = ANYKEY; e.kbchar = c; diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index 60334ca03..c1cf90325 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -12,7 +12,11 @@ #include "detect/ScanI2C.h" #include "mesh/generated/meshtastic/cannedmessages.pb.h" -#include "main.h" // for cardkb_found +#include "main.h" // for cardkb_found +#include "modules/ExternalNotificationModule.h" // for buzzer control +#if !MESHTASTIC_EXCLUDE_GPS +#include "GPS.h" +#endif #ifndef INPUTBROKER_MATRIX_TYPE #define INPUTBROKER_MATRIX_TYPE 0 @@ -397,6 +401,7 @@ int32_t CannedMessageModule::runOnce() } break; case 0x09: // tab + case 0x91: // alt+t for T-Deck that doesn't have a tab key if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_CHANNEL) { this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE; } else if (this->destSelect == CANNED_MESSAGE_DESTINATION_TYPE_NODE) { @@ -411,13 +416,44 @@ int32_t CannedMessageModule::runOnce() break; // handle fn+s for shutdown case 0x9b: - screen->startShutdownScreen(); + if (screen) + screen->startShutdownScreen(); shutdownAtMsec = millis() + DEFAULT_SHUTDOWN_SECONDS * 1000; + runState = CANNED_MESSAGE_RUN_STATE_INACTIVE; break; // and fn+r for reboot case 0x90: - screen->startRebootScreen(); + if (screen) + screen->startRebootScreen(); rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 1000; + runState = CANNED_MESSAGE_RUN_STATE_INACTIVE; + break; + case 0x9e: // toggle GPS like triple press does + if (gps != nullptr) { + gps->toggleGpsMode(); + } + if (screen) + screen->forceDisplay(); + runState = CANNED_MESSAGE_RUN_STATE_INACTIVE; + break; + + // mute (switch off/toggle) external notifications on fn+m + case 0xac: + if (moduleConfig.external_notification.enabled == true) { + if (externalNotificationModule->getMute()) { + externalNotificationModule->setMute(false); + runState = CANNED_MESSAGE_RUN_STATE_INACTIVE; + } else { + externalNotificationModule->stopNow(); // this will turn off all GPIO and sounds and idle the loop + externalNotificationModule->setMute(true); + runState = CANNED_MESSAGE_RUN_STATE_INACTIVE; + } + } + break; + case 0xaf: // fn+space send network ping like double press does + service.refreshLocalMeshNode(); + service.sendNetworkPing(NODENUM_BROADCAST, true); + runState = CANNED_MESSAGE_RUN_STATE_INACTIVE; break; default: if (this->cursor == this->freetext.length()) { diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp index 2a4fdd0ae..617796544 100644 --- a/src/modules/ExternalNotificationModule.cpp +++ b/src/modules/ExternalNotificationModule.cpp @@ -336,7 +336,7 @@ ExternalNotificationModule::ExternalNotificationModule() ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshPacket &mp) { - if (moduleConfig.external_notification.enabled) { + if (moduleConfig.external_notification.enabled && !isMuted) { #ifdef T_WATCH_S3 drv.setWaveform(0, 75); drv.setWaveform(1, 56); @@ -445,7 +445,7 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP setIntervalFromNow(0); // run once so we know if we should do something } } else { - LOG_INFO("External Notification Module Disabled\n"); + LOG_INFO("External Notification Module Disabled or muted\n"); } return ProcessMessage::CONTINUE; // Let others look at this message also if they want diff --git a/src/modules/ExternalNotificationModule.h b/src/modules/ExternalNotificationModule.h index 3331ec428..08e72c35a 100644 --- a/src/modules/ExternalNotificationModule.h +++ b/src/modules/ExternalNotificationModule.h @@ -38,6 +38,9 @@ class ExternalNotificationModule : public SinglePortModule, private concurrency: void setExternalOff(uint8_t index = 0); bool getExternal(uint8_t index = 0); + void setMute(bool mute) { isMuted = mute; } + bool getMute() { return isMuted; } + void stopNow(); void handleGetRingtone(const meshtastic_MeshPacket &req, meshtastic_AdminMessage *response); @@ -56,6 +59,8 @@ class ExternalNotificationModule : public SinglePortModule, private concurrency: bool isNagging = false; + bool isMuted = false; + virtual AdminMessageHandleResult handleAdminMessageForModule(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *request, meshtastic_AdminMessage *response) override; From 2db061ded9df0a495f83d0d1c0bdc5d11f14569b Mon Sep 17 00:00:00 2001 From: caveman99 Date: Sun, 7 Apr 2024 13:58:58 +0000 Subject: [PATCH 026/108] [create-pull-request] automated change --- protobufs | 2 +- src/mesh/generated/meshtastic/config.pb.h | 12 ++++++++---- src/mesh/generated/meshtastic/deviceonly.pb.h | 2 +- src/mesh/generated/meshtastic/localonly.pb.h | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/protobufs b/protobufs index 6157a5723..68720ed8d 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 6157a5723745b3a750720b94676198a7f3839e2a +Subproject commit 68720ed8dbcb2c055e3d1ecd4f78d60692f59493 diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index 67c745214..ed512f12f 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -281,6 +281,8 @@ typedef struct _meshtastic_Config_DeviceConfig { bool is_managed; /* Disables the triple-press of user button to enable or disable GPS */ bool disable_triple_click; + /* POSIX Timezone definition string from https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv. */ + char tzdef[65]; } meshtastic_Config_DeviceConfig; /* Position Config */ @@ -583,7 +585,7 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}} -#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0} +#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, ""} #define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN} #define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""} @@ -592,7 +594,7 @@ extern "C" { #define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0} #define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0} #define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}} -#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0} +#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, ""} #define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN} #define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""} @@ -612,6 +614,7 @@ extern "C" { #define meshtastic_Config_DeviceConfig_double_tap_as_button_press_tag 8 #define meshtastic_Config_DeviceConfig_is_managed_tag 9 #define meshtastic_Config_DeviceConfig_disable_triple_click_tag 10 +#define meshtastic_Config_DeviceConfig_tzdef_tag 11 #define meshtastic_Config_PositionConfig_position_broadcast_secs_tag 1 #define meshtastic_Config_PositionConfig_position_broadcast_smart_enabled_tag 2 #define meshtastic_Config_PositionConfig_fixed_position_tag 3 @@ -711,7 +714,8 @@ X(a, STATIC, SINGULAR, UENUM, rebroadcast_mode, 6) \ X(a, STATIC, SINGULAR, UINT32, node_info_broadcast_secs, 7) \ X(a, STATIC, SINGULAR, BOOL, double_tap_as_button_press, 8) \ X(a, STATIC, SINGULAR, BOOL, is_managed, 9) \ -X(a, STATIC, SINGULAR, BOOL, disable_triple_click, 10) +X(a, STATIC, SINGULAR, BOOL, disable_triple_click, 10) \ +X(a, STATIC, SINGULAR, STRING, tzdef, 11) #define meshtastic_Config_DeviceConfig_CALLBACK NULL #define meshtastic_Config_DeviceConfig_DEFAULT NULL @@ -829,7 +833,7 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg; /* Maximum encoded size of messages (where known) */ #define meshtastic_Config_BluetoothConfig_size 10 -#define meshtastic_Config_DeviceConfig_size 32 +#define meshtastic_Config_DeviceConfig_size 98 #define meshtastic_Config_DisplayConfig_size 28 #define meshtastic_Config_LoRaConfig_size 80 #define meshtastic_Config_NetworkConfig_IpV4Config_size 20 diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index cdd59d871..bec15eb90 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -307,7 +307,7 @@ extern const pb_msgdesc_t meshtastic_OEMStore_msg; /* meshtastic_DeviceState_size depends on runtime parameters */ #define meshtastic_ChannelFile_size 702 #define meshtastic_NodeInfoLite_size 160 -#define meshtastic_OEMStore_size 3278 +#define meshtastic_OEMStore_size 3344 #define meshtastic_PositionLite_size 28 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index f27c119bd..1f431d788 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -180,7 +180,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; #define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg /* Maximum encoded size of messages (where known) */ -#define meshtastic_LocalConfig_size 469 +#define meshtastic_LocalConfig_size 535 #define meshtastic_LocalModuleConfig_size 663 #ifdef __cplusplus From 40a7fd145a9f3e00712b33bd5c5223182e90fd0a Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sun, 7 Apr 2024 14:15:03 -0500 Subject: [PATCH 027/108] Update Dockerfile to remove sticky bit during build (#3567) * Update Dockerfile to remove sticky bit during build * no sudo? --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 76aa3e2a1..a6176c32b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN python3 -m venv /tmp/firmware RUN source ./bin/activate && pip3 install --no-cache-dir -U platformio==6.1.14 COPY . /tmp/firmware -RUN source ./bin/activate && chmod +x /tmp/firmware/bin/build-native.sh && ./bin/build-native.sh +RUN source ./bin/activate && chmod -t /tmp/firmware -R && chmod +x /tmp/firmware/bin/build-native.sh && ./bin/build-native.sh RUN cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd" From fde20db95f75aae36589474a1ad68997ddf1e9e9 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sun, 7 Apr 2024 14:22:39 -0500 Subject: [PATCH 028/108] move chmod -t to root section --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index a6176c32b..230ddc787 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ USER root RUN apt-get update && apt-get install --no-install-recommends -y wget python3 python3-pip python3-wheel python3-venv g++ zip git \ ca-certificates libgpiod-dev libyaml-cpp-dev libbluetooth-dev \ libulfius-dev liborcania-dev libssl-dev pkg-config && \ - apt-get clean && rm -rf /var/lib/apt/lists/* + apt-get clean && rm -rf /var/lib/apt/lists/* && mkdir /tmp/firmware && chmod -t /tmp/firmware RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh USER mesh @@ -27,7 +27,7 @@ RUN python3 -m venv /tmp/firmware RUN source ./bin/activate && pip3 install --no-cache-dir -U platformio==6.1.14 COPY . /tmp/firmware -RUN source ./bin/activate && chmod -t /tmp/firmware -R && chmod +x /tmp/firmware/bin/build-native.sh && ./bin/build-native.sh +RUN source ./bin/activate && chmod +x /tmp/firmware/bin/build-native.sh && ./bin/build-native.sh RUN cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd" From 47b8f7b6c63f919ebdb3658d28cb0e09d0b8fcc1 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sun, 7 Apr 2024 14:34:19 -0500 Subject: [PATCH 029/108] Don't forget to change directory owner --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 230ddc787..cd848208d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ RUN apt-get update && apt-get install --no-install-recommends -y wget python3 py libulfius-dev liborcania-dev libssl-dev pkg-config && \ apt-get clean && rm -rf /var/lib/apt/lists/* && mkdir /tmp/firmware && chmod -t /tmp/firmware -RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh +RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh && chown mesh:mesh /tmp/firmware USER mesh WORKDIR /tmp/firmware From 68e657fd07f416b855b7c4cd70d9c1b15b05e55a Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sun, 7 Apr 2024 15:52:43 -0500 Subject: [PATCH 030/108] Actually fix Docker - hopefully --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index cd848208d..fc6648dec 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ USER root RUN apt-get update && apt-get install --no-install-recommends -y wget python3 python3-pip python3-wheel python3-venv g++ zip git \ ca-certificates libgpiod-dev libyaml-cpp-dev libbluetooth-dev \ libulfius-dev liborcania-dev libssl-dev pkg-config && \ - apt-get clean && rm -rf /var/lib/apt/lists/* && mkdir /tmp/firmware && chmod -t /tmp/firmware + apt-get clean && rm -rf /var/lib/apt/lists/* && mkdir /tmp/firmware RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh && chown mesh:mesh /tmp/firmware USER mesh @@ -26,7 +26,7 @@ WORKDIR /tmp/firmware RUN python3 -m venv /tmp/firmware RUN source ./bin/activate && pip3 install --no-cache-dir -U platformio==6.1.14 -COPY . /tmp/firmware +COPY --chown=mesh:mesh . /tmp/firmware RUN source ./bin/activate && chmod +x /tmp/firmware/bin/build-native.sh && ./bin/build-native.sh RUN cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd" From aa3280c18c500cc29b9aac3cd19b6be4e37cf39d Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sun, 7 Apr 2024 17:08:17 -0500 Subject: [PATCH 031/108] add trunk ignore for docker chmod (#3568) * add trunk ignore for docker chmod * Fix incorrect comment type --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index fc6648dec..fee6c62d4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,7 @@ USER mesh WORKDIR /tmp/firmware RUN python3 -m venv /tmp/firmware RUN source ./bin/activate && pip3 install --no-cache-dir -U platformio==6.1.14 - +# trunk-ignore(terrascan/AC_DOCKER_00024): We would actually like these files to be owned by mesh tyvm COPY --chown=mesh:mesh . /tmp/firmware RUN source ./bin/activate && chmod +x /tmp/firmware/bin/build-native.sh && ./bin/build-native.sh RUN cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd" From 65e5bdc212e42f3a94f75d84e7ef9cc9c8cc6651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Mon, 8 Apr 2024 00:01:44 +0200 Subject: [PATCH 032/108] display log and onscreen times in local timezone --- src/RedirectablePrint.cpp | 2 +- src/gps/RTC.cpp | 39 +++++++++++++++++++++++++++++++++------ src/gps/RTC.h | 4 ++-- src/graphics/Screen.cpp | 2 +- src/main.cpp | 9 +++++++++ 5 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/RedirectablePrint.cpp b/src/RedirectablePrint.cpp index d3f39c377..16906e2e0 100644 --- a/src/RedirectablePrint.cpp +++ b/src/RedirectablePrint.cpp @@ -99,7 +99,7 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...) // If we are the first message on a report, include the header if (!isContinuationMessage) { - uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice); + uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // display local time on logfile if (rtc_sec > 0) { long hms = rtc_sec % SEC_PER_DAY; // hms += tz.tz_dsttime * SEC_PER_HOUR; diff --git a/src/gps/RTC.cpp b/src/gps/RTC.cpp index 10e9e0331..58b267a6c 100644 --- a/src/gps/RTC.cpp +++ b/src/gps/RTC.cpp @@ -128,7 +128,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv) #else rtc.initI2C(); #endif - tm *t = localtime(&tv->tv_sec); + tm *t = gmtime(&tv->tv_sec); rtc.setTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_wday, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); LOG_DEBUG("RV3028_RTC setTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec); @@ -142,7 +142,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv) #else rtc.begin(); #endif - tm *t = localtime(&tv->tv_sec); + tm *t = gmtime(&tv->tv_sec); rtc.setDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); LOG_DEBUG("PCF8563_RTC setDateTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec); @@ -175,7 +175,15 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t) The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970 (midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z). */ + // horrible hack to make mktime TZ agnostic - best practise according to + // https://www.gnu.org/software/libc/manual/html_node/Broken_002ddown-Time.html + setenv("TZ", "GMT0", 1); time_t res = mktime(&t); + if (*config.device.tzdef) { + setenv("TZ", config.device.tzdef, 1); + } else { + setenv("TZ", "UTC0", 1); + } struct timeval tv; tv.tv_sec = res; tv.tv_usec = 0; // time.centisecond() * (10 / 1000); @@ -189,14 +197,33 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t) } } +/** + * Returns the timezone offset in seconds. + * + * @return The timezone offset in seconds. + */ +int32_t getTZOffset() +{ + time_t now; + struct tm *gmt; + now = time(NULL); + gmt = gmtime(&now); + gmt->tm_isdst = -1; + return (int16_t)difftime(now, mktime(gmt)); +} + /** * Returns the current time in seconds since the Unix epoch (January 1, 1970). * * @return The current time in seconds since the Unix epoch. */ -uint32_t getTime() +uint32_t getTime(bool local) { - return (((uint32_t)millis() - timeStartMsec) / 1000) + zeroOffsetSecs; + if (local) { + return (((uint32_t)millis() - timeStartMsec) / 1000) + zeroOffsetSecs + getTZOffset(); + } else { + return (((uint32_t)millis() - timeStartMsec) / 1000) + zeroOffsetSecs; + } } /** @@ -205,7 +232,7 @@ uint32_t getTime() * @param minQuality The minimum quality of the RTC time required for it to be considered valid. * @return The current time from the RTC if it meets the minimum quality requirement, or 0 if the time is not valid. */ -uint32_t getValidTime(RTCQuality minQuality) +uint32_t getValidTime(RTCQuality minQuality, bool local) { - return (currentQuality >= minQuality) ? getTime() : 0; + return (currentQuality >= minQuality) ? getTime(local) : 0; } diff --git a/src/gps/RTC.h b/src/gps/RTC.h index 527b31f46..f74e17cd0 100644 --- a/src/gps/RTC.h +++ b/src/gps/RTC.h @@ -29,10 +29,10 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv); bool perhapsSetRTC(RTCQuality q, struct tm &t); /// Return time since 1970 in secs. While quality is RTCQualityNone we will be returning time based at zero -uint32_t getTime(); +uint32_t getTime(bool local = false); /// Return time since 1970 in secs. If quality is RTCQualityNone return zero -uint32_t getValidTime(RTCQuality minQuality); +uint32_t getValidTime(RTCQuality minQuality, bool local = false); void readFromRTC(); diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 11c0b7aa0..e5f392036 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -1896,7 +1896,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat // Show uptime as days, hours, minutes OR seconds std::string uptime = screen->drawTimeDelta(days, hours, minutes, seconds); - uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice); + uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // Display local timezone if (rtc_sec > 0) { long hms = rtc_sec % SEC_PER_DAY; // hms += tz.tz_dsttime * SEC_PER_HOUR; diff --git a/src/main.cpp b/src/main.cpp index e93acf0ff..47f3e2c22 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -663,6 +663,15 @@ void setup() // Initialize the screen first so we can show the logo while we start up everything else. screen = new graphics::Screen(screen_found, screen_model, screen_geometry); + // setup TZ prior to time actions. + if (*config.device.tzdef) { + setenv("TZ", config.device.tzdef, 1); + } else { + setenv("TZ", "GMT0", 1); + } + tzset(); + LOG_DEBUG("Set Timezone to %s\n", getenv("TZ")); + readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time) #if !MESHTASTIC_EXCLUDE_GPS From ea61808fd94a74e3a6c24a8cb7fb0df5a5133236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Tue, 9 Apr 2024 00:26:23 +0200 Subject: [PATCH 033/108] tryfix: use UTC on Phone API (#3576) --- src/gps/GPS.cpp | 2 +- src/gps/NMEAWPL.cpp | 4 ++-- src/gps/RTC.cpp | 24 +++++++++++++++--------- src/gps/RTC.h | 2 ++ 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index a6f68f2ef..6a0e3e44a 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -1379,7 +1379,7 @@ bool GPS::lookForLocation() t.tm_mon = reader.date.month() - 1; t.tm_year = reader.date.year() - 1900; t.tm_isdst = false; - p.timestamp = mktime(&t); + p.timestamp = gm_mktime(&t); // Nice to have, if available if (reader.satellites.isUpdated()) { diff --git a/src/gps/NMEAWPL.cpp b/src/gps/NMEAWPL.cpp index cdac3bb27..71943b76c 100644 --- a/src/gps/NMEAWPL.cpp +++ b/src/gps/NMEAWPL.cpp @@ -75,10 +75,10 @@ uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_Position &pos, const uint32_t printGGA(char *buf, size_t bufsz, const meshtastic_Position &pos) { GeoCoord geoCoord(pos.latitude_i, pos.longitude_i, pos.altitude); - tm *t = localtime((time_t *)&pos.timestamp); + tm *t = gmtime((time_t *)&pos.timestamp); if (getRTCQuality() > 0) { // use the device clock if we got time from somewhere. If not, use the GPS timestamp. uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice); - t = localtime((time_t *)&rtc_sec); + t = gmtime((time_t *)&rtc_sec); } uint32_t len = snprintf( diff --git a/src/gps/RTC.cpp b/src/gps/RTC.cpp index 58b267a6c..26af7cac2 100644 --- a/src/gps/RTC.cpp +++ b/src/gps/RTC.cpp @@ -40,7 +40,7 @@ void readFromRTC() t.tm_hour = rtc.getHour(); t.tm_min = rtc.getMinute(); t.tm_sec = rtc.getSecond(); - tv.tv_sec = mktime(&t); + tv.tv_sec = gm_mktime(&t); tv.tv_usec = 0; LOG_DEBUG("Read RTC time from RV3028 as %ld\n", tv.tv_sec); timeStartMsec = now; @@ -68,7 +68,7 @@ void readFromRTC() t.tm_hour = tc.hour; t.tm_min = tc.minute; t.tm_sec = tc.second; - tv.tv_sec = mktime(&t); + tv.tv_sec = gm_mktime(&t); tv.tv_usec = 0; LOG_DEBUG("Read RTC time from PCF8563 as %ld\n", tv.tv_sec); timeStartMsec = now; @@ -177,13 +177,7 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t) */ // horrible hack to make mktime TZ agnostic - best practise according to // https://www.gnu.org/software/libc/manual/html_node/Broken_002ddown-Time.html - setenv("TZ", "GMT0", 1); - time_t res = mktime(&t); - if (*config.device.tzdef) { - setenv("TZ", config.device.tzdef, 1); - } else { - setenv("TZ", "UTC0", 1); - } + time_t res = gm_mktime(&t); struct timeval tv; tv.tv_sec = res; tv.tv_usec = 0; // time.centisecond() * (10 / 1000); @@ -236,3 +230,15 @@ uint32_t getValidTime(RTCQuality minQuality, bool local) { return (currentQuality >= minQuality) ? getTime(local) : 0; } + +time_t gm_mktime(struct tm *tm) +{ + setenv("TZ", "GMT0", 1); + time_t res = mktime(tm); + if (*config.device.tzdef) { + setenv("TZ", config.device.tzdef, 1); + } else { + setenv("TZ", "UTC0", 1); + } + return res; +} diff --git a/src/gps/RTC.h b/src/gps/RTC.h index f74e17cd0..0561819bd 100644 --- a/src/gps/RTC.h +++ b/src/gps/RTC.h @@ -36,6 +36,8 @@ uint32_t getValidTime(RTCQuality minQuality, bool local = false); void readFromRTC(); +time_t gm_mktime(struct tm *tm); + #define SEC_PER_DAY 86400 #define SEC_PER_HOUR 3600 #define SEC_PER_MIN 60 \ No newline at end of file From e89575bfd173852ea60bd515b0735db9b1ac4580 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 18:43:10 -0500 Subject: [PATCH 034/108] [create-pull-request] automated change (#3577) Co-authored-by: thebentern --- version.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.properties b/version.properties index 5f162b8ae..6aedf1e72 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 3 -build = 4 +build = 5 From ec74fba2bd452cd40999158b322a628910210029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Tue, 9 Apr 2024 14:40:55 +0200 Subject: [PATCH 035/108] update to nanopb 0.4.8 and fix proto regen script (#3578) * update to nanopb 0.4.8 and fix proto regen script * trunk, damnit --- .github/workflows/update_protobufs.yml | 6 +++--- bin/regen-protos.bat | 2 +- bin/regen-protos.sh | 14 +++----------- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/.github/workflows/update_protobufs.yml b/.github/workflows/update_protobufs.yml index 6944d827e..30f9b3578 100644 --- a/.github/workflows/update_protobufs.yml +++ b/.github/workflows/update_protobufs.yml @@ -17,9 +17,9 @@ jobs: - name: Download nanopb run: | - wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.7-linux-x86.tar.gz - tar xvzf nanopb-0.4.7-linux-x86.tar.gz - mv nanopb-0.4.7-linux-x86 nanopb-0.4.7 + wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.8-linux-x86.tar.gz + tar xvzf nanopb-0.4.8-linux-x86.tar.gz + mv nanopb-0.4.8-linux-x86 nanopb-0.4.8 - name: Re-generate protocol buffers run: | diff --git a/bin/regen-protos.bat b/bin/regen-protos.bat index 1d55c2506..f28ef0025 100644 --- a/bin/regen-protos.bat +++ b/bin/regen-protos.bat @@ -1 +1 @@ -cd protobufs && ..\nanopb-0.4.7\generator-bin\protoc.exe --experimental_allow_proto3_optional "--nanopb_out=-S.cpp -v:..\src\mesh\generated\" -I=..\protobufs ..\protobufs\meshtastic\*.proto +cd protobufs && ..\nanopb-0.4.8\generator-bin\protoc.exe --experimental_allow_proto3_optional "--nanopb_out=-S.cpp -v:..\src\mesh\generated" -I=..\protobufs\ ..\protobufs\meshtastic\*.proto diff --git a/bin/regen-protos.sh b/bin/regen-protos.sh index 7c751208a..2e60784e3 100755 --- a/bin/regen-protos.sh +++ b/bin/regen-protos.sh @@ -2,18 +2,10 @@ set -e -echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.7 to be located in the" +echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.8 to be located in the" echo "firmware root directory if the following step fails, you should download the correct" -echo "prebuilt binaries for your computer into nanopb-0.4.7" +echo "prebuilt binaries for your computer into nanopb-0.4.8" # the nanopb tool seems to require that the .options file be in the current directory! cd protobufs -../nanopb-0.4.7/generator-bin/protoc "--nanopb_out=-S.cpp -v:../src/mesh/generated/" -I=../protobufs meshtastic/*.proto --experimental_allow_proto3_optional - -# sed -i 's/#include "meshtastic/#include "./g' -- * - -# sed -i 's/meshtastic_//g' -- * - -#echo "Regenerating protobuf documentation - if you see an error message" -#echo "you can ignore it unless doing a new protobuf release to github." -#bin/regen-docs.sh +../nanopb-0.4.8/generator-bin/protoc --experimental_allow_proto3_optional "--nanopb_out=-S.cpp -v:../src/mesh/generated/" -I=../protobufs meshtastic/*.proto From daa64b055a17a5060baf71e3259a9d323600b6e5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 08:00:19 -0500 Subject: [PATCH 036/108] [create-pull-request] automated change (#3579) Co-authored-by: caveman99 --- protobufs | 2 +- src/mesh/generated/meshtastic/admin.pb.cpp | 2 +- src/mesh/generated/meshtastic/admin.pb.h | 3 ++- src/mesh/generated/meshtastic/apponly.pb.cpp | 2 +- src/mesh/generated/meshtastic/apponly.pb.h | 3 ++- src/mesh/generated/meshtastic/atak.pb.cpp | 2 +- src/mesh/generated/meshtastic/atak.pb.h | 3 ++- .../generated/meshtastic/cannedmessages.pb.cpp | 2 +- .../generated/meshtastic/cannedmessages.pb.h | 3 ++- src/mesh/generated/meshtastic/channel.pb.cpp | 2 +- src/mesh/generated/meshtastic/channel.pb.h | 3 ++- src/mesh/generated/meshtastic/clientonly.pb.cpp | 2 +- src/mesh/generated/meshtastic/clientonly.pb.h | 2 +- src/mesh/generated/meshtastic/config.pb.cpp | 2 +- src/mesh/generated/meshtastic/config.pb.h | 3 ++- .../meshtastic/connection_status.pb.cpp | 2 +- .../generated/meshtastic/connection_status.pb.h | 3 ++- src/mesh/generated/meshtastic/deviceonly.pb.cpp | 2 +- src/mesh/generated/meshtastic/deviceonly.pb.h | 7 ++++--- src/mesh/generated/meshtastic/localonly.pb.cpp | 2 +- src/mesh/generated/meshtastic/localonly.pb.h | 3 ++- src/mesh/generated/meshtastic/mesh.pb.cpp | 2 +- src/mesh/generated/meshtastic/mesh.pb.h | 3 ++- .../generated/meshtastic/module_config.pb.cpp | 2 +- src/mesh/generated/meshtastic/module_config.pb.h | 3 ++- src/mesh/generated/meshtastic/mqtt.pb.cpp | 2 +- src/mesh/generated/meshtastic/mqtt.pb.h | 3 ++- src/mesh/generated/meshtastic/paxcount.pb.cpp | 2 +- src/mesh/generated/meshtastic/paxcount.pb.h | 3 ++- src/mesh/generated/meshtastic/portnums.pb.cpp | 2 +- src/mesh/generated/meshtastic/portnums.pb.h | 2 +- .../generated/meshtastic/remote_hardware.pb.cpp | 2 +- .../generated/meshtastic/remote_hardware.pb.h | 3 ++- src/mesh/generated/meshtastic/rtttl.pb.cpp | 2 +- src/mesh/generated/meshtastic/rtttl.pb.h | 3 ++- .../generated/meshtastic/storeforward.pb.cpp | 2 +- src/mesh/generated/meshtastic/storeforward.pb.h | 3 ++- src/mesh/generated/meshtastic/telemetry.pb.cpp | 2 +- src/mesh/generated/meshtastic/telemetry.pb.h | 16 +++++++++++----- src/mesh/generated/meshtastic/xmodem.pb.cpp | 2 +- src/mesh/generated/meshtastic/xmodem.pb.h | 3 ++- 41 files changed, 70 insertions(+), 47 deletions(-) diff --git a/protobufs b/protobufs index 68720ed8d..22cbd0d4c 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 68720ed8dbcb2c055e3d1ecd4f78d60692f59493 +Subproject commit 22cbd0d4cfafa4b8c1e64517e06edc2d7a22cca9 diff --git a/src/mesh/generated/meshtastic/admin.pb.cpp b/src/mesh/generated/meshtastic/admin.pb.cpp index 92835c89c..339960302 100644 --- a/src/mesh/generated/meshtastic/admin.pb.cpp +++ b/src/mesh/generated/meshtastic/admin.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/admin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/admin.pb.h b/src/mesh/generated/meshtastic/admin.pb.h index f0d4e81b6..d692a3f30 100644 --- a/src/mesh/generated/meshtastic/admin.pb.h +++ b/src/mesh/generated/meshtastic/admin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_ADMIN_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_ADMIN_PB_H_INCLUDED @@ -340,6 +340,7 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePinsResponse_msg; #define meshtastic_NodeRemoteHardwarePinsResponse_fields &meshtastic_NodeRemoteHardwarePinsResponse_msg /* Maximum encoded size of messages (where known) */ +#define MESHTASTIC_MESHTASTIC_ADMIN_PB_H_MAX_SIZE meshtastic_AdminMessage_size #define meshtastic_AdminMessage_size 500 #define meshtastic_HamParameters_size 32 #define meshtastic_NodeRemoteHardwarePinsResponse_size 496 diff --git a/src/mesh/generated/meshtastic/apponly.pb.cpp b/src/mesh/generated/meshtastic/apponly.pb.cpp index 8c3801ed7..44b0ea3cc 100644 --- a/src/mesh/generated/meshtastic/apponly.pb.cpp +++ b/src/mesh/generated/meshtastic/apponly.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/apponly.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/apponly.pb.h b/src/mesh/generated/meshtastic/apponly.pb.h index 253fdd8ef..54629f522 100644 --- a/src/mesh/generated/meshtastic/apponly.pb.h +++ b/src/mesh/generated/meshtastic/apponly.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_APPONLY_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_APPONLY_PB_H_INCLUDED @@ -54,6 +54,7 @@ extern const pb_msgdesc_t meshtastic_ChannelSet_msg; #define meshtastic_ChannelSet_fields &meshtastic_ChannelSet_msg /* Maximum encoded size of messages (where known) */ +#define MESHTASTIC_MESHTASTIC_APPONLY_PB_H_MAX_SIZE meshtastic_ChannelSet_size #define meshtastic_ChannelSet_size 658 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/atak.pb.cpp b/src/mesh/generated/meshtastic/atak.pb.cpp index 1413b748e..491336bcf 100644 --- a/src/mesh/generated/meshtastic/atak.pb.cpp +++ b/src/mesh/generated/meshtastic/atak.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/atak.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/atak.pb.h b/src/mesh/generated/meshtastic/atak.pb.h index 17d3cd3b9..c094727ed 100644 --- a/src/mesh/generated/meshtastic/atak.pb.h +++ b/src/mesh/generated/meshtastic/atak.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_ATAK_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_ATAK_PB_H_INCLUDED @@ -260,6 +260,7 @@ extern const pb_msgdesc_t meshtastic_PLI_msg; #define meshtastic_PLI_fields &meshtastic_PLI_msg /* Maximum encoded size of messages (where known) */ +#define MESHTASTIC_MESHTASTIC_ATAK_PB_H_MAX_SIZE meshtastic_TAKPacket_size #define meshtastic_Contact_size 242 #define meshtastic_GeoChat_size 323 #define meshtastic_Group_size 4 diff --git a/src/mesh/generated/meshtastic/cannedmessages.pb.cpp b/src/mesh/generated/meshtastic/cannedmessages.pb.cpp index fffa3fdf9..71e659be2 100644 --- a/src/mesh/generated/meshtastic/cannedmessages.pb.cpp +++ b/src/mesh/generated/meshtastic/cannedmessages.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/cannedmessages.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/cannedmessages.pb.h b/src/mesh/generated/meshtastic/cannedmessages.pb.h index b81f65d0d..c3f9a8b9b 100644 --- a/src/mesh/generated/meshtastic/cannedmessages.pb.h +++ b/src/mesh/generated/meshtastic/cannedmessages.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_CANNEDMESSAGES_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_CANNEDMESSAGES_PB_H_INCLUDED @@ -40,6 +40,7 @@ extern const pb_msgdesc_t meshtastic_CannedMessageModuleConfig_msg; #define meshtastic_CannedMessageModuleConfig_fields &meshtastic_CannedMessageModuleConfig_msg /* Maximum encoded size of messages (where known) */ +#define MESHTASTIC_MESHTASTIC_CANNEDMESSAGES_PB_H_MAX_SIZE meshtastic_CannedMessageModuleConfig_size #define meshtastic_CannedMessageModuleConfig_size 203 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/channel.pb.cpp b/src/mesh/generated/meshtastic/channel.pb.cpp index f604f64e9..fe76d8140 100644 --- a/src/mesh/generated/meshtastic/channel.pb.cpp +++ b/src/mesh/generated/meshtastic/channel.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/channel.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/channel.pb.h b/src/mesh/generated/meshtastic/channel.pb.h index 1587483c0..185a47a98 100644 --- a/src/mesh/generated/meshtastic/channel.pb.h +++ b/src/mesh/generated/meshtastic/channel.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_CHANNEL_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_CHANNEL_PB_H_INCLUDED @@ -181,6 +181,7 @@ extern const pb_msgdesc_t meshtastic_Channel_msg; #define meshtastic_Channel_fields &meshtastic_Channel_msg /* Maximum encoded size of messages (where known) */ +#define MESHTASTIC_MESHTASTIC_CHANNEL_PB_H_MAX_SIZE meshtastic_Channel_size #define meshtastic_ChannelSettings_size 70 #define meshtastic_Channel_size 85 #define meshtastic_ModuleSettings_size 6 diff --git a/src/mesh/generated/meshtastic/clientonly.pb.cpp b/src/mesh/generated/meshtastic/clientonly.pb.cpp index ebc2ffabc..44c6f95ce 100644 --- a/src/mesh/generated/meshtastic/clientonly.pb.cpp +++ b/src/mesh/generated/meshtastic/clientonly.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/clientonly.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/clientonly.pb.h b/src/mesh/generated/meshtastic/clientonly.pb.h index 0f70e09c6..dc323292a 100644 --- a/src/mesh/generated/meshtastic/clientonly.pb.h +++ b/src/mesh/generated/meshtastic/clientonly.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_CLIENTONLY_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_CLIENTONLY_PB_H_INCLUDED diff --git a/src/mesh/generated/meshtastic/config.pb.cpp b/src/mesh/generated/meshtastic/config.pb.cpp index 0fa8ba588..f05e47573 100644 --- a/src/mesh/generated/meshtastic/config.pb.cpp +++ b/src/mesh/generated/meshtastic/config.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/config.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index ed512f12f..fd040c57f 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_CONFIG_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_CONFIG_PB_H_INCLUDED @@ -832,6 +832,7 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg; #define meshtastic_Config_BluetoothConfig_fields &meshtastic_Config_BluetoothConfig_msg /* Maximum encoded size of messages (where known) */ +#define MESHTASTIC_MESHTASTIC_CONFIG_PB_H_MAX_SIZE meshtastic_Config_size #define meshtastic_Config_BluetoothConfig_size 10 #define meshtastic_Config_DeviceConfig_size 98 #define meshtastic_Config_DisplayConfig_size 28 diff --git a/src/mesh/generated/meshtastic/connection_status.pb.cpp b/src/mesh/generated/meshtastic/connection_status.pb.cpp index 0675bc815..fc5a364dd 100644 --- a/src/mesh/generated/meshtastic/connection_status.pb.cpp +++ b/src/mesh/generated/meshtastic/connection_status.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/connection_status.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/connection_status.pb.h b/src/mesh/generated/meshtastic/connection_status.pb.h index 19ed69455..1c618e4d4 100644 --- a/src/mesh/generated/meshtastic/connection_status.pb.h +++ b/src/mesh/generated/meshtastic/connection_status.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_CONNECTION_STATUS_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_CONNECTION_STATUS_PB_H_INCLUDED @@ -175,6 +175,7 @@ extern const pb_msgdesc_t meshtastic_SerialConnectionStatus_msg; #define meshtastic_SerialConnectionStatus_fields &meshtastic_SerialConnectionStatus_msg /* Maximum encoded size of messages (where known) */ +#define MESHTASTIC_MESHTASTIC_CONNECTION_STATUS_PB_H_MAX_SIZE meshtastic_DeviceConnectionStatus_size #define meshtastic_BluetoothConnectionStatus_size 19 #define meshtastic_DeviceConnectionStatus_size 106 #define meshtastic_EthernetConnectionStatus_size 13 diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.cpp b/src/mesh/generated/meshtastic/deviceonly.pb.cpp index 127319b14..672192f67 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.cpp +++ b/src/mesh/generated/meshtastic/deviceonly.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/deviceonly.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index bec15eb90..9b3767180 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_INCLUDED @@ -174,12 +174,12 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_PositionLite_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN} #define meshtastic_NodeInfoLite_init_default {0, false, meshtastic_User_init_default, false, meshtastic_PositionLite_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, 0, 0} -#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default, 0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}, {{NULL}, NULL}} +#define meshtastic_DeviceState_init_default {false, meshtastic_MyNodeInfo_init_default, false, meshtastic_User_init_default, 0, {meshtastic_MeshPacket_init_default}, false, meshtastic_MeshPacket_init_default, 0, 0, 0, false, meshtastic_MeshPacket_init_default, 0, {meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default, meshtastic_NodeRemoteHardwarePin_init_default}, {0}} #define meshtastic_ChannelFile_init_default {0, {meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default, meshtastic_Channel_init_default}, 0} #define meshtastic_OEMStore_init_default {0, 0, {0, {0}}, _meshtastic_ScreenFonts_MIN, "", {0, {0}}, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default} #define meshtastic_PositionLite_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN} #define meshtastic_NodeInfoLite_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_PositionLite_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, 0, 0} -#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero, 0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}, {{NULL}, NULL}} +#define meshtastic_DeviceState_init_zero {false, meshtastic_MyNodeInfo_init_zero, false, meshtastic_User_init_zero, 0, {meshtastic_MeshPacket_init_zero}, false, meshtastic_MeshPacket_init_zero, 0, 0, 0, false, meshtastic_MeshPacket_init_zero, 0, {meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero, meshtastic_NodeRemoteHardwarePin_init_zero}, {0}} #define meshtastic_ChannelFile_init_zero {0, {meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero, meshtastic_Channel_init_zero}, 0} #define meshtastic_OEMStore_init_zero {0, 0, {0, {0}}, _meshtastic_ScreenFonts_MIN, "", {0, {0}}, false, meshtastic_LocalConfig_init_zero, false, meshtastic_LocalModuleConfig_init_zero} @@ -305,6 +305,7 @@ extern const pb_msgdesc_t meshtastic_OEMStore_msg; /* Maximum encoded size of messages (where known) */ /* meshtastic_DeviceState_size depends on runtime parameters */ +#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_OEMStore_size #define meshtastic_ChannelFile_size 702 #define meshtastic_NodeInfoLite_size 160 #define meshtastic_OEMStore_size 3344 diff --git a/src/mesh/generated/meshtastic/localonly.pb.cpp b/src/mesh/generated/meshtastic/localonly.pb.cpp index 8fc3f1139..9bc98fb85 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.cpp +++ b/src/mesh/generated/meshtastic/localonly.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/localonly.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index 1f431d788..fa7ebcfee 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_INCLUDED @@ -180,6 +180,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; #define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg /* Maximum encoded size of messages (where known) */ +#define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalModuleConfig_size #define meshtastic_LocalConfig_size 535 #define meshtastic_LocalModuleConfig_size 663 diff --git a/src/mesh/generated/meshtastic/mesh.pb.cpp b/src/mesh/generated/meshtastic/mesh.pb.cpp index 39713ae8d..4907affc6 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.cpp +++ b/src/mesh/generated/meshtastic/mesh.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/mesh.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index d15f968d4..14b6b4c1f 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_MESH_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_MESH_PB_H_INCLUDED @@ -1372,6 +1372,7 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg; #define meshtastic_NodeRemoteHardwarePin_fields &meshtastic_NodeRemoteHardwarePin_msg /* Maximum encoded size of messages (where known) */ +#define MESHTASTIC_MESHTASTIC_MESH_PB_H_MAX_SIZE meshtastic_FromRadio_size #define meshtastic_Compressed_size 243 #define meshtastic_Data_size 270 #define meshtastic_DeviceMetadata_size 46 diff --git a/src/mesh/generated/meshtastic/module_config.pb.cpp b/src/mesh/generated/meshtastic/module_config.pb.cpp index 594cf9628..88a771d5b 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.cpp +++ b/src/mesh/generated/meshtastic/module_config.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/module_config.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h index a2adbc1b9..ffda48704 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.h +++ b/src/mesh/generated/meshtastic/module_config.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_MODULE_CONFIG_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_MODULE_CONFIG_PB_H_INCLUDED @@ -827,6 +827,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg; #define meshtastic_RemoteHardwarePin_fields &meshtastic_RemoteHardwarePin_msg /* Maximum encoded size of messages (where known) */ +#define MESHTASTIC_MESHTASTIC_MODULE_CONFIG_PB_H_MAX_SIZE meshtastic_ModuleConfig_size #define meshtastic_ModuleConfig_AmbientLightingConfig_size 14 #define meshtastic_ModuleConfig_AudioConfig_size 19 #define meshtastic_ModuleConfig_CannedMessageConfig_size 49 diff --git a/src/mesh/generated/meshtastic/mqtt.pb.cpp b/src/mesh/generated/meshtastic/mqtt.pb.cpp index a43f364e1..f00dd823b 100644 --- a/src/mesh/generated/meshtastic/mqtt.pb.cpp +++ b/src/mesh/generated/meshtastic/mqtt.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/mqtt.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/mqtt.pb.h b/src/mesh/generated/meshtastic/mqtt.pb.h index 9ec29d5b1..8ec9f98c3 100644 --- a/src/mesh/generated/meshtastic/mqtt.pb.h +++ b/src/mesh/generated/meshtastic/mqtt.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_MQTT_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_MQTT_PB_H_INCLUDED @@ -120,6 +120,7 @@ extern const pb_msgdesc_t meshtastic_MapReport_msg; /* Maximum encoded size of messages (where known) */ /* meshtastic_ServiceEnvelope_size depends on runtime parameters */ +#define MESHTASTIC_MESHTASTIC_MQTT_PB_H_MAX_SIZE meshtastic_MapReport_size #define meshtastic_MapReport_size 108 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/paxcount.pb.cpp b/src/mesh/generated/meshtastic/paxcount.pb.cpp index 57d5f5be9..67f07a31b 100644 --- a/src/mesh/generated/meshtastic/paxcount.pb.cpp +++ b/src/mesh/generated/meshtastic/paxcount.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/paxcount.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/paxcount.pb.h b/src/mesh/generated/meshtastic/paxcount.pb.h index 4b643293c..09377d833 100644 --- a/src/mesh/generated/meshtastic/paxcount.pb.h +++ b/src/mesh/generated/meshtastic/paxcount.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_PAXCOUNT_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_PAXCOUNT_PB_H_INCLUDED @@ -48,6 +48,7 @@ extern const pb_msgdesc_t meshtastic_Paxcount_msg; #define meshtastic_Paxcount_fields &meshtastic_Paxcount_msg /* Maximum encoded size of messages (where known) */ +#define MESHTASTIC_MESHTASTIC_PAXCOUNT_PB_H_MAX_SIZE meshtastic_Paxcount_size #define meshtastic_Paxcount_size 18 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/portnums.pb.cpp b/src/mesh/generated/meshtastic/portnums.pb.cpp index dd0d00e20..8f32c0851 100644 --- a/src/mesh/generated/meshtastic/portnums.pb.cpp +++ b/src/mesh/generated/meshtastic/portnums.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/portnums.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/portnums.pb.h b/src/mesh/generated/meshtastic/portnums.pb.h index f576c7893..233e8d653 100644 --- a/src/mesh/generated/meshtastic/portnums.pb.h +++ b/src/mesh/generated/meshtastic/portnums.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_PORTNUMS_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_PORTNUMS_PB_H_INCLUDED diff --git a/src/mesh/generated/meshtastic/remote_hardware.pb.cpp b/src/mesh/generated/meshtastic/remote_hardware.pb.cpp index f368ec1ef..4a23698b2 100644 --- a/src/mesh/generated/meshtastic/remote_hardware.pb.cpp +++ b/src/mesh/generated/meshtastic/remote_hardware.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/remote_hardware.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/remote_hardware.pb.h b/src/mesh/generated/meshtastic/remote_hardware.pb.h index 26df97616..936034b62 100644 --- a/src/mesh/generated/meshtastic/remote_hardware.pb.h +++ b/src/mesh/generated/meshtastic/remote_hardware.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_REMOTE_HARDWARE_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_REMOTE_HARDWARE_PB_H_INCLUDED @@ -84,6 +84,7 @@ extern const pb_msgdesc_t meshtastic_HardwareMessage_msg; #define meshtastic_HardwareMessage_fields &meshtastic_HardwareMessage_msg /* Maximum encoded size of messages (where known) */ +#define MESHTASTIC_MESHTASTIC_REMOTE_HARDWARE_PB_H_MAX_SIZE meshtastic_HardwareMessage_size #define meshtastic_HardwareMessage_size 24 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/rtttl.pb.cpp b/src/mesh/generated/meshtastic/rtttl.pb.cpp index 685bbde45..8367fdbce 100644 --- a/src/mesh/generated/meshtastic/rtttl.pb.cpp +++ b/src/mesh/generated/meshtastic/rtttl.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/rtttl.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/rtttl.pb.h b/src/mesh/generated/meshtastic/rtttl.pb.h index aa55d0b7d..452b0cf4b 100644 --- a/src/mesh/generated/meshtastic/rtttl.pb.h +++ b/src/mesh/generated/meshtastic/rtttl.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_RTTTL_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_RTTTL_PB_H_INCLUDED @@ -40,6 +40,7 @@ extern const pb_msgdesc_t meshtastic_RTTTLConfig_msg; #define meshtastic_RTTTLConfig_fields &meshtastic_RTTTLConfig_msg /* Maximum encoded size of messages (where known) */ +#define MESHTASTIC_MESHTASTIC_RTTTL_PB_H_MAX_SIZE meshtastic_RTTTLConfig_size #define meshtastic_RTTTLConfig_size 232 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/storeforward.pb.cpp b/src/mesh/generated/meshtastic/storeforward.pb.cpp index 44a1c70c1..5b3fadd9a 100644 --- a/src/mesh/generated/meshtastic/storeforward.pb.cpp +++ b/src/mesh/generated/meshtastic/storeforward.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/storeforward.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/storeforward.pb.h b/src/mesh/generated/meshtastic/storeforward.pb.h index 55ab0b510..311596c7f 100644 --- a/src/mesh/generated/meshtastic/storeforward.pb.h +++ b/src/mesh/generated/meshtastic/storeforward.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_STOREFORWARD_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_STOREFORWARD_PB_H_INCLUDED @@ -207,6 +207,7 @@ extern const pb_msgdesc_t meshtastic_StoreAndForward_Heartbeat_msg; #define meshtastic_StoreAndForward_Heartbeat_fields &meshtastic_StoreAndForward_Heartbeat_msg /* Maximum encoded size of messages (where known) */ +#define MESHTASTIC_MESHTASTIC_STOREFORWARD_PB_H_MAX_SIZE meshtastic_StoreAndForward_size #define meshtastic_StoreAndForward_Heartbeat_size 12 #define meshtastic_StoreAndForward_History_size 18 #define meshtastic_StoreAndForward_Statistics_size 50 diff --git a/src/mesh/generated/meshtastic/telemetry.pb.cpp b/src/mesh/generated/meshtastic/telemetry.pb.cpp index 046998ae9..6388e37a0 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.cpp +++ b/src/mesh/generated/meshtastic/telemetry.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/telemetry.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index d73c6baa1..6955ac4e9 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_INCLUDED @@ -73,6 +73,9 @@ typedef struct _meshtastic_EnvironmentMetrics { float voltage; /* Current measured (To be depreciated in favor of PowerMetrics in Meshtastic 3.x) */ float current; + /* relative scale IAQ value as measured by Bosch BME680 . value 0-500. + Belongs to Air Quality but is not particle but VOC measurement. Other VOC values can also be put in here. */ + uint16_t iaq; } meshtastic_EnvironmentMetrics; /* Power Metrics (voltage / current / etc) */ @@ -154,12 +157,12 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_DeviceMetrics_init_default {0, 0, 0, 0} -#define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0} +#define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0, 0} #define meshtastic_PowerMetrics_init_default {0, 0, 0, 0, 0, 0} #define meshtastic_AirQualityMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}} #define meshtastic_DeviceMetrics_init_zero {0, 0, 0, 0} -#define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0} +#define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0, 0} #define meshtastic_PowerMetrics_init_zero {0, 0, 0, 0, 0, 0} #define meshtastic_AirQualityMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}} @@ -175,6 +178,7 @@ extern "C" { #define meshtastic_EnvironmentMetrics_gas_resistance_tag 4 #define meshtastic_EnvironmentMetrics_voltage_tag 5 #define meshtastic_EnvironmentMetrics_current_tag 6 +#define meshtastic_EnvironmentMetrics_iaq_tag 7 #define meshtastic_PowerMetrics_ch1_voltage_tag 1 #define meshtastic_PowerMetrics_ch1_current_tag 2 #define meshtastic_PowerMetrics_ch2_voltage_tag 3 @@ -214,7 +218,8 @@ X(a, STATIC, SINGULAR, FLOAT, relative_humidity, 2) \ X(a, STATIC, SINGULAR, FLOAT, barometric_pressure, 3) \ X(a, STATIC, SINGULAR, FLOAT, gas_resistance, 4) \ X(a, STATIC, SINGULAR, FLOAT, voltage, 5) \ -X(a, STATIC, SINGULAR, FLOAT, current, 6) +X(a, STATIC, SINGULAR, FLOAT, current, 6) \ +X(a, STATIC, SINGULAR, UINT32, iaq, 7) #define meshtastic_EnvironmentMetrics_CALLBACK NULL #define meshtastic_EnvironmentMetrics_DEFAULT NULL @@ -271,9 +276,10 @@ extern const pb_msgdesc_t meshtastic_Telemetry_msg; #define meshtastic_Telemetry_fields &meshtastic_Telemetry_msg /* Maximum encoded size of messages (where known) */ +#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size #define meshtastic_AirQualityMetrics_size 72 #define meshtastic_DeviceMetrics_size 21 -#define meshtastic_EnvironmentMetrics_size 30 +#define meshtastic_EnvironmentMetrics_size 34 #define meshtastic_PowerMetrics_size 30 #define meshtastic_Telemetry_size 79 diff --git a/src/mesh/generated/meshtastic/xmodem.pb.cpp b/src/mesh/generated/meshtastic/xmodem.pb.cpp index 9692a5eb4..8e5cde457 100644 --- a/src/mesh/generated/meshtastic/xmodem.pb.cpp +++ b/src/mesh/generated/meshtastic/xmodem.pb.cpp @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #include "meshtastic/xmodem.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/mesh/generated/meshtastic/xmodem.pb.h b/src/mesh/generated/meshtastic/xmodem.pb.h index 48d5aa5cd..67bd0869f 100644 --- a/src/mesh/generated/meshtastic/xmodem.pb.h +++ b/src/mesh/generated/meshtastic/xmodem.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7 */ +/* Generated by nanopb-0.4.8 */ #ifndef PB_MESHTASTIC_MESHTASTIC_XMODEM_PB_H_INCLUDED #define PB_MESHTASTIC_MESHTASTIC_XMODEM_PB_H_INCLUDED @@ -68,6 +68,7 @@ extern const pb_msgdesc_t meshtastic_XModem_msg; #define meshtastic_XModem_fields &meshtastic_XModem_msg /* Maximum encoded size of messages (where known) */ +#define MESHTASTIC_MESHTASTIC_XMODEM_PB_H_MAX_SIZE meshtastic_XModem_size #define meshtastic_XModem_size 141 #ifdef __cplusplus From 77082e35f5f53bf36db4403bd4bda19b1d92e6bb Mon Sep 17 00:00:00 2001 From: rcarteraz Date: Tue, 9 Apr 2024 09:37:38 -0700 Subject: [PATCH 037/108] Add unPhone to S3 build scripts (#3583) * add unphone to s3 devices * add unphone --- bin/device-install.bat | 2 +- bin/device-install.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/device-install.bat b/bin/device-install.bat index 1fe1df52a..6c880185e 100755 --- a/bin/device-install.bat +++ b/bin/device-install.bat @@ -32,7 +32,7 @@ IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% ( %PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME% @REM Account for S3 and C3 board's different OTA partition - IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% IF x%FILENAME:t-deck=%==x%FILENAME% IF x%FILENAME:wireless-paper=%==x%FILENAME% IF x%FILENAME:wireless-tracker=%==x%FILENAME% IF x%FILENAME:station-g2=%==x%FILENAME% ( + IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% IF x%FILENAME:t-deck=%==x%FILENAME% IF x%FILENAME:wireless-paper=%==x%FILENAME% IF x%FILENAME:wireless-tracker=%==x%FILENAME% IF x%FILENAME:station-g2=%==x%FILENAME% IF x%FILENAME:unphone=%==x%FILENAME% ( IF x%FILENAME:esp32c3=%==x%FILENAME% ( %PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin ) else ( diff --git a/bin/device-install.sh b/bin/device-install.sh index 6ef7b1204..563a87af4 100755 --- a/bin/device-install.sh +++ b/bin/device-install.sh @@ -52,7 +52,7 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then "$PYTHON" -m esptool erase_flash "$PYTHON" -m esptool write_flash 0x00 ${FILENAME} # Account for S3 board's different OTA partition - if [ -n "${FILENAME##*"s3"*}" ] && [ -n "${FILENAME##*"-v3"*}" ] && [ -n "${FILENAME##*"t-deck"*}" ] && [ -n "${FILENAME##*"wireless-paper"*}" ] && [ -n "${FILENAME##*"wireless-tracker"*}" ] && [ -n "${FILENAME##*"station-g2"*}" ]; then + if [ -n "${FILENAME##*"s3"*}" ] && [ -n "${FILENAME##*"-v3"*}" ] && [ -n "${FILENAME##*"t-deck"*}" ] && [ -n "${FILENAME##*"wireless-paper"*}" ] && [ -n "${FILENAME##*"wireless-tracker"*}" ] && [ -n "${FILENAME##*"station-g2"*}" ] && [ -n "${FILENAME##*"unphone"*}" ]; then if [ -n "${FILENAME##*"esp32c3"*}" ]; then "$PYTHON" -m esptool write_flash 0x260000 bleota.bin else From 6e7405e56b9ea31e324ad30a353898d537eb5ce8 Mon Sep 17 00:00:00 2001 From: rcarteraz Date: Tue, 9 Apr 2024 10:26:03 -0700 Subject: [PATCH 038/108] add unphone (#3584) --- .github/workflows/main_matrix.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml index 03d47f18e..9ca0764b5 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -100,6 +100,7 @@ jobs: - board: t-deck - board: picomputer-s3 - board: station-g2 + - board: unphone uses: ./.github/workflows/build_esp32_s3.yml with: board: ${{ matrix.board }} From cfd98b2c918e6e14da8e839de4b95dc6e2e504d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Tue, 9 Apr 2024 15:15:21 +0200 Subject: [PATCH 039/108] add BME680 IAQ reading. Range is from 0 (clean) - 500 (extremely polluted) --- src/modules/Telemetry/EnvironmentTelemetry.cpp | 2 ++ src/modules/Telemetry/Sensor/BME680Sensor.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp index 908062a5b..189ab7ed0 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.cpp +++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp @@ -181,6 +181,8 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt display->drawString(x, y += fontHeight(FONT_SMALL), "Volt/Cur: " + String(lastMeasurement.variant.environment_metrics.voltage, 0) + "V / " + String(lastMeasurement.variant.environment_metrics.current, 0) + "mA"); + if (lastMeasurement.variant.environment_metrics.iaq != 0) + display->drawString(x, y += fontHeight(FONT_SMALL), "IAQ: " + String(lastMeasurement.variant.environment_metrics.iaq)); } bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t) diff --git a/src/modules/Telemetry/Sensor/BME680Sensor.cpp b/src/modules/Telemetry/Sensor/BME680Sensor.cpp index 323dce31f..217fb5737 100644 --- a/src/modules/Telemetry/Sensor/BME680Sensor.cpp +++ b/src/modules/Telemetry/Sensor/BME680Sensor.cpp @@ -57,6 +57,7 @@ bool BME680Sensor::getMetrics(meshtastic_Telemetry *measurement) measurement->variant.environment_metrics.barometric_pressure = bme680.getData(BSEC_OUTPUT_RAW_PRESSURE).signal / 100.0F; measurement->variant.environment_metrics.gas_resistance = bme680.getData(BSEC_OUTPUT_RAW_GAS).signal / 1000.0; // Check if we need to save state to filesystem (every STATE_SAVE_PERIOD ms) + measurement->variant.environment_metrics.iaq = bme680.getData(BSEC_OUTPUT_IAQ).signal; updateState(); return true; } From 2d81c97b9816de793677e6a640190389d2c29acd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Tue, 9 Apr 2024 15:50:15 +0200 Subject: [PATCH 040/108] fix #2586 (lower IAQ quality for saving to 2 and rework save logic) --- src/modules/Telemetry/Sensor/BME680Sensor.cpp | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/modules/Telemetry/Sensor/BME680Sensor.cpp b/src/modules/Telemetry/Sensor/BME680Sensor.cpp index 217fb5737..e1222bba4 100644 --- a/src/modules/Telemetry/Sensor/BME680Sensor.cpp +++ b/src/modules/Telemetry/Sensor/BME680Sensor.cpp @@ -86,17 +86,17 @@ void BME680Sensor::updateState() if (stateUpdateCounter == 0) { /* First state update when IAQ accuracy is >= 3 */ accuracy = bme680.getData(BSEC_OUTPUT_IAQ).accuracy; - if (accuracy >= 3) { - LOG_DEBUG("%s state update IAQ accuracy %u >= 3\n", sensorName, accuracy); + if (accuracy >= 2) { + LOG_DEBUG("%s state update IAQ accuracy %u >= 2\n", sensorName, accuracy); update = true; stateUpdateCounter++; } else { - LOG_DEBUG("%s not updated, IAQ accuracy is %u >= 3\n", sensorName, accuracy); + LOG_DEBUG("%s not updated, IAQ accuracy is %u < 2\n", sensorName, accuracy); } } else { /* Update every STATE_SAVE_PERIOD minutes */ if ((stateUpdateCounter * STATE_SAVE_PERIOD) < millis()) { - LOG_DEBUG("%s state update every %d minutes\n", sensorName, STATE_SAVE_PERIOD); + LOG_DEBUG("%s state update every %d minutes\n", sensorName, STATE_SAVE_PERIOD / 60000); update = true; stateUpdateCounter++; } @@ -104,22 +104,15 @@ void BME680Sensor::updateState() if (update) { bme680.getState(bsecState); - std::string filenameTmp = bsecConfigFileName; - filenameTmp += ".tmp"; + if (FSCom.exists(bsecConfigFileName) && !FSCom.remove(bsecConfigFileName)) { + LOG_WARN("Can't remove old state file\n"); + } auto file = FSCom.open(bsecConfigFileName, FILE_O_WRITE); if (file) { LOG_INFO("%s state write to %s.\n", sensorName, bsecConfigFileName); file.write((uint8_t *)&bsecState, BSEC_MAX_STATE_BLOB_SIZE); file.flush(); file.close(); - // brief window of risk here ;-) - if (FSCom.exists(bsecConfigFileName) && !FSCom.remove(bsecConfigFileName)) { - LOG_WARN("Can't remove old state file\n"); - } - if (!renameFile(filenameTmp.c_str(), bsecConfigFileName)) { - LOG_ERROR("Error: can't rename new state file\n"); - } - } else { LOG_INFO("Can't write %s state (File: %s).\n", sensorName, bsecConfigFileName); } From 3bee6ce9c33faf7b84a964d49024d3324fb04843 Mon Sep 17 00:00:00 2001 From: GUVWAF <78759985+GUVWAF@users.noreply.github.com> Date: Wed, 10 Apr 2024 18:29:29 +0200 Subject: [PATCH 041/108] Only set NodeNum based on MAC if it's still zero (#3585) * Only set NodeNum based on MAC if it's still zero * Already declared --- src/mesh/NodeDB.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 262b0e039..fb2b79048 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -517,11 +517,12 @@ void NodeDB::installDefaultDeviceState() */ void NodeDB::pickNewNodeNum() { - - getMacAddr(ourMacAddr); // Make sure ourMacAddr is set - - // Pick an initial nodenum based on the macaddr - NodeNum nodeNum = (ourMacAddr[2] << 24) | (ourMacAddr[3] << 16) | (ourMacAddr[4] << 8) | ourMacAddr[5]; + NodeNum nodeNum = myNodeInfo.my_node_num; + if (nodeNum == 0) { + getMacAddr(ourMacAddr); // Make sure ourMacAddr is set + // Pick an initial nodenum based on the macaddr + nodeNum = (ourMacAddr[2] << 24) | (ourMacAddr[3] << 16) | (ourMacAddr[4] << 8) | ourMacAddr[5]; + } meshtastic_NodeInfoLite *found; while ((nodeNum == NODENUM_BROADCAST || nodeNum < NUM_RESERVED) || From 8e29efcb5021201cd4c1ed0cd5600a066085a85d Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Fri, 12 Apr 2024 00:02:50 +1200 Subject: [PATCH 042/108] Fix button interrupt after light sleep (#3587) * Make ButtonThread instance extern Previously was a static local instance in setup(). Now declared in ButtonThread.cpp, accessible via extern declaration in ButtonThread. * Extract attachInterrupt() calls to public method; create matching method for detachInterrupt() * Change suspension of button interrupts for light-sleep * Fix declaration for ARCH_PORTDUINO * Remove LOG_DEBUG used during testing * Don't assume device has a button.. * Guard entire constructor code * Don't use BUTTON_PIN with ARCH_PORTDUINO --------- Co-authored-by: Manuel <71137295+mverch67@users.noreply.github.com> --- src/ButtonThread.cpp | 86 ++++++++++++++++++++++++++++++++++---------- src/ButtonThread.h | 11 +++--- src/main.cpp | 3 -- src/sleep.cpp | 10 ++++-- 4 files changed, 80 insertions(+), 30 deletions(-) diff --git a/src/ButtonThread.cpp b/src/ButtonThread.cpp index 069a92308..206bb7239 100644 --- a/src/ButtonThread.cpp +++ b/src/ButtonThread.cpp @@ -23,18 +23,24 @@ using namespace concurrency; +ButtonThread *buttonThread; // Declared extern in header volatile ButtonThread::ButtonEventType ButtonThread::btnEvent = ButtonThread::BUTTON_EVENT_NONE; +#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) +OneButton ButtonThread::userButton; // Get reference to static member +#endif + ButtonThread::ButtonThread() : OSThread("Button") { -#if defined(ARCH_PORTDUINO) || defined(BUTTON_PIN) +#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) + #if defined(ARCH_PORTDUINO) if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) { - userButton = OneButton(settingsMap[user], true, true); + this->userButton = OneButton(settingsMap[user], true, true); LOG_DEBUG("Using GPIO%02d for button\n", settingsMap[user]); } #elif defined(BUTTON_PIN) - int pin = config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN; + int pin = config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN; // Resolved button pin this->userButton = OneButton(pin, true, true); LOG_DEBUG("Using GPIO%02d for button\n", pin); #endif @@ -43,6 +49,8 @@ ButtonThread::ButtonThread() : OSThread("Button") // Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did pinMode(pin, INPUT_PULLUP_SENSE); #endif + +#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) userButton.attachClick(userButtonPressed); userButton.setClickMs(250); userButton.setPressMs(c_longPressTime); @@ -53,21 +61,8 @@ ButtonThread::ButtonThread() : OSThread("Button") userButton.attachLongPressStart(userButtonPressedLongStart); userButton.attachLongPressStop(userButtonPressedLongStop); #endif -#if defined(ARCH_PORTDUINO) - if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) - wakeOnIrq(settingsMap[user], FALLING); -#else - static OneButton *pBtn = &userButton; // only one instance of ButtonThread is created, so static is safe - attachInterrupt( - pin, - []() { - BaseType_t higherWake = 0; - mainDelay.interruptFromISR(&higherWake); - pBtn->tick(); - }, - CHANGE); -#endif #endif + #ifdef BUTTON_PIN_ALT userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true); #ifdef INPUT_PULLUP_SENSE @@ -81,14 +76,15 @@ ButtonThread::ButtonThread() : OSThread("Button") userButtonAlt.attachDoubleClick(userButtonDoublePressed); userButtonAlt.attachLongPressStart(userButtonPressedLongStart); userButtonAlt.attachLongPressStop(userButtonPressedLongStop); - wakeOnIrq(BUTTON_PIN_ALT, FALLING); #endif #ifdef BUTTON_PIN_TOUCH userButtonTouch = OneButton(BUTTON_PIN_TOUCH, true, true); userButtonTouch.setPressMs(400); userButtonTouch.attachLongPressStart(touchPressedLongStart); // Better handling with longpress than click? - wakeOnIrq(BUTTON_PIN_TOUCH, FALLING); +#endif + + attachButtonInterrupts(); #endif } @@ -220,6 +216,58 @@ int32_t ButtonThread::runOnce() return 50; } +/* + * Attach (or re-attach) hardware interrupts for buttons + * Public method. Used outside class when waking from MCU sleep + */ +void ButtonThread::attachButtonInterrupts() +{ +#if defined(ARCH_PORTDUINO) + if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) + wakeOnIrq(settingsMap[user], FALLING); +#elif defined(BUTTON_PIN) + // Interrupt for user button, during normal use. Improves responsiveness. + attachInterrupt( + config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, + []() { + BaseType_t higherWake = 0; + mainDelay.interruptFromISR(&higherWake); + ButtonThread::userButton.tick(); + }, + CHANGE); +#endif + +#ifdef BUTTON_PIN_ALT + wakeOnIrq(BUTTON_PIN_ALT, FALLING); +#endif + +#ifdef BUTTON_PIN_TOUCH + wakeOnIrq(BUTTON_PIN_TOUCH, FALLING); +#endif +} + +/* + * Detach the "normal" button interrupts. + * Public method. Used before attaching a "wake-on-button" interrupt for MCU sleep + */ +void ButtonThread::detachButtonInterrupts() +{ +#if defined(ARCH_PORTDUINO) + if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) + detachInterrupt(settingsMap[user]); +#elif defined(BUTTON_PIN) + detachInterrupt(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN); +#endif + +#ifdef BUTTON_PIN_ALT + detachInterrupt(BUTTON_PIN_ALT); +#endif + +#ifdef BUTTON_PIN_TOUCH + detachInterrupt(BUTTON_PIN_TOUCH); +#endif +} + /** * Watch a GPIO and if we get an IRQ, wake the main thread. * Use to add wake on button press diff --git a/src/ButtonThread.h b/src/ButtonThread.h index 3f177302d..07c7ccff7 100644 --- a/src/ButtonThread.h +++ b/src/ButtonThread.h @@ -22,11 +22,13 @@ class ButtonThread : public concurrency::OSThread ButtonThread(); int32_t runOnce() override; + void attachButtonInterrupts(); + void detachButtonInterrupts(); void storeClickCount(); private: -#ifdef BUTTON_PIN - OneButton userButton; +#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) + static OneButton userButton; // Static - accessed from an interrupt #endif #ifdef BUTTON_PIN_ALT OneButton userButtonAlt; @@ -34,9 +36,6 @@ class ButtonThread : public concurrency::OSThread #ifdef BUTTON_PIN_TOUCH OneButton userButtonTouch; #endif -#if defined(ARCH_PORTDUINO) - OneButton userButton; -#endif // set during IRQ static volatile ButtonEventType btnEvent; @@ -54,3 +53,5 @@ class ButtonThread : public concurrency::OSThread static void userButtonPressedLongStop(); static void touchPressedLongStart() { btnEvent = BUTTON_EVENT_TOUCH_LONG_PRESSED; } }; + +extern ButtonThread *buttonThread; diff --git a/src/main.cpp b/src/main.cpp index 47f3e2c22..0f2ef7e67 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -188,9 +188,6 @@ uint32_t timeLastPowered = 0; static Periodic *ledPeriodic; static OSThread *powerFSMthread; -#if HAS_BUTTON || defined(ARCH_PORTDUINO) -static OSThread *buttonThread; -#endif static OSThread *accelerometerThread; static OSThread *ambientLightingThread; SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0); diff --git a/src/sleep.cpp b/src/sleep.cpp index 0d36112c1..5fbb733e6 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -4,6 +4,7 @@ #include "GPS.h" #endif +#include "ButtonThread.h" #include "MeshRadio.h" #include "MeshService.h" #include "NodeDB.h" @@ -337,7 +338,10 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r #ifdef BUTTON_PIN // The enableLoraInterrupt() method is using ext0_wakeup, so we are forced to use GPIO wakeup gpio_num_t pin = (gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN); - gpio_intr_disable(pin); + + // Have to *fully* detach the normal button-interrupts first + buttonThread->detachButtonInterrupts(); + gpio_wakeup_enable(pin, GPIO_INTR_LOW_LEVEL); esp_sleep_enable_gpio_wakeup(); #endif @@ -364,9 +368,9 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r assert(res == ESP_OK); #ifdef BUTTON_PIN + // Disable wake-on-button interrupt. Re-attach normal button-interrupts gpio_wakeup_disable(pin); - // Would have thought that need gpio_intr_enable() here, but nope.. - // Works fine without it; crashes with it. + buttonThread->attachButtonInterrupts(); #endif esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); From a4a8556aa2ad2fee6aa5556313f87088d90ff826 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 11 Apr 2024 07:41:37 -0500 Subject: [PATCH 043/108] [create-pull-request] automated change (#3595) Co-authored-by: thebentern --- protobufs | 2 +- src/mesh/generated/meshtastic/deviceonly.pb.h | 2 +- src/mesh/generated/meshtastic/mesh.pb.h | 2 +- src/mesh/generated/meshtastic/telemetry.pb.h | 12 ++++++++---- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/protobufs b/protobufs index 22cbd0d4c..f92900c5f 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 22cbd0d4cfafa4b8c1e64517e06edc2d7a22cca9 +Subproject commit f92900c5f884b04388fb7abf61d4df66783015e4 diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index 9b3767180..856eb6f4a 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -307,7 +307,7 @@ extern const pb_msgdesc_t meshtastic_OEMStore_msg; /* meshtastic_DeviceState_size depends on runtime parameters */ #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_OEMStore_size #define meshtastic_ChannelFile_size 702 -#define meshtastic_NodeInfoLite_size 160 +#define meshtastic_NodeInfoLite_size 166 #define meshtastic_OEMStore_size 3344 #define meshtastic_PositionLite_size 28 diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 14b6b4c1f..e674e28bb 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -1384,7 +1384,7 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg; #define meshtastic_MyNodeInfo_size 18 #define meshtastic_NeighborInfo_size 258 #define meshtastic_Neighbor_size 22 -#define meshtastic_NodeInfo_size 277 +#define meshtastic_NodeInfo_size 283 #define meshtastic_NodeRemoteHardwarePin_size 29 #define meshtastic_Position_size 144 #define meshtastic_QueueStatus_size 23 diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index 6955ac4e9..b6d3811a4 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -57,6 +57,8 @@ typedef struct _meshtastic_DeviceMetrics { float channel_utilization; /* Percent of airtime for transmission used within the last hour. */ float air_util_tx; + /* How long the device has been running since the last reboot (in seconds) */ + uint32_t uptime_seconds; } meshtastic_DeviceMetrics; /* Weather station or other environmental metrics */ @@ -156,12 +158,12 @@ extern "C" { /* Initializer values for message structs */ -#define meshtastic_DeviceMetrics_init_default {0, 0, 0, 0} +#define meshtastic_DeviceMetrics_init_default {0, 0, 0, 0, 0} #define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0, 0} #define meshtastic_PowerMetrics_init_default {0, 0, 0, 0, 0, 0} #define meshtastic_AirQualityMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}} -#define meshtastic_DeviceMetrics_init_zero {0, 0, 0, 0} +#define meshtastic_DeviceMetrics_init_zero {0, 0, 0, 0, 0} #define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0, 0} #define meshtastic_PowerMetrics_init_zero {0, 0, 0, 0, 0, 0} #define meshtastic_AirQualityMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} @@ -172,6 +174,7 @@ extern "C" { #define meshtastic_DeviceMetrics_voltage_tag 2 #define meshtastic_DeviceMetrics_channel_utilization_tag 3 #define meshtastic_DeviceMetrics_air_util_tx_tag 4 +#define meshtastic_DeviceMetrics_uptime_seconds_tag 5 #define meshtastic_EnvironmentMetrics_temperature_tag 1 #define meshtastic_EnvironmentMetrics_relative_humidity_tag 2 #define meshtastic_EnvironmentMetrics_barometric_pressure_tag 3 @@ -208,7 +211,8 @@ extern "C" { X(a, STATIC, SINGULAR, UINT32, battery_level, 1) \ X(a, STATIC, SINGULAR, FLOAT, voltage, 2) \ X(a, STATIC, SINGULAR, FLOAT, channel_utilization, 3) \ -X(a, STATIC, SINGULAR, FLOAT, air_util_tx, 4) +X(a, STATIC, SINGULAR, FLOAT, air_util_tx, 4) \ +X(a, STATIC, SINGULAR, UINT32, uptime_seconds, 5) #define meshtastic_DeviceMetrics_CALLBACK NULL #define meshtastic_DeviceMetrics_DEFAULT NULL @@ -278,7 +282,7 @@ extern const pb_msgdesc_t meshtastic_Telemetry_msg; /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size #define meshtastic_AirQualityMetrics_size 72 -#define meshtastic_DeviceMetrics_size 21 +#define meshtastic_DeviceMetrics_size 27 #define meshtastic_EnvironmentMetrics_size 34 #define meshtastic_PowerMetrics_size 30 #define meshtastic_Telemetry_size 79 From 927d07e2c6bb1a60f3b3e89ed65402843cc84d0d Mon Sep 17 00:00:00 2001 From: Manuel <71137295+mverch67@users.noreply.github.com> Date: Fri, 12 Apr 2024 02:39:07 +0200 Subject: [PATCH 044/108] fix: device PMU shutdown (part 2) (#3596) * fix: device PMU shutdown (part 2) * fix error + enable nimble deinit --- src/Power.cpp | 7 +----- src/nimble/NimbleBluetooth.cpp | 4 ++-- src/sleep.cpp | 39 ++++++++++++++++++++-------------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/Power.cpp b/src/Power.cpp index 779e32ff5..d13fd6891 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -500,12 +500,7 @@ void Power::shutdown() { LOG_INFO("Shutting down\n"); -#ifdef HAS_PMU - if (pmu_found == true) { - PMU->setChargingLedMode(XPOWERS_CHG_LED_OFF); - PMU->shutdown(); - } -#elif defined(ARCH_NRF52) || defined(ARCH_ESP32) +#if defined(ARCH_NRF52) || defined(ARCH_ESP32) #ifdef PIN_LED1 ledOff(PIN_LED1); #endif diff --git a/src/nimble/NimbleBluetooth.cpp b/src/nimble/NimbleBluetooth.cpp index 0b91bf44f..42b296e45 100644 --- a/src/nimble/NimbleBluetooth.cpp +++ b/src/nimble/NimbleBluetooth.cpp @@ -113,8 +113,8 @@ void NimbleBluetooth::shutdown() pAdvertising->reset(); pAdvertising->stop(); -#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0) - // Saving of ~1mA +#if defined(ARCH_ESP32) + // Saving of ~1mA for esp32-s3 and 0.1mA for esp32 // Probably applicable to other ESP32 boards - unverified NimBLEDevice::deinit(); #endif diff --git a/src/sleep.cpp b/src/sleep.cpp index 5fbb733e6..7ed264183 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -245,6 +245,22 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false) digitalWrite(VEXT_ENABLE, 1); // turn off the display power #endif +#ifdef ARCH_ESP32 + if (shouldLoraWake(msecToWake)) { + enableLoraInterrupt(); + } +#ifdef BUTTON_PIN + // Avoid leakage through button pin + pinMode(BUTTON_PIN, INPUT); + gpio_hold_en((gpio_num_t)BUTTON_PIN); +#endif + + // LoRa CS (RADIO_NSS) needs to stay HIGH, even during deep sleep + pinMode(LORA_CS, OUTPUT); + digitalWrite(LORA_CS, HIGH); + gpio_hold_en((gpio_num_t)LORA_CS); +#endif + #ifdef HAS_PMU if (pmu_found && PMU) { // Obsolete comment: from back when we we used to receive lora packets while CPU was in deep sleep. @@ -257,6 +273,7 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false) // If we want to leave the radio receiving in would be 11.5mA current draw, but most of the time it is just waiting // in its sequencer (true?) so the average power draw should be much lower even if we were listinging for packets // all the time. + PMU->setChargingLedMode(XPOWERS_CHG_LED_OFF); uint8_t model = PMU->getChipModel(); if (model == XPOWERS_AXP2101) { @@ -271,25 +288,15 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false) // t-beam v1.1 radio power channel PMU->disablePowerOutput(XPOWERS_LDO2); // lora radio power channel } + if (msecToWake == portMAX_DELAY) { + LOG_INFO("PMU shutdown.\n"); + console->flush(); + PMU->shutdown(); + } } #endif -#ifdef ARCH_ESP32 - if (shouldLoraWake(msecToWake)) { - enableLoraInterrupt(); - } - -#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0) // Applicable to most ESP32 boards? - // Avoid leakage through button pin - pinMode(BUTTON_PIN, INPUT); - rtc_gpio_hold_en((gpio_num_t)BUTTON_PIN); - - // LoRa CS (RADIO_NSS) needs to stay HIGH, even during deep sleep - pinMode(LORA_CS, OUTPUT); - digitalWrite(LORA_CS, HIGH); - rtc_gpio_hold_en((gpio_num_t)LORA_CS); -#endif -#endif + console->flush(); cpuDeepSleep(msecToWake); } From f4a2023dbad5e50ca6e0d4aa197a9bf92fb78041 Mon Sep 17 00:00:00 2001 From: Gareth Coleman <30833824+garethhcoleman@users.noreply.github.com> Date: Fri, 12 Apr 2024 01:40:14 +0100 Subject: [PATCH 045/108] LSM6DS3TR-C support (#3593) * started work on pulling in the unphone library and dependencies, to do e.g. power switch management and etc.; currently failing at Adafruit_ImageReader * now compiles with unphoneLibrary included * successfully pulled in unphone library to manage power switch and init vibe motor and etc. doesnt print to serial tho... * simplified the build a bit; when doing meshtastic do not depend on the MCCI lora libs etc., then also no need to config them via build flags * version that doesnt trigger brownout * cleaned up initVariant a little * note re. GPS * back to mesh upstream version * this time we're back to mesh upstream version * getting LSM6DS3TRC driver installed * shake to wake works, set threshold quite low may need increasing * whats the crack with these end of file changes? * paramatize the wake threshold * try to get the PR to just include real changes * got the right config item and also not giving compiler messages * moved the lib_deps for the LSM6DS3TRC driver from our variant platformio.ini to the main one in root so all boards have it * stuupid error #define-ing --------- Co-authored-by: Hamish Cunningham Co-authored-by: Ben Meadors --- platformio.ini | 1 + src/AccelerometerThread.h | 16 +++++++++++++++- src/configuration.h | 3 ++- src/detect/ScanI2C.cpp | 4 ++-- src/detect/ScanI2C.h | 1 + src/detect/ScanI2CTwoWire.cpp | 1 + variants/unphone/variant.h | 2 ++ 7 files changed, 24 insertions(+), 4 deletions(-) diff --git a/platformio.ini b/platformio.ini index 2c373ab00..d54a06d3e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -132,3 +132,4 @@ lib_deps = adafruit/Adafruit MPU6050@^2.2.4 adafruit/Adafruit LIS3DH@^1.2.4 https://github.com/lewisxhe/SensorLib#27fd0f721e20cd09e1f81383f0ba58a54fe84a17 + adafruit/Adafruit LSM6DS@^4.7.2 \ No newline at end of file diff --git a/src/AccelerometerThread.h b/src/AccelerometerThread.h index 6827908b7..fa5acdaae 100644 --- a/src/AccelerometerThread.h +++ b/src/AccelerometerThread.h @@ -5,6 +5,7 @@ #include "power.h" #include +#include #include #include #include @@ -108,6 +109,15 @@ class AccelerometerThread : public concurrency::OSThread bmaSensor.enableTiltIRQ(); // It corresponds to isDoubleClick interrupt bmaSensor.enableWakeupIRQ(); + } else if (acceleremoter_type == ScanI2C::DeviceType::LSM6DS3 && lsm.begin_I2C(accelerometer_found.address)) { + LOG_DEBUG("LSM6DS3 initializing\n"); + // Default threshold of 2G, less sensitive options are 4, 8 or 16G + lsm.setAccelRange(LSM6DS_ACCEL_RANGE_2_G); +#ifndef LSM6DS3_WAKE_THRESH +#define LSM6DS3_WAKE_THRESH 20 +#endif + lsm.enableWakeup(config.display.wake_on_tap_or_motion, 1, LSM6DS3_WAKE_THRESH); + // Duration is number of occurances needed to trigger, higher threshold is less sensitive } } @@ -133,6 +143,9 @@ class AccelerometerThread : public concurrency::OSThread wakeScreen(); return 500; } + } else if (acceleremoter_type == ScanI2C::DeviceType::LSM6DS3 && lsm.shake()) { + wakeScreen(); + return 500; } return ACCELEROMETER_CHECK_INTERVAL_MS; @@ -156,6 +169,7 @@ class AccelerometerThread : public concurrency::OSThread ScanI2C::DeviceType acceleremoter_type; Adafruit_MPU6050 mpu; Adafruit_LIS3DH lis; + Adafruit_LSM6DS3TRC lsm; }; -} // namespace concurrency +} // namespace concurrency \ No newline at end of file diff --git a/src/configuration.h b/src/configuration.h index 7ce1a0b8b..66ec607ff 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -128,6 +128,7 @@ along with this program. If not, see . #define MPU6050_ADDR 0x68 #define LIS3DH_ADR 0x18 #define BMA423_ADDR 0x19 +#define LSM6DS3_ADDR 0x6A // ----------------------------------------------------------------------------- // LED @@ -280,4 +281,4 @@ along with this program. If not, see . #ifdef MESHTASTIC_EXCLUDE_SCREEN #undef HAS_SCREEN #define HAS_SCREEN 0 -#endif +#endif \ No newline at end of file diff --git a/src/detect/ScanI2C.cpp b/src/detect/ScanI2C.cpp index bf206c190..149bb95f0 100644 --- a/src/detect/ScanI2C.cpp +++ b/src/detect/ScanI2C.cpp @@ -36,8 +36,8 @@ ScanI2C::FoundDevice ScanI2C::firstKeyboard() const ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const { - ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423}; - return firstOfOrNONE(3, types); + ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423, LSM6DS3}; + return firstOfOrNONE(4, types); } ScanI2C::FoundDevice ScanI2C::find(ScanI2C::DeviceType) const diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index ecb6db225..e87ede0a4 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -39,6 +39,7 @@ class ScanI2C LIS3DH, BMA423, BQ24295, + LSM6DS3, #ifdef HAS_NCP5623 NCP5623, #endif diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index ea6e692df..335892131 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -310,6 +310,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port) SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found\n") SCAN_SIMPLE_CASE(MPU6050_ADDR, MPU6050, "MPU6050 accelerometer found\n"); SCAN_SIMPLE_CASE(BMA423_ADDR, BMA423, "BMA423 accelerometer found\n"); + SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3 accelerometer found\n"); default: LOG_INFO("Device found at address 0x%x was not able to be enumerated\n", addr.address); diff --git a/variants/unphone/variant.h b/variants/unphone/variant.h index dff03b8d5..9306537f2 100644 --- a/variants/unphone/variant.h +++ b/variants/unphone/variant.h @@ -53,6 +53,8 @@ #define I2C_SDA 3 // I2C pins for this board #define I2C_SCL 4 +#define LSM6DS3_WAKE_THRESH 5 // higher values reduce the sensitivity of the wake threshold + // ratio of voltage divider = 3.20 (R1=100k, R2=220k) // #define ADC_MULTIPLIER 3.2 From 6de0363eea1ff91eeca219ef6a47a122a8de706e Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Fri, 12 Apr 2024 07:17:43 -0500 Subject: [PATCH 046/108] Pin RadioLib to 6.5.x (#3601) --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index d54a06d3e..27f9cf546 100644 --- a/platformio.ini +++ b/platformio.ini @@ -74,7 +74,7 @@ build_flags = -Wno-missing-field-initializers monitor_speed = 115200 lib_deps = - jgromes/RadioLib@^6.4.0 + jgromes/RadioLib@~6.5.0 https://github.com/meshtastic/esp8266-oled-ssd1306.git#ee628ee6c9588d4c56c9e3da35f0fc9448ad54a8 ; ESP8266_SSD1306 mathertel/OneButton@^2.5.0 ; OneButton library for non-blocking button debounce https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159 @@ -132,4 +132,4 @@ lib_deps = adafruit/Adafruit MPU6050@^2.2.4 adafruit/Adafruit LIS3DH@^1.2.4 https://github.com/lewisxhe/SensorLib#27fd0f721e20cd09e1f81383f0ba58a54fe84a17 - adafruit/Adafruit LSM6DS@^4.7.2 \ No newline at end of file + adafruit/Adafruit LSM6DS@^4.7.2 From 178877f2d9eccd7a046c142b6abee5d08ba9a817 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Sat, 13 Apr 2024 00:18:36 +1200 Subject: [PATCH 047/108] Enable T-Echo touch button by default (#3604) Co-authored-by: Ben Meadors --- src/mesh/NodeDB.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index fb2b79048..ea0a27992 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -346,6 +346,9 @@ void NodeDB::installDefaultModuleConfig() moduleConfig.external_notification.alert_message = true; moduleConfig.external_notification.output_ms = 100; moduleConfig.external_notification.active = true; +#endif +#ifdef TTGO_T_ECHO + config.display.wake_on_tap_or_motion = true; // Enable touch button for screen-on / refresh #endif moduleConfig.has_canned_message = true; From 8fd32f34525613448f17f962cd6e00f84b53a59f Mon Sep 17 00:00:00 2001 From: Oliver Seiler Date: Sat, 13 Apr 2024 00:19:48 +1200 Subject: [PATCH 048/108] enable USB CDC (#3597) --- boards/tbeam-s3-core.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/tbeam-s3-core.json b/boards/tbeam-s3-core.json index 7bda2e5a0..8d2c3eed6 100644 --- a/boards/tbeam-s3-core.json +++ b/boards/tbeam-s3-core.json @@ -8,7 +8,7 @@ "-DBOARD_HAS_PSRAM", "-DLILYGO_TBEAM_S3_CORE", "-DARDUINO_USB_CDC_ON_BOOT=1", - "-DARDUINO_USB_MODE=0", + "-DARDUINO_USB_MODE=1", "-DARDUINO_RUNNING_CORE=1", "-DARDUINO_EVENT_RUNNING_CORE=1" ], From 4c9646f7d97a063d366061adff9c9686da51f3e7 Mon Sep 17 00:00:00 2001 From: Manuel <71137295+mverch67@users.noreply.github.com> Date: Fri, 12 Apr 2024 17:01:24 +0200 Subject: [PATCH 049/108] fix: device sleep (part 1) (#3590) * fix sleep part 1 * always show wakeup reason in debug log * fix screen turn on issue * avoid unnecessary reboot when entering light sleep * set DIO1 based on radio type --------- Co-authored-by: Ben Meadors --- src/PowerFSM.cpp | 23 +++++++------- src/detect/LoRaRadioType.h | 5 ++++ src/main.cpp | 11 +++++++ src/sleep.cpp | 61 +++++++++++++++++++++++++++++--------- 4 files changed, 76 insertions(+), 24 deletions(-) create mode 100644 src/detect/LoRaRadioType.h diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 0002a62b4..a6b2aea27 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -102,18 +102,21 @@ static void lsIdle() powerFSM.trigger(EVENT_SERIAL_CONNECTED); break; - case ESP_SLEEP_WAKEUP_GPIO: - // GPIO wakeup is now used for all ESP32 devices during light sleep - powerFSM.trigger(EVENT_PRESS); - break; - default: - // We woke for some other reason (device interrupt?) - LOG_INFO("wakeCause2 %d\n", wakeCause2); + // We woke for some other reason (button press, device IRQ interrupt) - // Let the NB state handle the IRQ (and that state will handle stuff like IRQs etc) - // we lie and say "wake timer" because the interrupt will be handled by the regular IRQ code - powerFSM.trigger(EVENT_WAKE_TIMER); +#ifdef BUTTON_PIN + bool pressed = !digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN); +#else + bool pressed = false; +#endif + if (pressed) { // If we woke because of press, instead generate a PRESS event. + powerFSM.trigger(EVENT_PRESS); + } else { + // Otherwise let the NB state handle the IRQ (and that state will handle stuff like IRQs etc) + // we lie and say "wake timer" because the interrupt will be handled by the regular IRQ code + powerFSM.trigger(EVENT_WAKE_TIMER); + } break; } } else { diff --git a/src/detect/LoRaRadioType.h b/src/detect/LoRaRadioType.h new file mode 100644 index 000000000..eadd92e64 --- /dev/null +++ b/src/detect/LoRaRadioType.h @@ -0,0 +1,5 @@ +#pragma once + +enum LoRaRadioType { NO_RADIO, STM32WLx_RADIO, SIM_RADIO, RF95_RADIO, SX1262_RADIO, SX1268_RADIO, LLCC68_RADIO, SX1280_RADIO }; + +extern LoRaRadioType radioType; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 0f2ef7e67..32ac91412 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -69,6 +69,7 @@ NRF52Bluetooth *nrf52Bluetooth; #include "SX1262Interface.h" #include "SX1268Interface.h" #include "SX1280Interface.h" +#include "detect/LoRaRadioType.h" #ifdef ARCH_STM32WL #include "STM32WLE5JCInterface.h" @@ -142,6 +143,9 @@ ATECCX08A atecc; Adafruit_DRV2605 drv; #endif +// Global LoRa radio type +LoRaRadioType radioType = NO_RADIO; + bool isVibrating = false; bool eink_found = true; @@ -793,6 +797,7 @@ void setup() rIf = NULL; } else { LOG_INFO("STM32WL Radio init succeeded, using STM32WL radio\n"); + radioType = STM32WLx_RADIO; } } #endif @@ -806,6 +811,7 @@ void setup() rIf = NULL; } else { LOG_INFO("Using SIMULATED radio!\n"); + radioType = SIM_RADIO; } } #endif @@ -819,6 +825,7 @@ void setup() rIf = NULL; } else { LOG_INFO("RF95 Radio init succeeded, using RF95 radio\n"); + radioType = RF95_RADIO; } } #endif @@ -832,6 +839,7 @@ void setup() rIf = NULL; } else { LOG_INFO("SX1262 Radio init succeeded, using SX1262 radio\n"); + radioType = SX1262_RADIO; } } #endif @@ -845,6 +853,7 @@ void setup() rIf = NULL; } else { LOG_INFO("SX1268 Radio init succeeded, using SX1268 radio\n"); + radioType = SX1268_RADIO; } } #endif @@ -858,6 +867,7 @@ void setup() rIf = NULL; } else { LOG_INFO("LLCC68 Radio init succeeded, using LLCC68 radio\n"); + radioType = LLCC68_RADIO; } } #endif @@ -871,6 +881,7 @@ void setup() rIf = NULL; } else { LOG_INFO("SX1280 Radio init succeeded, using SX1280 radio\n"); + radioType = SX1280_RADIO; } } #endif diff --git a/src/sleep.cpp b/src/sleep.cpp index 7ed264183..fdfaf5e35 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -8,6 +8,7 @@ #include "MeshRadio.h" #include "MeshService.h" #include "NodeDB.h" +#include "detect/LoRaRadioType.h" #include "error.h" #include "main.h" #include "sleep.h" @@ -153,7 +154,7 @@ void initDeepSleep() // If waking from sleep, release any and all RTC GPIOs if (wakeCause != ESP_SLEEP_WAKEUP_UNDEFINED) { LOG_DEBUG("Disabling any holds on RTC IO pads\n"); - for (uint8_t i = 0; i <= 45; i++) { + for (uint8_t i = 0; i <= GPIO_NUM_MAX; i++) { if (rtc_gpio_is_valid_gpio((gpio_num_t)i)) rtc_gpio_hold_dis((gpio_num_t)i); } @@ -360,19 +361,23 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r #endif auto res = esp_sleep_enable_gpio_wakeup(); if (res != ESP_OK) { - LOG_DEBUG("esp_sleep_enable_gpio_wakeup result %d\n", res); + LOG_ERROR("esp_sleep_enable_gpio_wakeup result %d\n", res); } assert(res == ESP_OK); res = esp_sleep_enable_timer_wakeup(sleepUsec); if (res != ESP_OK) { - LOG_DEBUG("esp_sleep_enable_timer_wakeup result %d\n", res); + LOG_ERROR("esp_sleep_enable_timer_wakeup result %d\n", res); } assert(res == ESP_OK); + + console->flush(); res = esp_light_sleep_start(); if (res != ESP_OK) { - LOG_DEBUG("esp_light_sleep_start result %d\n", res); + LOG_ERROR("esp_light_sleep_start result %d\n", res); } - assert(res == ESP_OK); + // commented out because it's not that crucial; + // if it sporadically happens the node will go into light sleep during the next round + // assert(res == ESP_OK); #ifdef BUTTON_PIN // Disable wake-on-button interrupt. Re-attach normal button-interrupts @@ -380,13 +385,27 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r buttonThread->attachButtonInterrupts(); #endif +#if !defined(SOC_PM_SUPPORT_EXT_WAKEUP) && defined(LORA_DIO1) && (LORA_DIO1 != RADIOLIB_NC) + if (radioType != RF95_RADIO) { + gpio_wakeup_disable((gpio_num_t)LORA_DIO1); + } +#endif +#if defined(RF95_IRQ) && (RF95_IRQ != RADIOLIB_NC) + if (radioType == RF95_RADIO) { + gpio_wakeup_disable((gpio_num_t)RF95_IRQ); + } +#endif + esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); #ifdef BUTTON_PIN if (cause == ESP_SLEEP_WAKEUP_GPIO) { LOG_INFO("Exit light sleep gpio: btn=%d\n", !digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN)); - } + } else #endif + { + LOG_INFO("Exit light sleep cause: %d\n", cause); + } return cause; } @@ -428,20 +447,34 @@ bool shouldLoraWake(uint32_t msecToWake) void enableLoraInterrupt() { #if SOC_PM_SUPPORT_EXT_WAKEUP && defined(LORA_DIO1) && (LORA_DIO1 != RADIOLIB_NC) - rtc_gpio_pulldown_en((gpio_num_t)LORA_DIO1); + gpio_pulldown_en((gpio_num_t)LORA_DIO1); #if defined(LORA_RESET) && (LORA_RESET != RADIOLIB_NC) - rtc_gpio_pullup_en((gpio_num_t)LORA_RESET); + gpio_pullup_en((gpio_num_t)LORA_RESET); #endif #if defined(LORA_CS) && (LORA_CS != RADIOLIB_NC) - rtc_gpio_pullup_en((gpio_num_t)LORA_CS); + gpio_pullup_en((gpio_num_t)LORA_CS); #endif - // Setup deep sleep with wakeup by external source - esp_sleep_enable_ext0_wakeup((gpio_num_t)LORA_DIO1, RISING); + + if (rtc_gpio_is_valid_gpio((gpio_num_t)LORA_DIO1)) { + // Setup light/deep sleep with wakeup by external source + LOG_INFO("setup LORA_DIO1 (GPIO%02d) with wakeup by external source\n", LORA_DIO1); + esp_sleep_enable_ext0_wakeup((gpio_num_t)LORA_DIO1, HIGH); + } else { + LOG_INFO("setup LORA_DIO1 (GPIO%02d) with wakeup by gpio interrupt\n", LORA_DIO1); + gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL); + } + #elif defined(LORA_DIO1) && (LORA_DIO1 != RADIOLIB_NC) - gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL); // SX126x/SX128x interrupt, active high + if (radioType != RF95_RADIO) { + LOG_INFO("setup LORA_DIO1 (GPIO%02d) with wakeup by gpio interrupt\n", LORA_DIO1); + gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL); // SX126x/SX128x interrupt, active high + } #endif -#ifdef RF95_IRQ - gpio_wakeup_enable((gpio_num_t)RF95_IRQ, GPIO_INTR_HIGH_LEVEL); // RF95 interrupt, active high +#if defined(RF95_IRQ) && (RF95_IRQ != RADIOLIB_NC) + if (radioType == RF95_RADIO) { + LOG_INFO("setup RF95_IRQ (GPIO%02d) with wakeup by gpio interrupt\n", RF95_IRQ); + gpio_wakeup_enable((gpio_num_t)RF95_IRQ, GPIO_INTR_HIGH_LEVEL); // RF95 interrupt, active high + } #endif } #endif From 2c4db163364893becd37d6be48f40773eb2b51c0 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Fri, 12 Apr 2024 10:49:14 -0500 Subject: [PATCH 050/108] TinyGPSAltitude support for negative altitude (#3605) --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 27f9cf546..c5cbaf908 100644 --- a/platformio.ini +++ b/platformio.ini @@ -78,7 +78,7 @@ lib_deps = https://github.com/meshtastic/esp8266-oled-ssd1306.git#ee628ee6c9588d4c56c9e3da35f0fc9448ad54a8 ; ESP8266_SSD1306 mathertel/OneButton@^2.5.0 ; OneButton library for non-blocking button debounce https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159 - https://github.com/meshtastic/TinyGPSPlus.git#f9f4fef2183514aa52be91d714c1455dd6f26e45 + https://github.com/meshtastic/TinyGPSPlus.git#bc14cc3146b33e295fc845026289a472004d48dc https://github.com/meshtastic/ArduinoThread.git#1ae8778c85d0a2a729f989e0b1e7d7c4dc84eef0 nanopb/Nanopb@^0.4.7 erriez/ErriezCRC32@^1.0.1 @@ -132,4 +132,4 @@ lib_deps = adafruit/Adafruit MPU6050@^2.2.4 adafruit/Adafruit LIS3DH@^1.2.4 https://github.com/lewisxhe/SensorLib#27fd0f721e20cd09e1f81383f0ba58a54fe84a17 - adafruit/Adafruit LSM6DS@^4.7.2 + adafruit/Adafruit LSM6DS@^4.7.2 \ No newline at end of file From 917b739e6294cb9c081877fde9d2379703021ad7 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Fri, 12 Apr 2024 11:29:08 -0500 Subject: [PATCH 051/108] Update TinyGPS version to un-derped commit --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index c5cbaf908..e28b7424d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -78,7 +78,7 @@ lib_deps = https://github.com/meshtastic/esp8266-oled-ssd1306.git#ee628ee6c9588d4c56c9e3da35f0fc9448ad54a8 ; ESP8266_SSD1306 mathertel/OneButton@^2.5.0 ; OneButton library for non-blocking button debounce https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159 - https://github.com/meshtastic/TinyGPSPlus.git#bc14cc3146b33e295fc845026289a472004d48dc + https://github.com/meshtastic/TinyGPSPlus.git#f5b67909745c44590048594727865b3e9b055014 https://github.com/meshtastic/ArduinoThread.git#1ae8778c85d0a2a729f989e0b1e7d7c4dc84eef0 nanopb/Nanopb@^0.4.7 erriez/ErriezCRC32@^1.0.1 @@ -132,4 +132,4 @@ lib_deps = adafruit/Adafruit MPU6050@^2.2.4 adafruit/Adafruit LIS3DH@^1.2.4 https://github.com/lewisxhe/SensorLib#27fd0f721e20cd09e1f81383f0ba58a54fe84a17 - adafruit/Adafruit LSM6DS@^4.7.2 \ No newline at end of file + adafruit/Adafruit LSM6DS@^4.7.2 From b4009f9f2f6245cbdb5e93cb1163403ade3d3693 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Fri, 12 Apr 2024 11:49:35 -0500 Subject: [PATCH 052/108] New fixed copy-pasted more corrector hash --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index e28b7424d..a1082a84a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -78,7 +78,7 @@ lib_deps = https://github.com/meshtastic/esp8266-oled-ssd1306.git#ee628ee6c9588d4c56c9e3da35f0fc9448ad54a8 ; ESP8266_SSD1306 mathertel/OneButton@^2.5.0 ; OneButton library for non-blocking button debounce https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159 - https://github.com/meshtastic/TinyGPSPlus.git#f5b67909745c44590048594727865b3e9b055014 + https://github.com/meshtastic/TinyGPSPlus.git#964f75a72cccd6b53cd74e4add1f7a42c6f7344d https://github.com/meshtastic/ArduinoThread.git#1ae8778c85d0a2a729f989e0b1e7d7c4dc84eef0 nanopb/Nanopb@^0.4.7 erriez/ErriezCRC32@^1.0.1 @@ -132,4 +132,4 @@ lib_deps = adafruit/Adafruit MPU6050@^2.2.4 adafruit/Adafruit LIS3DH@^1.2.4 https://github.com/lewisxhe/SensorLib#27fd0f721e20cd09e1f81383f0ba58a54fe84a17 - adafruit/Adafruit LSM6DS@^4.7.2 + adafruit/Adafruit LSM6DS@^4.7.2 \ No newline at end of file From 11adfe05cea06ed21b781e53095cc498aaa5253e Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Fri, 12 Apr 2024 14:06:05 -0500 Subject: [PATCH 053/108] Drop unishox2 functions from Router (#3606) --- src/mesh/Router.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 266c4f78d..3fa933bb1 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -8,9 +8,6 @@ #include "main.h" #include "mesh-pb-constants.h" #include "modules/RoutingModule.h" -extern "C" { -#include "mesh/compression/unishox2.h" -} #if !MESHTASTIC_EXCLUDE_MQTT #include "mqtt/MQTT.h" #endif @@ -332,6 +329,7 @@ bool perhapsDecode(meshtastic_MeshPacket *p) p->which_payload_variant = meshtastic_MeshPacket_decoded_tag; // change type to decoded p->channel = chIndex; // change to store the index instead of the hash + /* Not actually ever used. // Decompress if needed. jm if (p->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_COMPRESSED_APP) { // Decompress the payload @@ -349,7 +347,7 @@ bool perhapsDecode(meshtastic_MeshPacket *p) // Switch the port from PortNum_TEXT_MESSAGE_COMPRESSED_APP to PortNum_TEXT_MESSAGE_APP p->decoded.portnum = meshtastic_PortNum_TEXT_MESSAGE_APP; - } + } */ printPacket("decoded message", p); return true; @@ -371,6 +369,7 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p) if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) { size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_Data_msg, &p->decoded); + /* Not actually used, so save the cycles // Only allow encryption on the text message app. // TODO: Allow modules to opt into compression. if (p->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP) { @@ -404,7 +403,7 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p) p->decoded.portnum = meshtastic_PortNum_TEXT_MESSAGE_COMPRESSED_APP; } - } + } */ if (numbytes > MAX_RHPACKETLEN) return meshtastic_Routing_Error_TOO_LARGE; @@ -500,4 +499,4 @@ void Router::perhapsHandleReceived(meshtastic_MeshPacket *p) handleReceived(p); packetPool.release(p); -} \ No newline at end of file +} From 3f45c2d4f06b51c5d02f70d37524bf3bb2d1236f Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Fri, 12 Apr 2024 14:14:56 -0500 Subject: [PATCH 054/108] Fix another LOG_DEBUG message that should be LOG_ERROR (#3607) --- src/mesh/RadioLibInterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index 3ad2abe23..fc1563ee3 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -319,7 +319,7 @@ void RadioLibInterface::handleReceiveInterrupt() // when this is called, we should be in receive mode - if we are not, just jump out instead of bombing. Possible Race // Condition? if (!isReceiving) { - LOG_DEBUG("*** WAS_ASSERT *** handleReceiveInterrupt called when not in receive mode\n"); + LOG_ERROR("handleReceiveInterrupt called when not in receive mode, which shouldn't happen.\n"); return; } @@ -414,4 +414,4 @@ void RadioLibInterface::startSend(meshtastic_MeshPacket *txp) // bits enableInterrupt(isrTxLevel0); } -} \ No newline at end of file +} From 2a6e26620e3976b23aba66da28e9d6034ae1362a Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Fri, 12 Apr 2024 20:17:25 -0500 Subject: [PATCH 055/108] Auto-favorite our node (#3609) --- src/mesh/PhoneAPI.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index f2d2a6e9d..efbcc9558 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -430,6 +430,8 @@ bool PhoneAPI::available() auto nextNode = nodeDB->readNextMeshNode(readIndex); if (nextNode) { nodeInfoForPhone = TypeConversions::ConvertToNodeInfo(nextNode); + nodeInfoForPhone.is_favorite = + nodeInfoForPhone.is_favorite || nodeInfoForPhone.num == nodeDB->getNodeNum(); // Our node is always a favorite } } return true; // Always say we have something, because we might need to advance our state machine From f1a1834ee2c5572dc6ae97997d401567138ef875 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sat, 13 Apr 2024 16:14:15 -0500 Subject: [PATCH 056/108] Update portduino to include SPI and setSetial fixes (#3611) --- arch/portduino/portduino.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index 3c996741c..07151c4a3 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -1,6 +1,6 @@ ; The Portduino based sim environment on top of any host OS, all hardware will be simulated [portduino_base] -platform = https://github.com/meshtastic/platform-native.git#117acc5e7fcc2047e9ba1dc11789daea26fc36d2 +platform = https://github.com/meshtastic/platform-native.git#c95616208ffff4c8a36d48df810a3f072cce3521 framework = arduino build_src_filter = From 0a246bfe9b93de6e7bd644ea8613b5af482de420 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sun, 14 Apr 2024 00:29:42 -0500 Subject: [PATCH 057/108] Add more useful error output in radio interfaces (#3615) * Add more useful error output in radio interfaces * trunk --- src/mesh/RF95Interface.cpp | 12 ++++++++++++ src/mesh/SX126xInterface.cpp | 17 +++++++++++++---- src/mesh/SX128xInterface.cpp | 15 +++++++++++---- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/mesh/RF95Interface.cpp b/src/mesh/RF95Interface.cpp index adc512ae2..b658a8ff6 100644 --- a/src/mesh/RF95Interface.cpp +++ b/src/mesh/RF95Interface.cpp @@ -128,12 +128,18 @@ bool RF95Interface::reconfigure() RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); err = lora->setSyncWord(syncWord); + if (err != RADIOLIB_ERR_NONE) + LOG_ERROR("Radiolib error %d when attempting RF95 setSyncWord!\n", err); assert(err == RADIOLIB_ERR_NONE); err = lora->setCurrentLimit(currentLimit); + if (err != RADIOLIB_ERR_NONE) + LOG_ERROR("Radiolib error %d when attempting RF95 setCurrentLimit!\n", err); assert(err == RADIOLIB_ERR_NONE); err = lora->setPreambleLength(preambleLength); + if (err != RADIOLIB_ERR_NONE) + LOG_ERROR("Radiolib error %d when attempting RF95 setPreambleLength!\n", err); assert(err == RADIOLIB_ERR_NONE); err = lora->setFrequency(getFreq()); @@ -164,6 +170,8 @@ void RF95Interface::addReceiveMetadata(meshtastic_MeshPacket *mp) void RF95Interface::setStandby() { int err = lora->standby(); + if (err != RADIOLIB_ERR_NONE) + LOG_ERROR("Radiolib error %d when attempting RF95 standby!\n", err); assert(err == RADIOLIB_ERR_NONE); isReceiving = false; // If we were receiving, not any more @@ -185,6 +193,8 @@ void RF95Interface::startReceive() setTransmitEnable(false); setStandby(); int err = lora->startReceive(); + if (err != RADIOLIB_ERR_NONE) + LOG_ERROR("Radiolib error %d when attempting RF95 startReceive!\n", err); assert(err == RADIOLIB_ERR_NONE); isReceiving = true; @@ -205,6 +215,8 @@ bool RF95Interface::isChannelActive() // LOG_DEBUG("Channel is busy!\n"); return true; } + if (result != RADIOLIB_ERR_WRONG_MODEM) + LOG_ERROR("Radiolib error %d when attempting RF95 isChannelActive!\n", result); assert(result != RADIOLIB_ERR_WRONG_MODEM); // LOG_DEBUG("Channel is free!\n"); diff --git a/src/mesh/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp index 104d0a5ed..0690f9e96 100644 --- a/src/mesh/SX126xInterface.cpp +++ b/src/mesh/SX126xInterface.cpp @@ -181,12 +181,18 @@ template bool SX126xInterface::reconfigure() RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); err = lora.setSyncWord(syncWord); + if (err != RADIOLIB_ERR_NONE) + LOG_ERROR("Radiolib error %d when attempting SX126X setSyncWord!\n", err); assert(err == RADIOLIB_ERR_NONE); err = lora.setCurrentLimit(currentLimit); + if (err != RADIOLIB_ERR_NONE) + LOG_ERROR("Radiolib error %d when attempting SX126X setCurrentLimit!\n", err); assert(err == RADIOLIB_ERR_NONE); err = lora.setPreambleLength(preambleLength); + if (err != RADIOLIB_ERR_NONE) + LOG_ERROR("Radiolib error %d when attempting SX126X setPreambleLength!\n", err); assert(err == RADIOLIB_ERR_NONE); err = lora.setFrequency(getFreq()); @@ -197,6 +203,8 @@ template bool SX126xInterface::reconfigure() power = SX126X_MAX_POWER; err = lora.setOutputPower(power); + if (err != RADIOLIB_ERR_NONE) + LOG_ERROR("Radiolib error %d when attempting SX126X setOutputPower!\n", err); assert(err == RADIOLIB_ERR_NONE); startReceive(); // restart receiving @@ -215,10 +223,8 @@ template void SX126xInterface::setStandby() int err = lora.standby(); - if (err != RADIOLIB_ERR_NONE) { + if (err != RADIOLIB_ERR_NONE) LOG_DEBUG("SX126x standby failed with error %d\n", err); - } - assert(err == RADIOLIB_ERR_NONE); isReceiving = false; // If we were receiving, not any more @@ -260,6 +266,8 @@ template void SX126xInterface::startReceive() int err = lora.startReceiveDutyCycleAuto(preambleLength, 8, RADIOLIB_SX126X_IRQ_RX_DEFAULT | RADIOLIB_SX126X_IRQ_PREAMBLE_DETECTED | RADIOLIB_SX126X_IRQ_HEADER_VALID); + if (err != RADIOLIB_ERR_NONE) + LOG_ERROR("Radiolib error %d when attempting SX126X startReceiveDutyCycleAuto!\n", err); assert(err == RADIOLIB_ERR_NONE); isReceiving = true; @@ -279,7 +287,8 @@ template bool SX126xInterface::isChannelActive() result = lora.scanChannel(); if (result == RADIOLIB_LORA_DETECTED) return true; - + if (result != RADIOLIB_ERR_WRONG_MODEM) + LOG_ERROR("Radiolib error %d when attempting SX126X scanChannel!\n", result); assert(result != RADIOLIB_ERR_WRONG_MODEM); return false; diff --git a/src/mesh/SX128xInterface.cpp b/src/mesh/SX128xInterface.cpp index 45325f339..564b80494 100644 --- a/src/mesh/SX128xInterface.cpp +++ b/src/mesh/SX128xInterface.cpp @@ -126,9 +126,13 @@ template bool SX128xInterface::reconfigure() RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); err = lora.setSyncWord(syncWord); + if (err != RADIOLIB_ERR_NONE) + LOG_ERROR("Radiolib error %d when attempting SX128X setSyncWord!\n", err); assert(err == RADIOLIB_ERR_NONE); err = lora.setPreambleLength(preambleLength); + if (err != RADIOLIB_ERR_NONE) + LOG_ERROR("Radiolib error %d when attempting SX128X setPreambleLength!\n", err); assert(err == RADIOLIB_ERR_NONE); err = lora.setFrequency(getFreq()); @@ -139,6 +143,8 @@ template bool SX128xInterface::reconfigure() power = SX128X_MAX_POWER; err = lora.setOutputPower(power); + if (err != RADIOLIB_ERR_NONE) + LOG_ERROR("Radiolib error %d when attempting SX128X setOutputPower!\n", err); assert(err == RADIOLIB_ERR_NONE); startReceive(); // restart receiving @@ -162,10 +168,8 @@ template void SX128xInterface::setStandby() int err = lora.standby(); - if (err != RADIOLIB_ERR_NONE) { + if (err != RADIOLIB_ERR_NONE) LOG_ERROR("SX128x standby failed with error %d\n", err); - } - assert(err == RADIOLIB_ERR_NONE); #if ARCH_PORTDUINO if (settingsMap[rxen] != RADIOLIB_NC) { @@ -255,6 +259,8 @@ template void SX128xInterface::startReceive() lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_SX128X_IRQ_RX_DEFAULT | RADIOLIB_SX128X_IRQ_PREAMBLE_DETECTED | RADIOLIB_SX128X_IRQ_HEADER_VALID); + if (err != RADIOLIB_ERR_NONE) + LOG_ERROR("Radiolib error %d when attempting SX128X startReceive!\n", err); assert(err == RADIOLIB_ERR_NONE); isReceiving = true; @@ -274,7 +280,8 @@ template bool SX128xInterface::isChannelActive() result = lora.scanChannel(); if (result == RADIOLIB_LORA_DETECTED) return true; - + if (result != RADIOLIB_ERR_WRONG_MODEM) + LOG_ERROR("Radiolib error %d when attempting SX128X scanChannel!\n", result); assert(result != RADIOLIB_ERR_WRONG_MODEM); return false; From ec3971bce5a3b65a5c2593dae8c8ab5b25d0f451 Mon Sep 17 00:00:00 2001 From: Manuel <71137295+mverch67@users.noreply.github.com> Date: Sun, 14 Apr 2024 15:11:22 +0200 Subject: [PATCH 058/108] fix upDown ISR (#3612) --- src/input/UpDownInterruptBase.cpp | 49 +++++++++++++++++++++---------- src/input/UpDownInterruptBase.h | 9 +++++- 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/input/UpDownInterruptBase.cpp b/src/input/UpDownInterruptBase.cpp index ecc3b944a..b1f83c56b 100644 --- a/src/input/UpDownInterruptBase.cpp +++ b/src/input/UpDownInterruptBase.cpp @@ -1,7 +1,7 @@ #include "UpDownInterruptBase.h" #include "configuration.h" -UpDownInterruptBase::UpDownInterruptBase(const char *name) +UpDownInterruptBase::UpDownInterruptBase(const char *name) : concurrency::OSThread(name) { this->_originName = name; } @@ -24,31 +24,48 @@ void UpDownInterruptBase::init(uint8_t pinDown, uint8_t pinUp, uint8_t pinPress, attachInterrupt(this->_pinUp, onIntUp, RISING); LOG_DEBUG("Up/down/press GPIO initialized (%d, %d, %d)\n", this->_pinUp, this->_pinDown, pinPress); + + this->setInterval(100); +} + +int32_t UpDownInterruptBase::runOnce() +{ + InputEvent e; + e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE; + + if (this->action == UPDOWN_ACTION_PRESSED) { + LOG_DEBUG("GPIO event Press\n"); + e.inputEvent = this->_eventPressed; + } else if (this->action == UPDOWN_ACTION_UP) { + LOG_DEBUG("GPIO event Up\n"); + e.inputEvent = this->_eventUp; + } else if (this->action == UPDOWN_ACTION_DOWN) { + LOG_DEBUG("GPIO event Down\n"); + e.inputEvent = this->_eventDown; + } + + if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) { + e.source = this->_originName; + e.kbchar = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE; + this->notifyObservers(&e); + } + + this->action = UPDOWN_ACTION_NONE; + + return 100; } void UpDownInterruptBase::intPressHandler() { - InputEvent e; - e.source = this->_originName; - LOG_DEBUG("GPIO event Press\n"); - e.inputEvent = this->_eventPressed; - this->notifyObservers(&e); + this->action = UPDOWN_ACTION_PRESSED; } void UpDownInterruptBase::intDownHandler() { - InputEvent e; - e.source = this->_originName; - LOG_DEBUG("GPIO event Down\n"); - e.inputEvent = this->_eventDown; - this->notifyObservers(&e); + this->action = UPDOWN_ACTION_DOWN; } void UpDownInterruptBase::intUpHandler() { - InputEvent e; - e.source = this->_originName; - LOG_DEBUG("GPIO event Up\n"); - e.inputEvent = this->_eventUp; - this->notifyObservers(&e); + this->action = UPDOWN_ACTION_UP; } diff --git a/src/input/UpDownInterruptBase.h b/src/input/UpDownInterruptBase.h index afa64d28d..7060a0d80 100644 --- a/src/input/UpDownInterruptBase.h +++ b/src/input/UpDownInterruptBase.h @@ -3,7 +3,7 @@ #include "InputBroker.h" #include "mesh/NodeDB.h" -class UpDownInterruptBase : public Observable +class UpDownInterruptBase : public Observable, public concurrency::OSThread { public: explicit UpDownInterruptBase(const char *name); @@ -13,6 +13,13 @@ class UpDownInterruptBase : public Observable void intDownHandler(); void intUpHandler(); + int32_t runOnce() override; + + protected: + enum UpDownInterruptBaseActionType { UPDOWN_ACTION_NONE, UPDOWN_ACTION_PRESSED, UPDOWN_ACTION_UP, UPDOWN_ACTION_DOWN }; + + volatile UpDownInterruptBaseActionType action = UPDOWN_ACTION_NONE; + private: uint8_t _pinDown = 0; uint8_t _pinUp = 0; From 5047468d9fee8aad3913514369f904ce6ef6fa85 Mon Sep 17 00:00:00 2001 From: Manuel <71137295+mverch67@users.noreply.github.com> Date: Sun, 14 Apr 2024 16:11:27 +0200 Subject: [PATCH 059/108] fix/enhancement: TFT device powersave (part 3) (#3600) * fix: device TFT powersave (part 3) * trunk fmt * trunk fmt * undo bluetooth deinit from #3596 * revert code for heltec tracker --------- Co-authored-by: Ben Meadors --- src/PowerFSM.cpp | 6 +++++- src/graphics/TFTDisplay.cpp | 13 +++++++++---- src/mesh/NodeDB.cpp | 6 ++++++ src/nimble/NimbleBluetooth.cpp | 4 ++-- src/sleep.cpp | 7 +++++++ variants/t-deck/variant.h | 2 ++ variants/t-watch-s3/platformio.ini | 2 -- variants/t-watch-s3/variant.h | 2 ++ 8 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index a6b2aea27..ac48e664c 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -17,6 +17,10 @@ #include "sleep.h" #include "target_specific.h" +#ifndef SLEEP_TIME +#define SLEEP_TIME 30 +#endif + /// Should we behave as if we have AC power now? static bool isPowered() { @@ -81,7 +85,7 @@ static void lsIdle() // If some other service would stall sleep, don't let sleep happen yet if (doPreflightSleep()) { // Briefly come out of sleep long enough to blink the led once every few seconds - uint32_t sleepTime = 30; + uint32_t sleepTime = SLEEP_TIME; setLed(false); // Never leave led on while in light sleep esp_sleep_source_t wakeCause2 = doLightSleep(sleepTime * 1000LL); diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index 8de415185..fb64553ef 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -561,8 +561,10 @@ void TFTDisplay::sendCommand(uint8_t com) #elif defined(ST7735_BL_V05) pinMode(ST7735_BL_V05, OUTPUT); digitalWrite(ST7735_BL_V05, TFT_BACKLIGHT_ON); -#endif -#if defined(TFT_BL) && defined(TFT_BACKLIGHT_ON) +#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE) + tft->wakeup(); + tft->powerSaveOff(); +#elif defined(TFT_BL) && defined(TFT_BACKLIGHT_ON) digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); #endif @@ -596,10 +598,13 @@ void TFTDisplay::sendCommand(uint8_t com) #elif defined(ST7735_BL_V05) pinMode(ST7735_BL_V05, OUTPUT); digitalWrite(ST7735_BL_V05, !TFT_BACKLIGHT_ON); -#endif -#if defined(TFT_BL) && defined(TFT_BACKLIGHT_ON) +#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE) + tft->sleep(); + tft->powerSaveOn(); +#elif defined(TFT_BL) && defined(TFT_BACKLIGHT_ON) digitalWrite(TFT_BL, !TFT_BACKLIGHT_ON); #endif + #ifdef VTFT_CTRL_V03 digitalWrite(VTFT_CTRL_V03, HIGH); #endif diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index ea0a27992..921935593 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -311,6 +311,12 @@ void NodeDB::initConfigIntervals() config.power.wait_bluetooth_secs = default_wait_bluetooth_secs; config.display.screen_on_secs = default_screen_on_secs; + +#if defined(T_WATCH_S3) || defined(T_DECK) + config.power.is_power_saving = true; + config.display.screen_on_secs = 30; + config.power.wait_bluetooth_secs = 30; +#endif } void NodeDB::installDefaultModuleConfig() diff --git a/src/nimble/NimbleBluetooth.cpp b/src/nimble/NimbleBluetooth.cpp index 42b296e45..0b91bf44f 100644 --- a/src/nimble/NimbleBluetooth.cpp +++ b/src/nimble/NimbleBluetooth.cpp @@ -113,8 +113,8 @@ void NimbleBluetooth::shutdown() pAdvertising->reset(); pAdvertising->stop(); -#if defined(ARCH_ESP32) - // Saving of ~1mA for esp32-s3 and 0.1mA for esp32 +#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0) + // Saving of ~1mA // Probably applicable to other ESP32 boards - unverified NimBLEDevice::deinit(); #endif diff --git a/src/sleep.cpp b/src/sleep.cpp index fdfaf5e35..6abe535d7 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -352,6 +352,9 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r gpio_wakeup_enable(pin, GPIO_INTR_LOW_LEVEL); esp_sleep_enable_gpio_wakeup(); +#endif +#ifdef T_WATCH_S3 + gpio_wakeup_enable((gpio_num_t)SCREEN_TOUCH_INT, GPIO_INTR_LOW_LEVEL); #endif enableLoraInterrupt(); #ifdef PMU_IRQ @@ -385,6 +388,10 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r buttonThread->attachButtonInterrupts(); #endif +#ifdef T_WATCH_S3 + gpio_wakeup_disable((gpio_num_t)SCREEN_TOUCH_INT); +#endif + #if !defined(SOC_PM_SUPPORT_EXT_WAKEUP) && defined(LORA_DIO1) && (LORA_DIO1 != RADIOLIB_NC) if (radioType != RF95_RADIO) { gpio_wakeup_disable((gpio_num_t)LORA_DIO1); diff --git a/variants/t-deck/variant.h b/variants/t-deck/variant.h index 62ac0a373..09db198ec 100644 --- a/variants/t-deck/variant.h +++ b/variants/t-deck/variant.h @@ -24,6 +24,8 @@ #define TOUCH_I2C_PORT 0 #define TOUCH_SLAVE_ADDRESS 0x5D // GT911 +#define SLEEP_TIME 120 + #define BUTTON_PIN 0 // #define BUTTON_NEED_PULLUP diff --git a/variants/t-watch-s3/platformio.ini b/variants/t-watch-s3/platformio.ini index d03273ed4..5d5904b30 100644 --- a/variants/t-watch-s3/platformio.ini +++ b/variants/t-watch-s3/platformio.ini @@ -3,8 +3,6 @@ extends = esp32s3_base board = t-watch-s3 upload_protocol = esptool -upload_speed = 115200 -upload_port = /dev/tty.usbmodem3485188D636C1 build_flags = ${esp32_base.build_flags} -DT_WATCH_S3 diff --git a/variants/t-watch-s3/variant.h b/variants/t-watch-s3/variant.h index c66fac5ef..ad7e6b56b 100644 --- a/variants/t-watch-s3/variant.h +++ b/variants/t-watch-s3/variant.h @@ -25,6 +25,8 @@ #define TOUCH_I2C_PORT 1 #define TOUCH_SLAVE_ADDRESS 0x38 +#define SLEEP_TIME 180 + #define I2C_SDA1 39 // Used for capacitive touch #define I2C_SCL1 40 // Used for capacitive touch From 4f205718f01b9de456388a9fe84d80668de65a6a Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sun, 14 Apr 2024 10:27:01 -0500 Subject: [PATCH 060/108] Device telemetry uptime in seconds (#3614) --- src/modules/Telemetry/DeviceTelemetry.cpp | 21 +++++++++------------ src/modules/Telemetry/DeviceTelemetry.h | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/modules/Telemetry/DeviceTelemetry.cpp b/src/modules/Telemetry/DeviceTelemetry.cpp index 2ae904b89..3529267cb 100644 --- a/src/modules/Telemetry/DeviceTelemetry.cpp +++ b/src/modules/Telemetry/DeviceTelemetry.cpp @@ -15,14 +15,14 @@ int32_t DeviceTelemetryModule::runOnce() { - uint32_t now = millis(); + refreshUptime(); if (((lastSentToMesh == 0) || - ((now - lastSentToMesh) >= Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval))) && + ((uptimeLastMs - lastSentToMesh) >= Default::getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval))) && airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) && airTime->isTxAllowedAirUtil() && config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER && config.device.role != meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN) { sendTelemetry(); - lastSentToMesh = now; + lastSentToMesh = uptimeLastMs; } else if (service.isToPhoneQueueEmpty()) { // Just send to phone when it's not our time to send to mesh yet // Only send while queue is empty (phone assumed connected) @@ -68,16 +68,12 @@ meshtastic_Telemetry DeviceTelemetryModule::getDeviceTelemetry() t.time = getTime(); t.which_variant = meshtastic_Telemetry_device_metrics_tag; - t.variant.device_metrics.air_util_tx = airTime->utilizationTXPercent(); - if (powerStatus->getIsCharging()) { - t.variant.device_metrics.battery_level = MAGIC_USB_BATTERY_LEVEL; - } else { - t.variant.device_metrics.battery_level = powerStatus->getBatteryChargePercent(); - } - + t.variant.device_metrics.battery_level = + powerStatus->getIsCharging() ? MAGIC_USB_BATTERY_LEVEL : powerStatus->getBatteryChargePercent(); t.variant.device_metrics.channel_utilization = airTime->channelUtilizationPercent(); t.variant.device_metrics.voltage = powerStatus->getBatteryVoltageMv() / 1000.0; + t.variant.device_metrics.uptime_seconds = getUptimeSeconds(); return t; } @@ -85,9 +81,10 @@ meshtastic_Telemetry DeviceTelemetryModule::getDeviceTelemetry() bool DeviceTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly) { meshtastic_Telemetry telemetry = getDeviceTelemetry(); - LOG_INFO("(Sending): air_util_tx=%f, channel_utilization=%f, battery_level=%i, voltage=%f\n", + LOG_INFO("(Sending): air_util_tx=%f, channel_utilization=%f, battery_level=%i, voltage=%f, uptime=%i\n", telemetry.variant.device_metrics.air_util_tx, telemetry.variant.device_metrics.channel_utilization, - telemetry.variant.device_metrics.battery_level, telemetry.variant.device_metrics.voltage); + telemetry.variant.device_metrics.battery_level, telemetry.variant.device_metrics.voltage, + telemetry.variant.device_metrics.uptime_seconds); meshtastic_MeshPacket *p = allocDataProtobuf(telemetry); p->to = dest; diff --git a/src/modules/Telemetry/DeviceTelemetry.h b/src/modules/Telemetry/DeviceTelemetry.h index 81f83ce0a..5f4e761f9 100644 --- a/src/modules/Telemetry/DeviceTelemetry.h +++ b/src/modules/Telemetry/DeviceTelemetry.h @@ -12,6 +12,8 @@ class DeviceTelemetryModule : private concurrency::OSThread, public ProtobufModu : concurrency::OSThread("DeviceTelemetryModule"), ProtobufModule("DeviceTelemetry", meshtastic_PortNum_TELEMETRY_APP, &meshtastic_Telemetry_msg) { + uptimeWrapCount = 0; + uptimeLastMs = millis(); setIntervalFromNow(45 * 1000); // Wait until NodeInfo is sent } virtual bool wantUIFrame() { return false; } @@ -28,8 +30,27 @@ class DeviceTelemetryModule : private concurrency::OSThread, public ProtobufModu */ bool sendTelemetry(NodeNum dest = NODENUM_BROADCAST, bool phoneOnly = false); + /** + * Get the uptime in seconds + * Loses some accuracy after 49 days, but that's fine + */ + uint32_t getUptimeSeconds() { return (0xFFFFFFFF / 1000) * uptimeWrapCount + (uptimeLastMs / 1000); } + private: meshtastic_Telemetry getDeviceTelemetry(); uint32_t sendToPhoneIntervalMs = SECONDS_IN_MINUTE * 1000; // Send to phone every minute uint32_t lastSentToMesh = 0; + + void refreshUptime() + { + auto now = millis(); + // If we wrapped around (~49 days), increment the wrap count + if (now < uptimeLastMs) + uptimeWrapCount++; + + uptimeLastMs = now; + } + + uint32_t uptimeWrapCount; + uint32_t uptimeLastMs; }; From 1447148811ff49119dc01e588d60380c4c6809f4 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sun, 14 Apr 2024 14:15:06 -0500 Subject: [PATCH 061/108] Make sure settingsStrings get initialized --- src/platform/portduino/PortduinoGlue.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index 72b2a3bc7..f686ef3dc 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -77,6 +77,10 @@ void portduinoSetup() gpioInit(); std::string gpioChipName = "gpiochip"; + settingsStrings[i2cdev] = ""; + settingsStrings[keyboardDevice] = ""; + settingsStrings[webserverrootpath] = ""; + settingsStrings[spidev] = ""; YAML::Node yamlConfig; @@ -280,4 +284,4 @@ int initGPIOPin(int pinNum, std::string gpioChipName) std::cout << "Warning, cannot claim pin " << gpio_name << (p ? p.__cxa_exception_type()->name() : "null") << std::endl; return ERRNO_DISABLED; } -} \ No newline at end of file +} From 00d4c011c7d901dea144ae452f0d419312bda164 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sun, 14 Apr 2024 14:36:11 -0500 Subject: [PATCH 062/108] Fix sx126x error log logic --- src/mesh/SX126xInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp index 0690f9e96..afaa13b7f 100644 --- a/src/mesh/SX126xInterface.cpp +++ b/src/mesh/SX126xInterface.cpp @@ -287,7 +287,7 @@ template bool SX126xInterface::isChannelActive() result = lora.scanChannel(); if (result == RADIOLIB_LORA_DETECTED) return true; - if (result != RADIOLIB_ERR_WRONG_MODEM) + if (result != RADIOLIB_CHANNEL_FREE) LOG_ERROR("Radiolib error %d when attempting SX126X scanChannel!\n", result); assert(result != RADIOLIB_ERR_WRONG_MODEM); From 5b52c31a76762eda5c1e7d61221e39c59cecdccc Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sun, 14 Apr 2024 14:36:39 -0500 Subject: [PATCH 063/108] Fix HAS_WIRE logic in main --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 32ac91412..587bcb56e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -387,7 +387,7 @@ void setup() // We need to scan here to decide if we have a screen for nodeDB.init() and because power has been applied to // accessories auto i2cScanner = std::unique_ptr(new ScanI2CTwoWire()); -#ifdef HAS_WIRE +#if HAS_WIRE LOG_INFO("Scanning for i2c devices...\n"); #endif From 1d9754404163b9bed92d79da92d6019053f91127 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Mon, 15 Apr 2024 23:50:42 +1200 Subject: [PATCH 064/108] Wireless Paper: Fix BLE after Lightsleep (#3629) * NimBLE deinit for deep-sleep only * Optionally disable blink during light-sleep * Advised to revert "blink disable" This reverts commit 66347ce19bb7e6ade64827a01b0ba834bff1e361. --- src/nimble/NimbleBluetooth.cpp | 8 ++++---- src/nimble/NimbleBluetooth.h | 1 + src/sleep.cpp | 6 ++++++ variants/heltec_wireless_paper/variant.h | 3 +++ variants/heltec_wireless_paper_v1/variant.h | 3 +++ 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/nimble/NimbleBluetooth.cpp b/src/nimble/NimbleBluetooth.cpp index 0b91bf44f..092aef470 100644 --- a/src/nimble/NimbleBluetooth.cpp +++ b/src/nimble/NimbleBluetooth.cpp @@ -112,12 +112,12 @@ void NimbleBluetooth::shutdown() NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising(); pAdvertising->reset(); pAdvertising->stop(); +} -#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0) - // Saving of ~1mA - // Probably applicable to other ESP32 boards - unverified +// Extra power-saving on some devices +void NimbleBluetooth::deinit() +{ NimBLEDevice::deinit(); -#endif } bool NimbleBluetooth::isActive() diff --git a/src/nimble/NimbleBluetooth.h b/src/nimble/NimbleBluetooth.h index df2d3e45a..d1e347830 100644 --- a/src/nimble/NimbleBluetooth.h +++ b/src/nimble/NimbleBluetooth.h @@ -6,6 +6,7 @@ class NimbleBluetooth : BluetoothApi public: void setup(); void shutdown(); + void deinit(); void clearBonds(); bool isActive(); bool isConnected(); diff --git a/src/sleep.cpp b/src/sleep.cpp index 6abe535d7..860a676df 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -206,6 +206,12 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false) // not using wifi yet, but once we are this is needed to shutoff the radio hw // esp_wifi_stop(); waitEnterSleep(skipPreflight); + +#ifdef NIMBLE_DEINIT_FOR_DEEPSLEEP + // Extra power saving on some devices + nimbleBluetooth->deinit(); +#endif + #ifdef ARCH_ESP32 if (shouldLoraWake(msecToWake)) { notifySleep.notifyObservers(NULL); diff --git a/variants/heltec_wireless_paper/variant.h b/variants/heltec_wireless_paper/variant.h index 29b8bbbd1..466925a2e 100644 --- a/variants/heltec_wireless_paper/variant.h +++ b/variants/heltec_wireless_paper/variant.h @@ -55,3 +55,6 @@ #define SX126X_DIO2_AS_RF_SWITCH #define SX126X_DIO3_TCXO_VOLTAGE 1.8 + +// Power management +#define NIMBLE_DEINIT_FOR_DEEPSLEEP // Required to reach manufacturers claim of 18uA diff --git a/variants/heltec_wireless_paper_v1/variant.h b/variants/heltec_wireless_paper_v1/variant.h index 29b8bbbd1..466925a2e 100644 --- a/variants/heltec_wireless_paper_v1/variant.h +++ b/variants/heltec_wireless_paper_v1/variant.h @@ -55,3 +55,6 @@ #define SX126X_DIO2_AS_RF_SWITCH #define SX126X_DIO3_TCXO_VOLTAGE 1.8 + +// Power management +#define NIMBLE_DEINIT_FOR_DEEPSLEEP // Required to reach manufacturers claim of 18uA From 2803fa964e337b58da26fec4f29f62c7338481a1 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Mon, 15 Apr 2024 07:22:05 -0500 Subject: [PATCH 065/108] Add LoadFileState to differentiate types of success / failures (#3625) --- src/mesh/NodeDB.cpp | 49 +++++++++++++--------- src/mesh/NodeDB.h | 16 ++++++- src/modules/CannedMessageModule.cpp | 6 +-- src/modules/ExternalNotificationModule.cpp | 4 +- src/modules/NeighborInfoModule.cpp | 4 +- 5 files changed, 52 insertions(+), 27 deletions(-) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 921935593..dce7e47af 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -551,12 +551,17 @@ static const char *moduleConfigFileName = "/prefs/module.proto"; static const char *channelFileName = "/prefs/channels.proto"; static const char *oemConfigFile = "/oem/oem.proto"; -/** Load a protobuf from a file, return true for success */ -bool NodeDB::loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct) +/** Load a protobuf from a file, return LoadFileResult */ +LoadFileResult NodeDB::loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, + void *dest_struct) { - bool okay = false; + LoadFileResult state = LoadFileResult::OTHER_FAILURE; #ifdef FSCom - // static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM + + if (!FSCom.exists(filename)) { + LOG_INFO("File %s not found\n", filename); + return LoadFileResult::NOT_FOUND; + } auto f = FSCom.open(filename, FILE_O_READ); @@ -564,30 +569,32 @@ bool NodeDB::loadProto(const char *filename, size_t protoSize, size_t objSize, c LOG_INFO("Loading %s\n", filename); pb_istream_t stream = {&readcb, &f, protoSize}; - // LOG_DEBUG("Preload channel name=%s\n", channelSettings.name); - memset(dest_struct, 0, objSize); if (!pb_decode(&stream, fields, dest_struct)) { LOG_ERROR("Error: can't decode protobuf %s\n", PB_GET_ERROR(&stream)); + state = LoadFileResult::DECODE_FAILED; } else { - okay = true; + LOG_INFO("Loaded %s successfully\n", filename); + state = LoadFileResult::SUCCESS; } - f.close(); } else { - LOG_INFO("No %s preferences found\n", filename); + LOG_ERROR("Could not open / read %s\n", filename); } #else LOG_ERROR("ERROR: Filesystem not implemented\n"); + state = LoadFileState::NO_FILESYSTEM; #endif - return okay; + return state; } void NodeDB::loadFromDisk() { // static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM - if (!loadProto(prefFileName, sizeof(meshtastic_DeviceState) + MAX_NUM_NODES * sizeof(meshtastic_NodeInfo), - sizeof(meshtastic_DeviceState), &meshtastic_DeviceState_msg, &devicestate)) { + auto state = loadProto(prefFileName, sizeof(meshtastic_DeviceState) + MAX_NUM_NODES * sizeof(meshtastic_NodeInfo), + sizeof(meshtastic_DeviceState), &meshtastic_DeviceState_msg, &devicestate); + + if (state != LoadFileResult::SUCCESS) { installDefaultDeviceState(); // Our in RAM copy might now be corrupt } else { if (devicestate.version < DEVICESTATE_MIN_VER) { @@ -602,8 +609,9 @@ void NodeDB::loadFromDisk() } meshNodes->resize(MAX_NUM_NODES); - if (!loadProto(configFileName, meshtastic_LocalConfig_size, sizeof(meshtastic_LocalConfig), &meshtastic_LocalConfig_msg, - &config)) { + state = loadProto(configFileName, meshtastic_LocalConfig_size, sizeof(meshtastic_LocalConfig), &meshtastic_LocalConfig_msg, + &config); + if (state != LoadFileResult::SUCCESS) { installDefaultConfig(); // Our in RAM copy might now be corrupt } else { if (config.version < DEVICESTATE_MIN_VER) { @@ -614,8 +622,9 @@ void NodeDB::loadFromDisk() } } - if (!loadProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, sizeof(meshtastic_LocalModuleConfig), - &meshtastic_LocalModuleConfig_msg, &moduleConfig)) { + state = loadProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, sizeof(meshtastic_LocalModuleConfig), + &meshtastic_LocalModuleConfig_msg, &moduleConfig); + if (state != LoadFileResult::SUCCESS) { installDefaultModuleConfig(); // Our in RAM copy might now be corrupt } else { if (moduleConfig.version < DEVICESTATE_MIN_VER) { @@ -626,8 +635,9 @@ void NodeDB::loadFromDisk() } } - if (!loadProto(channelFileName, meshtastic_ChannelFile_size, sizeof(meshtastic_ChannelFile), &meshtastic_ChannelFile_msg, - &channelFile)) { + state = loadProto(channelFileName, meshtastic_ChannelFile_size, sizeof(meshtastic_ChannelFile), &meshtastic_ChannelFile_msg, + &channelFile); + if (state != LoadFileResult::SUCCESS) { installDefaultChannels(); // Our in RAM copy might now be corrupt } else { if (channelFile.version < DEVICESTATE_MIN_VER) { @@ -638,7 +648,8 @@ void NodeDB::loadFromDisk() } } - if (loadProto(oemConfigFile, meshtastic_OEMStore_size, sizeof(meshtastic_OEMStore), &meshtastic_OEMStore_msg, &oemStore)) { + state = loadProto(oemConfigFile, meshtastic_OEMStore_size, sizeof(meshtastic_OEMStore), &meshtastic_OEMStore_msg, &oemStore); + if (state == LoadFileResult::SUCCESS) { LOG_INFO("Loaded OEMStore\n"); } } diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index 4d24d7225..1c1736f78 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -38,6 +38,19 @@ uint32_t sinceLastSeen(const meshtastic_NodeInfoLite *n); /// Given a packet, return how many seconds in the past (vs now) it was received uint32_t sinceReceived(const meshtastic_MeshPacket *p); +enum LoadFileResult { + // Successfully opened the file + SUCCESS = 1, + // File does not exist + NOT_FOUND = 2, + // Device does not have a filesystem + NO_FILESYSTEM = 3, + // File exists, but could not decode protobufs + DECODE_FAILED = 4, + // File exists, but open failed for some reason + OTHER_FAILURE = 5 +}; + class NodeDB { // NodeNum provisionalNodeNum; // if we are trying to find a node num this is our current attempt @@ -115,7 +128,8 @@ class NodeDB bool factoryReset(); - bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct); + LoadFileResult loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, + void *dest_struct); bool saveProto(const char *filename, size_t protoSize, const pb_msgdesc_t *fields, const void *dest_struct); void installRoleDefaults(meshtastic_Config_DeviceConfig_Role role); diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index c1cf90325..cbd6fee72 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -664,9 +664,9 @@ ProcessMessage CannedMessageModule::handleReceived(const meshtastic_MeshPacket & void CannedMessageModule::loadProtoForModule() { - if (!nodeDB->loadProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size, - sizeof(meshtastic_CannedMessageModuleConfig), &meshtastic_CannedMessageModuleConfig_msg, - &cannedMessageModuleConfig)) { + if (nodeDB->loadProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size, + sizeof(meshtastic_CannedMessageModuleConfig), &meshtastic_CannedMessageModuleConfig_msg, + &cannedMessageModuleConfig) != LoadFileResult::SUCCESS) { installDefaultCannedMessageModuleConfig(); } } diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp index 617796544..a38b231af 100644 --- a/src/modules/ExternalNotificationModule.cpp +++ b/src/modules/ExternalNotificationModule.cpp @@ -284,8 +284,8 @@ ExternalNotificationModule::ExternalNotificationModule() // moduleConfig.external_notification.alert_message_buzzer = true; if (moduleConfig.external_notification.enabled) { - if (!nodeDB->loadProto(rtttlConfigFile, meshtastic_RTTTLConfig_size, sizeof(meshtastic_RTTTLConfig), - &meshtastic_RTTTLConfig_msg, &rtttlConfig)) { + if (nodeDB->loadProto(rtttlConfigFile, meshtastic_RTTTLConfig_size, sizeof(meshtastic_RTTTLConfig), + &meshtastic_RTTTLConfig_msg, &rtttlConfig) != LoadFileResult::SUCCESS) { memset(rtttlConfig.ringtone, 0, sizeof(rtttlConfig.ringtone)); strncpy(rtttlConfig.ringtone, "24:d=32,o=5,b=565:f6,p,f6,4p,p,f6,p,f6,2p,p,b6,p,b6,p,b6,p,b6,p,b,p,b,p,b,p,b,p,b,p,b,p,b,p,b,1p.,2p.,p", diff --git a/src/modules/NeighborInfoModule.cpp b/src/modules/NeighborInfoModule.cpp index 92395ffc5..470234047 100644 --- a/src/modules/NeighborInfoModule.cpp +++ b/src/modules/NeighborInfoModule.cpp @@ -233,8 +233,8 @@ meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSen void NeighborInfoModule::loadProtoForModule() { - if (!nodeDB->loadProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, sizeof(meshtastic_NeighborInfo), - &meshtastic_NeighborInfo_msg, &neighborState)) { + if (nodeDB->loadProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, sizeof(meshtastic_NeighborInfo), + &meshtastic_NeighborInfo_msg, &neighborState) != LoadFileResult::SUCCESS) { neighborState = meshtastic_NeighborInfo_init_zero; } } From 1291da746b1e052793327105b7d0e6d46d37ce19 Mon Sep 17 00:00:00 2001 From: Gareth Coleman <30833824+garethhcoleman@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:30:45 +0100 Subject: [PATCH 066/108] Support for alt I2C address for LSM6DS3 sensor, identification of TCA9555 IO Expander, resolve serial hang issue (#3622) * basic identification of TCA9555 * recognise LSM6DS3 on alt address * keep variant.h changes out of this PR * 2nd attempt to keep variant.h changes out of this PR --------- Co-authored-by: Ben Meadors --- src/configuration.h | 6 +++++- src/detect/ScanI2C.h | 1 + src/detect/ScanI2CTwoWire.cpp | 9 ++++++++- variants/unphone/platformio.ini | 5 ++++- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/configuration.h b/src/configuration.h index 66ec607ff..37b67f666 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -138,9 +138,13 @@ along with this program. If not, see . // ----------------------------------------------------------------------------- // Security // ----------------------------------------------------------------------------- - #define ATECC608B_ADDR 0x35 +// ----------------------------------------------------------------------------- +// IO Expander +// ----------------------------------------------------------------------------- +#define TCA9555_ADDR 0x26 + // ----------------------------------------------------------------------------- // GPS // ----------------------------------------------------------------------------- diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index e87ede0a4..c8fcfee10 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -40,6 +40,7 @@ class ScanI2C BMA423, BQ24295, LSM6DS3, + TCA9555, #ifdef HAS_NCP5623 NCP5623, #endif diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index 335892131..13c2f4609 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -299,6 +299,12 @@ void ScanI2CTwoWire::scanPort(I2CPort port) if (registerValue == 0xC0) { type = BQ24295; LOG_INFO("BQ24295 PMU found\n"); + break; + } + registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 1); // get ID + if (registerValue == 0x6A) { + type = LSM6DS3; + LOG_INFO("LSM6DS3 accelerometer found at address 0x%x\n", (uint8_t)addr.address); } else { type = QMI8658; LOG_INFO("QMI8658 Highrate 6-Axis inertial measurement sensor found\n"); @@ -310,7 +316,8 @@ void ScanI2CTwoWire::scanPort(I2CPort port) SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found\n") SCAN_SIMPLE_CASE(MPU6050_ADDR, MPU6050, "MPU6050 accelerometer found\n"); SCAN_SIMPLE_CASE(BMA423_ADDR, BMA423, "BMA423 accelerometer found\n"); - SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3 accelerometer found\n"); + SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3 accelerometer found at address 0x%x\n", (uint8_t)addr.address); + SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555 I2C expander found\n"); default: LOG_INFO("Device found at address 0x%x was not able to be enumerated\n", addr.address); diff --git a/variants/unphone/platformio.ini b/variants/unphone/platformio.ini index 9a4a63807..06314eaa3 100644 --- a/variants/unphone/platformio.ini +++ b/variants/unphone/platformio.ini @@ -7,10 +7,13 @@ upload_speed = 921600 monitor_speed = 115200 monitor_filters = esp32_exception_decoder +build_unflags = + -D ARDUINO_USB_MODE + build_flags = ${esp32_base.build_flags} -D UNPHONE - -D BOARD_HAS_PSRAM -I variants/unphone + -D ARDUINO_USB_MODE=0 lib_deps = ${esp32s3_base.lib_deps} lovyan03/LovyanGFX@^1.1.8 \ No newline at end of file From 27ae4399bc3f8c0049d3061fe454981e5e27fa73 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Mon, 15 Apr 2024 16:35:52 -0500 Subject: [PATCH 067/108] Zero hop always for connected node (#3634) --- src/mesh/PhoneAPI.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index efbcc9558..2a69d6d56 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -430,6 +430,7 @@ bool PhoneAPI::available() auto nextNode = nodeDB->readNextMeshNode(readIndex); if (nextNode) { nodeInfoForPhone = TypeConversions::ConvertToNodeInfo(nextNode); + nodeInfoForPhone.hops_away = nodeInfoForPhone.num == nodeDB->getNodeNum() ? 0 : nodeInfoForPhone.hops_away; nodeInfoForPhone.is_favorite = nodeInfoForPhone.is_favorite || nodeInfoForPhone.num == nodeDB->getNodeNum(); // Our node is always a favorite } From 2f9b68e08b2ff5fd4c6aa40b9c84041d2f3351ac Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Mon, 15 Apr 2024 16:36:22 -0500 Subject: [PATCH 068/108] File management changes (Part 2 - Reboot instead of reformat NRF52 after two failed file saves) (#3630) * Add LoadFileState to differentiate types of success / failures * Try rebooting NRF52s with multiple failed saves * Trunkate --- src/mesh/NodeDB.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index dce7e47af..73aa29bbf 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -688,9 +688,13 @@ bool NodeDB::saveProto(const char *filename, size_t protoSize, const pb_msgdesc_ static uint8_t failedCounter = 0; failedCounter++; if (failedCounter >= 2) { - FSCom.format(); - // After formatting, the device needs to be restarted - nodeDB->resetRadioConfig(true); + LOG_ERROR("Failed to save file twice. Rebooting...\n"); + delay(100); + NVIC_SystemReset(); + // We used to blow away the filesystem here, but that's a bit extreme + // FSCom.format(); + // // After formatting, the device needs to be restarted + // nodeDB->resetRadioConfig(true); } #endif } @@ -734,6 +738,7 @@ void NodeDB::saveToDisk(int saveWhat) config.has_power = true; config.has_network = true; config.has_bluetooth = true; + saveProto(configFileName, meshtastic_LocalConfig_size, &meshtastic_LocalConfig_msg, &config); } @@ -745,6 +750,12 @@ void NodeDB::saveToDisk(int saveWhat) moduleConfig.has_serial = true; moduleConfig.has_store_forward = true; moduleConfig.has_telemetry = true; + moduleConfig.has_neighbor_info = true; + moduleConfig.has_detection_sensor = true; + moduleConfig.has_ambient_lighting = true; + moduleConfig.has_audio = true; + moduleConfig.has_paxcounter = true; + saveProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, &meshtastic_LocalModuleConfig_msg, &moduleConfig); } From 441638c2eba017e842ab5b96b18f6f05dbcc2828 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 20:23:49 -0500 Subject: [PATCH 069/108] [create-pull-request] automated change (#3636) Co-authored-by: thebentern --- version.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.properties b/version.properties index 6aedf1e72..f5ad818a2 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 3 -build = 5 +build = 6 From 7d3175dc833f19d78754075c8fae2d3afb3686b5 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Tue, 16 Apr 2024 07:22:31 -0500 Subject: [PATCH 070/108] More useful default input device for Pi 400 (#3639) --- bin/config-dist.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/config-dist.yaml b/bin/config-dist.yaml index 5a8e658cb..d8cb5a9dd 100644 --- a/bin/config-dist.yaml +++ b/bin/config-dist.yaml @@ -112,7 +112,7 @@ Touchscreen: ### Configure device for direct keyboard input Input: -# KeyboardDevice: /dev/input/event0 +# KeyboardDevice: /dev/input/by-id/usb-_Raspberry_Pi_Internal_Keyboard-event-kbd ### From 3413b9da412fb0f197096d34de2b3fd4b90ff5ee Mon Sep 17 00:00:00 2001 From: Gareth Coleman <30833824+garethhcoleman@users.noreply.github.com> Date: Tue, 16 Apr 2024 13:29:08 +0100 Subject: [PATCH 071/108] Fixed XPT2046 syntax and using unPhone library to clean up support (#3631) * Fixed XPT2046 syntax and using unPhone library to clean up main and TFTDisplay. * strange extra edits removed wtf --- src/graphics/TFTDisplay.cpp | 33 ++++++++++++--------------------- src/main.cpp | 16 +--------------- variants/unphone/platformio.ini | 15 +++++++++++++-- variants/unphone/variant.cpp | 20 ++++++++++++++++++++ variants/unphone/variant.h | 14 +++++++++++--- 5 files changed, 57 insertions(+), 41 deletions(-) create mode 100644 variants/unphone/variant.cpp diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index fb64553ef..b561f3b56 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -411,8 +411,7 @@ class LGFX : public lgfx::LGFX_Device lgfx::Panel_HX8357D _panel_instance; lgfx::Bus_SPI _bus_instance; #if defined(USE_XPT2046) - lgfx::ITouch *_touch_instance; -// lgfx::Touch_XPT2046 _touch_instance; + lgfx::Touch_XPT2046 _touch_instance; #endif public: @@ -466,8 +465,7 @@ class LGFX : public lgfx::LGFX_Device #if defined(USE_XPT2046) { // Configure settings for touch control. - _touch_instance = new lgfx::Touch_XPT2046; - auto touch_cfg = _touch_instance->config(); + auto touch_cfg = _touch_instance.config(); touch_cfg.pin_cs = TOUCH_CS; touch_cfg.x_min = 0; @@ -478,8 +476,8 @@ class LGFX : public lgfx::LGFX_Device touch_cfg.bus_shared = true; touch_cfg.offset_rotation = 1; - _touch_instance->config(touch_cfg); - //_panel_instance->setTouch(_touch_instance); + _touch_instance.config(touch_cfg); + _panel_instance.setTouch(&_touch_instance); } #endif setPanel(&_panel_instance); @@ -496,6 +494,11 @@ static LGFX *tft = nullptr; #include "TFTDisplay.h" #include +#ifdef UNPHONE +#include "unPhone.h" +extern unPhone unphone; +#endif + TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus) { LOG_DEBUG("TFTDisplay!\n"); @@ -576,11 +579,7 @@ void TFTDisplay::sendCommand(uint8_t com) digitalWrite(VTFT_CTRL, LOW); #endif #ifdef UNPHONE - Wire.beginTransmission(0x26); - Wire.write(0x02); - Wire.write(0x04); // Backlight on - Wire.write(0x22); // G&B LEDs off - Wire.endTransmission(); + unphone.backlight(true); // using unPhone library #endif #ifdef RAK14014 #elif !defined(M5STACK) @@ -612,11 +611,7 @@ void TFTDisplay::sendCommand(uint8_t com) digitalWrite(VTFT_CTRL, HIGH); #endif #ifdef UNPHONE - Wire.beginTransmission(0x26); - Wire.write(0x02); - Wire.write(0x00); // Backlight off - Wire.write(0x22); // G&B LEDs off - Wire.endTransmission(); + unphone.backlight(false); // using unPhone library #endif #ifdef RAK14014 #elif !defined(M5STACK) @@ -690,11 +685,7 @@ bool TFTDisplay::connect() digitalWrite(ST7735_BL_V05, TFT_BACKLIGHT_ON); #endif #ifdef UNPHONE - Wire.beginTransmission(0x26); - Wire.write(0x02); - Wire.write(0x04); // Backlight on - Wire.write(0x22); // G&B LEDs off - Wire.endTransmission(); + unphone.backlight(true); // using unPhone library LOG_INFO("Power to TFT Backlight\n"); #endif diff --git a/src/main.cpp b/src/main.cpp index 587bcb56e..744fda4de 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -590,20 +590,6 @@ void setup() if (config.display.oled != meshtastic_Config_DisplayConfig_OledType_OLED_AUTO) screen_model = config.display.oled; -#ifdef UNPHONE - // initialise IO expander with pinmodes - Wire.beginTransmission(0x26); - Wire.write(0x06); - Wire.write(0x7A); - Wire.write(0xDD); - Wire.endTransmission(); - Wire.beginTransmission(0x26); - Wire.write(0x02); - Wire.write(0x04); // Backlight on - Wire.write(0x22); // G&B LEDs off - Wire.endTransmission(); -#endif - #if defined(USE_SH1107) screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // set dimension of 128x128 display_geometry = GEOMETRY_128_128; @@ -1017,4 +1003,4 @@ void loop() mainDelay.delay(delayMsec); } // if (didWake) LOG_DEBUG("wake!\n"); -} +} \ No newline at end of file diff --git a/variants/unphone/platformio.ini b/variants/unphone/platformio.ini index 06314eaa3..dad9a7177 100644 --- a/variants/unphone/platformio.ini +++ b/variants/unphone/platformio.ini @@ -1,5 +1,7 @@ +; platformio.ini for unphone meshtastic + [env:unphone] -;build_type = debug ; to make it possible to step through our jtag debugger + extends = esp32s3_base board_level = extra board = unphone9 @@ -14,6 +16,15 @@ build_flags = ${esp32_base.build_flags} -D UNPHONE -I variants/unphone -D ARDUINO_USB_MODE=0 + -D UNPHONE_ACCEL=0 + -D UNPHONE_TOUCHS=0 + -D UNPHONE_SDCARD=0 + -D UNPHONE_UI0=0 + -D UNPHONE_LORA=0 + -D UNPHONE_FACTORY_MODE=0 + +build_src_filter = ${esp32_base.build_src_filter} +<../variants/unphone> lib_deps = ${esp32s3_base.lib_deps} - lovyan03/LovyanGFX@^1.1.8 \ No newline at end of file + lovyan03/LovyanGFX @ ^1.1.8 + https://gitlab.com/hamishcunningham/unphonelibrary#meshtastic @ ^9.0.0 \ No newline at end of file diff --git a/variants/unphone/variant.cpp b/variants/unphone/variant.cpp new file mode 100644 index 000000000..3f6d1c54d --- /dev/null +++ b/variants/unphone/variant.cpp @@ -0,0 +1,20 @@ +// meshtastic/firmware/variants/unphone/variant.cpp + +#include "unPhone.h" +unPhone unphone = unPhone("meshtastic_unphone"); + +void initVariant() +{ + unphone.begin(); // initialise hardware etc. + unphone.store(unphone.buildTime); + unphone.printWakeupReason(); // what woke us up? (stored, not printed :|) + unphone.checkPowerSwitch(); // if power switch is off, shutdown + unphone.backlight(false); // setup backlight and make sure its off + + for (int i = 0; i < 3; i++) { // buzz a bit + unphone.vibe(true); + delay(150); + unphone.vibe(false); + delay(150); + } +} \ No newline at end of file diff --git a/variants/unphone/variant.h b/variants/unphone/variant.h index 9306537f2..180fdfe2c 100644 --- a/variants/unphone/variant.h +++ b/variants/unphone/variant.h @@ -1,3 +1,7 @@ +// meshtastic/firmware/variants/unphone/variant.h + +#pragma once + #define SPI_SCK 39 #define SPI_MOSI 40 #define SPI_MISO 41 @@ -28,7 +32,7 @@ #define TFT_WIDTH 320 #define TFT_OFFSET_X 0 #define TFT_OFFSET_Y 0 -#define TFT_OFFSET_ROTATION 6 // the unPhone's screen is wired unusually, 0 is typical value here +#define TFT_OFFSET_ROTATION 6 // unPhone's screen wired unusually, 0 typical #define TFT_INVERT false #define SCREEN_ROTATE true #define SCREEN_TRANSITION_FRAMERATE 5 @@ -37,7 +41,10 @@ #define USE_XPT2046 1 #define TOUCH_CS 38 -#define HAS_GPS 0 // the unphone doesn't have a gps module +#define HAS_GPS \ + 0 // the unphone doesn't have a gps module by default (though + // GPS featherwing -- https://www.adafruit.com/product/3133 + // -- can be added) #undef GPS_RX_PIN #undef GPS_TX_PIN @@ -49,6 +56,7 @@ #define BUTTON_PIN 21 // Button 3 - square - top button in landscape mode #define BUTTON_NEED_PULLUP // we do need a helping hand up +#define BUTTON_PIN_ALT 45 // Button 1 - triangle - bottom button in landscape mode #define I2C_SDA 3 // I2C pins for this board #define I2C_SCL 4 @@ -58,6 +66,6 @@ // ratio of voltage divider = 3.20 (R1=100k, R2=220k) // #define ADC_MULTIPLIER 3.2 -// #define BATTERY_PIN 13 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +// #define BATTERY_PIN 13 // battery V measurement pin; vbat divider is here // #define ADC_CHANNEL ADC2_GPIO13_CHANNEL // #define BAT_MEASURE_ADC_UNIT 2 \ No newline at end of file From a01069a549584937ced04ab741f57cd35c110837 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Wed, 17 Apr 2024 00:36:14 +1200 Subject: [PATCH 072/108] No more printing power-state changes to screen (#3640) --- src/PowerFSM.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index ac48e664c..4f42b36b5 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -185,10 +185,12 @@ static void powerEnter() screen->setOn(true); setBluetoothEnable(true); // within enter() the function getState() returns the state we came from - if (strcmp(powerFSM.getState()->name, "BOOT") != 0 && strcmp(powerFSM.getState()->name, "POWER") != 0 && + + // Mothballed: print change of power-state to device screen + /* if (strcmp(powerFSM.getState()->name, "BOOT") != 0 && strcmp(powerFSM.getState()->name, "POWER") != 0 && strcmp(powerFSM.getState()->name, "DARK") != 0) { screen->print("Powered...\n"); - } + }*/ } } @@ -205,8 +207,10 @@ static void powerExit() { screen->setOn(true); setBluetoothEnable(true); - if (!isPowered()) - screen->print("Unpowered...\n"); + + // Mothballed: print change of power-state to device screen + /*if (!isPowered()) + screen->print("Unpowered...\n");*/ } static void onEnter() From 699ea7467299c8c5e19711111f0ad98f1c14b894 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 08:01:32 -0500 Subject: [PATCH 073/108] [create-pull-request] automated change (#3642) Co-authored-by: thebentern --- protobufs | 2 +- src/mesh/generated/meshtastic/mesh.pb.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/protobufs b/protobufs index f92900c5f..ecf105f66 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit f92900c5f884b04388fb7abf61d4df66783015e4 +Subproject commit ecf105f66d182531423b73f4408c53701313c4eb diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index e674e28bb..67b2edd15 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -146,6 +146,8 @@ typedef enum _meshtastic_HardwareModel { /* Teledatics TD-LORAC NRF52840 based M.2 LoRA module Compatible with the TD-WRLS development board */ meshtastic_HardwareModel_TD_LORAC = 60, + /* CDEBYTE EoRa-S3 board using their own MM modules, clone of LILYGO T3S3 */ + meshtastic_HardwareModel_CDEBYTE_EORA_S3 = 61, /* ------------------------------------------------------------------------------------------------------------------------------------------ Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. ------------------------------------------------------------------------------------------------------------------------------------------ */ From e813703bf5298b60eb5357608b6e5009ebd87def Mon Sep 17 00:00:00 2001 From: S5NC <145265251+S5NC@users.noreply.github.com> Date: Tue, 16 Apr 2024 15:00:16 +0100 Subject: [PATCH 074/108] Add support for CDEBYTE_EoRa-S3 (#3613) * Create CDEBYTE_EoRa-S3.json * Update CDEBYTE_EoRa-S3.json * Update architecture.h * Create variant.h * Create platformio.ini * Create pins_arduino.h * Update variant.h * Update variant.h * Update variant.h * Trunk format * update variant.h --------- Co-authored-by: Ben Meadors Co-authored-by: S5NC <> --- boards/CDEBYTE_EoRa-S3.json | 38 +++++++++++++++ src/platform/esp32/architecture.h | 2 + variants/CDEBYTE_EoRa-S3/pins_arduino.h | 37 +++++++++++++++ variants/CDEBYTE_EoRa-S3/platformio.ini | 8 ++++ variants/CDEBYTE_EoRa-S3/variant.h | 63 +++++++++++++++++++++++++ 5 files changed, 148 insertions(+) create mode 100644 boards/CDEBYTE_EoRa-S3.json create mode 100644 variants/CDEBYTE_EoRa-S3/pins_arduino.h create mode 100644 variants/CDEBYTE_EoRa-S3/platformio.ini create mode 100644 variants/CDEBYTE_EoRa-S3/variant.h diff --git a/boards/CDEBYTE_EoRa-S3.json b/boards/CDEBYTE_EoRa-S3.json new file mode 100644 index 000000000..9ecee3c9f --- /dev/null +++ b/boards/CDEBYTE_EoRa-S3.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-D CDEBYTE_EORA_S3", + "-D ARDUINO_USB_CDC_ON_BOOT=1", + "-D ARDUINO_USB_MODE=0", + "-D ARDUINO_RUNNING_CORE=1", + "-D ARDUINO_EVENT_RUNNING_CORE=1", + "-D BOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [["0x303A", "0x1001"]], + "mcu": "esp32s3", + "variant": "CDEBYTE_EoRa-S3" + }, + "connectivity": ["wifi"], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": ["arduino", "espidf"], + "name": "CDEBYTE EoRa-S3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.cdebyte.com/Module-Testkits-EoRaPI", + "vendor": "CDEBYTE" +} diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h index 6855265ac..15e437bb5 100644 --- a/src/platform/esp32/architecture.h +++ b/src/platform/esp32/architecture.h @@ -117,6 +117,8 @@ #define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER #elif defined(TLORA_T3S3_V1) #define HW_VENDOR meshtastic_HardwareModel_TLORA_T3_S3 +#elif defined(CDEBYTE_ELORA_S3) +#define HW_VENDOR meshtastic_HardwareModel_CDEBYTE_ELORA_S3 #elif defined(BETAFPV_2400_TX) #define HW_VENDOR meshtastic_HardwareModel_BETAFPV_2400_TX #elif defined(NANO_G1_EXPLORER) diff --git a/variants/CDEBYTE_EoRa-S3/pins_arduino.h b/variants/CDEBYTE_EoRa-S3/pins_arduino.h new file mode 100644 index 000000000..38a9103f0 --- /dev/null +++ b/variants/CDEBYTE_EoRa-S3/pins_arduino.h @@ -0,0 +1,37 @@ +// Need this file for ESP32-S3 +// No need to modify this file, changes to pins imported from variant.h +// Most is similar to https://github.com/espressif/arduino-esp32/blob/master/variants/esp32s3/pins_arduino.h + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +#define EXTERNAL_NUM_INTERRUPTS 46 +#define NUM_DIGITAL_PINS 48 +#define NUM_ANALOG_INPUTS 20 + +#define analogInputToDigitalPin(p) (((p) < 20) ? (analogChannelToDigitalPin(p)) : -1) +#define digitalPinToInterrupt(p) \ + (((p) < 48) ? (p) : -1) // Maybe it should be <= 48 but this is from a trustworthy source so it is likely correct +#define digitalPinHasPWM(p) (p < 46) + +// Serial +static const uint8_t TX = UART_TX; +static const uint8_t RX = UART_RX; + +// Default SPI will be mapped to Radio +static const uint8_t SS = LORA_CS; +static const uint8_t SCK = LORA_SCK; +static const uint8_t MOSI = LORA_MOSI; +static const uint8_t MISO = LORA_MISO; + +// The default Wire will be mapped to PMU and RTC +static const uint8_t SCL = I2C_SCL; +static const uint8_t SDA = I2C_SDA; + +#endif /* Pins_Arduino_h */ diff --git a/variants/CDEBYTE_EoRa-S3/platformio.ini b/variants/CDEBYTE_EoRa-S3/platformio.ini new file mode 100644 index 000000000..1ff54de88 --- /dev/null +++ b/variants/CDEBYTE_EoRa-S3/platformio.ini @@ -0,0 +1,8 @@ +[env:CDEBYTE_EoRa-S3] +extends = esp32s3_base +board = CDEBYTE_EoRa-S3 +build_flags = + ${esp32s3_base.build_flags} + -D CDEBYTE_EORA_S3 + -I variants/CDEBYTE_EoRa-S3 + -D GPS_POWER_TOGGLE diff --git a/variants/CDEBYTE_EoRa-S3/variant.h b/variants/CDEBYTE_EoRa-S3/variant.h new file mode 100644 index 000000000..5da99667b --- /dev/null +++ b/variants/CDEBYTE_EoRa-S3/variant.h @@ -0,0 +1,63 @@ +// LED - status indication +#define LED_PIN 37 + +// Button - user interface +#define BUTTON_PIN 0 // This is the BOOT button, and it has its own pull-up resistor + +// SD card - TODO: test, currently untested, copied from T3S3 variant +#define HAS_SDCARD +#define SDCARD_USE_SPI1 +// TODO: rename this to make this SD-card specific +#define SPI_CS 13 +#define SPI_SCK 14 +#define SPI_MOSI 11 +#define SPI_MISO 2 +// FIXME: there are two other SPI pins that are not defined here +// Compatibility +#define SDCARD_CS SPI_CS + +// Battery voltage monitoring - TODO: test, currently untested, copied from T3S3 variant +#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +#define ADC_CHANNEL ADC1_GPIO1_CHANNEL +#define ADC_MULTIPLIER \ + 2.11 // ratio of voltage divider = 2.0 (R10=1M, R13=1M), plus some undervoltage correction - TODO: this was carried over from + // the T3S3, test to see if the undervoltage correction is needed. + +// Display - OLED connected via I2C by the default hardware configuration +#define HAS_SCREEN 1 +#define USE_SSD1306 +#define I2C_SCL 17 +#define I2C_SDA 18 + +// UART - The 1mm JST SH connector closest to the USB-C port +#define UART_TX 43 +#define UART_RX 44 + +// Peripheral I2C - The 1mm JST SH connector furthest from the USB-C port which follows Adafruit connection standard. There are no +// pull-up resistors on these lines, the downstream device needs to include them. TODO: test, currently untested +#define I2C_SCL1 21 +#define I2C_SDA1 10 + +// Radio +#define USE_SX1262 // CDEBYTE EoRa-S3-900TB <- CDEBYTE E22-900MM22S <- Semtech SX1262 +#define USE_SX1268 // CDEBYTE EoRa-S3-400TB <- CDEBYTE E22-400MM22S <- Semtech SX1268 + +#define SX126X_CS 7 +#define LORA_SCK 5 +#define LORA_MOSI 6 +#define LORA_MISO 3 +#define SX126X_RESET 8 +#define SX126X_BUSY 34 +#define SX126X_DIO1 33 + +#define SX126X_DIO2_AS_RF_SWITCH // All switching is performed with DIO2, it is automatically inverted using circuitry. +// CDEBYTE EoRa-S3 uses an XTAL, thus we do not need DIO3 as TCXO voltage reference. Don't define SX126X_DIO3_TCXO_VOLTAGE for +// simplicity rather than defining it as 0. +#define SX126X_MAX_POWER \ + 22 // E22-900MM22S and E22-400MM22S have a raw SX1262 or SX1268 respsectively, they are rated to output up and including 22 + // dBm out of their SX126x IC. + +// Compatibility with old variant.h file structure - FIXME: this should be done in the respective radio interface modules to clean +// up all variants. +#define LORA_CS SX126X_CS +#define LORA_DIO1 SX126X_DIO1 \ No newline at end of file From 9599549477d015a747ae1a828ea75ee73bc6eb77 Mon Sep 17 00:00:00 2001 From: Andrew Yong Date: Tue, 16 Apr 2024 22:03:36 +0800 Subject: [PATCH 075/108] Add configuration option for LoRa Region Code override for region-locked builds/variants (#3540) The main use case for this will be to create a custom Heltec WiFi LoRa 32 V3 SG_923 variant, which will be pre-flashed and sent for regulatory approval for retail sale. Signed-off-by: Andrew Yong Co-authored-by: Ben Meadors --- src/configuration.h | 7 +++++++ src/mesh/RadioInterface.cpp | 8 +++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/configuration.h b/src/configuration.h index 37b67f666..701e07a32 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -74,6 +74,13 @@ along with this program. If not, see . #define RTC_DATA_ATTR #endif +// ----------------------------------------------------------------------------- +// Regulatory overrides for producing regional builds +// ----------------------------------------------------------------------------- + +// Define if region should override user saved region +// #define LORA_REGIONCODE meshtastic_Config_LoRaConfig_RegionCode_SG_923 + // ----------------------------------------------------------------------------- // Feature toggles // ----------------------------------------------------------------------------- diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 3aac9dfce..63912a03e 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -151,10 +151,16 @@ static uint8_t bytes[MAX_RHPACKETLEN]; void initRegion() { const RegionInfo *r = regions; +#ifdef LORA_REGIONCODE + for (; r->code != meshtastic_Config_LoRaConfig_RegionCode_UNSET && r->code != LORA_REGIONCODE; r++) + ; + LOG_INFO("Wanted region %d, regulatory override to %s\n", config.lora.region, r->name); +#else for (; r->code != meshtastic_Config_LoRaConfig_RegionCode_UNSET && r->code != config.lora.region; r++) ; - myRegion = r; LOG_INFO("Wanted region %d, using %s\n", config.lora.region, r->name); +#endif + myRegion = r; } /** From 55c9c3b29843a3301c5982ad6a46561d80d0fd94 Mon Sep 17 00:00:00 2001 From: David Ellefsen <93522+titan098@users.noreply.github.com> Date: Tue, 16 Apr 2024 16:03:51 +0200 Subject: [PATCH 076/108] Support for the ATGM336H series of GPS modules (#3610) Co-authored-by: Ben Meadors --- src/RedirectablePrint.cpp | 8 +- src/gps/GPS.cpp | 163 +++++++++++++++++++++++++++++++++++++- src/gps/GPS.h | 18 ++++- src/gps/cas.h | 63 +++++++++++++++ 4 files changed, 246 insertions(+), 6 deletions(-) create mode 100644 src/gps/cas.h diff --git a/src/RedirectablePrint.cpp b/src/RedirectablePrint.cpp index 16906e2e0..e09e5fe30 100644 --- a/src/RedirectablePrint.cpp +++ b/src/RedirectablePrint.cpp @@ -182,11 +182,11 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...) void RedirectablePrint::hexDump(const char *logLevel, unsigned char *buf, uint16_t len) { const char alphabet[17] = "0123456789abcdef"; - log(logLevel, " +------------------------------------------------+ +----------------+\n"); - log(logLevel, " |.0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .a .b .c .d .e .f | | ASCII |\n"); + log(logLevel, " +------------------------------------------------+ +----------------+\n"); + log(logLevel, " |.0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .a .b .c .d .e .f | | ASCII |\n"); for (uint16_t i = 0; i < len; i += 16) { if (i % 128 == 0) - log(logLevel, " +------------------------------------------------+ +----------------+\n"); + log(logLevel, " +------------------------------------------------+ +----------------+\n"); char s[] = "| | | |\n"; uint8_t ix = 1, iy = 52; for (uint8_t j = 0; j < 16; j++) { @@ -208,7 +208,7 @@ void RedirectablePrint::hexDump(const char *logLevel, unsigned char *buf, uint16 log(logLevel, "."); log(logLevel, s); } - log(logLevel, " +------------------------------------------------+ +----------------+\n"); + log(logLevel, " +------------------------------------------------+ +----------------+\n"); } std::string RedirectablePrint::mt_sprintf(const std::string fmt_str, ...) diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 6a0e3e44a..0d0bfd9a2 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -7,6 +7,8 @@ #include "main.h" // pmu_found #include "sleep.h" + +#include "cas.h" #include "ubx.h" #ifdef ARCH_PORTDUINO @@ -51,6 +53,28 @@ void GPS::UBXChecksum(uint8_t *message, size_t length) message[length - 1] = CK_B; } +// Calculate the checksum for a CAS packet +void GPS::CASChecksum(uint8_t *message, size_t length) +{ + uint32_t cksum = ((uint32_t)message[5] << 24); // Message ID + cksum += ((uint32_t)message[4]) << 16; // Class + cksum += message[2]; // Payload Len + + // Iterate over the payload as a series of uint32_t's and + // accumulate the cksum + uint32_t *payload = (uint32_t *)(message + 6); + for (size_t i = 0; i < (length - 10) / 4; i++) { + uint32_t p = payload[i]; + cksum += p; + } + + // Place the checksum values in the message + message[length - 4] = (cksum & 0xFF); + message[length - 3] = (cksum & (0xFF << 8)) >> 8; + message[length - 2] = (cksum & (0xFF << 16)) >> 16; + message[length - 1] = (cksum & (0xFF << 24)) >> 24; +} + // Function to create a ublox packet for editing in memory uint8_t GPS::makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg) { @@ -72,6 +96,41 @@ uint8_t GPS::makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_siz return (payload_size + 8); } +// Function to create a CAS packet for editing in memory +uint8_t GPS::makeCASPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg) +{ + // General CAS structure + // | H1 | H2 | payload_len | cls | msg | Payload ... | Checksum | + // Size: | 1 | 1 | 2 | 1 | 1 | payload_len | 4 | + // Pos: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 ... | 6 + payload_len ... | + // |------|------|-------------|------|------|------|--------------|---------------------------| + // | 0xBA | 0xCE | 0xXX | 0xXX | 0xXX | 0xXX | 0xXX | 0xXX ... | 0xXX | 0xXX | 0xXX | 0xXX | + + // Construct the CAS packet + UBXscratch[0] = 0xBA; // header 1 (0xBA) + UBXscratch[1] = 0xCE; // header 2 (0xCE) + UBXscratch[2] = payload_size; // length 1 + UBXscratch[3] = 0; // length 2 + UBXscratch[4] = class_id; // class + UBXscratch[5] = msg_id; // id + + UBXscratch[6 + payload_size] = 0x00; // Checksum + UBXscratch[7 + payload_size] = 0x00; + UBXscratch[8 + payload_size] = 0x00; + UBXscratch[9 + payload_size] = 0x00; + + for (int i = 0; i < payload_size; i++) { + UBXscratch[6 + i] = pgm_read_byte(&msg[i]); + } + CASChecksum(UBXscratch, (payload_size + 10)); + +#if defined(GPS_DEBUG) && defined(DEBUG_PORT) + LOG_DEBUG("Constructed CAS packet: \n"); + DEBUG_PORT.hexDump(MESHTASTIC_LOG_LEVEL_DEBUG, UBXscratch, payload_size + 10); +#endif + return (payload_size + 10); +} + GPS_RESPONSE GPS::getACK(const char *message, uint32_t waitMillis) { uint8_t buffer[768] = {0}; @@ -81,6 +140,7 @@ GPS_RESPONSE GPS::getACK(const char *message, uint32_t waitMillis) while (millis() < startTimeout) { if (_serial_gps->available()) { b = _serial_gps->read(); + #ifdef GPS_DEBUG LOG_DEBUG("%02X", (char *)buffer); #endif @@ -104,6 +164,67 @@ GPS_RESPONSE GPS::getACK(const char *message, uint32_t waitMillis) return GNSS_RESPONSE_NONE; } +GPS_RESPONSE GPS::getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis) +{ + uint32_t startTime = millis(); + uint8_t buffer[CAS_ACK_NACK_MSG_SIZE] = {0}; + uint8_t bufferPos = 0; + + // CAS-ACK-(N)ACK structure + // | H1 | H2 | Payload Len | cls | msg | Payload | Checksum (4) | + // | | | | | | Cls | Msg | Reserved | | + // |------|------|-------------|------|------|------|------|-------------|---------------------------| + // ACK-NACK| 0xBA | 0xCE | 0x04 | 0x00 | 0x05 | 0x00 | 0xXX | 0xXX | 0x00 | 0x00 | 0xXX | 0xXX | 0xXX | 0xXX | + // ACK-ACK | 0xBA | 0xCE | 0x04 | 0x00 | 0x05 | 0x01 | 0xXX | 0xXX | 0x00 | 0x00 | 0xXX | 0xXX | 0xXX | 0xXX | + + while (millis() - startTime < waitMillis) { + if (_serial_gps->available()) { + buffer[bufferPos++] = _serial_gps->read(); + + // keep looking at the first two bytes of buffer until + // we have found the CAS frame header (0xBA, 0xCE), if not + // keep reading bytes until we find a frame header or we run + // out of time. + if ((bufferPos == 2) && !(buffer[0] == 0xBA && buffer[1] == 0xCE)) { + buffer[0] = buffer[1]; + buffer[1] = 0; + bufferPos = 1; + } + } + + // we have read all the bytes required for the Ack/Nack (14-bytes) + // and we must have found a frame to get this far + if (bufferPos == sizeof(buffer) - 1) { + uint8_t msg_cls = buffer[4]; // message class should be 0x05 + uint8_t msg_msg_id = buffer[5]; // message id should be 0x00 or 0x01 + uint8_t payload_cls = buffer[6]; // payload class id + uint8_t payload_msg = buffer[7]; // payload message id + + // Check for an ACK-ACK for the specified class and message id + if ((msg_cls == 0x05) && (msg_msg_id == 0x01) && payload_cls == class_id && payload_msg == msg_id) { +#ifdef GPS_DEBUG + LOG_INFO("Got ACK for class %02X message %02X in %d millis.\n", class_id, msg_id, millis() - startTime); +#endif + return GNSS_RESPONSE_OK; + } + + // Check for an ACK-NACK for the specified class and message id + if ((msg_cls == 0x05) && (msg_msg_id == 0x00) && payload_cls == class_id && payload_msg == msg_id) { +#ifdef GPS_DEBUG + LOG_WARN("Got NACK for class %02X message %02X in %d millis.\n", class_id, msg_id, millis() - startTime); +#endif + return GNSS_RESPONSE_NAK; + } + + // This isn't the frame we are looking for, clear the buffer + // and try again until we run out of time. + memset(buffer, 0x0, sizeof(buffer)); + bufferPos = 0; + } + } + return GNSS_RESPONSE_NONE; +} + GPS_RESPONSE GPS::getACK(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis) { uint8_t b; @@ -313,6 +434,33 @@ bool GPS::setup() // Switch to Fitness Mode, for running and walking purpose with low speed (<5 m/s) _serial_gps->write("$PMTK886,1*29\r\n"); delay(250); + } else if (gnssModel == GNSS_MODEL_ATGM336H) { + // Set the intial configuration of the device - these _should_ work for most AT6558 devices + msglen = makeCASPacket(0x06, 0x07, sizeof(_message_CAS_CFG_NAVX_CONF), _message_CAS_CFG_NAVX_CONF); + _serial_gps->write(UBXscratch, msglen); + if (getACKCas(0x06, 0x07, 250) != GNSS_RESPONSE_OK) { + LOG_WARN("ATGM336H - Could not set Configuration"); + } + + // Set the update frequence to 1Hz + msglen = makeCASPacket(0x06, 0x04, sizeof(_message_CAS_CFG_RATE_1HZ), _message_CAS_CFG_RATE_1HZ); + _serial_gps->write(UBXscratch, msglen); + if (getACKCas(0x06, 0x04, 250) != GNSS_RESPONSE_OK) { + LOG_WARN("ATGM336H - Could not set Update Frequency"); + } + + // Set the NEMA output messages + // Ask for only RMC and GGA + uint8_t fields[] = {CAS_NEMA_RMC, CAS_NEMA_GGA}; + for (int i = 0; i < sizeof(fields); i++) { + // Construct a CAS-CFG-MSG packet + uint8_t cas_cfg_msg_packet[] = {0x4e, fields[i], 0x01, 0x00}; + msglen = makeCASPacket(0x06, 0x01, sizeof(cas_cfg_msg_packet), cas_cfg_msg_packet); + _serial_gps->write(UBXscratch, msglen); + if (getACKCas(0x06, 0x01, 250) != GNSS_RESPONSE_OK) { + LOG_WARN("ATGM336H - Could not enable NMEA MSG: %d\n", fields[i]); + } + } } else if (gnssModel == GNSS_MODEL_UC6580) { // The Unicore UC6580 can use a lot of sat systems, enable it to // use GPS L1 & L5 + BDS B1I & B2a + GLONASS L1 + GALILEO E1 & E5a + SBAS @@ -948,10 +1096,18 @@ GnssModel_t GPS::probe(int serialSpeed) uint8_t buffer[768] = {0}; delay(100); - // Close all NMEA sentences , Only valid for L76K MTK platform + // Close all NMEA sentences, valid for L76K, ATGM336H (and likely other AT6558 devices) _serial_gps->write("$PCAS03,0,0,0,0,0,0,0,0,0,0,,,0,0*02\r\n"); delay(20); + // Get version information + clearBuffer(); + _serial_gps->write("$PCAS06,1*1A\r\n"); + if (getACK("$GPTXT,01,01,02,HW=ATGM336H", 500) == GNSS_RESPONSE_OK) { + LOG_INFO("ATGM336H GNSS init succeeded, using ATGM336H Module\n"); + return GNSS_MODEL_ATGM336H; + } + // Get version information clearBuffer(); _serial_gps->write("$PCAS06,0*1B\r\n"); @@ -1216,6 +1372,11 @@ bool GPS::factoryReset() LOG_INFO("GNSS Factory Reset via PCAS10,3\n"); _serial_gps->write("$PCAS10,3*1F\r\n"); delay(100); + } else if (gnssModel == GNSS_MODEL_ATGM336H) { + LOG_INFO("Factory Reset via CAS-CFG-RST\n"); + uint8_t msglen = makeCASPacket(0x06, 0x02, sizeof(_message_CAS_CFG_RST_FACTORY), _message_CAS_CFG_RST_FACTORY); + _serial_gps->write(UBXscratch, msglen); + delay(100); } else { // fire this for good measure, if we have an L76B - won't harm other devices. _serial_gps->write("$PMTK104*37\r\n"); diff --git a/src/gps/GPS.h b/src/gps/GPS.h index 49f27e29f..77c6c0269 100644 --- a/src/gps/GPS.h +++ b/src/gps/GPS.h @@ -22,7 +22,14 @@ struct uBloxGnssModelInfo { char extension[10][30]; }; -typedef enum { GNSS_MODEL_MTK, GNSS_MODEL_UBLOX, GNSS_MODEL_UC6580, GNSS_MODEL_UNKNOWN, GNSS_MODEL_MTK_L76B } GnssModel_t; +typedef enum { + GNSS_MODEL_ATGM336H, + GNSS_MODEL_MTK, + GNSS_MODEL_UBLOX, + GNSS_MODEL_UC6580, + GNSS_MODEL_UNKNOWN, + GNSS_MODEL_MTK_L76B +} GnssModel_t; typedef enum { GNSS_RESPONSE_NONE, @@ -133,6 +140,11 @@ class GPS : private concurrency::OSThread static const uint8_t _message_VALSET_DISABLE_SBAS_RAM[]; static const uint8_t _message_VALSET_DISABLE_SBAS_BBR[]; + // CASIC commands for ATGM336H + static const uint8_t _message_CAS_CFG_RST_FACTORY[]; + static const uint8_t _message_CAS_CFG_NAVX_CONF[]; + static const uint8_t _message_CAS_CFG_RATE_1HZ[]; + meshtastic_Position p = meshtastic_Position_init_default; GPS() : concurrency::OSThread("GPS") {} @@ -174,6 +186,7 @@ class GPS : private concurrency::OSThread // Create a ublox packet for editing in memory uint8_t makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg); + uint8_t makeCASPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg); // scratch space for creating ublox packets uint8_t UBXscratch[250] = {0}; @@ -184,6 +197,8 @@ class GPS : private concurrency::OSThread GPS_RESPONSE getACK(uint8_t c, uint8_t i, uint32_t waitMillis); GPS_RESPONSE getACK(const char *message, uint32_t waitMillis); + GPS_RESPONSE getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis); + /** * Switch the GPS into a mode where we are actively looking for a lock, or alternatively switch GPS into a low power mode * @@ -243,6 +258,7 @@ class GPS : private concurrency::OSThread // Calculate checksum void UBXChecksum(uint8_t *message, size_t length); + void CASChecksum(uint8_t *message, size_t length); /** Get how long we should stay looking for each aquisition */ diff --git a/src/gps/cas.h b/src/gps/cas.h new file mode 100644 index 000000000..53d75cda9 --- /dev/null +++ b/src/gps/cas.h @@ -0,0 +1,63 @@ +#pragma once + +// CASIC binary message definitions +// Reference: https://www.icofchina.com/d/file/xiazai/2020-09-22/20f1b42b3a11ac52089caf3603b43fb5.pdf +// ATGM33H-5N: https://www.icofchina.com/pro/mokuai/2016-08-01/4.html +// (https://www.icofchina.com/d/file/xiazai/2016-12-05/b5c57074f4b1fcc62ba8c7868548d18a.pdf) + +// NEMA (Class ID - 0x4e) message IDs +#define CAS_NEMA_GGA 0x00 +#define CAS_NEMA_GLL 0x01 +#define CAS_NEMA_GSA 0x02 +#define CAS_NEMA_GSV 0x03 +#define CAS_NEMA_RMC 0x04 +#define CAS_NEMA_VTG 0x05 +#define CAS_NEMA_GST 0x07 +#define CAS_NEMA_ZDA 0x08 +#define CAS_NEMA_DHV 0x0D + +// Size of a CAS-ACK-(N)ACK message (14 bytes) +#define CAS_ACK_NACK_MSG_SIZE 0x0E + +// CFG-RST (0x06, 0x02) +// Factory reset +const uint8_t GPS::_message_CAS_CFG_RST_FACTORY[] = { + 0xFF, 0x03, // Fields to clear + 0x01, // Reset Mode: Controlled Software reset + 0x03 // Startup Mode: Factory +}; + +// CFG_RATE (0x06, 0x01) +// 1HZ update rate, this should always be the case after +// factory reset but update it regardless +const uint8_t GPS::_message_CAS_CFG_RATE_1HZ[] = { + 0xE8, 0x03, // Update Rate: 0x03E8 = 1000ms + 0x00, 0x00 // Reserved +}; + +// CFG-NAVX (0x06, 0x07) +// Initial ATGM33H-5N configuration, Updates for Dynamic Mode, Fix Mode, and SV system +// Qwirk: The ATGM33H-5N-31 should only support GPS+BDS, however it will happily enable +// and use GPS+BDS+GLONASS iff the correct CFG_NAVX command is used. +const uint8_t GPS::_message_CAS_CFG_NAVX_CONF[] = { + 0x03, 0x01, 0x00, 0x00, // Update Mask: Dynamic Mode, Fix Mode, Nav Settings + 0x03, // Dynamic Mode: Automotive + 0x03, // Fix Mode: Auto 2D/3D + 0x00, // Min SV + 0x00, // Max SVs + 0x00, // Min CNO + 0x00, // Reserved1 + 0x00, // Init 3D fix + 0x00, // Min Elevation + 0x00, // Dr Limit + 0x07, // Nav System: 2^0 = GPS, 2^1 = BDS 2^2 = GLONASS: 2^3 + // 3=GPS+BDS, 7=GPS+BDS+GLONASS + 0x00, 0x00, // Rollover Week + 0x00, 0x00, 0x00, 0x00, // Fix Altitude + 0x00, 0x00, 0x00, 0x00, // Fix Height Error + 0x00, 0x00, 0x00, 0x00, // PDOP Maximum + 0x00, 0x00, 0x00, 0x00, // TDOP Maximum + 0x00, 0x00, 0x00, 0x00, // Position Accuracy Max + 0x00, 0x00, 0x00, 0x00, // Time Accuracy Max + 0x00, 0x00, 0x00, 0x00 // Static Hold Threshold +}; \ No newline at end of file From c34956e9d8912f28c6ae65137298804d81d669ec Mon Sep 17 00:00:00 2001 From: GUVWAF <78759985+GUVWAF@users.noreply.github.com> Date: Wed, 17 Apr 2024 00:47:56 +0200 Subject: [PATCH 077/108] =?UTF-8?q?Cosmetics:=20rename=20remaining=20plugi?= =?UTF-8?q?ns=20=E2=86=92=20modules=20and=20less=20errors=20(#3645)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/mesh/MeshModule.cpp | 11 ++++++----- src/mesh/MeshModule.h | 6 +++--- src/mesh/RF95Interface.cpp | 2 +- src/mesh/Router.cpp | 4 ++-- src/mesh/SX128xInterface.cpp | 2 +- src/modules/AdminModule.cpp | 2 +- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/mesh/MeshModule.cpp b/src/mesh/MeshModule.cpp index c8dd7f3d1..2ef46e4db 100644 --- a/src/mesh/MeshModule.cpp +++ b/src/mesh/MeshModule.cpp @@ -12,7 +12,7 @@ const meshtastic_MeshPacket *MeshModule::currentRequest; /** * If any of the current chain of modules has already sent a reply, it will be here. This is useful to allow - * the RoutingPlugin to avoid sending redundant acks + * the RoutingModule to avoid sending redundant acks */ meshtastic_MeshPacket *MeshModule::currentReply; @@ -40,7 +40,7 @@ meshtastic_MeshPacket *MeshModule::allocAckNak(meshtastic_Routing_Error err, Nod c.error_reason = err; c.which_variant = meshtastic_Routing_error_reason_tag; - // Now that we have moded sendAckNak up one level into the class hierarchy we can no longer assume we are a RoutingPlugin + // Now that we have moded sendAckNak up one level into the class hierarchy we can no longer assume we are a RoutingModule // So we manually call pb_encode_to_bytes and specify routing port number // auto p = allocDataProtobuf(c); meshtastic_MeshPacket *p = router->allocForSending(); @@ -54,7 +54,8 @@ meshtastic_MeshPacket *MeshModule::allocAckNak(meshtastic_Routing_Error err, Nod p->to = to; p->decoded.request_id = idFrom; p->channel = chIndex; - LOG_ERROR("Alloc an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id); + if (err != meshtastic_Routing_Error_NONE) + LOG_ERROR("Alloc an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id); return p; } @@ -68,7 +69,7 @@ meshtastic_MeshPacket *MeshModule::allocErrorResponse(meshtastic_Routing_Error e return r; } -void MeshModule::callPlugins(meshtastic_MeshPacket &mp, RxSource src) +void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src) { // LOG_DEBUG("In call modules\n"); bool moduleFound = false; @@ -258,7 +259,7 @@ void MeshModule::observeUIEvents(Observer *observer) } } -AdminMessageHandleResult MeshModule::handleAdminMessageForAllPlugins(const meshtastic_MeshPacket &mp, +AdminMessageHandleResult MeshModule::handleAdminMessageForAllModules(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *request, meshtastic_AdminMessage *response) { diff --git a/src/mesh/MeshModule.h b/src/mesh/MeshModule.h index 6c431adb4..2e2af33e0 100644 --- a/src/mesh/MeshModule.h +++ b/src/mesh/MeshModule.h @@ -64,11 +64,11 @@ class MeshModule /** For use only by MeshService */ - static void callPlugins(meshtastic_MeshPacket &mp, RxSource src = RX_SRC_RADIO); + static void callModules(meshtastic_MeshPacket &mp, RxSource src = RX_SRC_RADIO); static std::vector GetMeshModulesWithUIFrames(); static void observeUIEvents(Observer *observer); - static AdminMessageHandleResult handleAdminMessageForAllPlugins(const meshtastic_MeshPacket &mp, + static AdminMessageHandleResult handleAdminMessageForAllModules(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *request, meshtastic_AdminMessage *response); #if HAS_SCREEN @@ -195,4 +195,4 @@ class MeshModule /** set the destination and packet parameters of packet p intended as a reply to a particular "to" packet * This ensures that if the request packet was sent reliably, the reply is sent that way as well. */ -void setReplyTo(meshtastic_MeshPacket *p, const meshtastic_MeshPacket &to); +void setReplyTo(meshtastic_MeshPacket *p, const meshtastic_MeshPacket &to); \ No newline at end of file diff --git a/src/mesh/RF95Interface.cpp b/src/mesh/RF95Interface.cpp index b658a8ff6..8c6c349fd 100644 --- a/src/mesh/RF95Interface.cpp +++ b/src/mesh/RF95Interface.cpp @@ -215,7 +215,7 @@ bool RF95Interface::isChannelActive() // LOG_DEBUG("Channel is busy!\n"); return true; } - if (result != RADIOLIB_ERR_WRONG_MODEM) + if (result != RADIOLIB_CHANNEL_FREE) LOG_ERROR("Radiolib error %d when attempting RF95 isChannelActive!\n", result); assert(result != RADIOLIB_ERR_WRONG_MODEM); diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 3fa933bb1..e4d67f019 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -479,7 +479,7 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src) // call modules here if (!skipHandle) - MeshModule::callPlugins(*p, src); + MeshModule::callModules(*p, src); } void Router::perhapsHandleReceived(meshtastic_MeshPacket *p) @@ -499,4 +499,4 @@ void Router::perhapsHandleReceived(meshtastic_MeshPacket *p) handleReceived(p); packetPool.release(p); -} +} \ No newline at end of file diff --git a/src/mesh/SX128xInterface.cpp b/src/mesh/SX128xInterface.cpp index 564b80494..9e4fbfa77 100644 --- a/src/mesh/SX128xInterface.cpp +++ b/src/mesh/SX128xInterface.cpp @@ -280,7 +280,7 @@ template bool SX128xInterface::isChannelActive() result = lora.scanChannel(); if (result == RADIOLIB_LORA_DETECTED) return true; - if (result != RADIOLIB_ERR_WRONG_MODEM) + if (result != RADIOLIB_CHANNEL_FREE) LOG_ERROR("Radiolib error %d when attempting SX128X scanChannel!\n", result); assert(result != RADIOLIB_ERR_WRONG_MODEM); diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index b40633af0..54eb577f7 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -256,7 +256,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta default: meshtastic_AdminMessage res = meshtastic_AdminMessage_init_default; - AdminMessageHandleResult handleResult = MeshModule::handleAdminMessageForAllPlugins(mp, r, &res); + AdminMessageHandleResult handleResult = MeshModule::handleAdminMessageForAllModules(mp, r, &res); if (handleResult == AdminMessageHandleResult::HANDLED_WITH_RESPONSE) { myReply = allocDataProtobuf(res); From 2450031b1bfd189c7e9723432922f5f6dd9d7245 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 17 Apr 2024 07:00:18 -0500 Subject: [PATCH 078/108] Add device metrics uptime to MQTT JSON (#3643) * Add device metrics uptime to MQTT JSON * Cast a spell --- src/mqtt/MQTT.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index 05d5486b2..da1c204b8 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -656,6 +656,7 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp) msgPayload["voltage"] = new JSONValue(decoded->variant.device_metrics.voltage); msgPayload["channel_utilization"] = new JSONValue(decoded->variant.device_metrics.channel_utilization); msgPayload["air_util_tx"] = new JSONValue(decoded->variant.device_metrics.air_util_tx); + msgPayload["uptime_seconds"] = new JSONValue((uint)decoded->variant.device_metrics.uptime_seconds); } else if (decoded->which_variant == meshtastic_Telemetry_environment_metrics_tag) { msgPayload["temperature"] = new JSONValue(decoded->variant.environment_metrics.temperature); msgPayload["relative_humidity"] = new JSONValue(decoded->variant.environment_metrics.relative_humidity); From bc085ab840af3ab00dca88eb34b30db74e83d61e Mon Sep 17 00:00:00 2001 From: GUVWAF <78759985+GUVWAF@users.noreply.github.com> Date: Wed, 17 Apr 2024 14:07:40 +0200 Subject: [PATCH 079/108] Fix #3641: Always set MAC when picking new NodeNum (#3651) Co-authored-by: Ben Meadors --- src/mesh/NodeDB.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 73aa29bbf..710b21593 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -527,8 +527,8 @@ void NodeDB::installDefaultDeviceState() void NodeDB::pickNewNodeNum() { NodeNum nodeNum = myNodeInfo.my_node_num; + getMacAddr(ourMacAddr); // Make sure ourMacAddr is set if (nodeNum == 0) { - getMacAddr(ourMacAddr); // Make sure ourMacAddr is set // Pick an initial nodenum based on the macaddr nodeNum = (ourMacAddr[2] << 24) | (ourMacAddr[3] << 16) | (ourMacAddr[4] << 8) | ourMacAddr[5]; } From d47e9bed196ae05c4dc1a2abd3bc783b9cbb965c Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Wed, 17 Apr 2024 14:25:52 -0500 Subject: [PATCH 080/108] Add multiple SPI devices for Radio, Display, and Touchscreen (#3638) This changeset gives us the ability to specify a separate SPI device for the LoRa, Display, and Touchscreen. The changes in Portduino also add support for specifying a new SPI speed for each transaction. All together, this means that we can let the Linux OS manage the CS lines, and also get much faster SPI speeds, leading to better framerates. * Add multiple SPI devices to put Radio, Display, and Touchscreen on each their own --------- Co-authored-by: Ben Meadors --- arch/portduino/portduino.ini | 2 +- bin/config-dist.yaml | 4 +- src/graphics/TFTDisplay.cpp | 4 +- src/graphics/mesh_bus_spi.cpp | 188 +++++++++++++++++++++++ src/graphics/mesh_bus_spi.h | 100 ++++++++++++ src/input/TouchScreenImpl1.cpp | 2 +- src/main.cpp | 12 +- src/main.h | 5 + src/platform/portduino/PortduinoGlue.cpp | 29 ++++ src/platform/portduino/PortduinoGlue.h | 6 +- 10 files changed, 340 insertions(+), 12 deletions(-) create mode 100644 src/graphics/mesh_bus_spi.cpp create mode 100644 src/graphics/mesh_bus_spi.h diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index 07151c4a3..53f06c9f3 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -1,6 +1,6 @@ ; The Portduino based sim environment on top of any host OS, all hardware will be simulated [portduino_base] -platform = https://github.com/meshtastic/platform-native.git#c95616208ffff4c8a36d48df810a3f072cce3521 +platform = https://github.com/meshtastic/platform-native.git#6fb39b6f94ece9c042141edb4afb91aca94dcaab framework = arduino build_src_filter = diff --git a/bin/config-dist.yaml b/bin/config-dist.yaml index d8cb5a9dd..f729f1ac7 100644 --- a/bin/config-dist.yaml +++ b/bin/config-dist.yaml @@ -101,11 +101,13 @@ Display: # Height: 240 Touchscreen: +### Note, at least for now, the touchscreen must have a CS pin defined, even if you let Linux manage the CS switching. + # Module: STMPE610 # CS: 7 # IRQ: 24 -# Module: XPT2046 +# Module: XPT2046 # Waveshare 2.8inch # CS: 7 # IRQ: 17 diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index b561f3b56..12e549424 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -1,6 +1,7 @@ #include "configuration.h" #include "main.h" #if ARCH_PORTDUINO +#include "mesh_bus_spi.h" #include "platform/portduino/PortduinoGlue.h" #endif @@ -339,7 +340,7 @@ static TFT_eSPI *tft = nullptr; // Invoke library, pins defined in User_Setup.h class LGFX : public lgfx::LGFX_Device { lgfx::Panel_LCD *_panel_instance; - lgfx::Bus_SPI _bus_instance; + lgfx::Mesh_Bus_SPI _bus_instance; lgfx::ITouch *_touch_instance; @@ -356,6 +357,7 @@ class LGFX : public lgfx::LGFX_Device _panel_instance = new lgfx::Panel_ILI9341; auto buscfg = _bus_instance.config(); buscfg.spi_mode = 0; + _bus_instance.spi_device(DisplaySPI, settingsStrings[displayspidev]); buscfg.pin_dc = settingsMap[displayDC]; // Set SPI DC pin number (-1 = disable) diff --git a/src/graphics/mesh_bus_spi.cpp b/src/graphics/mesh_bus_spi.cpp new file mode 100644 index 000000000..a9536d490 --- /dev/null +++ b/src/graphics/mesh_bus_spi.cpp @@ -0,0 +1,188 @@ +// This code has been copied from LovyanGFX to make the SPI device selectable for touchscreens. +// Ideally this could eventually be an inherited class from BUS_SPI, +// but currently too many internal objects are set private. + +#include "configuration.h" +#if ARCH_PORTDUINO +#include "lgfx/v1/misc/pixelcopy.hpp" +#include "main.h" +#include "mesh_bus_spi.h" +#include +#include + +namespace lgfx +{ +inline namespace v1 +{ +//---------------------------------------------------------------------------- + +void Mesh_Bus_SPI::config(const config_t &config) +{ + _cfg = config; + + if (_cfg.pin_dc >= 0) { + pinMode(_cfg.pin_dc, pin_mode_t::output); + gpio_hi(_cfg.pin_dc); + } +} + +bool Mesh_Bus_SPI::init(void) +{ + dc_h(); + pinMode(_cfg.pin_dc, pin_mode_t::output); + if (SPIName != "") + PrivateSPI->begin(SPIName.c_str()); + else + PrivateSPI->begin(); + return true; +} + +void Mesh_Bus_SPI::release(void) +{ + PrivateSPI->end(); +} + +void Mesh_Bus_SPI::spi_device(HardwareSPI *newSPI, std::string newSPIName) +{ + PrivateSPI = newSPI; + SPIName = newSPIName; +} +void Mesh_Bus_SPI::beginTransaction(void) +{ + dc_h(); + SPISettings setting(_cfg.freq_write, MSBFIRST, _cfg.spi_mode); + PrivateSPI->beginTransaction(setting); +} + +void Mesh_Bus_SPI::endTransaction(void) +{ + PrivateSPI->endTransaction(); + dc_h(); +} + +void Mesh_Bus_SPI::beginRead(void) +{ + PrivateSPI->endTransaction(); + // SPISettings setting(_cfg.freq_read, BitOrder::MSBFIRST, _cfg.spi_mode, false); + SPISettings setting(_cfg.freq_read, MSBFIRST, _cfg.spi_mode); + PrivateSPI->beginTransaction(setting); +} + +void Mesh_Bus_SPI::endRead(void) +{ + PrivateSPI->endTransaction(); + beginTransaction(); +} + +void Mesh_Bus_SPI::wait(void) {} + +bool Mesh_Bus_SPI::busy(void) const +{ + return false; +} + +bool Mesh_Bus_SPI::writeCommand(uint32_t data, uint_fast8_t bit_length) +{ + dc_l(); + PrivateSPI->transfer((uint8_t *)&data, bit_length >> 3); + dc_h(); + return true; +} + +void Mesh_Bus_SPI::writeData(uint32_t data, uint_fast8_t bit_length) +{ + PrivateSPI->transfer((uint8_t *)&data, bit_length >> 3); +} + +void Mesh_Bus_SPI::writeDataRepeat(uint32_t data, uint_fast8_t bit_length, uint32_t length) +{ + const uint8_t dst_bytes = bit_length >> 3; + uint32_t limit = (dst_bytes == 3) ? 12 : 16; + auto buf = _flip_buffer.getBuffer(512); + size_t fillpos = 0; + reinterpret_cast(buf)[0] = data; + fillpos += dst_bytes; + uint32_t len; + do { + len = ((length - 1) % limit) + 1; + if (limit <= 64) + limit <<= 1; + + while (fillpos < len * dst_bytes) { + memcpy(&buf[fillpos], buf, fillpos); + fillpos += fillpos; + } + + PrivateSPI->transfer(buf, len * dst_bytes); + } while (length -= len); +} + +void Mesh_Bus_SPI::writePixels(pixelcopy_t *param, uint32_t length) +{ + const uint8_t dst_bytes = param->dst_bits >> 3; + uint32_t limit = (dst_bytes == 3) ? 12 : 16; + uint32_t len; + do { + len = ((length - 1) % limit) + 1; + if (limit <= 32) + limit <<= 1; + auto buf = _flip_buffer.getBuffer(len * dst_bytes); + param->fp_copy(buf, 0, len, param); + PrivateSPI->transfer(buf, len * dst_bytes); + } while (length -= len); +} + +void Mesh_Bus_SPI::writeBytes(const uint8_t *data, uint32_t length, bool dc, bool use_dma) +{ + if (dc) + dc_h(); + else + dc_l(); + PrivateSPI->transfer(const_cast(data), length); + if (!dc) + dc_h(); +} + +uint32_t Mesh_Bus_SPI::readData(uint_fast8_t bit_length) +{ + uint32_t res = 0; + bit_length >>= 3; + if (!bit_length) + return res; + int idx = 0; + do { + res |= PrivateSPI->transfer(0) << idx; + idx += 8; + } while (--bit_length); + return res; +} + +bool Mesh_Bus_SPI::readBytes(uint8_t *dst, uint32_t length, bool use_dma) +{ + do { + dst[0] = PrivateSPI->transfer(0); + ++dst; + } while (--length); + return true; +} + +void Mesh_Bus_SPI::readPixels(void *dst, pixelcopy_t *param, uint32_t length) +{ + uint32_t bytes = param->src_bits >> 3; + uint32_t dstindex = 0; + uint32_t len = 4; + uint8_t buf[24]; + param->src_data = buf; + do { + if (len > length) + len = length; + readBytes((uint8_t *)buf, len * bytes, true); + param->src_x = 0; + dstindex = param->fp_copy(dst, dstindex, dstindex + len, param); + length -= len; + } while (length); +} + +} // namespace v1 +} // namespace lgfx +#endif \ No newline at end of file diff --git a/src/graphics/mesh_bus_spi.h b/src/graphics/mesh_bus_spi.h new file mode 100644 index 000000000..903f7ad9d --- /dev/null +++ b/src/graphics/mesh_bus_spi.h @@ -0,0 +1,100 @@ +#if ARCH_PORTDUINO +/*----------------------------------------------------------------------------/ + Lovyan GFX - Graphics library for embedded devices. + +Original Source: + https://github.com/lovyan03/LovyanGFX/ + +Licence: + [FreeBSD](https://github.com/lovyan03/LovyanGFX/blob/master/license.txt) + +Author: + [lovyan03](https://twitter.com/lovyan03) + +Contributors: + [ciniml](https://github.com/ciniml) + [mongonta0716](https://github.com/mongonta0716) + [tobozo](https://github.com/tobozo) +/----------------------------------------------------------------------------*/ +#pragma once + +#include + +#include "lgfx/v1/Bus.hpp" +#include "lgfx/v1/platforms/common.hpp" + +namespace lgfx +{ +inline namespace v1 +{ +//---------------------------------------------------------------------------- + +class Mesh_Bus_SPI : public IBus +{ + public: + struct config_t { + uint32_t freq_write = 16000000; + uint32_t freq_read = 8000000; + // bool spi_3wire = true; + // bool use_lock = true; + int16_t pin_sclk = -1; + int16_t pin_miso = -1; + int16_t pin_mosi = -1; + int16_t pin_dc = -1; + uint8_t spi_mode = 0; + }; + + const config_t &config(void) const { return _cfg; } + + void config(const config_t &config); + + bus_type_t busType(void) const override { return bus_type_t::bus_spi; } + + bool init(void) override; + void release(void) override; + void spi_device(HardwareSPI *newSPI, std::string newSPIName); + + void beginTransaction(void) override; + void endTransaction(void) override; + void wait(void) override; + bool busy(void) const override; + + bool writeCommand(uint32_t data, uint_fast8_t bit_length) override; + void writeData(uint32_t data, uint_fast8_t bit_length) override; + void writeDataRepeat(uint32_t data, uint_fast8_t bit_length, uint32_t count) override; + void writePixels(pixelcopy_t *param, uint32_t length) override; + void writeBytes(const uint8_t *data, uint32_t length, bool dc, bool use_dma) override; + + void initDMA(void) {} + void flush(void) {} + void addDMAQueue(const uint8_t *data, uint32_t length) override { writeBytes(data, length, true, true); } + void execDMAQueue(void) {} + uint8_t *getDMABuffer(uint32_t length) override { return _flip_buffer.getBuffer(length); } + + void beginRead(void) override; + void endRead(void) override; + uint32_t readData(uint_fast8_t bit_length) override; + bool readBytes(uint8_t *dst, uint32_t length, bool use_dma) override; + void readPixels(void *dst, pixelcopy_t *param, uint32_t length) override; + + private: + HardwareSPI *PrivateSPI; + std::string SPIName; + __attribute__((always_inline)) inline void dc_h(void) { gpio_hi(_cfg.pin_dc); } + __attribute__((always_inline)) inline void dc_l(void) { gpio_lo(_cfg.pin_dc); } + + config_t _cfg; + FlipBuffer _flip_buffer; + bool _need_wait; + uint32_t _mask_reg_dc; + uint32_t _last_apb_freq = -1; + uint32_t _clkdiv_write; + uint32_t _clkdiv_read; + volatile uint32_t *_gpio_reg_dc_h; + volatile uint32_t *_gpio_reg_dc_l; +}; + +//---------------------------------------------------------------------------- +} // namespace v1 +} // namespace lgfx +#endif \ No newline at end of file diff --git a/src/input/TouchScreenImpl1.cpp b/src/input/TouchScreenImpl1.cpp index 3e4ed4163..c863ead69 100644 --- a/src/input/TouchScreenImpl1.cpp +++ b/src/input/TouchScreenImpl1.cpp @@ -4,7 +4,7 @@ #include "configuration.h" #include "modules/ExternalNotificationModule.h" -#ifdef ARCH_PORTDUINO +#if ARCH_PORTDUINO #include "platform/portduino/PortduinoGlue.h" #endif diff --git a/src/main.cpp b/src/main.cpp index 744fda4de..b1a15634f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -630,14 +630,12 @@ void setup() pinMode(LORA_CS, OUTPUT); digitalWrite(LORA_CS, HIGH); SPI1.begin(false); -#else // HW_SPI1_DEVICE +#else // HW_SPI1_DEVICE SPI.setSCK(LORA_SCK); SPI.setTX(LORA_MOSI); SPI.setRX(LORA_MISO); SPI.begin(false); -#endif // HW_SPI1_DEVICE -#elif ARCH_PORTDUINO - SPI.begin(settingsStrings[spidev].c_str()); +#endif // HW_SPI1_DEVICE #elif !defined(ARCH_ESP32) // ARCH_RP2040 SPI.begin(); #else @@ -724,7 +722,7 @@ void setup() if (settingsMap[use_sx1262]) { if (!rIf) { LOG_DEBUG("Attempting to activate sx1262 radio on SPI port %s\n", settingsStrings[spidev].c_str()); - LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); + LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(*LoraSPI, spiSettings); rIf = new SX1262Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset], settingsMap[busy]); if (!rIf->init()) { @@ -738,7 +736,7 @@ void setup() } else if (settingsMap[use_rf95]) { if (!rIf) { LOG_DEBUG("Attempting to activate rf95 radio on SPI port %s\n", settingsStrings[spidev].c_str()); - LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); + LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(*LoraSPI, spiSettings); rIf = new RF95Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset], settingsMap[busy]); if (!rIf->init()) { @@ -753,7 +751,7 @@ void setup() } else if (settingsMap[use_sx1280]) { if (!rIf) { LOG_DEBUG("Attempting to activate sx1280 radio on SPI port %s\n", settingsStrings[spidev].c_str()); - LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); + LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(*LoraSPI, spiSettings); rIf = new SX1280Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset], settingsMap[busy]); if (!rIf->init()) { diff --git a/src/main.h b/src/main.h index 132fd190b..bb812b7b6 100644 --- a/src/main.h +++ b/src/main.h @@ -22,6 +22,11 @@ extern NimbleBluetooth *nimbleBluetooth; extern NRF52Bluetooth *nrf52Bluetooth; #endif +#if ARCH_PORTDUINO +extern HardwareSPI *DisplaySPI; +extern HardwareSPI *LoraSPI; + +#endif extern ScanI2C::DeviceAddress screen_found; extern ScanI2C::DeviceAddress cardkb_found; extern uint8_t kb_model; diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index f686ef3dc..f3415aaee 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -15,6 +15,8 @@ #include #include +HardwareSPI *DisplaySPI; +HardwareSPI *LoraSPI; std::map settingsMap; std::map settingsStrings; char *configPath = nullptr; @@ -81,6 +83,7 @@ void portduinoSetup() settingsStrings[keyboardDevice] = ""; settingsStrings[webserverrootpath] = ""; settingsStrings[spidev] = ""; + settingsStrings[displayspidev] = ""; YAML::Node yamlConfig; @@ -187,6 +190,9 @@ void portduinoSetup() settingsMap[displayOffsetY] = yamlConfig["Display"]["OffsetY"].as(0); settingsMap[displayRotate] = yamlConfig["Display"]["Rotate"].as(false); settingsMap[displayInvert] = yamlConfig["Display"]["Invert"].as(false); + if (yamlConfig["Display"]["spidev"]) { + settingsStrings[displayspidev] = "/dev/" + yamlConfig["Display"]["spidev"].as("spidev0.1"); + } } settingsMap[touchscreenModule] = no_touchscreen; if (yamlConfig["Touchscreen"]) { @@ -196,6 +202,9 @@ void portduinoSetup() settingsMap[touchscreenModule] = stmpe610; settingsMap[touchscreenCS] = yamlConfig["Touchscreen"]["CS"].as(-1); settingsMap[touchscreenIRQ] = yamlConfig["Touchscreen"]["IRQ"].as(-1); + if (yamlConfig["Touchscreen"]["spidev"]) { + settingsStrings[touchscreenspidev] = "/dev/" + yamlConfig["Touchscreen"]["spidev"].as(""); + } } if (yamlConfig["Input"]) { settingsStrings[keyboardDevice] = (yamlConfig["Input"]["KeyboardDevice"]).as(""); @@ -267,6 +276,26 @@ void portduinoSetup() initGPIOPin(settingsMap[touchscreenIRQ], gpioChipName); } + // if we specify a touchscreen dev, that is SPI. + // else if we specify a screen dev, that is SPI + // else if we specify a LoRa dev, that is SPI. + if (settingsStrings[touchscreenspidev] != "") { + SPI.begin(settingsStrings[touchscreenspidev].c_str()); + DisplaySPI = new HardwareSPI; + DisplaySPI->begin(settingsStrings[displayspidev].c_str()); + LoraSPI = new HardwareSPI; + LoraSPI->begin(settingsStrings[spidev].c_str()); + } else if (settingsStrings[displayspidev] != "") { + SPI.begin(settingsStrings[displayspidev].c_str()); + DisplaySPI = &SPI; + LoraSPI = new HardwareSPI; + LoraSPI->begin(settingsStrings[spidev].c_str()); + } else { + SPI.begin(settingsStrings[spidev].c_str()); + LoraSPI = &SPI; + DisplaySPI = &SPI; + } + return; } diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index 505c436d6..980fc63b8 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -21,6 +21,8 @@ enum configNames { touchscreenModule, touchscreenCS, touchscreenIRQ, + touchscreenspidev, + displayspidev, displayPanel, displayWidth, displayHeight, @@ -45,4 +47,6 @@ enum { level_error, level_warn, level_info, level_debug }; extern std::map settingsMap; extern std::map settingsStrings; -int initGPIOPin(int pinNum, std::string gpioChipname); \ No newline at end of file +int initGPIOPin(int pinNum, std::string gpioChipname); +extern HardwareSPI *DisplaySPI; +extern HardwareSPI *LoraSPI; \ No newline at end of file From 2e14234b77ed98ec63368fb5fb5b8cf6192f7018 Mon Sep 17 00:00:00 2001 From: Oliver Seiler Date: Thu, 18 Apr 2024 09:55:47 +1200 Subject: [PATCH 081/108] don't enable the CDC interface already at boot (#3652) Co-authored-by: Ben Meadors --- boards/tbeam-s3-core.json | 1 - 1 file changed, 1 deletion(-) diff --git a/boards/tbeam-s3-core.json b/boards/tbeam-s3-core.json index 8d2c3eed6..4c82a2789 100644 --- a/boards/tbeam-s3-core.json +++ b/boards/tbeam-s3-core.json @@ -7,7 +7,6 @@ "extra_flags": [ "-DBOARD_HAS_PSRAM", "-DLILYGO_TBEAM_S3_CORE", - "-DARDUINO_USB_CDC_ON_BOOT=1", "-DARDUINO_USB_MODE=1", "-DARDUINO_RUNNING_CORE=1", "-DARDUINO_EVENT_RUNNING_CORE=1" From 747c713ba925fd77f6f4a8bb000db3cedd9d45ab Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Fri, 19 Apr 2024 00:27:18 +1200 Subject: [PATCH 082/108] (ESP32) Fix bluetooth after light-sleep; de-init for deep sleep (#3655) --- src/nimble/NimbleBluetooth.cpp | 10 ++++++++-- src/platform/esp32/main-esp32.cpp | 5 +++-- src/sleep.cpp | 4 ++-- variants/heltec_wireless_paper/variant.h | 3 --- variants/heltec_wireless_paper_v1/variant.h | 3 --- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/nimble/NimbleBluetooth.cpp b/src/nimble/NimbleBluetooth.cpp index 092aef470..8f7e00461 100644 --- a/src/nimble/NimbleBluetooth.cpp +++ b/src/nimble/NimbleBluetooth.cpp @@ -106,20 +106,26 @@ static NimbleBluetoothFromRadioCallback *fromRadioCallbacks; void NimbleBluetooth::shutdown() { + // No measurable power saving for ESP32 during light-sleep(?) +#ifndef ARCH_ESP32 // Shutdown bluetooth for minimum power draw LOG_INFO("Disable bluetooth\n"); - // Bluefruit.Advertising.stop(); NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising(); pAdvertising->reset(); pAdvertising->stop(); +#endif } -// Extra power-saving on some devices +// Proper shutdown for ESP32. Needs reboot to reverse. void NimbleBluetooth::deinit() { +#ifdef ARCH_ESP32 + LOG_INFO("Disable bluetooth until reboot\n"); NimBLEDevice::deinit(); +#endif } +// Has initial setup been completed bool NimbleBluetooth::isActive() { return bleServer; diff --git a/src/platform/esp32/main-esp32.cpp b/src/platform/esp32/main-esp32.cpp index 3fb6e7774..2894a49fc 100644 --- a/src/platform/esp32/main-esp32.cpp +++ b/src/platform/esp32/main-esp32.cpp @@ -30,9 +30,10 @@ void setBluetoothEnable(bool enable) } if (enable && !nimbleBluetooth->isActive()) { nimbleBluetooth->setup(); - } else if (!enable) { - nimbleBluetooth->shutdown(); } + // For ESP32, no way to recover from bluetooth shutdown without reboot + // BLE advertising automatically stops when MCU enters light-sleep(?) + // For deep-sleep, shutdown hardware with nimbleBluetooth->deinit(). Requires reboot to reverse } } #else diff --git a/src/sleep.cpp b/src/sleep.cpp index 860a676df..a2a221d79 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -207,8 +207,8 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false) // esp_wifi_stop(); waitEnterSleep(skipPreflight); -#ifdef NIMBLE_DEINIT_FOR_DEEPSLEEP - // Extra power saving on some devices +#ifdef ARCH_ESP32 + // Full shutdown of bluetooth hardware nimbleBluetooth->deinit(); #endif diff --git a/variants/heltec_wireless_paper/variant.h b/variants/heltec_wireless_paper/variant.h index 466925a2e..29b8bbbd1 100644 --- a/variants/heltec_wireless_paper/variant.h +++ b/variants/heltec_wireless_paper/variant.h @@ -55,6 +55,3 @@ #define SX126X_DIO2_AS_RF_SWITCH #define SX126X_DIO3_TCXO_VOLTAGE 1.8 - -// Power management -#define NIMBLE_DEINIT_FOR_DEEPSLEEP // Required to reach manufacturers claim of 18uA diff --git a/variants/heltec_wireless_paper_v1/variant.h b/variants/heltec_wireless_paper_v1/variant.h index 466925a2e..29b8bbbd1 100644 --- a/variants/heltec_wireless_paper_v1/variant.h +++ b/variants/heltec_wireless_paper_v1/variant.h @@ -55,6 +55,3 @@ #define SX126X_DIO2_AS_RF_SWITCH #define SX126X_DIO3_TCXO_VOLTAGE 1.8 - -// Power management -#define NIMBLE_DEINIT_FOR_DEEPSLEEP // Required to reach manufacturers claim of 18uA From 425a71599595b1d4937f5d9030886a0f7e5c98fd Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Thu, 18 Apr 2024 14:20:39 -0500 Subject: [PATCH 083/108] Added one minute throttling to NodeDB save to disk (#3648) * Added one minute throttling to NodeDB * Derp --- src/mesh/Default.h | 3 ++- src/mesh/NodeDB.cpp | 7 +++++-- src/mesh/NodeDB.h | 3 ++- src/mesh/Throttle.cpp | 27 +++++++++++++++++++++++++++ src/mesh/Throttle.h | 9 +++++++++ 5 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 src/mesh/Throttle.cpp create mode 100644 src/mesh/Throttle.h diff --git a/src/mesh/Default.h b/src/mesh/Default.h index 734cdf519..95723744b 100644 --- a/src/mesh/Default.h +++ b/src/mesh/Default.h @@ -2,6 +2,7 @@ #include #include #define ONE_DAY 24 * 60 * 60 +#define ONE_MINUTE_MS 60 * 1000 #define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60) #define default_broadcast_interval_secs IF_ROUTER(ONE_DAY / 2, 15 * 60) @@ -27,4 +28,4 @@ class Default static uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval); static uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t defaultInterval); static uint32_t getConfiguredOrDefault(uint32_t configured, uint32_t defaultValue); -}; +}; \ No newline at end of file diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 710b21593..39422b454 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -813,6 +813,7 @@ size_t NodeDB::getNumOnlineMeshNodes(bool localOnly) } #include "MeshModule.h" +#include "Throttle.h" /** Update position info for this node based on received position data */ @@ -907,8 +908,10 @@ bool NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p, uint8_t chann powerFSM.trigger(EVENT_NODEDB_UPDATED); notifyObservers(true); // Force an update whether or not our node counts have changed - // We just changed something important about the user, store our DB - saveToDisk(SEGMENT_DEVICESTATE); + // We just changed something about the user, store our DB + Throttle::execute( + &lastNodeDbSave, ONE_MINUTE_MS, []() { nodeDB->saveToDisk(SEGMENT_DEVICESTATE); }, + []() { LOG_DEBUG("Deferring NodeDB saveToDisk for now, since we saved less than a minute ago\n"); }); } return changed; diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index 1c1736f78..57040fbd6 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -160,6 +160,7 @@ class NodeDB } private: + uint32_t lastNodeDbSave = 0; // when we last saved our db to flash /// Find a node in our DB, create an empty NodeInfoLite if missing meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n); @@ -229,4 +230,4 @@ extern uint32_t error_address; ModuleConfig_RangeTestConfig_size + ModuleConfig_SerialConfig_size + ModuleConfig_StoreForwardConfig_size + \ ModuleConfig_TelemetryConfig_size + ModuleConfig_size) -// Please do not remove this comment, it makes trunk and compiler happy at the same time. +// Please do not remove this comment, it makes trunk and compiler happy at the same time. \ No newline at end of file diff --git a/src/mesh/Throttle.cpp b/src/mesh/Throttle.cpp new file mode 100644 index 000000000..d8f23f9dc --- /dev/null +++ b/src/mesh/Throttle.cpp @@ -0,0 +1,27 @@ +#include "Throttle.h" +#include + +/// @brief Execute a function throttled to a minimum interval +/// @param lastExecutionMs Pointer to the last execution time in milliseconds +/// @param minumumIntervalMs Minimum execution interval in milliseconds +/// @param throttleFunc Function to execute if the execution is not deferred +/// @param onDefer Default to NULL, execute the function if the execution is deferred +/// @return true if the function was executed, false if it was deferred +bool Throttle::execute(uint32_t *lastExecutionMs, uint32_t minumumIntervalMs, void (*throttleFunc)(void), void (*onDefer)(void)) +{ + if (*lastExecutionMs == 0) { + *lastExecutionMs = millis(); + throttleFunc(); + return true; + } + uint32_t now = millis(); + + if ((now - *lastExecutionMs) >= minumumIntervalMs) { + throttleFunc(); + *lastExecutionMs = now; + return true; + } else if (onDefer != NULL) { + onDefer(); + } + return false; +} \ No newline at end of file diff --git a/src/mesh/Throttle.h b/src/mesh/Throttle.h new file mode 100644 index 000000000..8115595a4 --- /dev/null +++ b/src/mesh/Throttle.h @@ -0,0 +1,9 @@ +#pragma once +#include +#include + +class Throttle +{ + public: + static bool execute(uint32_t *lastExecutionMs, uint32_t minumumIntervalMs, void (*func)(void), void (*onDefer)(void) = NULL); +}; \ No newline at end of file From 4c0b7ea409a9ea372e202ca95bff1463ee13717c Mon Sep 17 00:00:00 2001 From: GUVWAF <78759985+GUVWAF@users.noreply.github.com> Date: Thu, 18 Apr 2024 21:28:11 +0200 Subject: [PATCH 084/108] StoreForward: Remove assert when receiving unhandled case (#3661) --- src/modules/esp32/StoreForwardModule.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/esp32/StoreForwardModule.cpp b/src/modules/esp32/StoreForwardModule.cpp index a60065e56..12cddc520 100644 --- a/src/modules/esp32/StoreForwardModule.cpp +++ b/src/modules/esp32/StoreForwardModule.cpp @@ -506,7 +506,7 @@ bool StoreForwardModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, break; default: - assert(0); // unexpected state + break; // no need to do anything } return true; // There's no need for others to look at this message. } From e4b5f2ce14fe118eb1455a38e7768871490b75fe Mon Sep 17 00:00:00 2001 From: GUVWAF <78759985+GUVWAF@users.noreply.github.com> Date: Thu, 18 Apr 2024 23:16:50 +0200 Subject: [PATCH 085/108] NeighborInfo: Only keep neighbors in RAM (#3660) * NeighborInfo: Only keep neighbors in RAM It fills up quickly when nodes are running >=2.3 * Defer first transmission as it's usually empty --------- Co-authored-by: Ben Meadors --- src/modules/NeighborInfoModule.cpp | 144 +++++++++-------------------- src/modules/NeighborInfoModule.h | 27 +----- 2 files changed, 50 insertions(+), 121 deletions(-) diff --git a/src/modules/NeighborInfoModule.cpp b/src/modules/NeighborInfoModule.cpp index 470234047..8c8135deb 100644 --- a/src/modules/NeighborInfoModule.cpp +++ b/src/modules/NeighborInfoModule.cpp @@ -4,11 +4,8 @@ #include "NodeDB.h" #include "RTC.h" -#define MAX_NUM_NEIGHBORS 10 // also defined in NeighborInfo protobuf options NeighborInfoModule *neighborInfoModule; -static const char *neighborInfoConfigFile = "/prefs/neighbors.proto"; - /* Prints a single neighbor info packet and associated neighbors Uses LOG_DEBUG, which equates to Console.log @@ -30,26 +27,23 @@ NOTE: for debugging only */ void NeighborInfoModule::printNodeDBNeighbors() { - int num_neighbors = getNumNeighbors(); - LOG_DEBUG("Our NodeDB contains %d neighbors\n", num_neighbors); - for (int i = 0; i < num_neighbors; i++) { - const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i); - LOG_DEBUG(" Node %d: node_id=0x%x, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr); + LOG_DEBUG("Our NodeDB contains %d neighbors\n", neighbors.size()); + for (size_t i = 0; i < neighbors.size(); i++) { + LOG_DEBUG("Node %d: node_id=0x%x, snr=%.2f\n", i, neighbors[i].node_id, neighbors[i].snr); } } /* Send our initial owner announcement 35 seconds after we start (to give network time to setup) */ NeighborInfoModule::NeighborInfoModule() : ProtobufModule("neighborinfo", meshtastic_PortNum_NEIGHBORINFO_APP, &meshtastic_NeighborInfo_msg), - concurrency::OSThread("NeighborInfoModule"), neighbors(neighborState.neighbors), - numNeighbors(&neighborState.neighbors_count) + concurrency::OSThread("NeighborInfoModule") { ourPortNum = meshtastic_PortNum_NEIGHBORINFO_APP; if (moduleConfig.neighbor_info.enabled) { isPromiscuous = true; // Update neighbors from all packets - this->loadProtoForModule(); - setIntervalFromNow(35 * 1000); + setIntervalFromNow( + Default::getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_broadcast_interval_secs)); } else { LOG_DEBUG("NeighborInfoModule is disabled\n"); disable(); @@ -63,18 +57,17 @@ Assumes that the neighborInfo packet has been allocated */ uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo) { - uint my_node_id = nodeDB->getNodeNum(); + NodeNum my_node_id = nodeDB->getNodeNum(); neighborInfo->node_id = my_node_id; neighborInfo->last_sent_by_id = my_node_id; neighborInfo->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval; - int num_neighbors = cleanUpNeighbors(); + cleanUpNeighbors(); - for (int i = 0; i < num_neighbors; i++) { - const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i); - if ((neighborInfo->neighbors_count < MAX_NUM_NEIGHBORS) && (dbEntry->node_id != my_node_id)) { - neighborInfo->neighbors[neighborInfo->neighbors_count].node_id = dbEntry->node_id; - neighborInfo->neighbors[neighborInfo->neighbors_count].snr = dbEntry->snr; + for (auto nbr : neighbors) { + if ((neighborInfo->neighbors_count < MAX_NUM_NEIGHBORS) && (nbr.node_id != my_node_id)) { + neighborInfo->neighbors[neighborInfo->neighbors_count].node_id = nbr.node_id; + neighborInfo->neighbors[neighborInfo->neighbors_count].snr = nbr.snr; // Note: we don't set the last_rx_time and node_broadcast_intervals_secs here, because we don't want to send this over // the mesh neighborInfo->neighbors_count++; @@ -85,41 +78,22 @@ uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighb } /* -Remove neighbors from the database that we haven't heard from in a while -@returns new number of neighbors + Remove neighbors from the database that we haven't heard from in a while */ -size_t NeighborInfoModule::cleanUpNeighbors() +void NeighborInfoModule::cleanUpNeighbors() { uint32_t now = getTime(); - int num_neighbors = getNumNeighbors(); NodeNum my_node_id = nodeDB->getNodeNum(); - - // Find neighbors to remove - std::vector indices_to_remove; - for (int i = 0; i < num_neighbors; i++) { - const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i); + for (auto it = neighbors.rbegin(); it != neighbors.rend();) { // We will remove a neighbor if we haven't heard from them in twice the broadcast interval - if ((now - dbEntry->last_rx_time > dbEntry->node_broadcast_interval_secs * 2) && (dbEntry->node_id != my_node_id)) { - indices_to_remove.push_back(i); + if ((now - it->last_rx_time > it->node_broadcast_interval_secs * 2) && (it->node_id != my_node_id)) { + LOG_DEBUG("Removing neighbor with node ID 0x%x\n", it->node_id); + it = std::vector::reverse_iterator( + neighbors.erase(std::next(it).base())); // Erase the element and update the iterator + } else { + ++it; } } - - // Update the neighbor list - for (uint i = 0; i < indices_to_remove.size(); i++) { - int index = indices_to_remove[i]; - LOG_DEBUG("Removing neighbor with node ID 0x%x\n", neighbors[index].node_id); - for (int j = index; j < num_neighbors - 1; j++) { - neighbors[j] = neighbors[j + 1]; - } - (*numNeighbors)--; - } - - // Save the neighbor list if we removed any neighbors or neighbors were already updated upon receiving a packet - if (indices_to_remove.size() > 0 || shouldSave) { - saveProtoForModule(); - } - - return *numNeighbors; } /* Send neighbor info to the mesh */ @@ -143,7 +117,9 @@ Will be used for broadcast. int32_t NeighborInfoModule::runOnce() { bool requestReplies = false; - sendNeighborInfo(NODENUM_BROADCAST, requestReplies); + if (airTime->isTxAllowedChannelUtil(true) && airTime->isTxAllowedAirUtil()) { + sendNeighborInfo(NODENUM_BROADCAST, requestReplies); + } return Default::getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_broadcast_interval_secs); } @@ -178,10 +154,7 @@ void NeighborInfoModule::alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtas void NeighborInfoModule::resetNeighbors() { - *numNeighbors = 0; - neighborState.neighbors_count = 0; - memset(neighborState.neighbors, 0, sizeof(neighborState.neighbors)); - saveProtoForModule(); + neighbors.clear(); } void NeighborInfoModule::updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np) @@ -201,61 +174,36 @@ meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSen n = nodeDB->getNodeNum(); } // look for one in the existing list - for (int i = 0; i < (*numNeighbors); i++) { - meshtastic_Neighbor *nbr = &neighbors[i]; - if (nbr->node_id == n) { + for (size_t i = 0; i < neighbors.size(); i++) { + if (neighbors[i].node_id == n) { // if found, update it - nbr->snr = snr; - nbr->last_rx_time = getTime(); + neighbors[i].snr = snr; + neighbors[i].last_rx_time = getTime(); // Only if this is the original sender, the broadcast interval corresponds to it if (originalSender == n && node_broadcast_interval_secs != 0) - nbr->node_broadcast_interval_secs = node_broadcast_interval_secs; - return nbr; + neighbors[i].node_broadcast_interval_secs = node_broadcast_interval_secs; + return &neighbors[i]; } } // otherwise, allocate one and assign data to it - // TODO: max memory for the database should take neighbors into account, but currently doesn't - if (*numNeighbors < MAX_NUM_NEIGHBORS) { - (*numNeighbors)++; - } - meshtastic_Neighbor *new_nbr = &neighbors[((*numNeighbors) - 1)]; - new_nbr->node_id = n; - new_nbr->snr = snr; - new_nbr->last_rx_time = getTime(); + + meshtastic_Neighbor new_nbr = meshtastic_Neighbor_init_zero; + new_nbr.node_id = n; + new_nbr.snr = snr; + new_nbr.last_rx_time = getTime(); // Only if this is the original sender, the broadcast interval corresponds to it if (originalSender == n && node_broadcast_interval_secs != 0) - new_nbr->node_broadcast_interval_secs = node_broadcast_interval_secs; + new_nbr.node_broadcast_interval_secs = node_broadcast_interval_secs; else // Assume the same broadcast interval as us for the neighbor if we don't know it - new_nbr->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval; - shouldSave = true; // Save the new neighbor upon next cleanup - return new_nbr; -} + new_nbr.node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval; -void NeighborInfoModule::loadProtoForModule() -{ - if (nodeDB->loadProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, sizeof(meshtastic_NeighborInfo), - &meshtastic_NeighborInfo_msg, &neighborState) != LoadFileResult::SUCCESS) { - neighborState = meshtastic_NeighborInfo_init_zero; + if (neighbors.size() < MAX_NUM_NEIGHBORS) { + neighbors.push_back(new_nbr); + } else { + // If we have too many neighbors, replace the oldest one + LOG_WARN("Neighbor DB is full, replacing oldest neighbor\n"); + neighbors.erase(neighbors.begin()); + neighbors.push_back(new_nbr); } -} - -/** - * @brief Save the module config to file. - * - * @return true On success. - * @return false On error. - */ -bool NeighborInfoModule::saveProtoForModule() -{ - bool okay = true; - -#ifdef FS - FS.mkdir("/prefs"); -#endif - - okay &= nodeDB->saveProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, &meshtastic_NeighborInfo_msg, &neighborState); - if (okay) - shouldSave = false; - - return okay; + return &neighbors.back(); } \ No newline at end of file diff --git a/src/modules/NeighborInfoModule.h b/src/modules/NeighborInfoModule.h index d47004981..496fdece5 100644 --- a/src/modules/NeighborInfoModule.h +++ b/src/modules/NeighborInfoModule.h @@ -1,13 +1,13 @@ #pragma once #include "ProtobufModule.h" +#define MAX_NUM_NEIGHBORS 10 // also defined in NeighborInfo protobuf options /* * Neighborinfo module for sending info on each node's 0-hop neighbors to the mesh */ class NeighborInfoModule : public ProtobufModule, private concurrency::OSThread { - meshtastic_Neighbor *neighbors; - pb_size_t *numNeighbors; + std::vector neighbors; public: /* @@ -18,15 +18,7 @@ class NeighborInfoModule : public ProtobufModule, priva /* Reset neighbor info after clearing nodeDB*/ void resetNeighbors(); - bool saveProtoForModule(); - - private: - bool shouldSave = false; // Whether we should save the neighbor info to flash - protected: - // Note: this holds our local info. - meshtastic_NeighborInfo neighborState; - /* * Called to handle a particular incoming message * @return true if you've guaranteed you've handled this message and no other handlers should be considered for it @@ -40,10 +32,9 @@ class NeighborInfoModule : public ProtobufModule, priva uint32_t collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo); /* - Remove neighbors from the database that we haven't heard from in a while - @returns new number of neighbors + Remove neighbors from the database that we haven't heard from in a while */ - size_t cleanUpNeighbors(); + void cleanUpNeighbors(); /* Allocate a new NeighborInfo packet */ meshtastic_NeighborInfo *allocateNeighborInfoPacket(); @@ -56,22 +47,12 @@ class NeighborInfoModule : public ProtobufModule, priva */ void sendNeighborInfo(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false); - size_t getNumNeighbors() { return *numNeighbors; } - - meshtastic_Neighbor *getNeighborByIndex(size_t x) - { - assert(x < *numNeighbors); - return &neighbors[x]; - } - /* update neighbors with subpacket sniffed from network */ void updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np); /* update a NeighborInfo packet with our NodeNum as last_sent_by_id */ void alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtastic_NeighborInfo *n) override; - void loadProtoForModule(); - /* Does our periodic broadcast */ int32_t runOnce() override; From 64edfb76e0ad1d7d434df27a9d9edac1e7003533 Mon Sep 17 00:00:00 2001 From: GUVWAF <78759985+GUVWAF@users.noreply.github.com> Date: Fri, 19 Apr 2024 00:44:13 +0200 Subject: [PATCH 086/108] Uplink to MQTT after potentially altering content (#3646) Mainly for traceroute module now Co-authored-by: Ben Meadors --- src/mesh/Router.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index e4d67f019..4189bca66 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -465,21 +465,22 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src) cancelSending(p->from, p->id); skipHandle = true; } -#if !MESHTASTIC_EXCLUDE_MQTT - // Publish received message to MQTT if we're not the original transmitter of the packet - if (!skipHandle && moduleConfig.mqtt.enabled && getFrom(p) != nodeDB->getNodeNum() && mqtt) - mqtt->onSend(*p_encrypted, *p, p->channel); -#endif - } else { printPacket("packet decoding failed or skipped (no PSK?)", p); } - packetPool.release(p_encrypted); // Release the encrypted packet - // call modules here - if (!skipHandle) + if (!skipHandle) { MeshModule::callModules(*p, src); + +#if !MESHTASTIC_EXCLUDE_MQTT + // After potentially altering it, publish received message to MQTT if we're not the original transmitter of the packet + if (decoded && moduleConfig.mqtt.enabled && getFrom(p) != nodeDB->getNodeNum() && mqtt) + mqtt->onSend(*p_encrypted, *p, p->channel); +#endif + } + + packetPool.release(p_encrypted); // Release the encrypted packet } void Router::perhapsHandleReceived(meshtastic_MeshPacket *p) From 7a3570aecf119825dba67784ecedb0338e1285bb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 18:29:50 -0500 Subject: [PATCH 087/108] [create-pull-request] automated change (#3662) Co-authored-by: thebentern --- protobufs | 2 +- src/mesh/generated/meshtastic/config.pb.h | 29 ++++++++++------------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/protobufs b/protobufs index ecf105f66..0d08acd9c 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit ecf105f66d182531423b73f4408c53701313c4eb +Subproject commit 0d08acd9c51c4e5575f3ea42368834ec990b2278 diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index fd040c57f..2abe040a6 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -324,35 +324,30 @@ typedef struct _meshtastic_Config_PositionConfig { /* Power Config\ See [Power Config](/docs/settings/config/power) for additional power config details. */ typedef struct _meshtastic_Config_PowerConfig { - /* If set, we are powered from a low-current source (i.e. solar), so even if it looks like we have power flowing in - we should try to minimize power consumption as much as possible. - YOU DO NOT NEED TO SET THIS IF YOU'VE set is_router (it is implied in that case). - Advanced Option */ + /* Description: Will sleep everything as much as possible, for the tracker and sensor role this will also include the lora radio. + Don't use this setting if you want to use your device with the phone apps or are using a device without a user button. + Technical Details: Works for ESP32 devices and NRF52 devices in the Sensor or Tracker roles */ bool is_power_saving; - /* If non-zero, the device will fully power off this many seconds after external power is removed. */ + /* Description: If non-zero, the device will fully power off this many seconds after external power is removed. */ uint32_t on_battery_shutdown_after_secs; /* Ratio of voltage divider for battery pin eg. 3.20 (R1=100k, R2=220k) Overrides the ADC_MULTIPLIER defined in variant for battery voltage calculation. - Should be set to floating point value between 2 and 4 - Fixes issues on Heltec v2 */ + https://meshtastic.org/docs/configuration/radio/power/#adc-multiplier-override + Should be set to floating point value between 2 and 6 */ float adc_multiplier_override; - /* Wait Bluetooth Seconds - The number of seconds for to wait before turning off BLE in No Bluetooth states - 0 for default of 1 minute */ + /* Description: The number of seconds for to wait before turning off BLE in No Bluetooth states + Technical Details: ESP32 Only 0 for default of 1 minute */ uint32_t wait_bluetooth_secs; /* Super Deep Sleep Seconds While in Light Sleep if mesh_sds_timeout_secs is exceeded we will lower into super deep sleep for this value (default 1 year) or a button press 0 for default of one year */ uint32_t sds_secs; - /* Light Sleep Seconds - In light sleep the CPU is suspended, LoRa radio is on, BLE is off an GPS is on - ESP32 Only - 0 for default of 300 */ + /* Description: In light sleep the CPU is suspended, LoRa radio is on, BLE is off an GPS is on + Technical Details: ESP32 Only 0 for default of 300 */ uint32_t ls_secs; - /* Minimum Wake Seconds - While in light sleep when we receive packets on the LoRa radio we will wake and handle them and stay awake in no BLE mode for this value - 0 for default of 10 seconds */ + /* Description: While in light sleep when we receive packets on the LoRa radio we will wake and handle them and stay awake in no BLE mode for this value + Technical Details: ESP32 Only 0 for default of 10 seconds */ uint32_t min_wake_secs; /* I2C address of INA_2XX to use for reading device battery voltage */ uint8_t device_battery_ina_address; From 65bde8538fae649939273d2f93a526acc6aa37f2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 18 Apr 2024 20:33:23 -0500 Subject: [PATCH 088/108] [create-pull-request] automated change (#3663) Co-authored-by: thebentern --- version.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.properties b/version.properties index f5ad818a2..485f55130 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 3 -build = 6 +build = 7 From 44aa248099fdcf2a27ae06285ceabc29d6479fd8 Mon Sep 17 00:00:00 2001 From: Manuel <71137295+mverch67@users.noreply.github.com> Date: Sat, 20 Apr 2024 02:27:13 +0200 Subject: [PATCH 089/108] added new display parameters (#3670) --- src/platform/portduino/PortduinoGlue.cpp | 19 +++++++++++++++++++ src/platform/portduino/PortduinoGlue.h | 11 +++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index f3415aaee..a04c9c12c 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -178,18 +178,31 @@ void portduinoSetup() settingsMap[displayPanel] = st7735; else if (yamlConfig["Display"]["Panel"].as("") == "ST7735S") settingsMap[displayPanel] = st7735s; + else if (yamlConfig["Display"]["Panel"].as("") == "ST7796") + settingsMap[displayPanel] = st7796; else if (yamlConfig["Display"]["Panel"].as("") == "ILI9341") settingsMap[displayPanel] = ili9341; + else if (yamlConfig["Display"]["Panel"].as("") == "ILI9488") + settingsMap[displayPanel] = ili9488; + else if (yamlConfig["Display"]["Panel"].as("") == "HX8357D") + settingsMap[displayPanel] = hx8357d; + else if (yamlConfig["Display"]["Panel"].as("") == "X11") + settingsMap[displayPanel] = x11; settingsMap[displayHeight] = yamlConfig["Display"]["Height"].as(0); settingsMap[displayWidth] = yamlConfig["Display"]["Width"].as(0); settingsMap[displayDC] = yamlConfig["Display"]["DC"].as(-1); settingsMap[displayCS] = yamlConfig["Display"]["CS"].as(-1); + settingsMap[displayRGBOrder] = yamlConfig["Display"]["RGBOrder"].as(false); settingsMap[displayBacklight] = yamlConfig["Display"]["Backlight"].as(-1); + settingsMap[displayBacklightInvert] = yamlConfig["Display"]["BacklightInvert"].as(false); + settingsMap[displayBacklightPWMChannel] = yamlConfig["Display"]["BacklightPWMChannel"].as(-1); settingsMap[displayReset] = yamlConfig["Display"]["Reset"].as(-1); settingsMap[displayOffsetX] = yamlConfig["Display"]["OffsetX"].as(0); settingsMap[displayOffsetY] = yamlConfig["Display"]["OffsetY"].as(0); settingsMap[displayRotate] = yamlConfig["Display"]["Rotate"].as(false); + settingsMap[displayOffsetRotate] = yamlConfig["Display"]["OffsetRotate"].as(1); settingsMap[displayInvert] = yamlConfig["Display"]["Invert"].as(false); + settingsMap[displayBusFrequency] = yamlConfig["Display"]["BusFrequency"].as(40000000); if (yamlConfig["Display"]["spidev"]) { settingsStrings[displayspidev] = "/dev/" + yamlConfig["Display"]["spidev"].as("spidev0.1"); } @@ -200,8 +213,14 @@ void portduinoSetup() settingsMap[touchscreenModule] = xpt2046; else if (yamlConfig["Touchscreen"]["Module"].as("") == "STMPE610") settingsMap[touchscreenModule] = stmpe610; + else if (yamlConfig["Touchscreen"]["Module"].as("") == "GT911") + settingsMap[touchscreenModule] = gt911; + else if (yamlConfig["Touchscreen"]["Module"].as("") == "FT5x06") + settingsMap[touchscreenModule] = ft5x06; settingsMap[touchscreenCS] = yamlConfig["Touchscreen"]["CS"].as(-1); settingsMap[touchscreenIRQ] = yamlConfig["Touchscreen"]["IRQ"].as(-1); + settingsMap[touchscreenBusFrequency] = yamlConfig["Touchscreen"]["BusFrequency"].as(1000000); + settingsMap[touchscreenRotate] = yamlConfig["Touchscreen"]["Rotate"].as(-1); if (yamlConfig["Touchscreen"]["spidev"]) { settingsStrings[touchscreenspidev] = "/dev/" + yamlConfig["Touchscreen"]["spidev"].as(""); } diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index 980fc63b8..ed2954eef 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -21,16 +21,23 @@ enum configNames { touchscreenModule, touchscreenCS, touchscreenIRQ, + touchscreenBusFrequency, + touchscreenRotate, touchscreenspidev, displayspidev, + displayBusFrequency, displayPanel, displayWidth, displayHeight, displayCS, displayDC, + displayRGBOrder, displayBacklight, + displayBacklightPWMChannel, + displayBacklightInvert, displayReset, displayRotate, + displayOffsetRotate, displayOffsetX, displayOffsetY, displayInvert, @@ -41,8 +48,8 @@ enum configNames { webserverrootpath, maxnodes }; -enum { no_screen, st7789, st7735, st7735s, ili9341 }; -enum { no_touchscreen, xpt2046, stmpe610 }; +enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9488, hx8357d }; +enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 }; enum { level_error, level_warn, level_info, level_debug }; extern std::map settingsMap; From e7828c4c64e306f1ec281633bc60650be8d9102a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 20 Apr 2024 07:36:53 -0500 Subject: [PATCH 090/108] [create-pull-request] automated change (#3676) Co-authored-by: thebentern --- protobufs | 2 +- src/mesh/generated/meshtastic/config.pb.h | 12 ++++++++---- src/mesh/generated/meshtastic/deviceonly.pb.h | 2 +- src/mesh/generated/meshtastic/localonly.pb.h | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/protobufs b/protobufs index 0d08acd9c..f4be94a7f 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 0d08acd9c51c4e5575f3ea42368834ec990b2278 +Subproject commit f4be94a7fc92d5db4a25b26886496934939dc8bd diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index 2abe040a6..105380044 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -283,6 +283,8 @@ typedef struct _meshtastic_Config_DeviceConfig { bool disable_triple_click; /* POSIX Timezone definition string from https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv. */ char tzdef[65]; + /* If true, inhibit blinking LED at LED_PIN regularly */ + bool status_led_off; } meshtastic_Config_DeviceConfig; /* Position Config */ @@ -580,7 +582,7 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}} -#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, ""} +#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0} #define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN} #define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""} @@ -589,7 +591,7 @@ extern "C" { #define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0} #define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0} #define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}} -#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, ""} +#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0, "", 0} #define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN} #define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""} @@ -610,6 +612,7 @@ extern "C" { #define meshtastic_Config_DeviceConfig_is_managed_tag 9 #define meshtastic_Config_DeviceConfig_disable_triple_click_tag 10 #define meshtastic_Config_DeviceConfig_tzdef_tag 11 +#define meshtastic_Config_DeviceConfig_status_led_off_tag 12 #define meshtastic_Config_PositionConfig_position_broadcast_secs_tag 1 #define meshtastic_Config_PositionConfig_position_broadcast_smart_enabled_tag 2 #define meshtastic_Config_PositionConfig_fixed_position_tag 3 @@ -710,7 +713,8 @@ X(a, STATIC, SINGULAR, UINT32, node_info_broadcast_secs, 7) \ X(a, STATIC, SINGULAR, BOOL, double_tap_as_button_press, 8) \ X(a, STATIC, SINGULAR, BOOL, is_managed, 9) \ X(a, STATIC, SINGULAR, BOOL, disable_triple_click, 10) \ -X(a, STATIC, SINGULAR, STRING, tzdef, 11) +X(a, STATIC, SINGULAR, STRING, tzdef, 11) \ +X(a, STATIC, SINGULAR, BOOL, status_led_off, 12) #define meshtastic_Config_DeviceConfig_CALLBACK NULL #define meshtastic_Config_DeviceConfig_DEFAULT NULL @@ -829,7 +833,7 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg; /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_CONFIG_PB_H_MAX_SIZE meshtastic_Config_size #define meshtastic_Config_BluetoothConfig_size 10 -#define meshtastic_Config_DeviceConfig_size 98 +#define meshtastic_Config_DeviceConfig_size 100 #define meshtastic_Config_DisplayConfig_size 28 #define meshtastic_Config_LoRaConfig_size 80 #define meshtastic_Config_NetworkConfig_IpV4Config_size 20 diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index 856eb6f4a..2506ec647 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -308,7 +308,7 @@ extern const pb_msgdesc_t meshtastic_OEMStore_msg; #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_OEMStore_size #define meshtastic_ChannelFile_size 702 #define meshtastic_NodeInfoLite_size 166 -#define meshtastic_OEMStore_size 3344 +#define meshtastic_OEMStore_size 3346 #define meshtastic_PositionLite_size 28 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index fa7ebcfee..1799f49da 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -181,7 +181,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalModuleConfig_size -#define meshtastic_LocalConfig_size 535 +#define meshtastic_LocalConfig_size 537 #define meshtastic_LocalModuleConfig_size 663 #ifdef __cplusplus From 419eb1396808497d837ff498588252b2f9009cd3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 20 Apr 2024 09:56:55 -0500 Subject: [PATCH 091/108] [create-pull-request] automated change (#3679) Co-authored-by: thebentern --- protobufs | 2 +- src/mesh/generated/meshtastic/telemetry.pb.h | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/protobufs b/protobufs index f4be94a7f..ea127fcbd 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit f4be94a7fc92d5db4a25b26886496934939dc8bd +Subproject commit ea127fcbd894458ecfe0eccaea6528afbf9e3275 diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index b6d3811a4..07a6bcae0 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -43,7 +43,9 @@ typedef enum _meshtastic_TelemetrySensorType { /* INA3221 3 Channel Voltage / Current Sensor */ meshtastic_TelemetrySensorType_INA3221 = 14, /* BMP085/BMP180 High accuracy temperature and pressure (older Version of BMP280) */ - meshtastic_TelemetrySensorType_BMP085 = 15 + meshtastic_TelemetrySensorType_BMP085 = 15, + /* RCWL-9620 Doppler Radar Distance Sensor, used for water level detection */ + meshtastic_TelemetrySensorType_RCWL9620 = 16 } meshtastic_TelemetrySensorType; /* Struct definitions */ @@ -78,6 +80,8 @@ typedef struct _meshtastic_EnvironmentMetrics { /* relative scale IAQ value as measured by Bosch BME680 . value 0-500. Belongs to Air Quality but is not particle but VOC measurement. Other VOC values can also be put in here. */ uint16_t iaq; + /* RCWL9620 Doppler Radar Distance Sensor, used for water level detection. Float value in mm. */ + float water_level; } meshtastic_EnvironmentMetrics; /* Power Metrics (voltage / current / etc) */ @@ -148,8 +152,8 @@ extern "C" { /* Helper constants for enums */ #define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET -#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_BMP085 -#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_BMP085+1)) +#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_RCWL9620 +#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_RCWL9620+1)) @@ -159,12 +163,12 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_DeviceMetrics_init_default {0, 0, 0, 0, 0} -#define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0, 0} +#define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_PowerMetrics_init_default {0, 0, 0, 0, 0, 0} #define meshtastic_AirQualityMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}} #define meshtastic_DeviceMetrics_init_zero {0, 0, 0, 0, 0} -#define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0, 0} +#define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_PowerMetrics_init_zero {0, 0, 0, 0, 0, 0} #define meshtastic_AirQualityMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}} @@ -182,6 +186,7 @@ extern "C" { #define meshtastic_EnvironmentMetrics_voltage_tag 5 #define meshtastic_EnvironmentMetrics_current_tag 6 #define meshtastic_EnvironmentMetrics_iaq_tag 7 +#define meshtastic_EnvironmentMetrics_water_level_tag 8 #define meshtastic_PowerMetrics_ch1_voltage_tag 1 #define meshtastic_PowerMetrics_ch1_current_tag 2 #define meshtastic_PowerMetrics_ch2_voltage_tag 3 @@ -223,7 +228,8 @@ X(a, STATIC, SINGULAR, FLOAT, barometric_pressure, 3) \ X(a, STATIC, SINGULAR, FLOAT, gas_resistance, 4) \ X(a, STATIC, SINGULAR, FLOAT, voltage, 5) \ X(a, STATIC, SINGULAR, FLOAT, current, 6) \ -X(a, STATIC, SINGULAR, UINT32, iaq, 7) +X(a, STATIC, SINGULAR, UINT32, iaq, 7) \ +X(a, STATIC, SINGULAR, FLOAT, water_level, 8) #define meshtastic_EnvironmentMetrics_CALLBACK NULL #define meshtastic_EnvironmentMetrics_DEFAULT NULL @@ -283,7 +289,7 @@ extern const pb_msgdesc_t meshtastic_Telemetry_msg; #define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size #define meshtastic_AirQualityMetrics_size 72 #define meshtastic_DeviceMetrics_size 27 -#define meshtastic_EnvironmentMetrics_size 34 +#define meshtastic_EnvironmentMetrics_size 39 #define meshtastic_PowerMetrics_size 30 #define meshtastic_Telemetry_size 79 From 0972a8dccb40ec9fc202b2810fda10f163a84133 Mon Sep 17 00:00:00 2001 From: caveman99 Date: Sat, 20 Apr 2024 18:24:40 +0000 Subject: [PATCH 092/108] [create-pull-request] automated change --- protobufs | 2 +- src/mesh/generated/meshtastic/telemetry.pb.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/protobufs b/protobufs index ea127fcbd..6e30bbb48 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit ea127fcbd894458ecfe0eccaea6528afbf9e3275 +Subproject commit 6e30bbb482c97a7de6efee168fb121c5af7b261b diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index 07a6bcae0..e670dd340 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -81,7 +81,7 @@ typedef struct _meshtastic_EnvironmentMetrics { Belongs to Air Quality but is not particle but VOC measurement. Other VOC values can also be put in here. */ uint16_t iaq; /* RCWL9620 Doppler Radar Distance Sensor, used for water level detection. Float value in mm. */ - float water_level; + float distance; } meshtastic_EnvironmentMetrics; /* Power Metrics (voltage / current / etc) */ @@ -186,7 +186,7 @@ extern "C" { #define meshtastic_EnvironmentMetrics_voltage_tag 5 #define meshtastic_EnvironmentMetrics_current_tag 6 #define meshtastic_EnvironmentMetrics_iaq_tag 7 -#define meshtastic_EnvironmentMetrics_water_level_tag 8 +#define meshtastic_EnvironmentMetrics_distance_tag 8 #define meshtastic_PowerMetrics_ch1_voltage_tag 1 #define meshtastic_PowerMetrics_ch1_current_tag 2 #define meshtastic_PowerMetrics_ch2_voltage_tag 3 @@ -229,7 +229,7 @@ X(a, STATIC, SINGULAR, FLOAT, gas_resistance, 4) \ X(a, STATIC, SINGULAR, FLOAT, voltage, 5) \ X(a, STATIC, SINGULAR, FLOAT, current, 6) \ X(a, STATIC, SINGULAR, UINT32, iaq, 7) \ -X(a, STATIC, SINGULAR, FLOAT, water_level, 8) +X(a, STATIC, SINGULAR, FLOAT, distance, 8) #define meshtastic_EnvironmentMetrics_CALLBACK NULL #define meshtastic_EnvironmentMetrics_DEFAULT NULL From ec39e1136a5e5f0d949c94fcaeea58875975d0d2 Mon Sep 17 00:00:00 2001 From: Ric In New Mexico <78682404+RicInNewMexico@users.noreply.github.com> Date: Sat, 20 Apr 2024 14:58:21 -0600 Subject: [PATCH 093/108] INA3221 Mis-identification fix (#3681) --- src/detect/ScanI2CTwoWire.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index 13c2f4609..e2e2188b6 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -271,9 +271,14 @@ void ScanI2CTwoWire::scanPort(I2CPort port) } break; case INA3221_ADDR: - LOG_INFO("INA3221 sensor found at address 0x%x\n", (uint8_t)addr.address); - type = INA3221; - break; + registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2); + LOG_DEBUG("Register MFG_UID: 0x%x\n", registerValue); + if (registerValue == 0x5449) { + LOG_INFO("INA3221 sensor found at address 0x%x\n", (uint8_t)addr.address); + type = INA3221; + } else { // Unknown device + LOG_INFO("No INA3221 found at address 0x%x\n", (uint8_t)addr.address); + } case MCP9808_ADDR: registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2); if (registerValue == 0x0400) { From e72792afc846ed0559fda6586a3e7753baf95848 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 20 Apr 2024 15:58:42 -0500 Subject: [PATCH 094/108] [create-pull-request] automated change (#3683) Co-authored-by: thebentern --- protobufs | 2 +- src/mesh/generated/meshtastic/config.pb.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/protobufs b/protobufs index 6e30bbb48..eade2c6be 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 6e30bbb482c97a7de6efee168fb121c5af7b261b +Subproject commit eade2c6befb65a9c46c5d28ae1e8e24c37a1a3d0 diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index 105380044..0830ed851 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -283,8 +283,8 @@ typedef struct _meshtastic_Config_DeviceConfig { bool disable_triple_click; /* POSIX Timezone definition string from https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv. */ char tzdef[65]; - /* If true, inhibit blinking LED at LED_PIN regularly */ - bool status_led_off; + /* If true, disable the default blinking LED (LED_PIN) behavior on the device */ + bool led_heartbeat_disabled; } meshtastic_Config_DeviceConfig; /* Position Config */ @@ -612,7 +612,7 @@ extern "C" { #define meshtastic_Config_DeviceConfig_is_managed_tag 9 #define meshtastic_Config_DeviceConfig_disable_triple_click_tag 10 #define meshtastic_Config_DeviceConfig_tzdef_tag 11 -#define meshtastic_Config_DeviceConfig_status_led_off_tag 12 +#define meshtastic_Config_DeviceConfig_led_heartbeat_disabled_tag 12 #define meshtastic_Config_PositionConfig_position_broadcast_secs_tag 1 #define meshtastic_Config_PositionConfig_position_broadcast_smart_enabled_tag 2 #define meshtastic_Config_PositionConfig_fixed_position_tag 3 @@ -714,7 +714,7 @@ X(a, STATIC, SINGULAR, BOOL, double_tap_as_button_press, 8) \ X(a, STATIC, SINGULAR, BOOL, is_managed, 9) \ X(a, STATIC, SINGULAR, BOOL, disable_triple_click, 10) \ X(a, STATIC, SINGULAR, STRING, tzdef, 11) \ -X(a, STATIC, SINGULAR, BOOL, status_led_off, 12) +X(a, STATIC, SINGULAR, BOOL, led_heartbeat_disabled, 12) #define meshtastic_Config_DeviceConfig_CALLBACK NULL #define meshtastic_Config_DeviceConfig_DEFAULT NULL From 820c5dc8c5a9cd300e15a2fd9aa9e3a5c35d09af Mon Sep 17 00:00:00 2001 From: S5NC <145265251+S5NC@users.noreply.github.com> Date: Sun, 21 Apr 2024 13:24:39 +0100 Subject: [PATCH 095/108] Update architecture.h (#3688) --- src/platform/esp32/architecture.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h index 15e437bb5..c6d90970f 100644 --- a/src/platform/esp32/architecture.h +++ b/src/platform/esp32/architecture.h @@ -117,8 +117,8 @@ #define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER #elif defined(TLORA_T3S3_V1) #define HW_VENDOR meshtastic_HardwareModel_TLORA_T3_S3 -#elif defined(CDEBYTE_ELORA_S3) -#define HW_VENDOR meshtastic_HardwareModel_CDEBYTE_ELORA_S3 +#elif defined(CDEBYTE_EORA_S3) +#define HW_VENDOR meshtastic_HardwareModel_CDEBYTE_EORA_S3 #elif defined(BETAFPV_2400_TX) #define HW_VENDOR meshtastic_HardwareModel_BETAFPV_2400_TX #elif defined(NANO_G1_EXPLORER) From f6cfdfe881871ccae66017d9421cd8ea1a730f48 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Mon, 22 Apr 2024 00:25:12 +1200 Subject: [PATCH 096/108] (ESP-32S) Fix "critical error 3" after deep-sleep (#3685) --- src/sleep.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/sleep.cpp b/src/sleep.cpp index a2a221d79..548ef2c54 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -157,6 +157,10 @@ void initDeepSleep() for (uint8_t i = 0; i <= GPIO_NUM_MAX; i++) { if (rtc_gpio_is_valid_gpio((gpio_num_t)i)) rtc_gpio_hold_dis((gpio_num_t)i); + + // ESP32 (original) + else if (GPIO_IS_VALID_OUTPUT_GPIO((gpio_num_t)i)) + gpio_hold_dis((gpio_num_t)i); } } #endif @@ -258,14 +262,17 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false) } #ifdef BUTTON_PIN // Avoid leakage through button pin - pinMode(BUTTON_PIN, INPUT); - gpio_hold_en((gpio_num_t)BUTTON_PIN); + if (GPIO_IS_VALID_OUTPUT_GPIO(BUTTON_PIN)) { + pinMode(BUTTON_PIN, INPUT); + gpio_hold_en((gpio_num_t)BUTTON_PIN); + } #endif - - // LoRa CS (RADIO_NSS) needs to stay HIGH, even during deep sleep - pinMode(LORA_CS, OUTPUT); - digitalWrite(LORA_CS, HIGH); - gpio_hold_en((gpio_num_t)LORA_CS); + if (GPIO_IS_VALID_OUTPUT_GPIO(LORA_CS)) { + // LoRa CS (RADIO_NSS) needs to stay HIGH, even during deep sleep + pinMode(LORA_CS, OUTPUT); + digitalWrite(LORA_CS, HIGH); + gpio_hold_en((gpio_num_t)LORA_CS); + } #endif #ifdef HAS_PMU From dfc43bae1859d677c0f1580ce1b44f6d0ae2f435 Mon Sep 17 00:00:00 2001 From: todd-herbert Date: Mon, 22 Apr 2024 00:25:58 +1200 Subject: [PATCH 097/108] Fix crash on shutdown, if Bluetooth not enabled (#3686) Previously attempted to call deinit method for a nullptr --- src/sleep.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sleep.cpp b/src/sleep.cpp index 548ef2c54..e58c3872a 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -213,7 +213,8 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false) #ifdef ARCH_ESP32 // Full shutdown of bluetooth hardware - nimbleBluetooth->deinit(); + if (nimbleBluetooth) + nimbleBluetooth->deinit(); #endif #ifdef ARCH_ESP32 From 41f355749145bd40ee0228c151c233e7af90b76b Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sun, 21 Apr 2024 07:42:36 -0500 Subject: [PATCH 098/108] Refactor smart position to use throttle helper (#3671) * Added one minute throttling to NodeDB * Derp * Refactor smart-position to use throttle --- src/modules/PositionModule.cpp | 76 ++++++++++++++++------------------ src/modules/PositionModule.h | 7 +++- 2 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/modules/PositionModule.cpp b/src/modules/PositionModule.cpp index dcfe03f7f..250daec57 100644 --- a/src/modules/PositionModule.cpp +++ b/src/modules/PositionModule.cpp @@ -17,6 +17,7 @@ extern "C" { #include "mesh/compression/unishox2.h" +#include } PositionModule *positionModule; @@ -63,11 +64,11 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes } // Log packet size and data fields - LOG_INFO("POSITION node=%08x l=%d latI=%d lonI=%d msl=%d hae=%d geo=%d pdop=%d hdop=%d vdop=%d siv=%d fxq=%d fxt=%d pts=%d " - "time=%d\n", - getFrom(&mp), mp.decoded.payload.size, p.latitude_i, p.longitude_i, p.altitude, p.altitude_hae, - p.altitude_geoidal_separation, p.PDOP, p.HDOP, p.VDOP, p.sats_in_view, p.fix_quality, p.fix_type, p.timestamp, - p.time); + LOG_DEBUG("POSITION node=%08x l=%d latI=%d lonI=%d msl=%d hae=%d geo=%d pdop=%d hdop=%d vdop=%d siv=%d fxq=%d fxt=%d pts=%d " + "time=%d\n", + getFrom(&mp), mp.decoded.payload.size, p.latitude_i, p.longitude_i, p.altitude, p.altitude_hae, + p.altitude_geoidal_separation, p.PDOP, p.HDOP, p.VDOP, p.sats_in_view, p.fix_quality, p.fix_type, p.timestamp, + p.time); if (p.time && channels.getByIndex(mp.channel).role == meshtastic_Channel_Role_PRIMARY) { struct timeval tv; @@ -222,6 +223,16 @@ meshtastic_MeshPacket *PositionModule::allocAtakPli() return mp; } +void PositionModule::sendOurPosition() +{ + bool requestReplies = currentGeneration != radioGeneration; + currentGeneration = radioGeneration; + + // If we changed channels, ask everyone else for their latest info + LOG_INFO("Sending pos@%x:6 to mesh (wantReplies=%d)\n", localPosition.timestamp, requestReplies); + sendOurPosition(NODENUM_BROADCAST, requestReplies); +} + void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t channel) { // cancel any not yet sent (now stale) position packets @@ -299,12 +310,7 @@ int32_t PositionModule::runOnce() lastGpsLatitude = node->position.latitude_i; lastGpsLongitude = node->position.longitude_i; - // If we changed channels, ask everyone else for their latest info - bool requestReplies = currentGeneration != radioGeneration; - currentGeneration = radioGeneration; - - LOG_INFO("Sending pos@%x:6 to mesh (wantReplies=%d)\n", localPosition.timestamp, requestReplies); - sendOurPosition(NODENUM_BROADCAST, requestReplies); + sendOurPosition(); if (config.device.role == meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND) { sendLostAndFoundText(); } @@ -314,29 +320,23 @@ int32_t PositionModule::runOnce() if (hasValidPosition(node2)) { // The minimum time (in seconds) that would pass before we are able to send a new position packet. - const uint32_t minimumTimeThreshold = - Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30); auto smartPosition = getDistanceTraveledSinceLastSend(node->position); + uint32_t msSinceLastSend = now - lastGpsSend; - if (smartPosition.hasTraveledOverThreshold && msSinceLastSend >= minimumTimeThreshold) { - bool requestReplies = currentGeneration != radioGeneration; - currentGeneration = radioGeneration; + if (smartPosition.hasTraveledOverThreshold && + Throttle::execute( + &lastGpsSend, minimumTimeThreshold, []() { positionModule->sendOurPosition(); }, + []() { LOG_DEBUG("Skipping send smart broadcast due to time throttling\n"); })) { - LOG_INFO("Sending smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, " - "minTimeInterval=%ims)\n", - localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold, - msSinceLastSend, minimumTimeThreshold); - sendOurPosition(NODENUM_BROADCAST, requestReplies); + LOG_DEBUG("Sent smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, " + "minTimeInterval=%ims)\n", + localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold, + msSinceLastSend, minimumTimeThreshold); // Set the current coords as our last ones, after we've compared distance with current and decided to send lastGpsLatitude = node->position.latitude_i; lastGpsLongitude = node->position.longitude_i; - - /* Update lastGpsSend to now. This means if the device is stationary, then - getPref_position_broadcast_secs will still apply. - */ - lastGpsSend = now; } } } @@ -396,27 +396,21 @@ void PositionModule::handleNewPosition() meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum()); const meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position // We limit our GPS broadcasts to a max rate - uint32_t now = millis(); - uint32_t msSinceLastSend = now - lastGpsSend; - if (hasValidPosition(node2)) { auto smartPosition = getDistanceTraveledSinceLastSend(node->position); - if (smartPosition.hasTraveledOverThreshold) { - bool requestReplies = currentGeneration != radioGeneration; - currentGeneration = radioGeneration; - - LOG_INFO("Sending smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims)\n", - localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold, msSinceLastSend); - sendOurPosition(NODENUM_BROADCAST, requestReplies); + uint32_t msSinceLastSend = millis() - lastGpsSend; + if (smartPosition.hasTraveledOverThreshold && + Throttle::execute( + &lastGpsSend, minimumTimeThreshold, []() { positionModule->sendOurPosition(); }, + []() { LOG_DEBUG("Skipping send smart broadcast due to time throttling\n"); })) { + LOG_DEBUG("Sent smart pos@%x:6 to mesh (distanceTraveled=%fm, minDistanceThreshold=%im, timeElapsed=%ims, " + "minTimeInterval=%ims)\n", + localPosition.timestamp, smartPosition.distanceTraveled, smartPosition.distanceThreshold, msSinceLastSend, + minimumTimeThreshold); // Set the current coords as our last ones, after we've compared distance with current and decided to send lastGpsLatitude = node->position.latitude_i; lastGpsLongitude = node->position.longitude_i; - - /* Update lastGpsSend to now. This means if the device is stationary, then - getPref_position_broadcast_secs will still apply. - */ - lastGpsSend = now; } } } diff --git a/src/modules/PositionModule.h b/src/modules/PositionModule.h index 68171ab0e..0e24e3a9e 100644 --- a/src/modules/PositionModule.h +++ b/src/modules/PositionModule.h @@ -1,4 +1,5 @@ #pragma once +#include "Default.h" #include "ProtobufModule.h" #include "concurrency/OSThread.h" @@ -29,7 +30,8 @@ class PositionModule : public ProtobufModule, private concu /** * Send our position into the mesh */ - void sendOurPosition(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false, uint8_t channel = 0); + void sendOurPosition(NodeNum dest, bool wantReplies = false, uint8_t channel = 0); + void sendOurPosition(); void handleNewPosition(); @@ -52,6 +54,9 @@ class PositionModule : public ProtobufModule, private concu meshtastic_MeshPacket *allocAtakPli(); uint32_t precision; void sendLostAndFoundText(); + + const uint32_t minimumTimeThreshold = + Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30); }; struct SmartPosition { From 9822a8527487f377c38dd4143288299faf2d8c8a Mon Sep 17 00:00:00 2001 From: S5NC <145265251+S5NC@users.noreply.github.com> Date: Sun, 21 Apr 2024 14:40:23 +0100 Subject: [PATCH 099/108] Add board and variant definitions for EBYTE_ESP32-S3 (#2882) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Create ESP32-S3-WROOM-1-N4.json * Create pins_arduino.h * Create platformio.ini * Create variant.h * Update mesh.pb.h * Update architecture.h * Update mesh.pb.h * Update variant.h * Update variant.h Add example schematic * Update architecture.h * Revert update architecture.h * Create variant.h * Create pins_arduino.h * Create platformio.ini * Delete variants/E22-900M_S3 directory * Update architecture.h * Update variant.h * Update platformio.ini * Update variant.h * Update variant.h * Update architecture.h * Update platformio.ini * Update architecture.h * Update ESP32-S3-WROOM-1-N4.json * Update platformio.ini * Update ESP32-S3-WROOM-1-N4.json * Update variant.h * Update variant.h * Update variant.h * Update variant.h * Update pins_arduino.h * Update architecture.h * add SX1268 allow * GPS * Commit * Whitespace * Update variant.h * Update variant.h * trunk --------- Co-authored-by: Ben Meadors Co-authored-by: Thomas Göttgens Co-authored-by: S5NC <> --- boards/ESP32-S3-WROOM-1-N4.json | 39 +++++ src/platform/esp32/architecture.h | 4 + variants/EBYTE_ESP32-S3/pins_arduino.h | 37 +++++ variants/EBYTE_ESP32-S3/platformio.ini | 9 ++ variants/EBYTE_ESP32-S3/variant.h | 193 +++++++++++++++++++++++++ 5 files changed, 282 insertions(+) create mode 100644 boards/ESP32-S3-WROOM-1-N4.json create mode 100644 variants/EBYTE_ESP32-S3/pins_arduino.h create mode 100644 variants/EBYTE_ESP32-S3/platformio.ini create mode 100644 variants/EBYTE_ESP32-S3/variant.h diff --git a/boards/ESP32-S3-WROOM-1-N4.json b/boards/ESP32-S3-WROOM-1-N4.json new file mode 100644 index 000000000..3620a711d --- /dev/null +++ b/boards/ESP32-S3-WROOM-1-N4.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-D ARDUINO_USB_CDC_ON_BOOT=0", + "-D ARDUINO_USB_MSC_ON_BOOT=0", + "-D ARDUINO_USB_DFU_ON_BOOT=0", + "-D ARDUINO_USB_MODE=0", + "-D ARDUINO_RUNNING_CORE=1", + "-D ARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [["0x303A", "0x1001"]], + "mcu": "esp32s3", + "variant": "ESP32-S3-WROOM-1-N4" + }, + "connectivity": ["wifi"], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": ["esp-builtin"], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": ["arduino", "espidf"], + "name": "ESP32-S3-WROOM-1-N4 (4 MB Flash, No PSRAM)", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 524288, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdf", + "vendor": "Espressif" +} diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h index c6d90970f..27088f86f 100644 --- a/src/platform/esp32/architecture.h +++ b/src/platform/esp32/architecture.h @@ -127,6 +127,10 @@ #define HW_VENDOR meshtastic_HardwareModel_BETAFPV_900_NANO_TX #elif defined(PICOMPUTER_S3) #define HW_VENDOR meshtastic_HardwareModel_PICOMPUTER_S3 +#elif defined(HELTEC_HT62) +#define HW_VENDOR meshtastic_HardwareModel_HELTEC_HT62 +#elif defined(EBYTE_ESP32_S3) +#define HW_VENDOR meshtastic_HardwareModel_EBYTE_ESP32_S3 #elif defined(ESP32_S3_PICO) #define HW_VENDOR meshtastic_HardwareModel_ESP32_S3_PICO #elif defined(SENSELORA_S3) diff --git a/variants/EBYTE_ESP32-S3/pins_arduino.h b/variants/EBYTE_ESP32-S3/pins_arduino.h new file mode 100644 index 000000000..38a9103f0 --- /dev/null +++ b/variants/EBYTE_ESP32-S3/pins_arduino.h @@ -0,0 +1,37 @@ +// Need this file for ESP32-S3 +// No need to modify this file, changes to pins imported from variant.h +// Most is similar to https://github.com/espressif/arduino-esp32/blob/master/variants/esp32s3/pins_arduino.h + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +#define EXTERNAL_NUM_INTERRUPTS 46 +#define NUM_DIGITAL_PINS 48 +#define NUM_ANALOG_INPUTS 20 + +#define analogInputToDigitalPin(p) (((p) < 20) ? (analogChannelToDigitalPin(p)) : -1) +#define digitalPinToInterrupt(p) \ + (((p) < 48) ? (p) : -1) // Maybe it should be <= 48 but this is from a trustworthy source so it is likely correct +#define digitalPinHasPWM(p) (p < 46) + +// Serial +static const uint8_t TX = UART_TX; +static const uint8_t RX = UART_RX; + +// Default SPI will be mapped to Radio +static const uint8_t SS = LORA_CS; +static const uint8_t SCK = LORA_SCK; +static const uint8_t MOSI = LORA_MOSI; +static const uint8_t MISO = LORA_MISO; + +// The default Wire will be mapped to PMU and RTC +static const uint8_t SCL = I2C_SCL; +static const uint8_t SDA = I2C_SDA; + +#endif /* Pins_Arduino_h */ diff --git a/variants/EBYTE_ESP32-S3/platformio.ini b/variants/EBYTE_ESP32-S3/platformio.ini new file mode 100644 index 000000000..10de91386 --- /dev/null +++ b/variants/EBYTE_ESP32-S3/platformio.ini @@ -0,0 +1,9 @@ +[env:EBYTE_ESP32-S3] +extends = esp32s3_base +; board assumes the lowest spec WROOM module: 4 MB (Quad SPI) Flash, No PSRAM +board = ESP32-S3-WROOM-1-N4 +board_level = extra +build_flags = + ${esp32s3_base.build_flags} + -D EBYTE_ESP32_S3 + -I variants/EBYTE_ESP32-S3 diff --git a/variants/EBYTE_ESP32-S3/variant.h b/variants/EBYTE_ESP32-S3/variant.h new file mode 100644 index 000000000..10b39617b --- /dev/null +++ b/variants/EBYTE_ESP32-S3/variant.h @@ -0,0 +1,193 @@ +// Supporting information: https://github.com/S5NC/EBYTE_ESP32-S3/ + +// Originally developed for E22-900M30S with ESP32-S3-WROOM-1-N4 +// NOTE: Uses ESP32-S3-WROOM-1-N4.json in boards folder (via platformio.ini board field), assumes 4 MB (quad SPI) flash, no PSRAM + +// FIXME: implement SX12 module type autodetection and have setup for each case (add E32 support) +// E32 has same pinout except having extra pins. I assume that the GND on it is connected internally to other GNDs so it is not a +// problem to NC the extra GND pins. + +// For each EBYTE module pin in this section, provide the pin number of the ESP32-S3 you connected it to +// The ESP32-S3 is great because YOU CAN USE PRACTICALLY ANY PINS for the connections, but avoid some pins (such as on the WROOM +// modules the following): strapping pins (except 0 as a user button input as it already has a pulldown resistor in typical +// application schematic) (0, 3, 45, 46), USB-reserved (19, 20), and pins which aren't present on the WROOM-2 module for +// compatiblity as it uses octal SPI, or are likely connected internally in either WROOM version (26-37), and avoid pins whose +// voltages are set by the SPI voltage (47, 48), and pins that don't exist (22-25) You can ALSO set the SPI pins (SX126X_CS, +// SX126X_SCK, SX126X_MISO, SX126X_MOSI) to any pin with the ESP32-S3 due to \ GPIO Matrix / IO MUX / RTC IO MUX \, and also the +// serial pins, but this isn't recommended for Serial0 as the WROOM modules have a 499 Ohm resistor on U0TXD (to reduce harmonics +// but also acting as a sort of protection) + +// We have many free pins on the ESP32-S3-WROOM-X-Y module, perhaps it is best to use one of its pins to control TXEN, and use +// DIO2 as an extra interrupt, but right now Meshtastic does not benefit from having another interrupt pin available. + +// Adding two 0-ohm links on your PCB design so that you can choose between the two modes for controlling the E22's TXEN would +// enable future software to make the most of an extra available interrupt pin + +// Possible improvement: can add extremely low resistance MOSFET to physically toggle power to E22 module when in full sleep (not +// waiting for interrupt)? + +// PA stands for Power Amplifier, used when transmitting to increase output power +// LNA stands for Low Noise Amplifier, used when \ listening for / receiving \ data to increase sensitivity + +////////////////////////////////////////////////////////////////////////////////// +// // +// Have custom connections or functionality? Configure them in this section // +// // +////////////////////////////////////////////////////////////////////////////////// + +#define SX126X_CS 14 // EBYTE module's NSS pin // FIXME: rename to SX126X_SS +#define LORA_SCK 21 // EBYTE module's SCK pin +#define LORA_MOSI 38 // EBYTE module's MOSI pin +#define LORA_MISO 39 // EBYTE module's MISO pin +#define SX126X_RESET 40 // EBYTE module's NRST pin +#define SX126X_BUSY 41 // EBYTE module's BUSY pin +#define SX126X_DIO1 42 // EBYTE module's DIO1 pin +// We don't define a pin for SX126X_DIO2 as Meshtastic doesn't use it as an interrupt output, so it is never connected to an MCU +// pin! Also E22 module datasheets say not to connect it to an MCU pin. +// We don't define a pin for SX126X_DIO3 as Meshtastic doesn't use it as an interrupt output, so it is never connected to an MCU +// pin! Also E22 module datasheets say to use it as the TCXO's reference voltage. +// E32 module (which uses SX1276) may not have ability to set TCXO voltage using a DIO pin. + +// The radio module needs to be told whether to enable RX mode or TX mode. Each radio module takes different actions based on +// these values, but generally the path from the antenna to SX1262 is changed from signal output to signal input. Also, if there +// are LNAs (Low-Noise Amplifiers) or PAs (Power Amplifiers) in the output or input paths, their power is also controlled by +// these pins. You should never have both TXEN and RXEN set high, this can cause problems for some radio modules, and is +// commonly referred to as 'undefined behaviour' in datasheets. For the SX1262, you shouldn't connect DIO2 to the MCU. DIO2 is +// an output only, and can be controlled via SPI instructions, the use for this is to save an MCU pin by using the DIO2 pin to +// control the RF switching mode. + +// Choose ONLY ONE option from below, comment in/out the '/*'s and '*/'s +// SX126X_TXEN is the E22's [SX1262's] TXEN pin, SX126X_RXEN is the E22's [SX1262's] RXEN pin + +// Option 1: E22's TXEN pin connected to E22's DIO2 pin, E22's RXEN pin connected to NEGATED output of E22's DIO2 pin (more +// expensive option hardware-wise, is the 'most proper' way, removes need for routing one/two traces from MCU to RF switching +// pins), however you can't have E22 in low-power 'sleep' mode (TXEN and RXEN both low cannot be achieved this this option). +/* +#define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_TXEN RADIOLIB_NC +#define SX126X_RXEN RADIOLIB_NC +*/ + +// Option 2: E22's TXEN pin connected to E22's DIO2 pin, E22's RXEN pin connected to MCU pin (cheaper option hardware-wise, +// removes need for routing another trace from MCU to an RF switching pin). +// /* +#define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_TXEN RADIOLIB_NC +#define SX126X_RXEN 10 +// */ + +// Option 3: E22's TXEN pin connected to MCU pin, E22's RXEN pin connected to MCU pin (cheaper option hardware-wise, allows for +// ramping up PA before transmission (add/expand on feature yourself in RadioLib) if PA takes a while to stabilise) +// Don't define DIO2_AS_RF_SWITCH because we only use DIO2 or an MCU pin mutually exclusively to connect to E22's TXEN (to prevent +// a short if they are both connected at the same time (suboptimal PCB design) and there's a slight non-neglibible delay and/or +// voltage difference between DIO2 and TXEN). Can use DIO2 as an IRQ (but not in Meshtastic at the moment). +/* +#define SX126X_TXEN 9 +#define SX126X_RXEN 10 +*/ + +// (NOT RECOMMENDED, if need to ramp up PA before transmission, better to use option 3) +// Option 4: E22's TXEN pin connected to MCU pin, E22's RXEN pin connected to NEGATED output of E22's DIO2 pin (more expensive +// option hardware-wise, allows for ramping up PA before transmission (add/expand on feature yourself in RadioLib) if PA takes +// a while to stabilise, removes need for routing another trace from MCU to an RF switching pin, however may mean if in +// RadioLib you don't tell DIO2 to go high to indicate transmission (so the negated output goes to RXEN to turn the LNA off) +// then you may end up enabling E22's TXEN and RXEN pins at the same time whilst you ramp up the PA which is not ideal, +// changing DIO2's switching advance in RadioLib may not even be possible, may be baked into the SX126x). +/* +#define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_TXEN 9 +#define SX126X_RXEN RADIOLIB_NC +*/ + +// Status +#define LED_PIN 1 +#define LED_INVERTED 0 +// External notification +// FIXME: Check if EXT_NOTIFY_OUT actualy has any effect and removes the need for setting the external notication pin in the +// app/preferences +#define EXT_NOTIFY_OUT 2 // The GPIO pin that acts as the external notification output (here we connect an LED to it) +// Buzzer +#define PIN_BUZZER 11 +// Buttons +#define BUTTON_PIN 0 // Use the BOOT button as the user button +// I2C +#define I2C_SCL 18 +#define I2C_SDA 8 +// UART +#define UART_TX 43 +#define UART_RX 44 + +// Power +// Outputting 22dBm from SX1262 results in ~30dBm E22-900M30S output (module only uses last stage of the YP2233W PA) +// Respect local regulations! If your E22-900M30S outputs the advertised 30 dBm and you use a 6 dBi antenna, you are at the +// equivalent of 36 EIRP (Effective Isotropic Radiated Power), which in this case is the limit for non-HAM users in the US (4W +// EIRP, at SPECIFIC frequencies). +// In the EU (and UK), as of now, you are allowed 27 dBm ERP which is 29.15 EIRP. +// https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32022D0180 +// https://www.legislation.gov.uk/uksi/1999/930/schedule/6/made +// To respect the 29.15 dBm EIRP (at SPECIFIC frequencies, others are lower) EU limit with a 2.5 dBi gain antenna, consulting +// https://github.com/S5NC/EBYTE_ESP32-S3/blob/main/power%20testing.txt, assuming 0.1 dBm insertion loss, output 20 dBm from the +// E22-900M30S's SX1262. It is worth noting that if you are in this situation and don't have a HAM license, you may be better off +// with a lower gain antenna, and output the difference as a higher total power input into the antenna, as your EIRP would be the +// same, but you would get a wider angle of coverage. Also take insertion loss and possibly VSWR into account +// (https://www.everythingrf.com/tech-resources/vswr). Please check regulations yourself and check airtime, usage (for example +// whether you are airborne), frequency, and power laws. +#define SX126X_MAX_POWER 22 // SX126xInterface.cpp defaults to 22 if not defined, but here we define it for good practice + +// Display +// FIXME: change behavior in src to default to not having screen if is undefined +// FIXME: remove 0/1 option for HAS_SCREEN in src, change to being defined or not +// FIXME: check if it actually causes a crash when not specifiying that a display isn't present +#define HAS_SCREEN 0 // Assume no screen present by default to prevent crash... + +// GPS +// FIXME: unsure what to define HAS_GPS as if GPS isn't always present +#define HAS_GPS 1 // Don't need to set this to 0 to prevent a crash as it doesn't crash if GPS not found, will probe by default +#define PIN_GPS_EN 15 +#define GPS_EN_ACTIVE 1 +#define GPS_TX_PIN 16 +#define GPS_RX_PIN 17 + +///////////////////////////////////////////////////////////////////////////////// +// // +// You should have no need to modify the code below, nor in pins_arduino.h // +// // +///////////////////////////////////////////////////////////////////////////////// + +#define USE_SX1262 // E22-900M30S, E22-900M22S, and E22-900MM22S (not E220!) use SX1262 +#define USE_SX1268 // E22-400M30S, E22-400M33S, E22-400M22S, and E22-400MM22S use SX1268 + +// The below isn't needed as we directly define SX126X_TXEN and SX126X_RXEN instead of using proxies E22_TXEN and E22_RXEN +/* +// FALLBACK: If somehow E22_TXEN isn't defined or clearly isn't a valid pin number, set it to RADIOLIB_NC to avoid SX126X_TXEN +being defined but having no value #if (!defined(E22_TXEN) || !(0 <= E22_TXEN && E22_TXEN <= 48)) #define E22_TXEN RADIOLIB_NC +#endif +// FALLBACK: If somehow E22_RXEN isn't defined or clearly isn't a valid pin number, set it to RADIOLIB_NC to avoid SX126X_RXEN +being defined but having no value #if (!defined(E22_RXEN) || !(0 <= E22_RXEN && E22_RXEN <= 48)) #define E22_RXEN RADIOLIB_NC +#endif +#define SX126X_TXEN E22_TXEN +#define SX126X_RXEN E22_RXEN +*/ + +// E22 series TCXO voltage is 1.8V per https://www.ebyte.com/en/pdf-down.aspx?id=781 (source +// https://github.com/jgromes/RadioLib/issues/12#issuecomment-520695575), so set it as such +#define SX126X_DIO3_TCXO_VOLTAGE 1.8 + +#define LORA_CS SX126X_CS // FIXME: for some reason both are used in /src + +// Many of the below values would only be used if USE_RF95 was defined, but it's not as we aren't actually using an RF95, just +// that the 4 pins above are named like it If they aren't used they don't need to be defined and doing so cause confusion to those +// adapting this file LORA_RESET value is never used in src (as we are not using RF95), so no need to define LORA_DIO0 is not used +// in src (as we are not using RF95) as SX1262 does not have it per SX1262 datasheet, so no need to define +// FIXME: confirm that the linked lines below are actually only called when using the SX126x or SX128x and no other modules +// then use SX126X_DIO1 and SX128X_DIO1 respectively for that purpose, removing the need for RF95-style LORA_* definitions when +// the RF95 isn't used +#define LORA_DIO1 \ + SX126X_DIO1 // The old name is used in + // https://github.com/meshtastic/firmware/blob/7eff5e7bcb2084499b723c5e3846c15ee089e36d/src/sleep.cpp#L298, so + // must also define the old name +// LORA_DIO2 value is never used in src (as we are not using RF95), so no need to define, and if DIO2_AS_RF_SWITCH is set then it +// cannot serve any extra function even if requested to LORA_DIO3 value is never used in src (as we are not using RF95), so no +// need to define, and DIO3_AS_TCXO_AT_1V8 is set so it cannot serve any extra function even if requested to (from 13.3.2.1 +// DioxMask in SX1262 datasheet: Note that if DIO2 or DIO3 are used to control the RF Switch or the TCXO, the IRQ will not be +// generated even if it is mapped to the pins.) \ No newline at end of file From ac87c0065fa3c95bf2ab5aad39be331777782091 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sun, 21 Apr 2024 08:45:36 -0500 Subject: [PATCH 100/108] Also refresh timestamp for "timeonly" fixed position nodes (#3689) --- src/mesh/NodeDB.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index 57040fbd6..8e3784e58 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -150,12 +150,13 @@ class NodeDB void setLocalPosition(meshtastic_Position position, bool timeOnly = false) { if (timeOnly) { - LOG_DEBUG("Setting local position time only: time=%i\n", position.time); + LOG_DEBUG("Setting local position time only: time=%i timestamp=%i\n", position.time, position.timestamp); localPosition.time = position.time; + localPosition.timestamp = position.timestamp > 0 ? position.timestamp : position.time; return; } - LOG_DEBUG("Setting local position: latitude=%i, longitude=%i, time=%i\n", position.latitude_i, position.longitude_i, - position.time); + LOG_DEBUG("Setting local position: latitude=%i, longitude=%i, time=%i, timeestamp=%i\n", position.latitude_i, + position.longitude_i, position.time, position.timestamp); localPosition = position; } From 679e068e19519b274b26c9cd9e5deb950236944c Mon Sep 17 00:00:00 2001 From: Ric In New Mexico <78682404+RicInNewMexico@users.noreply.github.com> Date: Sun, 21 Apr 2024 11:35:42 -0600 Subject: [PATCH 101/108] Missing break in INA3221 i2c scan (#3692) * INA3221 Mis-identification fix * Missing break in INA3221 i2c scan --- src/detect/ScanI2CTwoWire.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index e2e2188b6..ba2820a77 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -279,6 +279,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port) } else { // Unknown device LOG_INFO("No INA3221 found at address 0x%x\n", (uint8_t)addr.address); } + break; case MCP9808_ADDR: registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2); if (registerValue == 0x0400) { From 0406be82d22f1e546b90d3aa5145409f2ec84d39 Mon Sep 17 00:00:00 2001 From: Mictronics Date: Sun, 21 Apr 2024 19:36:37 +0200 Subject: [PATCH 102/108] Use correct format specifier and fixed typo. (#3696) * Fix LED pinout for T-Echo board marked v1.0, date 2021-6-28 * Merge PR #420 * Fixed double and missing Default class. * Use correct format specifier and fixed typo. --------- Co-authored-by: Ben Meadors --- src/mesh/NodeDB.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index 8e3784e58..4946672ec 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -150,12 +150,12 @@ class NodeDB void setLocalPosition(meshtastic_Position position, bool timeOnly = false) { if (timeOnly) { - LOG_DEBUG("Setting local position time only: time=%i timestamp=%i\n", position.time, position.timestamp); + LOG_DEBUG("Setting local position time only: time=%u timestamp=%u\n", position.time, position.timestamp); localPosition.time = position.time; localPosition.timestamp = position.timestamp > 0 ? position.timestamp : position.time; return; } - LOG_DEBUG("Setting local position: latitude=%i, longitude=%i, time=%i, timeestamp=%i\n", position.latitude_i, + LOG_DEBUG("Setting local position: latitude=%i, longitude=%i, time=%u, timestamp=%u\n", position.latitude_i, position.longitude_i, position.time, position.timestamp); localPosition = position; } From 39bbf0d352fca0735643b53518646341b7fef67c Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sun, 21 Apr 2024 14:40:47 -0500 Subject: [PATCH 103/108] Added more clear RTC handling and quality logging (#3691) * Also refresh timestamp for "timeonly" fixed position nodes * Added more clear RTC quality handling * Fix clock drift from Phone GPS / NTP too --- src/gps/RTC.cpp | 28 ++++++++++++++++++++++++---- src/gps/RTC.h | 3 +++ src/modules/PositionModule.cpp | 18 +++++++++++------- src/modules/PositionModule.h | 1 + 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/gps/RTC.cpp b/src/gps/RTC.cpp index 26af7cac2..85931900f 100644 --- a/src/gps/RTC.cpp +++ b/src/gps/RTC.cpp @@ -104,13 +104,15 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv) bool shouldSet; if (q > currentQuality) { shouldSet = true; - LOG_DEBUG("Upgrading time to quality %d\n", q); - } else if (q == RTCQualityGPS && (now - lastSetMsec) > (12 * 60 * 60 * 1000UL)) { - // Every 12 hrs we will slam in a new GPS time, to correct for local RTC clock drift + LOG_DEBUG("Upgrading time to quality %s\n", RtcName(q)); + } else if (q >= RTCQualityNTP && (now - lastSetMsec) > (12 * 60 * 60 * 1000UL)) { + // Every 12 hrs we will slam in a new GPS or Phone GPS / NTP time, to correct for local RTC clock drift shouldSet = true; LOG_DEBUG("Reapplying external time to correct clock drift %ld secs\n", tv->tv_sec); - } else + } else { shouldSet = false; + LOG_DEBUG("Current RTC quality: %s. Ignoring time of RTC quality of %s\n", RtcName(currentQuality), RtcName(q)); + } if (shouldSet) { currentQuality = q; @@ -162,6 +164,24 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv) } } +const char *RtcName(RTCQuality quality) +{ + switch (quality) { + case RTCQualityNone: + return "None"; + case RTCQualityDevice: + return "Device"; + case RTCQualityFromNet: + return "Net"; + case RTCQualityNTP: + return "NTP"; + case RTCQualityGPS: + return "GPS"; + default: + return "Unknown"; + } +} + /** * Sets the RTC time if the provided time is of higher quality than the current RTC time. * diff --git a/src/gps/RTC.h b/src/gps/RTC.h index 0561819bd..1d609f136 100644 --- a/src/gps/RTC.h +++ b/src/gps/RTC.h @@ -28,6 +28,9 @@ RTCQuality getRTCQuality(); bool perhapsSetRTC(RTCQuality q, const struct timeval *tv); bool perhapsSetRTC(RTCQuality q, struct tm &t); +/// Return a string name for the quality +const char *RtcName(RTCQuality quality); + /// Return time since 1970 in secs. While quality is RTCQualityNone we will be returning time based at zero uint32_t getTime(bool local = false); diff --git a/src/modules/PositionModule.cpp b/src/modules/PositionModule.cpp index 250daec57..658b8b5a7 100644 --- a/src/modules/PositionModule.cpp +++ b/src/modules/PositionModule.cpp @@ -71,14 +71,8 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes p.time); if (p.time && channels.getByIndex(mp.channel).role == meshtastic_Channel_Role_PRIMARY) { - struct timeval tv; - uint32_t secs = p.time; - - tv.tv_sec = secs; - tv.tv_usec = 0; - // Set from phone RTC Quality to RTCQualityNTP since it should be approximately so - perhapsSetRTC(isLocal ? RTCQualityNTP : RTCQualityFromNet, &tv); + trySetRtc(p, isLocal); } nodeDB->updatePosition(getFrom(&mp), p); @@ -93,6 +87,16 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes return false; // Let others look at this message also if they want } +void PositionModule::trySetRtc(meshtastic_Position p, bool isLocal) +{ + struct timeval tv; + uint32_t secs = p.time; + + tv.tv_sec = secs; + tv.tv_usec = 0; + perhapsSetRTC(isLocal ? RTCQualityNTP : RTCQualityFromNet, &tv); +} + meshtastic_MeshPacket *PositionModule::allocReply() { if (precision == 0) { diff --git a/src/modules/PositionModule.h b/src/modules/PositionModule.h index 0e24e3a9e..89ff50c64 100644 --- a/src/modules/PositionModule.h +++ b/src/modules/PositionModule.h @@ -52,6 +52,7 @@ class PositionModule : public ProtobufModule, private concu private: struct SmartPosition getDistanceTraveledSinceLastSend(meshtastic_PositionLite currentPosition); meshtastic_MeshPacket *allocAtakPli(); + void trySetRtc(meshtastic_Position p, bool isLocal); uint32_t precision; void sendLostAndFoundText(); From 4a48a3fb52c35f38d77954b9c8d013c323c160a9 Mon Sep 17 00:00:00 2001 From: Nicholas Baddorf <42445164+nbaddorf@users.noreply.github.com> Date: Sun, 21 Apr 2024 15:41:22 -0400 Subject: [PATCH 104/108] Fixed bug making t-deck reboot when muted (#3694) --- src/modules/ExternalNotificationModule.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp index a38b231af..b898e72ee 100644 --- a/src/modules/ExternalNotificationModule.cpp +++ b/src/modules/ExternalNotificationModule.cpp @@ -244,7 +244,8 @@ void ExternalNotificationModule::stopNow() { rtttl::stop(); #ifdef HAS_I2S - audioThread->stop(); + if (audioThread->isPlaying()) + audioThread->stop(); #endif nagCycleCutoff = 1; // small value isNagging = false; From fd9461505f2322027955ae8d38f6e04350888243 Mon Sep 17 00:00:00 2001 From: quimnut Date: Mon, 22 Apr 2024 10:51:02 +1000 Subject: [PATCH 105/108] adjust adc for rak11310 devices (#3698) --- variants/rak11310/variant.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/variants/rak11310/variant.h b/variants/rak11310/variant.h index ba3d4fed7..f9dcbd91a 100644 --- a/variants/rak11310/variant.h +++ b/variants/rak11310/variant.h @@ -14,7 +14,7 @@ #define BATTERY_PIN 26 #define BATTERY_SENSE_RESOLUTION_BITS ADC_RESOLUTION // ratio of voltage divider = 3.0 (R17=200k, R18=100k) -#define ADC_MULTIPLIER 3.1 // 3.0 + a bit for being optimistic +#define ADC_MULTIPLIER 1.84 #define DETECTION_SENSOR_EN 28 @@ -47,4 +47,4 @@ // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3 #define SX126X_DIO2_AS_RF_SWITCH #define SX126X_DIO3_TCXO_VOLTAGE 1.8 -#endif \ No newline at end of file +#endif From f47b40cf6880f9560b8ece533f2a9e1c6a1bdf70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Sun, 21 Apr 2024 22:29:17 +0200 Subject: [PATCH 106/108] fix signedness warnings of NRF52 toolchain --- src/gps/GPS.cpp | 4 ++-- src/mesh/RadioInterface.cpp | 2 +- src/modules/RoutingModule.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 0d0bfd9a2..17e35a4b3 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -452,7 +452,7 @@ bool GPS::setup() // Set the NEMA output messages // Ask for only RMC and GGA uint8_t fields[] = {CAS_NEMA_RMC, CAS_NEMA_GGA}; - for (int i = 0; i < sizeof(fields); i++) { + for (uint i = 0; i < sizeof(fields); i++) { // Construct a CAS-CFG-MSG packet uint8_t cas_cfg_msg_packet[] = {0x4e, fields[i], 0x01, 0x00}; msglen = makeCASPacket(0x06, 0x01, sizeof(cas_cfg_msg_packet), cas_cfg_msg_packet); @@ -1584,7 +1584,7 @@ bool GPS::hasFlow() bool GPS::whileIdle() { - int charsInBuf = 0; + uint charsInBuf = 0; bool isValid = false; if (!isAwake) { clearBuffer(); diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 63912a03e..4fa0bef7a 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -492,7 +492,7 @@ void RadioInterface::applyModemConfig() // If user has manually specified a channel num, then use that, otherwise generate one by hashing the name const char *channelName = channels.getName(channels.getPrimaryIndex()); // channel_num is actually (channel_num - 1), since modulus (%) returns values from 0 to (numChannels - 1) - int channel_num = (loraConfig.channel_num ? loraConfig.channel_num - 1 : hash(channelName)) % numChannels; + uint channel_num = (loraConfig.channel_num ? loraConfig.channel_num - 1 : hash(channelName)) % numChannels; // Check if we use the default frequency slot RadioInterface::uses_default_frequency_slot = diff --git a/src/modules/RoutingModule.cpp b/src/modules/RoutingModule.cpp index a52328ca4..fe1abab05 100644 --- a/src/modules/RoutingModule.cpp +++ b/src/modules/RoutingModule.cpp @@ -51,7 +51,7 @@ uint8_t RoutingModule::getHopLimitForResponse(uint8_t hopStart, uint8_t hopLimit uint8_t hopsUsed = hopStart < hopLimit ? config.lora.hop_limit : hopStart - hopLimit; if (hopsUsed > config.lora.hop_limit) { return hopsUsed; // If the request used more hops than the limit, use the same amount of hops - } else if (hopsUsed + 2 < config.lora.hop_limit) { + } else if ((uint8_t)(hopsUsed + 2) < config.lora.hop_limit) { return hopsUsed + 2; // Use only the amount of hops needed with some margin as the way back may be different } } From 30d4c3a94587e6b8bdb91a2801a68ef7bda84f50 Mon Sep 17 00:00:00 2001 From: David Ellefsen Date: Mon, 22 Apr 2024 10:47:11 +0200 Subject: [PATCH 107/108] Updates for esp32s2 build --- arch/esp32/esp32s2.ini | 7 +++++-- src/modules/esp32/PaxcounterModule.cpp | 2 +- src/sleep.cpp | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/esp32/esp32s2.ini b/arch/esp32/esp32s2.ini index 5de0fa549..df66de2ed 100644 --- a/arch/esp32/esp32s2.ini +++ b/arch/esp32/esp32s2.ini @@ -2,14 +2,17 @@ extends = esp32_base build_src_filter = - ${esp32_base.build_src_filter} - - + ${esp32_base.build_src_filter} - - - monitor_speed = 115200 build_flags = ${esp32_base.build_flags} -DHAS_BLUETOOTH=0 + -DMESHTASTIC_EXCLUDE_PAXCOUNTER + -DMESHTASTIC_EXCLUDE_BLUETOOTH lib_ignore = ${esp32_base.lib_ignore} - NimBLE-Arduino \ No newline at end of file + NimBLE-Arduino + libpax \ No newline at end of file diff --git a/src/modules/esp32/PaxcounterModule.cpp b/src/modules/esp32/PaxcounterModule.cpp index aad7b5d63..b9fdfcb63 100644 --- a/src/modules/esp32/PaxcounterModule.cpp +++ b/src/modules/esp32/PaxcounterModule.cpp @@ -1,5 +1,5 @@ #include "configuration.h" -#if defined(ARCH_ESP32) +#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_PAXCOUNTER #include "Default.h" #include "MeshService.h" #include "PaxcounterModule.h" diff --git a/src/sleep.cpp b/src/sleep.cpp index e58c3872a..fe73a755c 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -211,7 +211,7 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false) // esp_wifi_stop(); waitEnterSleep(skipPreflight); -#ifdef ARCH_ESP32 +#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH // Full shutdown of bluetooth hardware if (nimbleBluetooth) nimbleBluetooth->deinit(); From 250cf16bf8793aefed95b9cedb9c20b2f2e7a2a7 Mon Sep 17 00:00:00 2001 From: Andrew Yong Date: Mon, 22 Apr 2024 21:21:50 +0800 Subject: [PATCH 108/108] Add ability to turn off heartbeat LED blinking (#3674) * Add ability to turn off status LED blinking Fixes #3635 and depends on [protobufs PR #485](https://github.com/meshtastic/protobufs/pull/485) Signed-off-by: Andrew Yong * led_heartbeat_disabled * trunk --------- Signed-off-by: Andrew Yong Co-authored-by: Ben Meadors --- src/main.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index b1a15634f..f40fd0789 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -179,6 +179,11 @@ const char *getDeviceName() static int32_t ledBlinker() { + // Still set up the blinking (heartbeat) interval but skip code path below, so LED will blink if + // config.device.led_heartbeat_disabled is changed + if (config.device.led_heartbeat_disabled) + return 1000; + static bool ledOn; ledOn ^= 1; @@ -1001,4 +1006,4 @@ void loop() mainDelay.delay(delayMsec); } // if (didWake) LOG_DEBUG("wake!\n"); -} \ No newline at end of file +}