From 8d5ae1d5d26debc5b33f7a260cff029d56078189 Mon Sep 17 00:00:00 2001 From: GUVWAF <78759985+GUVWAF@users.noreply.github.com> Date: Fri, 15 Aug 2025 19:09:25 +0200 Subject: [PATCH 01/24] Fix marking LoRa transport mechanism (#7634) --- src/mesh/RadioInterface.cpp | 4 +++- src/mesh/Router.cpp | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 99e99922b..c210d5d48 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -666,8 +666,10 @@ void RadioInterface::limitPower(int8_t loraMaxPower) void RadioInterface::deliverToReceiver(meshtastic_MeshPacket *p) { - if (router) + if (router) { + p->transport_mechanism = meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA; router->enqueueReceivedMessage(p); + } } /*** diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 065d627e9..a54dcb976 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -66,7 +66,6 @@ int32_t Router::runOnce() { meshtastic_MeshPacket *mp; while ((mp = fromRadioQueue.dequeuePtr(0)) != NULL) { - mp->transport_mechanism = meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA; // printPacket("handle fromRadioQ", mp); perhapsHandleReceived(mp); } From 4a241deb968470e9b953a16071b8d045aeef6ed9 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Fri, 15 Aug 2025 14:41:21 -0500 Subject: [PATCH 02/24] Thinknode button and backlight fixes (#7641) * Thinknode button and backlight fixes * Save backlight value between reboots --- platformio.ini | 4 ++-- src/graphics/Screen.cpp | 20 +++++++++---------- src/graphics/draw/MenuHandler.cpp | 18 ++++++++++++++--- src/input/ButtonThread.cpp | 5 ++++- src/main.cpp | 1 - .../esp32s3/ELECROW-ThinkNode-M5/variant.h | 2 +- 6 files changed, 31 insertions(+), 19 deletions(-) diff --git a/platformio.ini b/platformio.ini index 62bbf8a24..520ec740e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -61,8 +61,8 @@ monitor_filters = direct lib_deps = # renovate: datasource=git-refs depName=meshtastic-esp8266-oled-ssd1306 packageName=https://github.com/meshtastic/esp8266-oled-ssd1306 gitBranch=master https://github.com/meshtastic/esp8266-oled-ssd1306/archive/0119501e9983bd894830b02f545c377ee08d66fe.zip - # renovate: datasource=custom.pio depName=OneButton packageName=mathertel/library/OneButton - mathertel/OneButton@2.6.1 + # renovate: datasource=git-refs depName=meshtastic-OneButton packageName=https://github.com/meshtastic/OneButton gitBranch=master + https://github.com/meshtastic/OneButton/archive/fa352d668c53f290cfa480a5f79ad422cd828c70.zip # renovate: datasource=git-refs depName=meshtastic-arduino-fsm packageName=https://github.com/meshtastic/arduino-fsm gitBranch=master https://github.com/meshtastic/arduino-fsm/archive/7db3702bf0cfe97b783d6c72595e3f38e0b19159.zip # renovate: datasource=git-refs depName=meshtastic-TinyGPSPlus packageName=https://github.com/meshtastic/TinyGPSPlus gitBranch=master diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 8d5635f89..88955145a 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -365,9 +365,6 @@ void Screen::doDeepSleep() { #ifdef USE_EINK setOn(false, graphics::UIRenderer::drawDeepSleepFrame); -#ifdef PIN_EINK_EN - digitalWrite(PIN_EINK_EN, LOW); // power off backlight -#endif #else // Without E-Ink display: setOn(false); @@ -391,8 +388,12 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) dispdev->displayOn(); #endif -#ifdef ELECROW_ThinkNode_M5 - io.digitalWrite(PCA_PIN_EINK_EN, HIGH); +#ifdef PIN_EINK_EN + if (uiconfig.screen_brightness == 1) + digitalWrite(PIN_EINK_EN, HIGH); +#elif defined(PCA_PIN_EINK_EN) + if (uiconfig.screen_brightness == 1) + io.digitalWrite(PCA_PIN_EINK_EN, HIGH); #endif #if defined(ST7789_CS) && \ @@ -424,13 +425,10 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) // eInkScreensaver parameter is usually NULL (default argument), default frame used instead setScreensaverFrames(einkScreensaver); #endif -#ifdef ELECROW_ThinkNode_M1 - if (digitalRead(PIN_EINK_EN) == HIGH) { - digitalWrite(PIN_EINK_EN, LOW); - } -#endif -#ifdef ELECROW_ThinkNode_M5 +#ifdef PIN_EINK_EN + digitalWrite(PIN_EINK_EN, LOW); +#elif defined(PCA_PIN_EINK_EN) io.digitalWrite(PCA_PIN_EINK_EN, LOW); #endif diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index b7bd068c4..fa738309a 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -318,7 +318,7 @@ void menuHandler::homeBaseMenu() static int optionsEnumArray[enumEnd] = {Back}; int options = 1; -#ifdef PIN_EINK_EN +#if defined(PIN_EINK_EN) || defined(PCA_PIN_EINK_EN) optionsArray[options] = "Toggle Backlight"; optionsEnumArray[options++] = Backlight; #else @@ -342,12 +342,24 @@ void menuHandler::homeBaseMenu() bannerOptions.optionsCount = options; bannerOptions.bannerCallback = [](int selected) -> void { if (selected == Backlight) { -#ifdef PIN_EINK_EN - if (digitalRead(PIN_EINK_EN) == HIGH) { +#if defined(PIN_EINK_EN) + if (uiconfig.screen_brightness == 1) { + uiconfig.screen_brightness = 0; digitalWrite(PIN_EINK_EN, LOW); } else { + uiconfig.screen_brightness = 1; digitalWrite(PIN_EINK_EN, HIGH); } + saveUIConfig(); +#elif defined(PCA_PIN_EINK_EN) + if (uiconfig.screen_brightness == 1) { + uiconfig.screen_brightness = 0; + io.digitalWrite(PCA_PIN_EINK_EN, LOW); + } else { + uiconfig.screen_brightness = 1; + io.digitalWrite(PCA_PIN_EINK_EN, HIGH); + } + saveUIConfig(); #endif } else if (selected == Sleep) { screen->setOn(false); diff --git a/src/input/ButtonThread.cpp b/src/input/ButtonThread.cpp index 233bbefe0..f26b3c970 100644 --- a/src/input/ButtonThread.cpp +++ b/src/input/ButtonThread.cpp @@ -92,8 +92,11 @@ bool ButtonThread::initButton(const ButtonConfig &config) if (config.shortLong != INPUT_BROKER_NONE) { _shortLong = config.shortLong; } - +#ifdef USE_EINK + userButton.setDebounceMs(0); +#else userButton.setDebounceMs(1); +#endif userButton.setPressMs(_longPressTime); if (screen) { diff --git a/src/main.cpp b/src/main.cpp index 9e46021c9..c5be175c4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -304,7 +304,6 @@ void setup() Wire.begin(48, 47); io.pinMode(PCA_PIN_EINK_EN, OUTPUT); io.pinMode(PCA_PIN_POWER_EN, OUTPUT); - io.digitalWrite(PCA_PIN_EINK_EN, HIGH); io.digitalWrite(PCA_PIN_POWER_EN, HIGH); // io.pinMode(C2_PIN, OUTPUT); #endif diff --git a/variants/esp32s3/ELECROW-ThinkNode-M5/variant.h b/variants/esp32s3/ELECROW-ThinkNode-M5/variant.h index 61d6149d2..a55808170 100644 --- a/variants/esp32s3/ELECROW-ThinkNode-M5/variant.h +++ b/variants/esp32s3/ELECROW-ThinkNode-M5/variant.h @@ -61,7 +61,7 @@ #define LORA_DIO1 SX126X_DIO1 #define USE_EINK -#define PIN_EINK_EN -1 // Note: this is really just backlight power +// Note: this is really just backlight power #define PCA_PIN_EINK_EN 5 // This is the pin number on the GPIO expander #define PIN_EINK_CS 39 #define PIN_EINK_BUSY 42 From 0046d957f1ead3cd4da5632d91c6a2a1fafefc6c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 21:42:51 +0200 Subject: [PATCH 03/24] Update protobufs (#7647) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/mesh.pb.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/protobufs b/protobufs index e2c0831aa..5dd723fe6 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit e2c0831aa3d34a58a36c2b9fdcb828e58961cbc5 +Subproject commit 5dd723fe6f33a8613ec81acf5e15be26365c7cce diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 1d1ff47e0..ce3722aa7 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -270,6 +270,8 @@ typedef enum _meshtastic_HardwareModel { /* MeshSolar is an integrated power management and communication solution designed for outdoor low-power devices. https://heltec.org/project/meshsolar/ */ meshtastic_HardwareModel_HELTEC_MESH_SOLAR = 108, + /* Lilygo T-Echo Lite */ + meshtastic_HardwareModel_T_ECHO_LITE = 109, /* ------------------------------------------------------------------------------------------------------------------------------------------ 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 a02017a5c8e2f5506e7222babff855e886ee3c1e Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Fri, 15 Aug 2025 19:45:41 -0500 Subject: [PATCH 04/24] Remove JSON serialization from most NRF52 targets (#7640) * Remove JSON serialization from most NRF52 targets * Slin networking base down for NRF52 by removing syslog * Update platformio.ini --- arch/nrf52/nrf52.ini | 2 +- platformio.ini | 8 ++++++++ variants/nrf52840/rak2560/platformio.ini | 4 ++-- variants/nrf52840/rak4631/platformio.ini | 2 +- variants/nrf52840/rak4631_eth_gw/platformio.ini | 2 +- variants/nrf52840/rak_wismeshtap/platformio.ini | 2 +- 6 files changed, 14 insertions(+), 6 deletions(-) diff --git a/arch/nrf52/nrf52.ini b/arch/nrf52/nrf52.ini index 4a77ec4b2..36effe017 100644 --- a/arch/nrf52/nrf52.ini +++ b/arch/nrf52/nrf52.ini @@ -23,7 +23,7 @@ build_flags = -DMESHTASTIC_EXCLUDE_PAXCOUNTER=1 build_src_filter = - ${arduino_base.build_src_filter} - - - - - - - - - - + ${arduino_base.build_src_filter} - - - - - - - - - - - lib_deps= ${arduino_base.lib_deps} diff --git a/platformio.ini b/platformio.ini index 520ec740e..528563def 100644 --- a/platformio.ini +++ b/platformio.ini @@ -102,6 +102,14 @@ lib_deps = # renovate: datasource=custom.pio depName=Syslog packageName=arcao/library/Syslog arcao/Syslog@2.0.0 +; Minimal networking libs for nrf52 (excludes Syslog to save flash) +[nrf52_networking_base] +lib_deps = + # renovate: datasource=custom.pio depName=TBPubSubClient packageName=thingsboard/library/TBPubSubClient + thingsboard/TBPubSubClient@2.12.1 + # renovate: datasource=custom.pio depName=NTPClient packageName=arduino-libraries/library/NTPClient + arduino-libraries/NTPClient@3.2.1 + [radiolib_base] lib_deps = # renovate: datasource=custom.pio depName=RadioLib packageName=jgromes/library/RadioLib diff --git a/variants/nrf52840/rak2560/platformio.ini b/variants/nrf52840/rak2560/platformio.ini index 2b73aca03..edc648b9b 100644 --- a/variants/nrf52840/rak2560/platformio.ini +++ b/variants/nrf52840/rak2560/platformio.ini @@ -11,10 +11,10 @@ build_flags = ${nrf52840_base.build_flags} -DRADIOLIB_EXCLUDE_SX127X=1 -DRADIOLIB_EXCLUDE_LR11X0=1 -DHAS_RAKPROT=1 ; Define if RAk OneWireSerial is used (disables GPS) -build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak2560> + + +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak2560> + + + lib_deps = ${nrf52840_base.lib_deps} - ${networking_base.lib_deps} + ${nrf52_networking_base.lib_deps} melopero/Melopero RV3028@^1.1.0 https://github.com/beegee-tokyo/RAK-OneWireSerial/archive/0.0.2.zip debug_tool = jlink diff --git a/variants/nrf52840/rak4631/platformio.ini b/variants/nrf52840/rak4631/platformio.ini index 199e17570..83feaa06c 100644 --- a/variants/nrf52840/rak4631/platformio.ini +++ b/variants/nrf52840/rak4631/platformio.ini @@ -17,7 +17,7 @@ build_flags = ${nrf52840_base.build_flags} build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak4631> + + + lib_deps = ${nrf52840_base.lib_deps} - ${networking_base.lib_deps} + ${nrf52_networking_base.lib_deps} melopero/Melopero RV3028@^1.1.0 https://github.com/RAKWireless/RAK13800-W5100S/archive/1.0.2.zip rakwireless/RAKwireless NCP5623 RGB LED library@^1.0.2 diff --git a/variants/nrf52840/rak4631_eth_gw/platformio.ini b/variants/nrf52840/rak4631_eth_gw/platformio.ini index a1c1b4610..79cdb28c7 100644 --- a/variants/nrf52840/rak4631_eth_gw/platformio.ini +++ b/variants/nrf52840/rak4631_eth_gw/platformio.ini @@ -24,7 +24,7 @@ build_flags = ${nrf52840_base.build_flags} -DMESHTASTIC_EXCLUDE_STOREFORWARD=1 -DMESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 -DMESHTASTIC_EXCLUDE_WAYPOINT=1 -build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak4631_eth_gw> + + + +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak4631_eth_gw> + + + + lib_deps = ${nrf52840_base.lib_deps} ${networking_base.lib_deps} diff --git a/variants/nrf52840/rak_wismeshtap/platformio.ini b/variants/nrf52840/rak_wismeshtap/platformio.ini index f6ee8fd23..adf301537 100644 --- a/variants/nrf52840/rak_wismeshtap/platformio.ini +++ b/variants/nrf52840/rak_wismeshtap/platformio.ini @@ -18,7 +18,7 @@ build_flags = ${nrf52840_base.build_flags} build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/rak_wismeshtap> + + + lib_deps = ${nrf52840_base.lib_deps} - ${networking_base.lib_deps} + ${nrf52_networking_base.lib_deps} melopero/Melopero RV3028@^1.1.0 https://github.com/RAKWireless/RAK13800-W5100S/archive/1.0.2.zip rakwireless/RAKwireless NCP5623 RGB LED library@^1.0.2 From 8e552a9f0c0a67b920062123b120b6034c0dfaa4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 16 Aug 2025 05:57:20 -0500 Subject: [PATCH 05/24] Upgrade trunk (#7626) Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com> --- .trunk/trunk.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index f62255aea..10bb1bd00 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -9,9 +9,9 @@ plugins: lint: enabled: - checkov@3.2.461 - - renovate@41.63.0 + - renovate@41.71.1 - prettier@3.6.2 - - trufflehog@3.90.3 + - trufflehog@3.90.4 - yamllint@1.37.1 - bandit@1.8.6 - trivy@0.64.1 From c64c196778038c0888a8e31651cd1957c6134586 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sat, 16 Aug 2025 06:10:44 -0500 Subject: [PATCH 06/24] Wait for lead up before enable longlong action (#7648) --- src/buzz/buzz.cpp | 4 ++++ src/input/ButtonThread.cpp | 9 +++++---- src/input/ButtonThread.h | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/buzz/buzz.cpp b/src/buzz/buzz.cpp index b09d7a82c..b0d162a44 100644 --- a/src/buzz/buzz.cpp +++ b/src/buzz/buzz.cpp @@ -140,6 +140,10 @@ bool playNextLeadUpNote() playTones(¬e, 1); // Play single note using existing playTones function leadUpNoteIndex++; + + if (leadUpNoteIndex >= leadUpNotesCount) { + return false; // this was the final note + } return true; // Note was played (playTones handles buzzer availability internally) } diff --git a/src/input/ButtonThread.cpp b/src/input/ButtonThread.cpp index f26b3c970..32882f7ae 100644 --- a/src/input/ButtonThread.cpp +++ b/src/input/ButtonThread.cpp @@ -140,8 +140,7 @@ int32_t ButtonThread::runOnce() } // Progressive lead-up sound system - if (buttonCurrentlyPressed && (millis() - buttonPressStartTime) >= BUTTON_LEADUP_MS && - (millis() - buttonPressStartTime) < _longLongPressTime) { + if (buttonCurrentlyPressed && (millis() - buttonPressStartTime) >= BUTTON_LEADUP_MS) { // Start the progressive sequence if not already active if (!leadUpSequenceActive) { @@ -153,13 +152,14 @@ int32_t ButtonThread::runOnce() else if ((millis() - lastLeadUpNoteTime) >= 400) { // 400ms interval between notes if (playNextLeadUpNote()) { lastLeadUpNoteTime = millis(); + } else { + leadUpPlayed = true; } } } // Reset when button is released if (!buttonCurrentlyPressed && buttonWasPressed) { - leadUpPlayed = false; leadUpSequenceActive = false; resetLeadUpSequence(); } @@ -256,12 +256,13 @@ int32_t ButtonThread::runOnce() LOG_INFO("LONG PRESS RELEASE AFTER %u MILLIS", millis() - buttonPressStartTime); if (millis() > 30000 && _longLongPress != INPUT_BROKER_NONE && - (millis() - buttonPressStartTime) >= _longLongPressTime) { + (millis() - buttonPressStartTime) >= _longLongPressTime && leadUpPlayed) { evt.inputEvent = _longLongPress; this->notifyObservers(&evt); } // Reset combination tracking waitingForLongPress = false; + leadUpPlayed = false; break; } diff --git a/src/input/ButtonThread.h b/src/input/ButtonThread.h index bbc8da2a7..c6d6557e2 100644 --- a/src/input/ButtonThread.h +++ b/src/input/ButtonThread.h @@ -92,7 +92,7 @@ class ButtonThread : public Observable, public concurrency:: voidFuncPtr _intRoutine = nullptr; uint16_t _longPressTime = 500; - uint16_t _longLongPressTime = 5000; + uint16_t _longLongPressTime = 3900; int _pinNum = 0; bool _activeLow = true; bool _touchQuirk = false; From d538ad170ce1fc3c7203d7c340d1c307ee873f59 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sun, 17 Aug 2025 05:55:00 -0500 Subject: [PATCH 07/24] Add onboard message for devices with screens (#7655) * Add onboard message for devices with screens * Add message for TFT --- src/graphics/Screen.cpp | 2 +- src/graphics/draw/MenuHandler.cpp | 24 ++++++++++++++++++++++ src/graphics/draw/MenuHandler.h | 2 ++ src/graphics/draw/NotificationRenderer.cpp | 7 ++++++- 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 88955145a..fa71e17d8 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -692,7 +692,7 @@ int32_t Screen::runOnce() #ifndef DISABLE_WELCOME_UNSET if (!NotificationRenderer::isOverlayBannerShowing() && config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET) { - menuHandler::LoraRegionPicker(0); + menuHandler::OnboardMessage(); } #endif if (!NotificationRenderer::isOverlayBannerShowing() && rebootAtMsec != 0) { diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index fa738309a..512f650ec 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -26,6 +26,27 @@ menuHandler::screenMenus menuHandler::menuQueue = menu_none; bool test_enabled = false; uint8_t test_count = 0; +void menuHandler::OnboardMessage() +{ + static const char *optionsArray[] = {"OK", "Got it!"}; + enum optionsNumbers { OK, got }; + BannerOverlayOptions bannerOptions; +#if HAS_TFT + bannerOptions.message = "Welcome to Meshtastic!\nSwipe to navigate and\nlong press to select\nor open a menu."; +#elif defined(BUTTON_PIN) + bannerOptions.message = "Welcome to Meshtastic!\nClick to navigate and\nlong press to select\nor open a menu."; +#else + bannerOptions.message = "Welcome to Meshtastic!\nUse the Select button\nto open menus\nand make selections."; +#endif + bannerOptions.optionsArrayPtr = optionsArray; + bannerOptions.optionsCount = 2; + bannerOptions.bannerCallback = [](int selected) -> void { + menuHandler::menuQueue = menuHandler::no_timeout_lora_picker; + screen->runNow(); + }; + screen->showOverlayBanner(bannerOptions); +} + void menuHandler::LoraRegionPicker(uint32_t duration) { static const char *optionsArray[] = {"Back", @@ -1132,6 +1153,9 @@ void menuHandler::handleMenuSwitch(OLEDDisplay *display) case lora_picker: LoraRegionPicker(); break; + case no_timeout_lora_picker: + LoraRegionPicker(0); + break; case TZ_picker: TZPicker(); break; diff --git a/src/graphics/draw/MenuHandler.h b/src/graphics/draw/MenuHandler.h index 87a0b055e..b15cf237d 100644 --- a/src/graphics/draw/MenuHandler.h +++ b/src/graphics/draw/MenuHandler.h @@ -10,6 +10,7 @@ class menuHandler enum screenMenus { menu_none, lora_picker, + no_timeout_lora_picker, TZ_picker, twelve_hour_picker, clock_face_picker, @@ -41,6 +42,7 @@ class menuHandler }; static screenMenus menuQueue; + static void OnboardMessage(); static void LoraRegionPicker(uint32_t duration = 30000); static void handleMenuSwitch(OLEDDisplay *display); static void showConfirmationBanner(const char *message, std::function onConfirm); diff --git a/src/graphics/draw/NotificationRenderer.cpp b/src/graphics/draw/NotificationRenderer.cpp index d9cf280ac..3d635e588 100644 --- a/src/graphics/draw/NotificationRenderer.cpp +++ b/src/graphics/draw/NotificationRenderer.cpp @@ -383,7 +383,9 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp uint8_t firstOptionToShow = 0; if (alertBannerOptions > 0) { - if (curSelected > 1 && alertBannerOptions > visibleTotalLines - lineCount) { + if (visibleTotalLines - lineCount == 1) { + firstOptionToShow = curSelected; + } else if (curSelected > 1 && alertBannerOptions > visibleTotalLines - lineCount) { if (curSelected > alertBannerOptions - visibleTotalLines + lineCount) firstOptionToShow = alertBannerOptions - visibleTotalLines + lineCount; else @@ -392,6 +394,9 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp firstOptionToShow = 0; } } + // Useful log line for troubleshooting: + /* LOG_WARN("alertBannerOptions: %u, curSelected: %u, visibleTotalLines: %u, lineCount: %u, firstOptionToShow: %u", + alertBannerOptions, curSelected, visibleTotalLines, lineCount, firstOptionToShow); */ for (int i = firstOptionToShow; i < alertBannerOptions && linesShown < visibleTotalLines; i++, linesShown++) { if (i == curSelected) { From e5e8683cdba133e726033101586c3235a8678893 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Sun, 17 Aug 2025 05:56:06 -0500 Subject: [PATCH 08/24] Don't update the NodeDB if the nodeinfo has a mismatching public key (#7652) --- src/mesh/NodeDB.cpp | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 79361bb46..97a1e463c 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -1631,24 +1631,33 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde printBytes("Incoming Pubkey: ", p.public_key.bytes, 32); // Alert the user if a remote node is advertising public key that matches our own - if (owner.public_key.size == 32 && memcmp(p.public_key.bytes, owner.public_key.bytes, 32) == 0 && !duplicateWarned) { - duplicateWarned = true; - char warning[] = "Remote device %s has advertised your public key. This may indicate a compromised key. You may need " - "to regenerate your public keys."; - LOG_WARN(warning, p.long_name); - meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); - cn->level = meshtastic_LogRecord_Level_WARNING; - cn->time = getValidTime(RTCQualityFromNet); - sprintf(cn->message, warning, p.long_name); - service->sendClientNotification(cn); + if (owner.public_key.size == 32 && memcmp(p.public_key.bytes, owner.public_key.bytes, 32) == 0) { + if (!duplicateWarned) { + duplicateWarned = true; + char warning[] = + "Remote device %s has advertised your public key. This may indicate a compromised key. You may need " + "to regenerate your public keys."; + LOG_WARN(warning, p.long_name); + meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); + cn->level = meshtastic_LogRecord_Level_WARNING; + cn->time = getValidTime(RTCQualityFromNet); + sprintf(cn->message, warning, p.long_name); + service->sendClientNotification(cn); + } + return false; } } - if (info->user.public_key.size > 0) { // if we have a key for this user already, don't overwrite with a new one + if (info->user.public_key.size == 32) { // if we have a key for this user already, don't overwrite with a new one + // if the key doesn't match, don't update nodeDB at all. + if (p.public_key.size != 32 || (memcmp(p.public_key.bytes, info->user.public_key.bytes, 32) != 0)) { + LOG_WARN("Public Key mismatch, dropping NodeInfo"); + return false; + } LOG_INFO("Public Key set for node, not updating!"); // we copy the key into the incoming packet, to prevent overwrite p.public_key.size = 32; memcpy(p.public_key.bytes, info->user.public_key.bytes, 32); - } else if (p.public_key.size > 0) { + } else if (p.public_key.size == 32) { LOG_INFO("Update Node Pubkey!"); } #endif From 9feb1d378edb2847cc12755beac9aa57a10c571f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20G=C3=B6ttgens?= Date: Sun, 17 Aug 2025 13:37:12 +0200 Subject: [PATCH 09/24] Support for T-Echo Lite, credits to @Szetya for doing all the heavy lifting! (#7636) * Support for T-Echo Lite, credts to @Szetya for doing all the heavy lifting! * move define to ini file --- src/BluetoothStatus.h | 8 + src/graphics/EInkDisplay2.cpp | 4 +- src/main.cpp | 4 + src/modules/SerialModule.cpp | 14 +- src/nimble/NimbleBluetooth.cpp | 5 +- src/platform/nrf52/architecture.h | 2 + variants/nrf52840/t-echo-lite/platformio.ini | 25 +++ variants/nrf52840/t-echo-lite/variant.cpp | 44 ++++ variants/nrf52840/t-echo-lite/variant.h | 207 +++++++++++++++++++ 9 files changed, 303 insertions(+), 10 deletions(-) create mode 100644 variants/nrf52840/t-echo-lite/platformio.ini create mode 100644 variants/nrf52840/t-echo-lite/variant.cpp create mode 100644 variants/nrf52840/t-echo-lite/variant.h diff --git a/src/BluetoothStatus.h b/src/BluetoothStatus.h index f6bb43cc2..680aec929 100644 --- a/src/BluetoothStatus.h +++ b/src/BluetoothStatus.h @@ -89,14 +89,22 @@ class BluetoothStatus : public Status case ConnectionState::CONNECTED: LOG_DEBUG("BluetoothStatus CONNECTED"); #ifdef BLE_LED +#ifdef BLE_LED_INVERTED + digitalWrite(BLE_LED, LOW); +#else digitalWrite(BLE_LED, HIGH); +#endif #endif break; case ConnectionState::DISCONNECTED: LOG_DEBUG("BluetoothStatus DISCONNECTED"); #ifdef BLE_LED +#ifdef BLE_LED_INVERTED + digitalWrite(BLE_LED, HIGH); +#else digitalWrite(BLE_LED, LOW); +#endif #endif break; } diff --git a/src/graphics/EInkDisplay2.cpp b/src/graphics/EInkDisplay2.cpp index a627a42cc..1c9f290b6 100644 --- a/src/graphics/EInkDisplay2.cpp +++ b/src/graphics/EInkDisplay2.cpp @@ -140,13 +140,13 @@ bool EInkDisplay::connect() #endif #endif -#if defined(TTGO_T_ECHO) || defined(ELECROW_ThinkNode_M1) +#if defined(TTGO_T_ECHO) || defined(ELECROW_ThinkNode_M1) || defined(T_ECHO_LITE) { auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, SPI1); adafruitDisplay = new GxEPD2_BW(*lowLevel); adafruitDisplay->init(); -#ifdef ELECROW_ThinkNode_M1 +#if defined(ELECROW_ThinkNode_M1) || defined(T_ECHO_LITE) adafruitDisplay->setRotation(4); #else adafruitDisplay->setRotation(3); diff --git a/src/main.cpp b/src/main.cpp index c5be175c4..c53877e37 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -325,8 +325,12 @@ void setup() #ifdef BLE_LED pinMode(BLE_LED, OUTPUT); +#ifdef BLE_LED_INVERTED + digitalWrite(BLE_LED, HIGH); +#else digitalWrite(BLE_LED, LOW); #endif +#endif #if defined(T_DECK) // GPIO10 manages all peripheral power supplies diff --git a/src/modules/SerialModule.cpp b/src/modules/SerialModule.cpp index 39b297965..866497ecc 100644 --- a/src/modules/SerialModule.cpp +++ b/src/modules/SerialModule.cpp @@ -60,7 +60,7 @@ SerialModule *serialModule; SerialModuleRadio *serialModuleRadio; -#if defined(TTGO_T_ECHO) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1) || \ +#if defined(TTGO_T_ECHO) || defined(T_ECHO_LITE) || defined(CANARYONE) || defined(MESHLINK) || defined(ELECROW_ThinkNode_M1) || \ defined(ELECROW_ThinkNode_M5) SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial") {} static Print *serialPrint = &Serial; @@ -179,8 +179,8 @@ int32_t SerialModule::runOnce() Serial.begin(baud); Serial.setTimeout(moduleConfig.serial.timeout > 0 ? moduleConfig.serial.timeout : TIMEOUT); } -#elif !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && \ - !defined(ELECROW_ThinkNode_M5) +#elif !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \ + !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5) if (moduleConfig.serial.rxd && moduleConfig.serial.txd) { #ifdef ARCH_RP2040 Serial2.setFIFOSize(RX_BUFFER); @@ -236,8 +236,8 @@ int32_t SerialModule::runOnce() } } -#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && \ - !defined(ELECROW_ThinkNode_M5) +#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(MESHLINK) && \ + !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5) else if ((moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85)) { processWXSerial(); @@ -496,8 +496,8 @@ ParsedLine parseLine(const char *line) */ void SerialModule::processWXSerial() { -#if !defined(TTGO_T_ECHO) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(MESHLINK) && \ - !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5) +#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && \ + !defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M5) static unsigned int lastAveraged = 0; static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded. static double dir_sum_sin = 0; diff --git a/src/nimble/NimbleBluetooth.cpp b/src/nimble/NimbleBluetooth.cpp index 834184292..95e191c8e 100644 --- a/src/nimble/NimbleBluetooth.cpp +++ b/src/nimble/NimbleBluetooth.cpp @@ -223,9 +223,12 @@ void NimbleBluetooth::deinit() LOG_INFO("Disable bluetooth until reboot"); #ifdef BLE_LED +#ifdef BLE_LED_INVERTED + digitalWrite(BLE_LED, HIGH); +#else digitalWrite(BLE_LED, LOW); #endif - +#endif NimBLEDevice::deinit(); #endif } diff --git a/src/platform/nrf52/architecture.h b/src/platform/nrf52/architecture.h index ce42bf849..064bd8ef0 100644 --- a/src/platform/nrf52/architecture.h +++ b/src/platform/nrf52/architecture.h @@ -60,6 +60,8 @@ #define HW_VENDOR meshtastic_HardwareModel_RAK4631 #elif defined(TTGO_T_ECHO) #define HW_VENDOR meshtastic_HardwareModel_T_ECHO +#elif defined(T_ECHO_LITE) +#define HW_VENDOR meshtastic_HardwareModel_T_ECHO_LITE #elif defined(ELECROW_ThinkNode_M1) #define HW_VENDOR meshtastic_HardwareModel_THINKNODE_M1 #elif defined(NANO_G2_ULTRA) diff --git a/variants/nrf52840/t-echo-lite/platformio.ini b/variants/nrf52840/t-echo-lite/platformio.ini new file mode 100644 index 000000000..68ae59dcb --- /dev/null +++ b/variants/nrf52840/t-echo-lite/platformio.ini @@ -0,0 +1,25 @@ +; Using original screen class +[env:t-echo-lite] +extends = nrf52840_base +board = t-echo +board_check = true +debug_tool = jlink + +# add -DCFG_SYSVIEW if you want to use the Segger systemview tool for OS profiling. +build_flags = ${nrf52840_base.build_flags} + -Ivariants/nrf52840/t-echo-lite + -D T_ECHO_LITE + -D GPS_POWER_TOGGLE + -D EINK_DISPLAY_MODEL=GxEPD2_122_T61 + -D EINK_WIDTH=192 + -D EINK_HEIGHT=176 + -D USE_EINK + -D USE_EINK_DYNAMICDISPLAY ; Enable Dynamic EInk + -D EINK_LIMIT_FASTREFRESH=20 ; How many consecutive fast-refreshes are permitted + -D EINK_BACKGROUND_USES_FAST ; (Optional) Use FAST refresh for both BACKGROUND and RESPONSIVE, until a limit is reached. + +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/t-echo-lite> +lib_deps = + ${nrf52840_base.lib_deps} + https://github.com/meshtastic/GxEPD2/archive/a05c11c02862624266b61599b0d6ba93e33c6f24.zip +;upload_protocol = fs diff --git a/variants/nrf52840/t-echo-lite/variant.cpp b/variants/nrf52840/t-echo-lite/variant.cpp new file mode 100644 index 000000000..cae079b74 --- /dev/null +++ b/variants/nrf52840/t-echo-lite/variant.cpp @@ -0,0 +1,44 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. All right reserved. + Copyright (c) 2016 Sandeep Mistry All right reserved. + Copyright (c) 2018, Adafruit Industries (adafruit.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "variant.h" +#include "nrf.h" +#include "wiring_constants.h" +#include "wiring_digital.h" + +const uint32_t g_ADigitalPinMap[] = { + // P0 - pins 0 and 1 are hardwired for xtal and should never be enabled + 0xff, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + + // P1 + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}; + +void initVariant() +{ + // LED1 & LED2 + pinMode(PIN_LED1, OUTPUT); + ledOff(PIN_LED1); + + pinMode(PIN_LED2, OUTPUT); + ledOff(PIN_LED2); + + pinMode(PIN_LED3, OUTPUT); + ledOff(PIN_LED3); +} diff --git a/variants/nrf52840/t-echo-lite/variant.h b/variants/nrf52840/t-echo-lite/variant.h new file mode 100644 index 000000000..2e2cdce72 --- /dev/null +++ b/variants/nrf52840/t-echo-lite/variant.h @@ -0,0 +1,207 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. All right reserved. + Copyright (c) 2016 Sandeep Mistry All right reserved. + Copyright (c) 2018, Adafruit Industries (adafruit.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _VARIANT_TTGO_EINK_V1_0_ +#define _VARIANT_TTGO_EINK_V1_0_ + +/** Master clock frequency */ +#define VARIANT_MCK (64000000ul) + +#define USE_LFXO // Board uses 32khz crystal for LF + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "WVariant.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// Number of pins defined in PinDescription array +#define PINS_COUNT (48) +#define NUM_DIGITAL_PINS (48) +#define NUM_ANALOG_INPUTS (1) +#define NUM_ANALOG_OUTPUTS (0) + +// LEDs +#define PIN_LED1 (32 + 7) // Green LED +#define PIN_LED2 (32 + 5) // Blue LED +// Unused(by firmware) LEDs: +#define PIN_LED3 (32 + 14) // Red LED inside, under the display. + +#define LED_RED PIN_LED3 +#define LED_BLUE PIN_LED2 +#define LED_GREEN PIN_LED1 + +#define BLE_LED LED_BLUE +#define BLE_LED_INVERTED 1 +#define LED_BUILTIN LED_GREEN +#define LED_CONN LED_GREEN +#define LED_STATE_ON 0 // State when LED is lit + +// Buttons +#define PIN_BUTTON1 (0 + 24) +#define PIN_BUTTON2 (0 + 18) // 0.18 is labeled on the board as RESET but we configure it in the bootloader as a regular GPIO + +#define BUTTON_CLICK_MS 400 + +// Analog pins +#define PIN_A0 (0 + 2) // Battery ADC + +#define BATTERY_PIN PIN_A0 + +static const uint8_t A0 = PIN_A0; + +#define ADC_RESOLUTION 14 + +#define ADC_CTRL (0 + 31) +#define ADC_CTRL_ENABLED HIGH + +// NFC +#define PIN_NFC1 (9) +#define PIN_NFC2 (10) + +// Wire Interfaces +#define WIRE_INTERFACES_COUNT 1 + +#define PIN_WIRE_SDA (32 + 4) +#define PIN_WIRE_SCL (32 + 2) + +/* + Internal, PCB PAD interrupt PIN. Currently not used. (Not built in my device) +*/ +// #define PIN_IMU_INT (0 + 16) // Interrupt from the IMU, macro name correct?! + +// External serial flash ZD25WQ32CEIGR +// QSPI Pins +#define PIN_QSPI_SCK (0 + 4) +#define PIN_QSPI_CS (0 + 12) +#define PIN_QSPI_IO0 (0 + 6) // MOSI if using two bit interface +#define PIN_QSPI_IO1 (0 + 8) // MISO if using two bit interface +#define PIN_QSPI_IO2 (32 + 9) // WP if using two bit interface (i.e. not used) +#define PIN_QSPI_IO3 (0 + 26) // HOLD if using two bit interface (i.e. not used) + +// On-board QSPI Flash +#define EXTERNAL_FLASH_DEVICES ZD25WQ32CEIGR +#define EXTERNAL_FLASH_USE_QSPI + +// Lora radio + +#define USE_SX1262 +// #define USE_SX1268 // currently only available with XS1262. +#define SX126X_CS (0 + 11) +#define SX126X_DIO1 (32 + 8) +#define SX126X_DIO2 (0 + 5) +#define SX126X_BUSY (0 + 14) +#define SX126X_RESET (0 + 7) +#define SX126X_RXEN (32 + 1) +#define SX126X_TXEN (0 + 27) +// #define TCXO_OPTIONAL +#define SX126X_DIO3_TCXO_VOLTAGE 1.8 + +// eink display pins +#define VEXT_ENABLE (32 + 12) +#define VEXT_ON_VALUE LOW +#define PIN_EINK_CS (0 + 22) +#define PIN_EINK_BUSY (0 + 3) +#define PIN_EINK_DC (0 + 21) +#define PIN_EINK_RES (0 + 28) +#define PIN_EINK_SCLK (0 + 19) +#define PIN_EINK_MOSI (0 + 20) + +// Controls power 3V3 for all peripherals (eink + GPS + LoRa + Sensor) +#define PIN_POWER_EN (0 + 30) // 3V3 POWER Enable + +#define PIN_SPI1_MISO (-1) // The display does not use MISO. +#define PIN_SPI1_MOSI PIN_EINK_MOSI +#define PIN_SPI1_SCK PIN_EINK_SCLK + +// GPS pins +// #define GPS_DEBUG +#define GPS_L76K +#define GPS_BAUDRATE 9600 +#define HAS_GPS 1 +// #define PIN_GPS_REINIT (32 + 5) // An output to reset L76K GPS. As per datasheet, low for > 100ms will reset the L76K + +#define PIN_GPS_STANDBY (32 + 10) // An output to wake GPS, low means allow sleep, high means force wake +// Seems to be missing on this new board +#define PIN_GPS_PPS (0 + 29) // Pulse per second input from the GPS +#define GPS_TX_PIN (32 + 15) // This is for bits going TOWARDS the CPU +#define GPS_RX_PIN (32 + 13) // This is for bits going TOWARDS the GPS + +#define GPS_THREAD_INTERVAL 50 + +#define PIN_SERIAL1_RX GPS_TX_PIN +#define PIN_SERIAL1_TX GPS_RX_PIN + +// SPI Interfaces +#define SPI_INTERFACES_COUNT 2 + +// For LORA, SPI 0 +#define PIN_SPI_MISO (0 + 17) +#define PIN_SPI_MOSI (0 + 15) +#define PIN_SPI_SCK (0 + 13) + +// Battery +// The battery sense is hooked to pin A0 (2) +// it is defined in the analogue pin section of this file +// and has 12 bit resolution +#define BATTERY_SENSE_RESOLUTION_BITS 12 +#define BATTERY_SENSE_RESOLUTION 4096.0 +#undef AREF_VOLTAGE +#define AREF_VOLTAGE 3.0 +#define VBAT_AR_INTERNAL AR_INTERNAL_3_0 +#define ADC_MULTIPLIER (2.0F) + +// #define NO_EXT_GPIO 1 +// PINs back side +// Batt & solar connector left up corner +/* +------------------------------- +| VDDH, VBAT, 0.23, SCL , 1.06 | +| GND , SDA , 0.09, 0.10, 0.25 | +------------------------------- + -------- + | VDDH | + | GND | + | 1.13 | - Wake Up/standby + | 1.15 | - PPS + | 0.29 | - TX + | 1.10 | - RX + | 1.11 | - EN + -------- +------------------------------- +| 3V3 , GND , 0.16, 1.03, G_WU | 0.16 internal solder pad interrupt PIN, +| G_EN, G_RX, G_TX, GND , PPS | +------------------------------- +*/ + +// To debug via the segger JLINK console rather than the CDC-ACM serial device +// #define USE_SEGGER + +#ifdef __cplusplus +} +#endif + +/*---------------------------------------------------------------------------- + * Arduino objects - C++ only + *----------------------------------------------------------------------------*/ + +#endif \ No newline at end of file From 78c5309e9a1195b8b93d49c67c45f65b7e04abab Mon Sep 17 00:00:00 2001 From: Manuel <71137295+mverch67@users.noreply.github.com> Date: Sun, 17 Aug 2025 21:48:24 +0200 Subject: [PATCH 10/24] apply 180 degree hw roration Indicator BaseUI (#7660) --- src/graphics/TFTDisplay.cpp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index 3e9bafc6c..24ea6c47a 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -849,9 +849,29 @@ static LGFX *tft = nullptr; #include #include +class PanelInit_ST7701 : public lgfx::Panel_ST7701 +{ + public: + const uint8_t *getInitCommands(uint8_t listno) const override + { + // 180 degree hw rotation: vertical flip, horizontal flip + static constexpr const uint8_t list1[] = {0x36, 1, 0x10, // MADCTL for vertical flip + 0xFF, 5, 0x77, 0x01, 0x00, 0x00, 0x10, // Command2 BK0 SEL + 0xC7, 1, 0x04, // SDIR: X-direction Control (Horizontal Flip) + 0xFF, 5, 0x77, 0x01, 0x00, 0x00, 0x00, // Command2 BK0 DIS + 0xFF, 0xFF}; + switch (listno) { + case 1: + return list1; + default: + return lgfx::Panel_ST7701::getInitCommands(listno); + } + } +}; + class LGFX : public lgfx::LGFX_Device { - lgfx::Panel_ST7701 _panel_instance; + PanelInit_ST7701 _panel_instance; lgfx::Bus_RGB _bus_instance; lgfx::Light_PWM _light_instance; lgfx::Touch_FT5x06 _touch_instance; @@ -1184,9 +1204,9 @@ bool TFTDisplay::connect() attachInterrupt(digitalPinToInterrupt(SCREEN_TOUCH_INT), rak14014_tpIntHandle, FALLING); #elif defined(T_DECK) || defined(PICOMPUTER_S3) || defined(CHATTER_2) tft->setRotation(1); // T-Deck has the TFT in landscape -#elif defined(T_WATCH_S3) || defined(SENSECAP_INDICATOR) +#elif defined(T_WATCH_S3) tft->setRotation(2); // T-Watch S3 left-handed orientation -#elif ARCH_PORTDUINO +#elif ARCH_PORTDUINO || defined(SENSECAP_INDICATOR) tft->setRotation(0); // use config.yaml to set rotation #else tft->setRotation(3); // Orient horizontal and wide underneath the silkscreen name label From 36e8dc74f45c6da09e9d4c44bd22320867f6f7ed Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 18 Aug 2025 05:52:02 -0500 Subject: [PATCH 11/24] Upgrade trunk (#7665) Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com> --- .trunk/trunk.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 10bb1bd00..de38e3ec0 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -9,9 +9,9 @@ plugins: lint: enabled: - checkov@3.2.461 - - renovate@41.71.1 + - renovate@41.74.0 - prettier@3.6.2 - - trufflehog@3.90.4 + - trufflehog@3.90.5 - yamllint@1.37.1 - bandit@1.8.6 - trivy@0.64.1 From 95200e8f6b532d4498cd8e7738109d7996db54b3 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Mon, 18 Aug 2025 16:33:52 -0500 Subject: [PATCH 12/24] Adds rfswitch on Portduino (#7663) * Initial attempt to get rfswitch working on Portduino * Make portduino_config global --- src/mesh/LR11x0Interface.cpp | 15 ++++----- src/platform/portduino/PortduinoGlue.cpp | 43 ++++++++++++++++++++++++ src/platform/portduino/PortduinoGlue.h | 10 +++++- 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/src/mesh/LR11x0Interface.cpp b/src/mesh/LR11x0Interface.cpp index a20db808e..a0d992c42 100644 --- a/src/mesh/LR11x0Interface.cpp +++ b/src/mesh/LR11x0Interface.cpp @@ -6,6 +6,10 @@ #include "mesh/NodeDB.h" #ifdef LR11X0_DIO_AS_RF_SWITCH #include "rfswitch.h" +#elif ARCH_PORTDUINO +#include "PortduinoGlue.h" +#define rfswitch_dio_pins portduino_config.rfswitch_dio_pins +#define rfswitch_table portduino_config.rfswitch_table #else static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC}; static const Module::RfSwitchMode_t rfswitch_table[] = { @@ -14,10 +18,6 @@ static const Module::RfSwitchMode_t rfswitch_table[] = { }; #endif -#ifdef ARCH_PORTDUINO -#include "PortduinoGlue.h" -#endif - // Particular boards might define a different max power based on what their hardware can do, default to max power output if not // specified (may be dangerous if using external PA and LR11x0 power config forgotten) #if ARCH_PORTDUINO @@ -117,17 +117,14 @@ template bool LR11x0Interface::init() #ifdef LR11X0_DIO_AS_RF_SWITCH bool dioAsRfSwitch = true; #elif defined(ARCH_PORTDUINO) - bool dioAsRfSwitch = false; - if (settingsMap[dio2_as_rf_switch]) { - dioAsRfSwitch = true; - } + bool dioAsRfSwitch = portduino_config.has_rfswitch_table; #else bool dioAsRfSwitch = false; #endif if (dioAsRfSwitch) { lora.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table); - LOG_DEBUG("Set DIO RF switch", res); + LOG_DEBUG("Set DIO RF switch"); } if (res == RADIOLIB_ERR_NONE) { diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index 5f99ec2c3..ac4e79af1 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -29,6 +29,7 @@ std::map settingsMap; std::map settingsStrings; +portduino_config_struct portduino_config; std::ofstream traceFile; Ch341Hal *ch341Hal = nullptr; char *configPath = nullptr; @@ -553,6 +554,48 @@ bool loadConfig(const char *configPath) } } } + if (yamlConfig["Lora"]["rfswitch_table"]) { + portduino_config.has_rfswitch_table = true; + portduino_config.rfswitch_table[0].mode = LR11x0::MODE_STBY; + portduino_config.rfswitch_table[1].mode = LR11x0::MODE_RX; + portduino_config.rfswitch_table[2].mode = LR11x0::MODE_TX; + portduino_config.rfswitch_table[3].mode = LR11x0::MODE_TX_HP; + portduino_config.rfswitch_table[4].mode = LR11x0::MODE_TX_HF; + portduino_config.rfswitch_table[5].mode = LR11x0::MODE_GNSS; + portduino_config.rfswitch_table[6].mode = LR11x0::MODE_WIFI; + portduino_config.rfswitch_table[7] = END_OF_MODE_TABLE; + + for (int i = 0; i < 5; i++) { + + // set up the pin array first + if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as("") == "DIO5") + portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO5; + if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as("") == "DIO6") + portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO6; + if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as("") == "DIO7") + portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO7; + if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as("") == "DIO8") + portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO8; + if (yamlConfig["Lora"]["rfswitch_table"]["pins"][i].as("") == "DIO10") + portduino_config.rfswitch_dio_pins[i] = RADIOLIB_LR11X0_DIO10; + + // now fill in the table + if (yamlConfig["Lora"]["rfswitch_table"]["MODE_STBY"][i].as("") == "HIGH") + portduino_config.rfswitch_table[0].values[i] = HIGH; + if (yamlConfig["Lora"]["rfswitch_table"]["MODE_RX"][i].as("") == "HIGH") + portduino_config.rfswitch_table[1].values[i] = HIGH; + if (yamlConfig["Lora"]["rfswitch_table"]["MODE_TX"][i].as("") == "HIGH") + portduino_config.rfswitch_table[2].values[i] = HIGH; + if (yamlConfig["Lora"]["rfswitch_table"]["MODE_TX_HP"][i].as("") == "HIGH") + portduino_config.rfswitch_table[3].values[i] = HIGH; + if (yamlConfig["Lora"]["rfswitch_table"]["MODE_TX_HF"][i].as("") == "HIGH") + portduino_config.rfswitch_table[4].values[i] = HIGH; + if (yamlConfig["Lora"]["rfswitch_table"]["MODE_GNSS"][i].as("") == "HIGH") + portduino_config.rfswitch_table[5].values[i] = HIGH; + if (yamlConfig["Lora"]["rfswitch_table"]["MODE_WIFI"][i].as("") == "HIGH") + portduino_config.rfswitch_table[6].values[i] = HIGH; + } + } } if (yamlConfig["GPIO"]) { settingsMap[userButtonPin] = yamlConfig["GPIO"]["User"].as(RADIOLIB_NC); diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index 288870eef..64277322a 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -3,6 +3,8 @@ #include #include +#include "LR11x0Interface.h" +#include "Module.h" #include "platform/portduino/USBHal.h" // Product strings for auto-configuration @@ -126,4 +128,10 @@ bool loadConfig(const char *configPath); static bool ends_with(std::string_view str, std::string_view suffix); void getMacAddr(uint8_t *dmac); bool MAC_from_string(std::string mac_str, uint8_t *dmac); -std::string exec(const char *cmd); \ No newline at end of file +std::string exec(const char *cmd); + +extern struct portduino_config_struct { + bool has_rfswitch_table = false; + uint32_t rfswitch_dio_pins[5] = {RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC}; + Module::RfSwitchMode_t rfswitch_table[8]; +} portduino_config; \ No newline at end of file From f65e2c639ea87acd2d5d871508932e6d1cde76b5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 19 Aug 2025 05:35:25 -0500 Subject: [PATCH 13/24] Update protobufs (#7679) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/telemetry.pb.h | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/protobufs b/protobufs index 5dd723fe6..be5137698 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 5dd723fe6f33a8613ec81acf5e15be26365c7cce +Subproject commit be5137698027f9e9fe6e68d5d5d638049f61ba8f diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index f758995c2..9af095e78 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -99,7 +99,9 @@ typedef enum _meshtastic_TelemetrySensorType { /* Sensirion SFA30 Formaldehyde sensor */ meshtastic_TelemetrySensorType_SFA30 = 42, /* SEN5X PM SENSORS */ - meshtastic_TelemetrySensorType_SEN5X = 43 + meshtastic_TelemetrySensorType_SEN5X = 43, + /* TSL2561 light sensor */ + meshtastic_TelemetrySensorType_TSL2561 = 44 } meshtastic_TelemetrySensorType; /* Struct definitions */ @@ -434,8 +436,8 @@ extern "C" { /* Helper constants for enums */ #define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET -#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SEN5X -#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SEN5X+1)) +#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_TSL2561 +#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_TSL2561+1)) From 2d7818797db11663eaa4428ba8806977f87ccbd1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 Aug 2025 05:43:10 -0500 Subject: [PATCH 14/24] Update platform-native digest to cd32f4e (#7662) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- 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 ae68159eb..33a4c4d05 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -2,7 +2,7 @@ [portduino_base] platform = # renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop - https://github.com/meshtastic/platform-native/archive/6cb7a455b440dd0738e8ed74a18136ed5cf7ea63.zip + https://github.com/meshtastic/platform-native/archive/cd32f4ed20812d1fe9c8f74c0b6e80dc93dfce54.zip framework = arduino build_src_filter = From 1691e885f21d69382c9f4e8381e38b8af84e1a40 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Tue, 19 Aug 2025 06:00:29 -0500 Subject: [PATCH 15/24] Display test results --- .github/workflows/pr_tests.yml | 244 +++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 .github/workflows/pr_tests.yml diff --git a/.github/workflows/pr_tests.yml b/.github/workflows/pr_tests.yml new file mode 100644 index 000000000..f6a678a45 --- /dev/null +++ b/.github/workflows/pr_tests.yml @@ -0,0 +1,244 @@ +name: Tests + +on: + pull_request: + branches: [master, develop] + paths-ignore: + - "**.md" + - "docs/**" + - "images/**" + pull_request_target: + branches: [master, develop] + paths-ignore: + - "**.md" + - "docs/**" + - "images/**" + +concurrency: + group: tests-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read + actions: read + checks: write + pull-requests: write + +jobs: + native-tests: + name: "πŸ§ͺ Native Tests" + if: github.repository == 'meshtastic/firmware' + uses: ./.github/workflows/test_native.yml + permissions: + contents: read + actions: read + checks: write + + test-summary: + name: "πŸ“Š Test Results" + runs-on: ubuntu-latest + needs: [native-tests] + if: always() + permissions: + contents: read + actions: read + checks: write + pull-requests: write + steps: + - uses: actions/checkout@v5 + with: + ref: ${{github.event.pull_request.head.ref}} + repository: ${{github.event.pull_request.head.repo.full_name}} + + - name: Get release version string + run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT + id: version + + - name: Download test artifacts + if: needs.native-tests.result != 'skipped' + uses: actions/download-artifact@v5 + with: + name: platformio-test-report-${{ steps.version.outputs.long }}.zip + merge-multiple: true + + - name: Parse test results and create detailed summary + id: test-results + run: | + echo "## πŸ§ͺ Test Results Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Check overall job status first + if [[ "${{ needs.native-tests.result }}" == "success" ]]; then + echo "βœ… **Overall Status**: PASSED" >> $GITHUB_STEP_SUMMARY + elif [[ "${{ needs.native-tests.result }}" == "failure" ]]; then + echo "❌ **Overall Status**: FAILED" >> $GITHUB_STEP_SUMMARY + elif [[ "${{ needs.native-tests.result }}" == "cancelled" ]]; then + echo "⏸️ **Overall Status**: CANCELLED" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Tests were cancelled before completion." >> $GITHUB_STEP_SUMMARY + exit 0 + else + echo "⚠️ **Overall Status**: SKIPPED" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Tests were skipped." >> $GITHUB_STEP_SUMMARY + exit 0 + fi + + echo "" >> $GITHUB_STEP_SUMMARY + + # Parse detailed test results if available + if [ -f "testreport.xml" ]; then + echo "### πŸ” Individual Test Results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + python3 << 'EOF' + import xml.etree.ElementTree as ET + import os + + try: + tree = ET.parse('testreport.xml') + root = tree.getroot() + + total_tests = 0 + passed_tests = 0 + failed_tests = 0 + skipped_tests = 0 + + # Parse testsuite elements + for testsuite in root.findall('.//testsuite'): + suite_name = testsuite.get('name', 'Unknown') + suite_tests = int(testsuite.get('tests', '0')) + suite_failures = int(testsuite.get('failures', '0')) + suite_errors = int(testsuite.get('errors', '0')) + suite_skipped = int(testsuite.get('skipped', '0')) + + total_tests += suite_tests + failed_tests += suite_failures + suite_errors + skipped_tests += suite_skipped + passed_tests += suite_tests - suite_failures - suite_errors - suite_skipped + + if suite_tests > 0: + status = "βœ…" if (suite_failures + suite_errors) == 0 else "❌" + print(f"**{status} Test Suite: {suite_name}**") + print(f"- Total: {suite_tests}") + print(f"- Passed: βœ… {suite_tests - suite_failures - suite_errors - suite_skipped}") + print(f"- Failed: ❌ {suite_failures + suite_errors}") + if suite_skipped > 0: + print(f"- Skipped: ⏭️ {suite_skipped}") + print("") + + # Show individual test results for failed suites + if suite_failures + suite_errors > 0: + print("**Failed Tests:**") + for testcase in testsuite.findall('testcase'): + test_name = testcase.get('name', 'Unknown') + failure = testcase.find('failure') + error = testcase.find('error') + + if failure is not None: + msg = failure.get('message', 'Unknown error')[:100] + print(f"- ❌ `{test_name}`: {msg}") + elif error is not None: + msg = error.get('message', 'Unknown error')[:100] + print(f"- ❌ `{test_name}`: ERROR - {msg}") + print("") + else: + # Show passed tests for successful suites + passed_count = 0 + for testcase in testsuite.findall('testcase'): + if testcase.find('failure') is None and testcase.find('error') is None: + if passed_count < 5: # Limit to first 5 to avoid spam + test_name = testcase.get('name', 'Unknown') + print(f"- βœ… `{test_name}`: PASSED") + passed_count += 1 + if passed_count > 5: + print(f"- ... and {passed_count - 5} more tests passed") + print("") + + # Summary statistics + print("### πŸ“Š Test Statistics") + print(f"- **Total Tests**: {total_tests}") + print(f"- **Passed**: βœ… {passed_tests}") + print(f"- **Failed**: ❌ {failed_tests}") + if skipped_tests > 0: + print(f"- **Skipped**: ⏭️ {skipped_tests}") + + if failed_tests > 0: + print(f"\n❌ **{failed_tests} tests failed out of {total_tests} total**") + else: + print(f"\nβœ… **All {total_tests} tests passed!**") + + except Exception as e: + print(f"❌ Error parsing test results: {e}") + EOF + else + echo "⚠️ **No detailed test report available**" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Test artifacts may not have been generated properly." >> $GITHUB_STEP_SUMMARY + fi + + echo "" >> $GITHUB_STEP_SUMMARY + echo "---" >> $GITHUB_STEP_SUMMARY + echo "View detailed logs in the [Actions tab](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY + + - name: Comment test results on PR + if: github.event_name == 'pull_request' && needs.native-tests.result != 'skipped' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + + // Read the step summary to use as PR comment + let testSummary = "## πŸ§ͺ Test Results Summary\n\n"; + + if ("${{ needs.native-tests.result }}" === "success") { + testSummary += "βœ… **All tests passed!**\n\n"; + } else if ("${{ needs.native-tests.result }}" === "failure") { + testSummary += "❌ **Some tests failed.**\n\n"; + } else { + testSummary += "⚠️ **Tests did not complete normally.**\n\n"; + } + + testSummary += `View detailed results: [Actions Run](${context.payload.repository.html_url}/actions/runs/${context.runId})\n\n`; + testSummary += "---\n"; + testSummary += "*This comment will be automatically updated when new commits are pushed.*"; + + // Find existing comment + const comments = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number + }); + + const botComment = comments.data.find(comment => + comment.user.type === 'Bot' && + comment.body.includes('πŸ§ͺ Test Results Summary') + ); + + if (botComment) { + // Update existing comment + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + body: testSummary + }); + } else { + // Create new comment + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: testSummary + }); + } + + - name: Set overall status + run: | + if [[ "${{ needs.native-tests.result }}" == "success" ]]; then + echo "All tests passed! βœ…" + exit 0 + else + echo "Some tests failed! ❌" + exit 1 + fi From e55084629aac7b297efa2c24112ff92690d71e61 Mon Sep 17 00:00:00 2001 From: jake-b <1012393+jake-b@users.noreply.github.com> Date: Tue, 19 Aug 2025 09:10:53 -0400 Subject: [PATCH 16/24] Move heartbeat response before !available guard. (#7672) * Move heartbeat response before !available guard. * fix formatting. --------- Co-authored-by: Jake-B Co-authored-by: Ben Meadors --- src/mesh/PhoneAPI.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index 305689fff..a3a8a2087 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -192,12 +192,6 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength) size_t PhoneAPI::getFromRadio(uint8_t *buf) { - if (!available()) { - return 0; - } - // In case we send a FromRadio packet - memset(&fromRadioScratch, 0, sizeof(fromRadioScratch)); - // Respond to heartbeat by sending queue status if (heartbeatReceived) { memset(&fromRadioScratch, 0, sizeof(fromRadioScratch)); @@ -209,6 +203,12 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) return numbytes; } + if (!available()) { + return 0; + } + // In case we send a FromRadio packet + memset(&fromRadioScratch, 0, sizeof(fromRadioScratch)); + // Advance states as needed switch (state) { case STATE_SEND_NOTHING: From 5b62bbe8e6e19643a91fee0c43b320f7a48aa580 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Tue, 19 Aug 2025 11:30:19 -0500 Subject: [PATCH 17/24] Disable for now --- .github/workflows/pr_tests.yml | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/.github/workflows/pr_tests.yml b/.github/workflows/pr_tests.yml index f6a678a45..786feeced 100644 --- a/.github/workflows/pr_tests.yml +++ b/.github/workflows/pr_tests.yml @@ -1,18 +1,13 @@ name: Tests +# DISABLED: Changed from automatic PR triggers to manual only on: - pull_request: - branches: [master, develop] - paths-ignore: - - "**.md" - - "docs/**" - - "images/**" - pull_request_target: - branches: [master, develop] - paths-ignore: - - "**.md" - - "docs/**" - - "images/**" + workflow_dispatch: + inputs: + reason: + description: "Reason for manual test run" + required: false + default: "Manual test execution" concurrency: group: tests-${{ github.head_ref || github.run_id }} @@ -47,8 +42,7 @@ jobs: steps: - uses: actions/checkout@v5 with: - ref: ${{github.event.pull_request.head.ref}} - repository: ${{github.event.pull_request.head.repo.full_name}} + submodules: recursive - name: Get release version string run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT From 68726a1b0e184432f4bbf56a0e2f61c11592a7f1 Mon Sep 17 00:00:00 2001 From: Austin Date: Tue, 19 Aug 2025 15:06:43 -0400 Subject: [PATCH 18/24] Docker: fix web assets location (#7683) --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6a2ddeece..b1e151ac7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -61,7 +61,7 @@ RUN apt-get update && apt-get --no-install-recommends -y install \ # Fetch compiled binary from the builder COPY --from=builder /tmp/firmware/release/meshtasticd /usr/bin/ -COPY --from=builder /tmp/web /usr/share/meshtasticd/ +COPY --from=builder /tmp/web /usr/share/meshtasticd/web/ # Copy config templates COPY ./bin/config.d /etc/meshtasticd/available.d From 9654f5b21867d2f911b264006e1bc36ee39ac34a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 Aug 2025 14:13:25 -0500 Subject: [PATCH 19/24] Update platform-native digest to 37d9864 (#7684) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- 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 33a4c4d05..20b3f8e3d 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -2,7 +2,7 @@ [portduino_base] platform = # renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop - https://github.com/meshtastic/platform-native/archive/cd32f4ed20812d1fe9c8f74c0b6e80dc93dfce54.zip + https://github.com/meshtastic/platform-native/archive/37d986499ce24511952d7146db72d667c6bdaff7.zip framework = arduino build_src_filter = From eb6ef1cbea08bab0619a001a9d3c95a9887a5069 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 Aug 2025 14:13:53 -0500 Subject: [PATCH 20/24] Update meshtastic-esp8266-oled-ssd1306 digest to 9573abb (#7686) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 528563def..3d1360cc4 100644 --- a/platformio.ini +++ b/platformio.ini @@ -60,7 +60,7 @@ monitor_speed = 115200 monitor_filters = direct lib_deps = # renovate: datasource=git-refs depName=meshtastic-esp8266-oled-ssd1306 packageName=https://github.com/meshtastic/esp8266-oled-ssd1306 gitBranch=master - https://github.com/meshtastic/esp8266-oled-ssd1306/archive/0119501e9983bd894830b02f545c377ee08d66fe.zip + https://github.com/meshtastic/esp8266-oled-ssd1306/archive/9573abb64dc9c94f3051348f2bf4fc5cedf03c22.zip # renovate: datasource=git-refs depName=meshtastic-OneButton packageName=https://github.com/meshtastic/OneButton gitBranch=master https://github.com/meshtastic/OneButton/archive/fa352d668c53f290cfa480a5f79ad422cd828c70.zip # renovate: datasource=git-refs depName=meshtastic-arduino-fsm packageName=https://github.com/meshtastic/arduino-fsm gitBranch=master From 1c1462e7766a5b0658ad3226dc52218fcb7d50a7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 Aug 2025 14:14:12 -0500 Subject: [PATCH 21/24] Update meshtastic/device-ui digest to 8f5094b (#7633) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 3d1360cc4..ac30eb32e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -118,7 +118,7 @@ lib_deps = [device-ui_base] lib_deps = # renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master - https://github.com/meshtastic/device-ui/archive/0cd108ff783539e41ef38258ba2784ab3b1bdc97.zip + https://github.com/meshtastic/device-ui/archive/8f5094b248c15ea2f9acf19cedfef6d2248fc1ff.zip ; Common libs for environmental measurements in telemetry module [environmental_base] From 5de61b1a3ddfd3a177fb7bcbf48c2f51f9080309 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Tue, 19 Aug 2025 14:15:05 -0500 Subject: [PATCH 22/24] Only gate PKC behind the simradio CLI flag (#7681) * Only gate PKC behind the simradio CLI flag * Hide router.cpp simradio check behind #if ARCH_PORTDUINO --- src/mesh/Router.cpp | 6 ++++-- src/platform/portduino/PortduinoGlue.cpp | 5 ++--- src/platform/portduino/PortduinoGlue.h | 1 + 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index a54dcb976..cceacfe9e 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -523,8 +523,10 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p) // is not in the local nodedb // First, only PKC encrypt packets we are originating if (isFromUs(p) && - // Don't use PKC with simulator - radioType != SIM_RADIO && +#if ARCH_PORTDUINO + // Sim radio via the cli flag skips PKC + !portduino_config.force_simradio && +#endif // Don't use PKC with Ham mode !owner.is_licensed && // Don't use PKC if it's not explicitly requested and a non-primary channel is requested diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index ac4e79af1..3753c944c 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -34,7 +34,6 @@ std::ofstream traceFile; Ch341Hal *ch341Hal = nullptr; char *configPath = nullptr; char *optionMac = nullptr; -bool forceSimulated = false; bool verboseEnabled = false; const char *argp_program_version = optstr(APP_VERSION); @@ -67,7 +66,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) configPath = arg; break; case 's': - forceSimulated = true; + portduino_config.force_simradio = true; break; case 'h': optionMac = arg; @@ -190,7 +189,7 @@ void portduinoSetup() YAML::Node yamlConfig; - if (forceSimulated == true) { + if (portduino_config.force_simradio == true) { settingsMap[use_simradio] = true; } else if (configPath != nullptr) { if (loadConfig(configPath)) { diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index 64277322a..6e450c90e 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -134,4 +134,5 @@ extern struct portduino_config_struct { bool has_rfswitch_table = false; uint32_t rfswitch_dio_pins[5] = {RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC}; Module::RfSwitchMode_t rfswitch_table[8]; + bool force_simradio = false; } portduino_config; \ No newline at end of file From c19f573b49f6c2d75f3a33a66efbee0fee983836 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Tue, 19 Aug 2025 20:10:47 -0500 Subject: [PATCH 23/24] Fix TLS port bug on default mqtt validation --- src/mqtt/MQTT.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index d94aeff95..7f7a9d511 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -279,6 +279,8 @@ struct PubSubConfig { // Defaults static constexpr uint16_t defaultPort = 1883; + static constexpr uint16_t defaultPortTls = 8883; + uint16_t serverPort = defaultPort; String serverAddr = default_mqtt_address; const char *mqttUsername = default_mqtt_username; @@ -641,7 +643,7 @@ bool MQTT::isValidConfig(const meshtastic_ModuleConfig_MQTTConfig &config, MQTTC } const bool defaultServer = isDefaultServer(parsed.serverAddr); - if (defaultServer && parsed.serverPort != PubSubConfig::defaultPort) { + if (defaultServer && !IS_ONE_OF(parsed.serverPort, PubSubConfig::defaultPort, PubSubConfig::defaultPortTls)) { const char *warning = "Invalid MQTT config: default server address must not have a port specified"; LOG_ERROR(warning); #if !IS_RUNNING_TESTS From f413c49555fdf95730b265072a819ba78e637f23 Mon Sep 17 00:00:00 2001 From: Wilson Date: Wed, 20 Aug 2025 11:52:10 +0800 Subject: [PATCH 24/24] Add Meshtiny device (#7676) * Add Meshtiny device - nRF52 OLED upDown encoder * Update platformio.ini * Update platformio.ini * Add GPS Exclude to Meshtiny. --------- Co-authored-by: Ben Meadors --- boards/meshtiny.json | 52 ++++++ variants/nrf52840/meshtiny/platformio.ini | 19 +++ variants/nrf52840/meshtiny/variant.cpp | 54 ++++++ variants/nrf52840/meshtiny/variant.h | 199 ++++++++++++++++++++++ 4 files changed, 324 insertions(+) create mode 100644 boards/meshtiny.json create mode 100644 variants/nrf52840/meshtiny/platformio.ini create mode 100644 variants/nrf52840/meshtiny/variant.cpp create mode 100644 variants/nrf52840/meshtiny/variant.h diff --git a/boards/meshtiny.json b/boards/meshtiny.json new file mode 100644 index 000000000..1473388ea --- /dev/null +++ b/boards/meshtiny.json @@ -0,0 +1,52 @@ +{ + "build": { + "arduino": { + "ldscript": "nrf52840_s140_v6.ld" + }, + "core": "nRF5", + "cpu": "cortex-m4", + "extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA", + "f_cpu": "64000000L", + "hwids": [ + ["0x239A", "0x8029"], + ["0x239A", "0x0029"], + ["0x239A", "0x002A"], + ["0x239A", "0x802A"] + ], + "usb_product": "MeshTiny", + "mcu": "nrf52840", + "variant": "meshtiny", + "bsp": { + "name": "adafruit" + }, + "softdevice": { + "sd_flags": "-DS140", + "sd_name": "s140", + "sd_version": "6.1.1", + "sd_fwid": "0x00B6" + }, + "bootloader": { + "settings_addr": "0xFF000" + } + }, + "connectivity": ["bluetooth"], + "debug": { + "jlink_device": "nRF52840_xxAA", + "svd_path": "nrf52840.svd", + "openocd_target": "nrf52840-mdk-rs" + }, + "frameworks": ["arduino", "freertos"], + "name": "MeshTiny", + "upload": { + "maximum_ram_size": 248832, + "maximum_size": 815104, + "speed": 115200, + "protocol": "nrfutil", + "protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"], + "use_1200bps_touch": true, + "require_upload_port": true, + "wait_for_upload_port": true + }, + "url": "https://github.com/meshtastic/firmware", + "vendor": "MTools Tec" +} diff --git a/variants/nrf52840/meshtiny/platformio.ini b/variants/nrf52840/meshtiny/platformio.ini new file mode 100644 index 000000000..ef744a1c3 --- /dev/null +++ b/variants/nrf52840/meshtiny/platformio.ini @@ -0,0 +1,19 @@ +; MeshTiny - Custom device based on GAT562 with encoder and buzzer support +[env:meshtiny] +extends = nrf52840_base +board = meshtiny +board_level = extra +build_flags = ${nrf52840_base.build_flags} -Ivariants/nrf52840/meshtiny -D MESHTINY + -DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. + -DRADIOLIB_EXCLUDE_SX128X=1 + -DRADIOLIB_EXCLUDE_SX127X=1 + -DRADIOLIB_EXCLUDE_LR11X0=1 + -D INPUTDRIVER_ENCODER_TYPE=2 + -D INPUTDRIVER_ENCODER_UP=4 + -D INPUTDRIVER_ENCODER_DOWN=26 + -D INPUTDRIVER_ENCODER_BTN=28 + -D USE_PIN_BUZZER=PIN_BUZZER + -D MESHTASTIC_EXCLUDE_GPS=1 +build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/meshtiny> +lib_deps = + ${nrf52840_base.lib_deps} diff --git a/variants/nrf52840/meshtiny/variant.cpp b/variants/nrf52840/meshtiny/variant.cpp new file mode 100644 index 000000000..2e8b00e4b --- /dev/null +++ b/variants/nrf52840/meshtiny/variant.cpp @@ -0,0 +1,54 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. All right reserved. + Copyright (c) 2016 Sandeep Mistry All right reserved. + Copyright (c) 2018, Adafruit Industries (adafruit.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "variant.h" +#include "nrf.h" +#include "wiring_constants.h" +#include "wiring_digital.h" + +const uint32_t g_ADigitalPinMap[] = { + // P0 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + + // P1 + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47}; + +void initVariant() +{ + // LED1 & LED2 + pinMode(PIN_LED1, OUTPUT); + ledOff(PIN_LED1); + + pinMode(PIN_LED2, OUTPUT); + ledOff(PIN_LED2); + + // 3V3 Power Rail + pinMode(PIN_3V3_EN, OUTPUT); + digitalWrite(PIN_3V3_EN, HIGH); + + // Initialize Encoder pins + pinMode(INPUTDRIVER_ENCODER_UP, INPUT_PULLUP); + pinMode(INPUTDRIVER_ENCODER_DOWN, INPUT_PULLUP); + pinMode(INPUTDRIVER_ENCODER_BTN, INPUT_PULLUP); + + // Initialize Buzzer pin + pinMode(PIN_BUZZER, OUTPUT); + digitalWrite(PIN_BUZZER, LOW); +} diff --git a/variants/nrf52840/meshtiny/variant.h b/variants/nrf52840/meshtiny/variant.h new file mode 100644 index 000000000..83ad4c5b9 --- /dev/null +++ b/variants/nrf52840/meshtiny/variant.h @@ -0,0 +1,199 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. All right reserved. + Copyright (c) 2016 Sandeep Mistry All right reserved. + Copyright (c) 2018, Adafruit Industries (adafruit.com) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _VARIANT_MESHTINY_ +#define _VARIANT_MESHTINY_ + +#define MESHTINY + +// #define RAK4630 + +/** Master clock frequency */ +#define VARIANT_MCK (64000000ul) + +#define USE_LFXO // Board uses 32khz crystal for LF +// define USE_LFRC // Board uses RC for LF + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "WVariant.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// Number of pins defined in PinDescription array +#define PINS_COUNT (48) +#define NUM_DIGITAL_PINS (48) +#define NUM_ANALOG_INPUTS (6) +#define NUM_ANALOG_OUTPUTS (0) + +// LEDs +#define PIN_LED1 (35) +#define PIN_LED2 (36) + +#define LED_BUILTIN PIN_LED1 +#define LED_CONN PIN_LED2 + +#define LED_GREEN PIN_LED1 +#define LED_BLUE PIN_LED2 + +#define LED_STATE_ON 1 // State when LED is litted + +/* + * Encoder + */ +#define INPUTDRIVER_ENCODER_TYPE 2 +#define INPUTDRIVER_ENCODER_UP 26 +#define INPUTDRIVER_ENCODER_DOWN 4 +#define INPUTDRIVER_ENCODER_BTN 28 + +#define CANNED_MESSAGE_MODULE_ENABLE 1 + +/* + * Buzzer - PWM + */ +#define PIN_BUZZER 30 + +/* + * Buttons + */ + +#define PIN_BUTTON1 9 +#define BUTTON_NEED_PULLUP +#define PIN_BUTTON2 12 +#define PIN_BUTTON3 24 +#define PIN_BUTTON4 25 + +/* + * Analog pins + */ +#define PIN_A0 (5) +#define PIN_A1 (31) +#define PIN_A2 (28) +#define PIN_A3 (29) +#define PIN_A4 (30) +#define PIN_A5 (31) +#define PIN_A6 (0xff) +#define PIN_A7 (0xff) + +static const uint8_t A0 = PIN_A0; +static const uint8_t A1 = PIN_A1; +static const uint8_t A2 = PIN_A2; +static const uint8_t A3 = PIN_A3; +static const uint8_t A4 = PIN_A4; +static const uint8_t A5 = PIN_A5; +static const uint8_t A6 = PIN_A6; +static const uint8_t A7 = PIN_A7; +#define ADC_RESOLUTION 14 + +// Other pins +#define PIN_AREF (2) +#define PIN_NFC1 (9) +#define PIN_NFC2 (10) + +static const uint8_t AREF = PIN_AREF; + +/* + * Serial interfaces + */ +#define PIN_SERIAL1_RX (15) +#define PIN_SERIAL1_TX (16) + +// Connected to Jlink CDC +#define PIN_SERIAL2_RX (8) +#define PIN_SERIAL2_TX (6) + +/* + * SPI Interfaces + */ +#define SPI_INTERFACES_COUNT 2 + +#define PIN_SPI_MISO (45) +#define PIN_SPI_MOSI (44) +#define PIN_SPI_SCK (43) + +#define PIN_SPI1_MISO (29) // (0 + 29) +#define PIN_SPI1_MOSI (30) // (0 + 30) +#define PIN_SPI1_SCK (3) // (0 + 3) + +static const uint8_t SS = 42; +static const uint8_t MOSI = PIN_SPI_MOSI; +static const uint8_t MISO = PIN_SPI_MISO; +static const uint8_t SCK = PIN_SPI_SCK; + +#define HAS_SCREEN 1 +#define USE_SSD1306 + +/* + * Wire Interfaces + */ +#define WIRE_INTERFACES_COUNT 1 + +#define PIN_WIRE_SDA (13) +#define PIN_WIRE_SCL (14) + +// QSPI Pins +#define PIN_QSPI_SCK 3 +#define PIN_QSPI_CS 22 // Changed from 26 to avoid conflict with encoder +#define PIN_QSPI_IO0 27 // Changed from 30 to avoid conflict with buzzer +#define PIN_QSPI_IO1 29 +#define PIN_QSPI_IO2 21 // Changed from 28 to avoid conflict with encoder button +#define PIN_QSPI_IO3 2 + +// On-board QSPI Flash +#define EXTERNAL_FLASH_DEVICES IS25LP080D +#define EXTERNAL_FLASH_USE_QSPI + +#define USE_SX1262 +#define SX126X_CS (42) +#define SX126X_DIO1 (47) +#define SX126X_BUSY (46) +#define SX126X_RESET (38) +#define SX126X_POWER_EN (37) +// 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 + +// Testing USB detection +#define NRF_APM + +#define PIN_3V3_EN (34) + +// Battery +// The battery sense is hooked to pin A0 (5) +#define BATTERY_PIN PIN_A0 +// and has 12 bit resolution +#define BATTERY_SENSE_RESOLUTION_BITS 12 +#define BATTERY_SENSE_RESOLUTION 4096.0 +#undef AREF_VOLTAGE +#define AREF_VOLTAGE 3.0 +#define VBAT_AR_INTERNAL AR_INTERNAL_3_0 +#define ADC_MULTIPLIER 1.73 + +#ifdef __cplusplus +} +#endif + +/*---------------------------------------------------------------------------- + * Arduino objects - C++ only + *----------------------------------------------------------------------------*/ + +#endif